]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge pull request #1094 from SISheogorath/insp20+fixed-Override
authorAdam <adam@sigterm.info>
Wed, 17 May 2017 23:46:28 +0000 (19:46 -0400)
committerGitHub <noreply@github.com>
Wed, 17 May 2017 23:46:28 +0000 (19:46 -0400)
fix override issue

69 files changed:
.travis.yml [new file with mode: 0644]
configure
docs/conf/helpop-full.conf.example
docs/conf/helpop.conf.example
docs/conf/inspircd.conf.example
docs/conf/modules.conf.example
include/base.h
include/configreader.h
include/dns.h
include/inspircd.h
include/modules.h
make/calcdep.pl
make/check_epoll.cpp
make/check_eventfd.cpp
make/check_kqueue.cpp [new file with mode: 0644]
make/check_stdint.cpp [new file with mode: 0644]
make/check_strlcpy.cpp [new file with mode: 0644]
make/opensslcert.pm
make/template/inspircd
make/template/main.mk
make/utilities.pm
modulemanager
src/commands/cmd_kill.cpp
src/commands/cmd_list.cpp
src/commands/cmd_oper.cpp
src/commands/cmd_stats.cpp
src/commands/cmd_who.cpp
src/configparser.cpp
src/configreader.cpp
src/dns.cpp
src/inspircd.cpp
src/mode.cpp
src/modules/extra/m_ldapauth.cpp
src/modules/extra/m_sqlite3.cpp
src/modules/extra/m_ssl_gnutls.cpp
src/modules/extra/m_ssl_openssl.cpp
src/modules/m_callerid.cpp
src/modules/m_cap.cpp
src/modules/m_cap.h
src/modules/m_censor.cpp
src/modules/m_cgiirc.cpp
src/modules/m_check.cpp
src/modules/m_cloaking.cpp
src/modules/m_dccallow.cpp
src/modules/m_dnsbl.cpp
src/modules/m_hideoper.cpp
src/modules/m_httpd_stats.cpp
src/modules/m_ircv3.cpp
src/modules/m_jumpserver.cpp
src/modules/m_namedmodes.cpp
src/modules/m_operprefix.cpp
src/modules/m_permchannels.cpp
src/modules/m_sakick.cpp
src/modules/m_sasl.cpp
src/modules/m_securelist.cpp
src/modules/m_spanningtree/capab.cpp
src/modules/m_spanningtree/fjoin.cpp
src/modules/m_spanningtree/netburst.cpp
src/modules/m_spanningtree/postcommand.cpp
src/modules/m_spanningtree/protocolinterface.cpp
src/modules/m_spanningtree/treesocket.h
src/modules/m_sslinfo.cpp
src/socketengines/socketengine_epoll.cpp
src/usermanager.cpp
src/users.cpp
src/version.sh
tools/travis-ci.sh [new file with mode: 0755]
win/CMakeLists.txt
win/inspircd_win32wrapper.h

diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..bb82add
--- /dev/null
@@ -0,0 +1,13 @@
+compiler:
+  - clang
+  - gcc
+dist: trusty
+env:
+  - PURE_STATIC=1
+  -
+language: cpp
+notifications:
+  email: false
+script:
+  - sh ./tools/travis-ci.sh
+sudo: required
index 76ef8ce361270b8708df180c131bbc072ba2a379..b380b5700046cad908714e057d3370ae2cc080e4 100755 (executable)
--- a/configure
+++ b/configure
@@ -28,6 +28,7 @@
 
 BEGIN {
        require 5.8.0;
+       push @INC, '.';
 }
 
 use strict;
@@ -268,10 +269,9 @@ if (defined $opt_cc)
 {
        $config{CC} = $opt_cc;
 }
-our $exec = $config{CC} . " -dumpversion | cut -c 1";
-chomp($config{GCCVER}          = `$exec`);                             # Major GCC Version
-$exec = $config{CC} . " -dumpversion | cut -c 3";
-chomp($config{GCCMINOR}                = `$exec`);
+`$config{CC} -dumpversion` =~ /^(\d+)(?:\.(\d+))?/;
+$config{GCCVER} = defined $1 ? $1 : '';
+$config{GCCMINOR} = defined $2 ? $2 : '0';
 $config{MAXBUF}                        = "512";                                # Max buffer size
 
 if ($config{HAS_OPENSSL} =~ /^([-[:digit:].]+)(?:[a-z])?(?:\-[a-z][0-9])?/) {
@@ -347,57 +347,21 @@ print ($cache_loaded ? "found\n" : "not found\n");
 $config{SYSTEM} = lc $^O;
 print "Checking operating system version... $config{SYSTEM}\n";
 
-$exec = $config{CC} . " -dumpversion | cut -c 1";
-chomp($config{GCCVER}          = `$exec`);                             # Major GCC Version
-$exec = $config{CC} . " -dumpversion | cut -c 3";
-chomp($config{GCCMINOR}                = `$exec`);
+`$config{CC} -dumpversion` =~ /^(\d+)(?:\.(\d+))?/;
+$config{GCCVER} = defined $1 ? $1 : '';
+$config{GCCMINOR} = defined $2 ? $2 : '0';
 
 printf "Checking if stdint.h exists... ";
-$config{HAS_STDINT} = "true";
-our $fail = 0;
-open(STDINT, "</usr/include/stdint.h") or $config{HAS_STDINT} = "false";
-if ($config{HAS_STDINT} eq "true") {
-       close(STDINT);
-}
-print "yes\n" if $config{HAS_STDINT} eq "true";
-print "no\n" if $config{HAS_STDINT} eq "false";
+$config{HAS_STDINT} = test_compile('stdint');
+print $config{HAS_STDINT} ? "yes\n" : "no\n";
 
 printf "Checking if strlcpy exists... ";
-# Perform the strlcpy() test..
-$config{HAS_STRLCPY} = "false";
-$fail = 0;
-open(STRLCPY, "</usr/include/string.h") or $fail = 1;
-if (!$fail) {
-       while (defined(my $line = <STRLCPY>)) {
-               chomp($line);
-               # try and find the delcaration of:
-               # size_t strlcpy(...)
-               if ($line =~ /size_t(\0x9|\s)+strlcpy/) {
-                       $config{HAS_STRLCPY} = "true";
-               }
-       }
-       close(STRLCPY);
-}
-print "yes\n" if $config{HAS_STRLCPY} eq "true";
-print "no\n" if $config{HAS_STRLCPY} eq "false";
+$config{HAS_STRLCPY} = test_compile('strlcpy');
+print $config{HAS_STRLCPY} ? "yes\n" : "no\n";
 
 printf "Checking if kqueue exists... ";
-$has_kqueue = 0;
-$fail = 0;
-open(KQUEUE, "</usr/include/sys/event.h") or $fail = 1;
-if (!$fail) {
-       while (defined(my $line = <KQUEUE>)) {
-               chomp($line);
-               # try and find the delcaration of:
-               # int kqueue(void);
-               if ($line =~ /int(\0x9|\s)+kqueue/) {
-                       $has_kqueue = 1;
-               }
-       }
-       close(KQUEUE);
-}
-print "yes\n" if $has_kqueue == 1;
-print "no\n" if $has_kqueue == 0;
+$has_kqueue = test_compile('kqueue');
+print $has_kqueue ? "yes\n" : "no\n";
 
 printf "Checking for epoll support... ";
 $has_epoll = test_compile('epoll');
@@ -523,8 +487,9 @@ should NOT be used. You should probably specify a newer compiler.\n\n";
                        }
                        chomp(my $foo = `$config{CC} -dumpversion | cut -c 1`);
                        if ($foo ne "") {
-                               chomp($config{GCCVER}       = `$config{CC} -dumpversion | cut -c 1`); # we must redo these if we change compilers
-                               chomp($config{GCCMINOR}     = `$config{CC} -dumpversion | cut -c 3`);
+                               `$config{CC} -dumpversion` =~ /^(\d+)(?:\.(\d+))?/;
+                               $config{GCCVER} = defined $1 ? $1 : '';
+                               $config{GCCMINOR} = defined $2 ? $2 : '0';
                                print "Queried compiler: \e[1;32m$config{CC}\e[0m (version \e[1;32m$config{GCCVER}.$config{GCCMINOR}\e[0m)\n";
                                if ($config{GCCVER} < 3) {
                                        print "\e[1;32mGCC 2.x WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
@@ -874,8 +839,8 @@ sub writefiles {
                open(FILEHANDLE, ">include/inspircd_config.h.tmp");
                print FILEHANDLE <<EOF;
 /* Auto generated by configure, do not modify! */
-#ifndef __CONFIGURATION_AUTO__
-#define __CONFIGURATION_AUTO__
+#ifndef INSPIRCD_CONFIG_H
+#define INSPIRCD_CONFIG_H
 
 /* this is for windows support. */
 #define CoreExport /**/
@@ -911,6 +876,10 @@ print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
                }
                if ($config{OSNAME} !~ /DARWIN/i) {
                        print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
+               } else {
+                       print FILEHANDLE "#ifdef MAC_OS_X_VERSION_10_12\n";
+                       print FILEHANDLE "# define HAS_CLOCK_GETTIME\n";
+                       print FILEHANDLE "#endif\n";
                }
                my $use_hiperf = 0;
                if (($has_kqueue) && ($config{USE_KQUEUE} eq "y")) {
@@ -1000,6 +969,9 @@ EOF
        my @dotfiles = qw(main.mk inspircd);
        push @dotfiles, 'org.inspircd.plist' if $config{OSNAME} eq 'darwin';
 
+       # HACK: we need to know if we are on GCC6 to disable the omission of `this` null pointer checks.
+       $config{GCC6} = `$config{CC} --version 2>/dev/null` =~ /gcc/i && $config{GCCVER} ge "6" ? "true" : "false";
+
        foreach my $file (@dotfiles) {
                open(FILEHANDLE, "make/template/$file") or die "Can't open make/template/$file: $!";
                $_ = join '', <FILEHANDLE>;
@@ -1009,7 +981,7 @@ EOF
 
                for my $var (qw(
                        CC SYSTEM BASE_DIR CONFIG_DIR MODULE_DIR BINARY_DIR BUILD_DIR DATA_DIR UID
-                       STARTSCRIPT DESTINATION SOCKETENGINE LOG_DIR
+                       STARTSCRIPT DESTINATION SOCKETENGINE LOG_DIR GCC6
                )) {
                        s/\@$var\@/$config{$var}/g;
                }
index a3529b9dcfd51d6af3e4ac7d4a7c025ce879dde3..ed82c6e02d07e7750bd722576f86e1bef3ba09d8 100644 (file)
@@ -381,6 +381,7 @@ Sets your name to the specified name.">
 
 OPERMOTD  CHECK     CLONES      USERIP   TLINE
 ALLTIME   WALLOPS   GLOBOPS     MODENOTICE
+CLOAK
 
 SETHOST   SETIDENT  CHGHOST     CHGIDENT CHGNAME
 SETIDLE   SWHOIS
@@ -759,10 +760,9 @@ The duration may be specified in seconds, or in the format
 1y2w3d4h5m6s - meaning one year, two weeks, three days, 4 hours,
 5 minutes and 6 seconds. All fields in this format are optional.">
 
-<helpop key="clearcache" value="/CLEARCACHE {servername}
+<helpop key="clearcache" value="/CLEARCACHE
 
-This command clears the DNS cache of the specified server. If no
-server is specified, the local server's DNS cache will be cleared.">
+This command clears the DNS cache of the local server.">
 
 <helpop key="close" value="/CLOSE
 
@@ -774,6 +774,12 @@ Sends a notice to all users who have the given mode(s) set.
 If multiple mode letters are given, the notice is only sent to users
 who have all of them set.">
 
+<helpop key="cloak" value="/CLOAK <host>
+
+Generate the cloak of a host or IP. This is useful for example when
+trying to get the cloak of a user from /WHOWAS and they were not
+using their cloak when they quit.">
+
 ######################
 # User/Channel Modes #
 ######################
@@ -809,6 +815,8 @@ who have all of them set.">
               hideoper module).
  I            Hides a user's entire channel list in WHOIS from
               non-IRCops (requires hidechans module).
+ L            Stops redirections done by m_redirect (mode must be
+              enabled in the config).
  R            Blocks private messages from unregistered users
               (requires services account module).
  S            Strips mIRC color/bold/underline codes out of private
index 32884ea16c25ccd6c0b47f4a8ce27b195d3214ca..b4d3214f6e74e85af23096ad31f9ea7200b5e128 100644 (file)
@@ -51,6 +51,7 @@ OPER">
 
 OPERMOTD  CHECK     CLONES      USERIP   TLINE
 ALLTIME   WALLOPS   GLOBOPS     MODENOTICE
+CLOAK
 
 SETHOST   SETIDENT  CHGHOST     CHGIDENT CHGNAME
 SETIDLE   SWHOIS
@@ -102,6 +103,8 @@ LOCKSERV       UNLOCKSERV">
               hideoper module).
  I            Hides a user's entire channel list in WHOIS from
               non-IRCops (requires hidechans module).
+ L            Stops redirections done by m_redirect (mode must be
+              enabled in the config).
  R            Blocks private messages from unregistered users
               (requires services account module).
  S            Strips mIRC color/bold/underline codes out of private
index 9fd0adfd34d1e17e43c3bd379d3eb3c954d5bb54..7099cefe262a6a7c4b53e4c7ca6dfa6696c1a9fb 100644 (file)
           # hidekills: If defined, replaces who set a /kill with a custom string.
           hidekills=""
 
+          # hideulinekills: Hide kills from clients of ulined servers from server notices.
+          hideulinekills="yes"
+
           # hidesplits: If enabled, non-opers will not be able to see which
           # servers split in a netsplit, they will only be able to see that one
           # occurred (If their client has netsplit detection).
index 364c30a14c042478c86cea163a9129d790a49b26..003b4d04ba5b7949600fc9abc224f9975ce4134d 100644 (file)
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 # Channelban: Implements extended ban j:, which stops anyone already
 # in a channel matching a ban like +b j:#channel*mask from joining.
+# Note that by default wildcard characters * and ? are allowed in
+# channel names. To disallow them, load m_channames and add characters
+# 42 and 63 to denyrange (see above).
 #<module name="m_channelban.so">
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 # Chanprotect module: Gives +q and +a channel modes.
+#
+# IMPORTANT: This module has been removed in the next major version of
+# InspIRCd. You should use m_customprefix instead.
 #<module name="m_chanprotect.so">
 
 <chanprotect
 # key3, key4; the values must be less than 0x80000000 and should be   #
 # picked at random. Prefix is mandatory, will default to network name #
 # if not specified, and will always have a "-" appended.              #
+#                                                                     #
+# IMPORTANT: The compat-host and compat-ip modes have been removed in #
+# the next major version of InspIRCd. You should ONLY use them if you #
+# need backwards compatibility with InspIRCd 1.2.                     #
 #
 #<cloak mode="half"
 #       key="secret"
 #  length            - Default duration of entries in DCCALLOW list.
 #  action            - Default action to take if no action is
 #                      specified, can be 'block' or 'allow'.
+#  maxentries        - Max number of nicks to allow on a DCCALLOW list.
 #
 # File configuration:
 #  pattern           - The glob pattern to match against.
 #                      that matches this pattern, can be 'block' or
 #                      'allow'.
 #
-#<dccallow blockchat="yes" length="5m" action="block">
+#<dccallow blockchat="yes" length="5m" action="block" maxentries="20">
 #<banfile pattern="*.exe" action="block">
 #<banfile pattern="*.txt" action="allow">
 
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 # Halfop module: Provides the +h (halfops) channel status mode.
+#
+# IMPORTANT: This module has been removed in the next major version of
+# InspIRCd. You should use m_customprefix instead.
 #<module name="m_halfop.so">
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
 #           binddn="cn=Manager,dc=brainbox,dc=cc"                     #
 #           bindauth="mysecretpass"                                   #
 #           verbose="yes"                                             #
-#           host="$uid.$ou.inspircd.org">                             #
+#           host="$uid.$ou.inspircd.org"                              #
+#           useusername="no">                                         #
 #                                                                     #
 # <ldapwhitelist cidr="10.42.0.0/16">                                 #
 #                                                                     #
 # The attribute value indicates the attribute which is used to locate #
 # a user account by name. On POSIX systems this is usually 'uid'.     #
 #                                                                     #
+# 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.                                                   #
+#                                                                     #
 # The server parameter indicates the LDAP server to connect to. The   #
 # ldap:// style scheme before the hostname proper is MANDATORY.       #
 #                                                                     #
 #
 #-#-#-#-#-#-#-#-#-# 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.      #
 # 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
+# m_sslinfo module (see below).
 #<module name="m_sslmodes.so">
 
 #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
index 0a4456f3a7fd398c2aea015b38dc88c76a5d5ded..19222a6f5d2ac4ac592ae84797c7044c31d7a1a1 100644 (file)
@@ -201,7 +201,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.
         * The module should probably put something informative here as the user will see this upon failure.
         */
index b01a979a7c2703384bb17155e52688370af0d3df..4a697d05c314a1edbe5de12ec9240978f2cb3b43 100644 (file)
@@ -438,6 +438,10 @@ class CoreExport ServerConfig
         */
        std::string HideKillsServer;
 
+       /** Set to hide kills from clients of ulined servers in snotices.
+        */
+       bool HideULineKills;
+
        /** The full pathname and filename of the PID
         * file as defined in the configuration.
         */
index de4bcf4223fb713273b3edc2a4a1243f67b35490..05df6f69cb3baeb1efb5ac747b120126bbc580dc 100644 (file)
@@ -302,6 +302,10 @@ class CoreExport DNS : public EventHandler
         */
        static const int MAX_REQUEST_ID = 0xFFFF;
 
+       /** Maximum number of entries in cache
+        */
+       static const unsigned int MAX_CACHE_SIZE = 1000;
+
        /**
         * Currently cached items
         */
index e2eaf82927171fd7b8cec3bb9bc23cb3987caa7b..78348ed54c4957d411c97a6a657d0c13eee8f4c7 100644 (file)
@@ -779,9 +779,10 @@ class CoreExport InspIRCd
 
        /** Attempt to write the process id to a given file
         * @param filename The PID file to attempt to write to
+        * @param exitonfail If true and the PID fail cannot be written log to stdout and exit, otherwise only log on failure
         * @return This function may bail if the file cannot be written
         */
-       void WritePID(const std::string &filename);
+       void WritePID(const std::string& filename, bool exitonfail = true);
 
        /** This constructor initialises all the subsystems and reads the config file.
         * @param argc The argument count passed to main()
index 9857012fcfc0ac1c71793198e15f5b0a902d5e0c..4d4d0871fb07b18214d6de024b5fd55c97786b86 100644 (file)
@@ -116,7 +116,7 @@ struct ModResult {
  * and numerical comparisons in preprocessor macros if they wish to support
  * multiple versions of InspIRCd in one file.
  */
-#define INSPIRCD_VERSION_API 9
+#define INSPIRCD_VERSION_API 10
 
 /**
  * This #define allows us to call a method in all
index 4a759a24a163692ca19682cad0abb44ecc7ff11c..49506dd3be8fe35c05251bad55f477c582880e9b 100755 (executable)
@@ -160,7 +160,7 @@ END
 obj/ld-extra.cmd: $core_src
        \@\$(SOURCEPATH)/make/unit-cc.pl gen-ld\$(VERBOSE) \$\@ \$^ \$>
 
-bin/inspircd: obj/ld-extra.cmd $core_mk
+bin/inspircd: $core_mk obj/ld-extra.cmd
        \@\$(SOURCEPATH)/make/unit-cc.pl static-ld\$(VERBOSE) \$\@ \$^ \$>
 
 inspircd: bin/inspircd
index 918d3907e832e8861c045222dce4af8483bee371..a5ed1c10b207f66146324fb6f5f39716a9980cc8 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
+ *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
  *
  * 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
index 980d04485bb2774d896474c27a4f31ae50e4d424..9b38b793b3e32072fef964f1accd249468af104f 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
+ *   Copyright (C) 2012 William Pitcock <nenolod@dereferenced.org>
+ *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
  *
  * 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/check_kqueue.cpp b/make/check_kqueue.cpp
new file mode 100644 (file)
index 0000000..6034253
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 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
+ * 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 <sys/types.h>
+#include <sys/event.h>
+
+int main() {
+       int fd = kqueue();
+       return (fd < 0);
+}
diff --git a/make/check_stdint.cpp b/make/check_stdint.cpp
new file mode 100644 (file)
index 0000000..fbd01b8
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 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
+ * 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 <stdint.h>
+
+int main() {
+       uint32_t ret = 0;
+       return ret;
+}
diff --git a/make/check_strlcpy.cpp b/make/check_strlcpy.cpp
new file mode 100644 (file)
index 0000000..e51d18d
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 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
+ * 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 <string.h>
+
+int main() {
+       char test[5];
+       strlcpy(test, "test", sizeof(test));
+}
index 1bf27df159f7f50993e3bb0c0ead13a5bb7a7bfd..20da704f72434f3d8230c8489f7990a1bbfc372f 100644 (file)
@@ -46,6 +46,7 @@ sub make_openssl_cert()
        my $state = promptstring_s('What state are you located in?', 'Example State');
        my $country = promptstring_s('What is the ISO 3166-1 code for the country you are located in?', 'XZ');
        my $time = promptstring_s('How many days do you want your certificate to be valid for?', '365');
+       my $use_1024 = promptstring_s('Do you want to generate less secure dhparams which are compatible with old versions of Java?', 'n');
        print FH <<__END__;
 $country
 $state
@@ -56,8 +57,9 @@ $commonname
 $email
 __END__
 close(FH);
-system("cat openssl.template | openssl req -x509 -nodes -newkey rsa:1024 -keyout key.pem -out cert.pem -days $time 2>/dev/null");
-system("openssl dhparam -out dhparams.pem 1024");
+my $dhbits = $use_1024 =~ /^(1|on|true|yes|y)$/ ? 1024 : 2048;
+system("cat openssl.template | openssl req -x509 -nodes -newkey rsa:2048 -keyout key.pem -out cert.pem -days $time 2>/dev/null");
+system("openssl dhparam -out dhparams.pem $dhbits");
 unlink("openssl.template");
 }
 
index 7cd83a8e15fdd0615e020592e102277f5117a9f6..b43ad60c9ecbb67981cf36258dc765964c36b860 100644 (file)
@@ -135,7 +135,7 @@ sub cmd_rehash()
 
 sub cmd_cron()
 {
-       if (getstatus() == 0) { goto &cmd_start(); }
+       if (getstatus() == 0) { goto &cmd_start(@_); }
        exit();
 }
 
@@ -149,7 +149,7 @@ sub cmd_restart(@)
 {
        cmd_stop();
        unlink($pidfile) if (-e $pidfile);
-       goto &cmd_start;
+       goto &cmd_start(@_);
 }
 
 sub hid_cheese_sandwich()
index 1dff0fc20201151a50c0f93f2b77bb519846c0bf..23daa7efc02a0d2069cc70f694b56958f1870571 100644 (file)
@@ -89,6 +89,11 @@ INSTMODE_LIB = 0644
   D=0
 @ENDIF
 
+GCC6=@GCC6@
+@IFEQ $(GCC6) true
+  CXXFLAGS += -fno-delete-null-pointer-checks
+@ENDIF
+
 DBGOK=0
 @IFEQ $(D) 0
   CXXFLAGS += -O2
@@ -124,8 +129,8 @@ CXXFLAGS += -Iinclude
 @ELSE
   @GNU_ONLY MAKEFLAGS += --silent
   @BSD_ONLY MAKE += -s
-  RUNCC = perl $(SOURCEPATH)/make/run-cc.pl $(CC)
-  RUNLD = perl $(SOURCEPATH)/make/run-cc.pl $(CC)
+  RUNCC = perl "$(SOURCEPATH)/make/run-cc.pl" $(CC)
+  RUNLD = perl "$(SOURCEPATH)/make/run-cc.pl" $(CC)
   VERBOSE =
 @ENDIF
 
@@ -160,7 +165,7 @@ all: $(FOOTER)
 
 target: $(HEADER)
        $(MAKEENV) perl make/calcdep.pl
-       cd $(BUILDPATH); $(MAKEENV) $(MAKE) -f real.mk $(TARGET)
+       cd "$(BUILDPATH)"; $(MAKEENV) $(MAKE) -f real.mk $(TARGET)
 
 debug:
        @${MAKE} D=1 all
@@ -227,9 +232,9 @@ install: target
        @-$(INSTALL) -d -m $(INSTMODE_DIR) $(CONPATH)/examples/aliases
        @-$(INSTALL) -d -m $(INSTMODE_DIR) $(CONPATH)/examples/modules
        @-$(INSTALL) -d -m $(INSTMODE_DIR) $(MODPATH)
-       [ $(BUILDPATH)/bin/ -ef $(BINPATH) ] || $(INSTALL) -m $(INSTMODE_BIN) $(BUILDPATH)/bin/inspircd $(BINPATH)
+       [ "$(BUILDPATH)/bin/" -ef $(BINPATH) ] || $(INSTALL) -m $(INSTMODE_BIN) "$(BUILDPATH)/bin/inspircd" $(BINPATH)
 @IFNDEF PURE_STATIC
-       [ $(BUILDPATH)/modules/ -ef $(MODPATH) ] || $(INSTALL) -m $(INSTMODE_LIB) $(BUILDPATH)/modules/*.so $(MODPATH)
+       [ "$(BUILDPATH)/modules/" -ef $(MODPATH) ] || $(INSTALL) -m $(INSTMODE_LIB) "$(BUILDPATH)/modules/"*.so $(MODPATH)
 @ENDIF
        -$(INSTALL) -m $(INSTMODE_BIN) @STARTSCRIPT@ $(BASE) 2>/dev/null
        -$(INSTALL) -m $(INSTMODE_LIB) tools/gdbargs $(BASE)/.gdbargs 2>/dev/null
@@ -258,16 +263,17 @@ GNUmakefile BSDmakefile: make/template/main.mk configure $(RCS_FILES)
 
 clean:
        @echo Cleaning...
-       -rm -f $(BUILDPATH)/bin/inspircd $(BUILDPATH)/include $(BUILDPATH)/real.mk
-       -rm -rf $(BUILDPATH)/obj $(BUILDPATH)/modules
-       @-rmdir $(BUILDPATH)/bin 2>/dev/null
-       @-rmdir $(BUILDPATH) 2>/dev/null
+       -rm -f "$(BUILDPATH)/bin/inspircd" "$(BUILDPATH)/include" "$(BUILDPATH)/real.mk"
+       -rm -rf "$(BUILDPATH)/obj" "$(BUILDPATH)/modules"
+       @-rmdir "$(BUILDPATH)/bin" 2>/dev/null
+       @-rmdir "$(BUILDPATH)" 2>/dev/null
        @echo Completed.
 
 deinstall:
        -rm -f $(BINPATH)/inspircd
        -rm -rf $(CONPATH)/examples
-       -rm -f $(MODPATH)/*.so
+       -rm -f $(MODPATH)/cmd_*.so
+       -rm -f $(MODPATH)/m_*.so
        -rm -f $(BASE)/.gdbargs
        -rm -f $(BASE)/org.inspircd.plist
 
@@ -283,8 +289,8 @@ configureclean:
        -rm -f org.inspircd.plist
 
 distclean: clean configureclean
-       -rm -rf $(SOURCEPATH)/run
-       find $(SOURCEPATH)/src/modules -type l | xargs rm -f
+       -rm -rf "$(SOURCEPATH)/run"
+       find "$(SOURCEPATH)/src/modules" -type l | xargs rm -f
 
 help:
        @echo 'InspIRCd Makefile'
@@ -314,4 +320,6 @@ help:
        @echo ' deinstall Removes the files created by "make install"'
        @echo
 
+.NOTPARALLEL:
+
 .PHONY: all target debug debug-header mod-header mod-footer std-header finishmessage install clean deinstall squeakyclean configureclean help
index ae16ce3dc92836f238ab8f04d54223c58371f567..baba584ad240754030525f0d60fcaae7ec975302 100644 (file)
@@ -29,6 +29,7 @@ use warnings FATAL => qw(all);
 
 use Exporter 'import';
 use POSIX;
+use File::Temp;
 use Getopt::Long;
 use Fcntl;
 our @EXPORT = qw(make_rpath pkgconfig_get_include_dirs pkgconfig_get_lib_dirs pkgconfig_check_version translate_functions promptstring);
@@ -404,7 +405,7 @@ sub translate_functions($$)
                        my $tmpfile;
                        do
                        {
-                               $tmpfile = tmpnam();
+                               $tmpfile = File::Temp::tmpnam();
                        } until sysopen(TF, $tmpfile, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, 0700);
                        print "(Created and executed \e[1;32m$tmpfile\e[0m)\n";
                        print TF $1;
index af5bf113caa6f75b1d16b43bfbb5c8b74d193bb0..42566d3b1ce77f4ed738cbd4062e8868e08b7cb6 100755 (executable)
 use strict;
 use warnings FATAL => qw(all);
 
-use make::configure;
+BEGIN {
+       require 5.8.0;
+       push @INC, '.';
+}
 
 BEGIN {
+       # HACK: for some reason this needs to be in a second BEGIN block
+       # or it doesn't receive the updated @INC from above.
+       use make::configure;
        unless (module_installed("LWP::Simple")) {
                die "Your system is missing the LWP::Simple Perl module!";
        }
index 17c8a76a053479968f229916dd216ce69c9ab138..7bdf32c74f8c92d9e95fd13fa049429379cb63af 100644 (file)
@@ -111,7 +111,8 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User
                if (!IS_LOCAL(u))
                {
                        // remote kill
-                       ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
+                       if (!ServerInstance->Config->HideULineKills || !ServerInstance->ULine(user->server))
+                               ServerInstance->SNO->WriteToSnoMask('K', "Remote kill by %s: %s (%s)", user->nick.c_str(), u->GetFullRealHost().c_str(), parameters[1].c_str());
                        FOREACH_MOD(I_OnRemoteKill, OnRemoteKill(user, u, killreason, killreason));
                }
                else
@@ -121,10 +122,13 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User
                         * 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 (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());
+                       if (!ServerInstance->Config->HideULineKills || !ServerInstance->ULine(user->server))
+                       {
+                               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",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());
                        /* Bug #419, make sure this message can only occur once even in the case of multiple KILL messages crossing the network, and change to show
                         * hidekillsserver as source if possible
@@ -134,7 +138,7 @@ CmdResult CommandKill::Handle (const std::vector<std::string>& parameters, User
                                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(),
-                                               user->dhost.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());
                        }
index 2c420d1dde6561f5bb5223a717806a8bd7993b2c..eb28fb89c0ffe09fbd5f21e1702ae1fd6f5dc89b 100644 (file)
@@ -49,8 +49,7 @@ CmdResult CommandList::Handle (const std::vector<std::string>& parameters, User
 
        user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str());
 
-       /* Work around mIRC suckyness. YOU SUCK, KHALED! */
-       if (parameters.size() == 1)
+       if ((parameters.size() == 1) && (!parameters[0].empty()))
        {
                if (parameters[0][0] == '<')
                {
index 1a5e7e1783a4331911d89196b3353722b151ca53..95f6b98df3f45bc7a04a2b3073c1d7a082db4b11 100644 (file)
@@ -69,7 +69,7 @@ CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, L
        snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
 
        OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]);
-       if (i != ServerInstance->Config->oper_blocks.end())
+       if ((i != ServerInstance->Config->oper_blocks.end()) && (i->second->oper_block))
        {
                OperInfo* ifo = i->second;
                ConfigTag* tag = ifo->oper_block;
index d547635ed37968e1931e520fad687eba0de64a3b..aa5bf44cd50dd1cb1492c00858799a540adf759b 100644 (file)
@@ -39,7 +39,7 @@ class CommandStats : public Command
  public:
        /** Constructor for stats.
         */
-       CommandStats ( Module* parent) : Command(parent,"STATS",1,2) { syntax = "<stats-symbol> [<servername>]"; }
+       CommandStats ( Module* parent) : Command(parent,"STATS",1,2) { allow_empty_last_param = false; syntax = "<stats-symbol> [<servername>]"; }
        /** Handle command.
         * @param parameters The parameters to the comamnd
         * @param pcnt The number of parameters passed to teh command
index 90c26a974d4b8c3676fe5b23f673b6753b5f8acf..8438f8cdd0e07d222252eb96c76df49a0d5741f1 100644 (file)
@@ -58,13 +58,15 @@ class CommandWho : public Command
 };
 
 
-static Channel* get_first_visible_channel(User *u)
+static Channel* get_first_visible_channel(User *source, User *u)
 {
        UCListIter i = u->chans.begin();
        while (i != u->chans.end())
        {
                Channel* c = *i++;
-               if (!c->IsModeSet('s'))
+
+               /* XXX move the +I check into m_hidechans */
+               if (source == u || !(c->IsModeSet('s') || c->IsModeSet('p') || u->IsModeSet('I')) || c->HasUser(source))
                        return c;
        }
        return NULL;
@@ -189,7 +191,7 @@ bool CommandWho::CanView(Channel* chan, User* user)
 void CommandWho::SendWhoLine(User* user, const std::vector<std::string>& parms, const std::string &initial, Channel* ch, User* u, std::vector<std::string> &whoresults)
 {
        if (!ch)
-               ch = get_first_visible_channel(u);
+               ch = get_first_visible_channel(user, u);
 
        std::string wholine = initial + (ch ? ch->name : "*") + " " + u->ident + " " +
                (opt_showrealhost ? u->host : u->dhost) + " ";
index 94192a71bb9166c2e8bda7124793f96c260fbe91..409ebdd395e67fe38de058edd0e823e73d28d3f2 100644 (file)
@@ -388,19 +388,20 @@ bool ParseStack::ParseExec(const std::string& name, int flags, const std::string
        return ok;
 }
 
-bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf)
-{
 #ifdef __clang__
 # pragma clang diagnostic push
 # pragma clang diagnostic ignored "-Wunknown-pragmas"
 # pragma clang diagnostic ignored "-Wundefined-bool-conversion"
+#elif defined __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpragmas"
+# pragma GCC diagnostic ignored "-Wnonnull-compare"
 #endif
+bool ConfigTag::readString(const std::string& key, std::string& value, bool allow_lf)
+{
        // TODO: this is undefined behaviour but changing the API is too risky for 2.0.
        if (!this)
                return false;
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
        for(std::vector<KeyVal>::iterator j = items.begin(); j != items.end(); ++j)
        {
                if(j->first != key)
@@ -418,6 +419,11 @@ bool ConfigTag::readString(const std::string& key, std::string& value, bool allo
        }
        return false;
 }
+#ifdef __clang__
+# pragma clang diagnostic pop
+#elif defined __GNUC__
+# pragma GCC diagnostic pop
+#endif
 
 std::string ConfigTag::getString(const std::string& key, const std::string& def)
 {
index bcee938d55208e1aefc3dcc5d0db93cf81820175..301db14e87187c849db0150bd8221461ee7f1386 100644 (file)
@@ -531,6 +531,7 @@ void ServerConfig::Fill()
        HideBans = security->getBool("hidebans");
        HideWhoisServer = security->getString("hidewhois");
        HideKillsServer = security->getString("hidekills");
+       HideULineKills = security->getBool("hideulinekills");
        RestrictBannedUsers = security->getBool("restrictbannedusers", true);
        GenericOper = security->getBool("genericoper");
        NoUserDns = ConfValue("performance")->getBool("nouserdns");
@@ -728,7 +729,7 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
 
        // write once here, to try it out and make sure its ok
        if (valid)
-               ServerInstance->WritePID(this->PID);
+               ServerInstance->WritePID(this->PID, !old);
 
        if (old && valid)
        {
index 14305ccab2f49a2a4e94f94ee67dc543c34e92c2..3d3bc947fee2cfbee4f045e04b56b5eeb0730687 100644 (file)
@@ -121,7 +121,7 @@ class CacheTimer : public Timer
        DNS* dns;
  public:
        CacheTimer(DNS* thisdns)
-               : Timer(3600, ServerInstance->Time(), true), dns(thisdns) { }
+               : Timer(5*60, ServerInstance->Time(), true), dns(thisdns) { }
 
        virtual void Tick(time_t)
        {
@@ -162,6 +162,8 @@ class RequestTimeout : public Timer
 
 CachedQuery::CachedQuery(const std::string &res, QueryType qt, unsigned int ttl) : data(res), type(qt)
 {
+       if (ttl > 5*60)
+               ttl = 5*60;
        expires = ServerInstance->Time() + ttl;
 }
 
@@ -1058,7 +1060,11 @@ void DNS::HandleEvent(EventType, int)
                                        ServerInstance->stats->statsDnsGood++;
 
                                if (!this->GetCache(res.original.c_str()))
+                               {
+                                       if (cache->size() >= MAX_CACHE_SIZE)
+                                               cache->clear();
                                        this->cache->insert(std::make_pair(res.original.c_str(), CachedQuery(res.result, res.type, res.ttl)));
+                               }
 
                                Classes[res.id]->OnLookupComplete(res.result, res.ttl, false);
                                delete Classes[res.id];
index 766aeaf8ef05d92cb4979252aac8423ce7825a0c..0fa90fca5b6028ed764f94f6878d470b530320cb 100644 (file)
@@ -294,7 +294,7 @@ bool InspIRCd::DaemonSeed()
 #endif
 }
 
-void InspIRCd::WritePID(const std::string &filename)
+void InspIRCd::WritePID(const std::string& filename, bool exitonfail)
 {
 #ifndef _WIN32
        std::string fname(filename);
@@ -307,10 +307,12 @@ void InspIRCd::WritePID(const std::string &filename)
                outfile.close();
        }
        else
-       {
-               std::cout << "Failed to write PID-file '" << fname << "', exiting." << std::endl;
-               this->Logs->Log("STARTUP",DEFAULT,"Failed to write PID-file '%s', exiting.",fname.c_str());
-               Exit(EXIT_STATUS_PID);
+       {\r
+               if (exitonfail)\r
+                       std::cout << "Failed to write PID-file '" << fname << "', exiting." << std::endl;
+               this->Logs->Log("STARTUP",DEFAULT,"Failed to write PID-file '%s'%s",fname.c_str(), (exitonfail ? ", exiting." : ""));\r
+               if (exitonfail)
+                       Exit(EXIT_STATUS_PID);\r
        }
 #endif
 }
@@ -814,11 +816,11 @@ int InspIRCd::Run()
                        /* Allow a buffer of two seconds drift on this so that ntpdate etc dont harass admins */
                        if (TIME.tv_sec < OLDTIME - 2)
                        {
-                               SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %lu secs.", (unsigned long)OLDTIME-TIME.tv_sec);
+                               SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %lu secs.", (unsigned long)(OLDTIME-TIME.tv_sec));
                        }
                        else if (TIME.tv_sec > OLDTIME + 2)
                        {
-                               SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is jumping FORWARDS! Clock skipped %lu secs.", (unsigned long)TIME.tv_sec - OLDTIME);
+                               SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is jumping FORWARDS! Clock skipped %lu secs.", (unsigned long)(TIME.tv_sec - OLDTIME));
                        }
 \r
                        OLDTIME = TIME.tv_sec;
index 89ff37fa1e7fd0b709bd411c220abdf15cf6b1f4..0f5d457834ba33538a28abb713c193751b9f6d71 100644 (file)
@@ -837,11 +837,19 @@ std::string ModeParser::GiveModeList(ModeMasks m)
        return type1 + "," + type2 + "," + type3 + "," + type4;
 }
 
+struct PrefixModeSorter
+{
+       bool operator()(ModeHandler* lhs, ModeHandler* rhs)
+       {
+               return lhs->GetPrefixRank() < rhs->GetPrefixRank();
+       }
+};
+
 std::string ModeParser::BuildPrefixes(bool lettersAndModes)
 {
        std::string mletters;
        std::string mprefixes;
-       std::map<int,std::pair<char,char> > prefixes;
+       std::vector<ModeHandler*> prefixes;
 
        for (unsigned char mode = 'A'; mode <= 'z'; mode++)
        {
@@ -849,15 +857,15 @@ std::string ModeParser::BuildPrefixes(bool lettersAndModes)
 
                if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
                {
-                       prefixes[modehandlers[pos]->GetPrefixRank()] = std::make_pair(
-                               modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetModeChar());
+                       prefixes.push_back(modehandlers[pos]);
                }
        }
 
-       for(std::map<int,std::pair<char,char> >::reverse_iterator n = prefixes.rbegin(); n != prefixes.rend(); n++)
+       std::sort(prefixes.begin(), prefixes.end(), PrefixModeSorter());
+       for (std::vector<ModeHandler*>::const_reverse_iterator n = prefixes.rbegin(); n != prefixes.rend(); ++n)
        {
-               mletters = mletters + n->second.first;
-               mprefixes = mprefixes + n->second.second;
+               mletters += (*n)->GetPrefix();
+               mprefixes += (*n)->GetModeChar();
        }
 
        return lettersAndModes ? "(" + mprefixes + ")" + mletters : mletters;
index 6c765fb2ece23f9b0b586d4b964349024f965906..405bab082bef6df6522de1327408505ec533c9ef 100644 (file)
@@ -310,36 +310,25 @@ public:
                }
 
                RAIILDAPMessage msg;
-               std::string what = (attribute + "=" + (useusername ? user->ident : user->nick));
-               if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS)
+               std::string what;
+               std::string::size_type pos = user->password.find(':');
+               // If a username is provided in PASS, use it, othewrise user their nick or ident
+               if (pos != std::string::npos)
                {
-                       // Do a second search, based on password, if it contains a :
-                       // That is, PASS <user>:<password> will work.
-                       size_t pos = user->password.find(":");
-                       if (pos != std::string::npos)
-                       {
-                               // manpage says we must deallocate regardless of success or failure
-                               // since we're about to do another query (and reset msg), first
-                               // free the old one.
-                               msg.dealloc();
-
-                               std::string cutpassword = user->password.substr(0, pos);
-                               res = ldap_search_ext_s(conn, base.c_str(), searchscope, cutpassword.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg);
-
-                               if (res == LDAP_SUCCESS)
-                               {
-                                       // Trim the user: prefix, leaving just 'pass' for later password check
-                                       user->password = user->password.substr(pos + 1);
-                               }
-                       }
+                       what = (attribute + "=" + user->password.substr(0, pos));
 
-                       // It may have found based on user:pass check above.
-                       if (res != LDAP_SUCCESS)
-                       {
-                               if (verbose)
-                                       ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search failed: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res));
-                               return false;
-                       }
+                       // 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));
+               }
+               if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS)
+               {
+                       if (verbose)
+                               ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search failed: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res));
+                       return false;
                }
                if (ldap_count_entries(conn, msg) > 1)
                {
@@ -404,7 +393,7 @@ public:
                        std::string dnPart;
                        while (stream.GetToken(dnPart))
                        {
-                               std::string::size_type pos = dnPart.find('=');
+                               pos = dnPart.find('=');
                                if (pos == std::string::npos) // malformed
                                        continue;
 
index 1e3a65a18fdea27e4483daff11f05fd366534116..47880c02c51ef83a5585e886eabe11e94bda1b39 100644 (file)
@@ -90,8 +90,10 @@ class SQLConn : public SQLProvider
                std::string host = tag->getString("hostname");
                if (sqlite3_open_v2(host.c_str(), &conn, SQLITE_OPEN_READWRITE, 0) != SQLITE_OK)
                {
-                       ServerInstance->Logs->Log("m_sqlite3",DEFAULT, "WARNING: Could not open DB with id: " + tag->getString("id"));
+                       // Even in case of an error conn must be closed
+                       sqlite3_close(conn);
                        conn = NULL;
+                       ServerInstance->Logs->Log("m_sqlite3",DEFAULT, "WARNING: Could not open DB with id: " + tag->getString("id"));
                }
        }
 
index 59ac1acb3bcd62295ba9ea5e531ef7479ed480e0..2f4acf3f05edbb14454642940bf70fa37ae2759a 100644 (file)
@@ -28,7 +28,7 @@
 #include "m_cap.h"
 
 #ifdef _WIN32
-# pragma comment(lib, "libgnutls-28.lib")
+# pragma comment(lib, "libgnutls-30.lib")
 #endif
 
 /* $ModDesc: Provides SSL support for clients */
@@ -703,6 +703,9 @@ class ModuleSSLGnuTLS : public Module
                        if (ret > 0)
                        {
                                recvq.append(buffer, ret);
+                               // Schedule a read if there is still data in the GnuTLS buffer
+                               if (gnutls_record_check_pending(session->sess) > 0)
+                                       ServerInstance->SE->ChangeEventMask(user, FD_ADD_TRIAL_READ);
                                return 1;
                        }
                        else if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
index b21091d3fddc6f2b6c5ca53bdd26ebd3a0b95c70..aee7a5e3428a86afc8e2817c21fea3566aed3365 100644 (file)
@@ -405,12 +405,19 @@ class ModuleSSLOpenSSL : public Module
 #endif
 
                        ERR_clear_error();
-                       if ((SSL_CTX_set_tmp_dh(ctx, ret) < 0) || (SSL_CTX_set_tmp_dh(clictx, ret) < 0))
+                       if (ret)
                        {
-                               ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s. SSL errors follow:", dhfile.c_str());
-                               ERR_print_errors_cb(error_callback, this);
+                               if ((SSL_CTX_set_tmp_dh(ctx, ret) < 0) || (SSL_CTX_set_tmp_dh(clictx, ret) < 0))
+                               {
+                                       ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s. SSL errors follow:", dhfile.c_str());
+                                       ERR_print_errors_cb(error_callback, this);
+                               }
+                               DH_free(ret);
+                       }
+                       else
+                       {
+                               ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s.", dhfile.c_str());
                        }
-                       DH_free(ret);
                }
 
 #ifndef _WIN32
@@ -591,8 +598,15 @@ class ModuleSSLOpenSSL : public Module
                        if (ret > 0)
                        {
                                recvq.append(buffer, ret);
+
+                               int mask = 0;
+                               // Schedule a read if there is still data in the OpenSSL buffer
+                               if (SSL_pending(session->sess) > 0)
+                                       mask |= FD_ADD_TRIAL_READ;
                                if (session->data_to_write)
-                                       ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_SINGLE_WRITE);
+                                       mask |= FD_WANT_POLL_READ | FD_WANT_SINGLE_WRITE;
+                               if (mask != 0)
+                                       ServerInstance->SE->ChangeEventMask(user, mask);
                                return 1;
                        }
                        else if (ret == 0)
index 4147f0b161f57a4453ea9eb3c040173d19a10576..2df6d7af0cdb46c9a3c42b160bbe266ce69057aa 100644 (file)
@@ -68,7 +68,12 @@ struct CallerIDExtInfo : public ExtensionItem
 
        void unserialize(SerializeFormat format, Extensible* container, const std::string& value)
        {
+               void* old = get_raw(container);
+               if (old)
+                       this->free(old);
                callerid_data* dat = new callerid_data;
+               set_raw(container, dat);
+
                irc::commasepstream s(value);
                std::string tok;
                if (s.GetToken(tok))
@@ -89,10 +94,6 @@ struct CallerIDExtInfo : public ExtensionItem
                                }
                        }
                }
-
-               void* old = set_raw(container, dat);
-               if (old)
-                       this->free(old);
        }
 
        callerid_data* get(User* user, bool create)
index e9f4dae90e09684c37d9286e23543ca9d636817a..6b4387fdd96ccec55db075d0391be07a6478c02f 100644 (file)
@@ -66,23 +66,28 @@ class CommandCAP : public Command
 
                        while (cap_stream.GetToken(cap_))
                        {
-                               Data.wanted.push_back(cap_);
+                               // Whilst the handling of extraneous spaces is not currently defined in the CAP specification
+                               // every single other implementation ignores extraneous spaces. Lets copy them for
+                               // compatibility purposes.
+                               trim(cap_);
+                               if (!cap_.empty())
+                                       Data.wanted.push_back(cap_);
                        }
 
                        reghold.set(user, 1);
                        Data.Send();
 
-                       if (Data.ack.size() > 0)
+                       if (Data.wanted.empty())
                        {
-                               std::string AckResult = irc::stringjoiner(" ", Data.ack, 0, Data.ack.size() - 1).GetJoined();
-                               user->WriteServ("CAP %s ACK :%s", user->nick.c_str(), AckResult.c_str());
+                               user->WriteServ("CAP %s ACK :%s", user->nick.c_str(), parameters[1].c_str());
+                               return CMD_SUCCESS;
                        }
 
-                       if (Data.wanted.size() > 0)
-                       {
-                               std::string NakResult = irc::stringjoiner(" ", Data.wanted, 0, Data.wanted.size() - 1).GetJoined();
-                               user->WriteServ("CAP %s NAK :%s", user->nick.c_str(), NakResult.c_str());
-                       }
+                       // HACK: reset all of the caps which were enabled on this user because a cap request is atomic.
+                       for (std::vector<std::pair<GenericCap*, int> >::iterator iter = Data.changed.begin(); iter != Data.changed.end(); ++iter)
+                               iter->first->ext.set(user, iter->second);
+
+                       user->WriteServ("CAP %s NAK :%s", user->nick.c_str(), parameters[1].c_str());
                }
                else if (subcommand == "END")
                {
index 409671f482aeb5301cf3e62e3c6c75979424b917..23cf8cf69a748ef9a373340c1f3e5745b5340e2f 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef M_CAP_H
 #define M_CAP_H
 
+class GenericCap;
+
 class CapEvent : public Event
 {
  public:
@@ -35,6 +37,7 @@ class CapEvent : public Event
        CapEventType type;
        std::vector<std::string> wanted;
        std::vector<std::string> ack;
+       std::vector<std::pair<GenericCap*, int> > changed; // HACK: clean this up before 2.2
        User* user;
        CapEvent(Module* sender, User* u, CapEventType capevtype) : Event(sender, "cap_request"), type(capevtype), user(u) {}
 };
@@ -67,7 +70,7 @@ class GenericCap
                                        // we can handle this, so ACK it, and remove it from the wanted list
                                        data->ack.push_back(*it);
                                        data->wanted.erase(it);
-                                       ext.set(data->user, enablecap ? 1 : 0);
+                                       data->changed.push_back(std::make_pair(this, ext.set(data->user, enablecap ? 1 : 0)));
                                        break;
                                }
                        }
index 50c8e22a7212d738b33075f15f74a848167f1ea5..65b965df288f8acac65d152f05cded53d3a9eb86 100644 (file)
@@ -101,7 +101,7 @@ class ModuleCensor : public Module
                        {
                                if (index->second.empty())
                                {
-                                       user->WriteNumeric(ERR_WORDFILTERED, "%s %s %s :Your message contained a censored word, and was blocked", user->nick.c_str(), ((Channel*)dest)->name.c_str(), index->first.c_str());
+                                       user->WriteNumeric(ERR_WORDFILTERED, "%s %s %s :Your message contained a censored word, and was blocked", user->nick.c_str(), ((target_type == TYPE_CHANNEL) ? ((Channel*)dest)->name.c_str() : ((User*)dest)->nick.c_str()), index->first.c_str());
                                        return MOD_RES_DENY;
                                }
 
index cce2e785531ad3c38b6fd3283fdeb173a8712aa0..09f6a4659d88e0d760a85d48166514ed825b68d8 100644 (file)
@@ -73,6 +73,7 @@ class CommandWebirc : public Command
                  realhost("cgiirc_realhost", Creator), realip("cgiirc_realip", Creator),
                  webirc_hostname("cgiirc_webirc_hostname", Creator), webirc_ip("cgiirc_webirc_ip", Creator)
                {
+                       allow_empty_last_param = false;
                        works_before_reg = true;
                        this->syntax = "password client hostname ip";
                }
@@ -81,6 +82,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))
@@ -108,6 +117,7 @@ class CommandWebirc : public Command
                                }
                        }
 
+                       IS_LOCAL(user)->CommandFloodPenalty += 5000;
                        ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s tried to use WEBIRC, but didn't match any configured webirc blocks.", user->GetFullRealHost().c_str());
                        return CMD_FAILURE;
                }
index 9c5c414f195473386d4b7bf2b2ad95061a694d10..5063368b81506e023fff508298071b3c516bea81 100644 (file)
@@ -174,7 +174,7 @@ class CommandCheck : public Command
                        /* /check on a channel */
                        user->SendText(checkstr + " timestamp " + timestring(targchan->age));
 
-                       if (targchan->topic[0] != 0)
+                       if (!targchan->topic.empty())
                        {
                                /* there is a topic, assume topic related information exists */
                                user->SendText(checkstr + " topic " + targchan->topic);
index 105d688337d20d0afb767059815bf10ace8c5671..f4cfdb54f8b07c7186e11f1e5b27b1196a6c5ee5 100644 (file)
@@ -96,6 +96,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)
@@ -493,11 +497,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_COMPAT_HOST:
                        {
-                               if (ipstr != host)
+                               if (!host_is_ip)
                                {
                                        std::string tail = LastTwoDomainParts(host);
 
@@ -520,7 +527,7 @@ class ModuleCloaking : public Module
                                break;
                        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);
index 829c1d3378ce91a3229f4de51ef15a6fc7a47611..05fff89377f5c09f6d2faf1a097eaf70c0c2040c 100644 (file)
@@ -58,6 +58,7 @@ SimpleExtItem<dccallowlist>* ext;
 class CommandDccallow : public Command
 {
  public:
+       unsigned int maxentries;
        CommandDccallow(Module* parent) : Command(parent, "DCCALLOW", 0)
        {
                syntax = "[(+|-)<nick> [<time>]]|[LIST|HELP]";
@@ -140,6 +141,12 @@ class CommandDccallow : public Command
                                                ul.push_back(user);
                                        }
 
+                                       if (dl->size() >= maxentries)
+                                       {
+                                               user->WriteNumeric(996, "%s %s :Too many nicks on DCCALLOW list", user->nick.c_str(), user->nick.c_str());
+                                               return CMD_FAILURE;
+                                       }
+
                                        for (dccallowlist::const_iterator k = dl->begin(); k != dl->end(); ++k)
                                        {
                                                if (k->nickname == target->nick)
@@ -264,7 +271,7 @@ class ModuleDCCAllow : public Module
                ext = new SimpleExtItem<dccallowlist>("dccallow", this);
                ServerInstance->Modules->AddService(*ext);
                ServerInstance->Modules->AddService(cmd);
-               ReadFileConf();
+               OnRehash(NULL);
                Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserQuit, I_OnUserPostNick, I_OnRehash };
                ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
        }
@@ -272,6 +279,8 @@ class ModuleDCCAllow : public Module
        virtual void OnRehash(User* user)
        {
                ReadFileConf();
+               ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow");
+               cmd.maxentries = tag->getInt("maxentries", 20);
        }
 
        virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
@@ -331,29 +340,43 @@ class ModuleDCCAllow : public Module
                                                                return MOD_RES_PASSTHRU;
                                        }
 
-                                       // tokenize
-                                       std::stringstream ss(text);
-                                       std::string buf;
-                                       std::vector<std::string> tokens;
-
-                                       while (ss >> buf)
-                                               tokens.push_back(buf);
-
-                                       if (tokens.size() < 2)
+                                       std::string buf = text.substr(5);
+                                       size_t s = buf.find(' ');
+                                       if (s == std::string::npos)
                                                return MOD_RES_PASSTHRU;
 
-                                       irc::string type = tokens[1].c_str();
+                                       irc::string type = assign(buf.substr(0, s));
 
                                        ConfigTag* conftag = ServerInstance->Config->ConfValue("dccallow");
                                        bool blockchat = conftag->getBool("blockchat");
 
                                        if (type == "SEND")
                                        {
-                                               if (tokens.size() < 3)
+                                               size_t first;
+
+                                               buf = buf.substr(s + 1);
+
+                                               if (!buf.empty() && buf[0] == '"')
+                                               {
+                                                       s = buf.find('"', 1);
+
+                                                       if (s == std::string::npos || s <= 1)
+                                                               return MOD_RES_PASSTHRU;
+
+                                                       --s;
+                                                       first = 1;
+                                               }
+                                               else
+                                               {
+                                                       s = buf.find(' ');
+                                                       first = 0;
+                                               }
+
+                                               if (s == std::string::npos)
                                                        return MOD_RES_PASSTHRU;
 
                                                std::string defaultaction = conftag->getString("action");
-                                               std::string filename = tokens[2];
+                                               std::string filename = buf.substr(first, s);
 
                                                bool found = false;
                                                for (unsigned int i = 0; i < bfl.size(); i++)
index d4101686a03c1daaba9115da2a8244e2898838d0..3dea080cee59dd99474510ae5fe5567f4eda3b44 100644 (file)
@@ -70,8 +70,8 @@ class DNSBLResolver : public Resolver
                        int i = countExt.get(them);
                        if (i)
                                countExt.set(them, i - 1);
-                       // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
-                       if(result.length())
+                       // All replies should be in 127.0.0.0/8
+                       if (result.compare(0, 4, "127.") == 0)
                        {
                                unsigned int bitmask = 0, record = 0;
                                bool match = false;
@@ -82,6 +82,7 @@ class DNSBLResolver : public Resolver
                                switch (ConfEntry->type)
                                {
                                        case DNSBLConfEntry::A_BITMASK:
+                                               // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
                                                bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */
                                                bitmask &= ConfEntry->bitmask;
                                                match = (bitmask != 0);
@@ -196,7 +197,11 @@ class DNSBLResolver : public Resolver
                                        ConfEntry->stats_misses++;
                        }
                        else
+                       {
+                               if (!result.empty())
+                                       ServerInstance->SNO->WriteGlobalSno('a', "DNSBL: %s returned address outside of acceptable subnet 127.0.0.0/8: %s", ConfEntry->domain.c_str(), result.c_str());
                                ConfEntry->stats_misses++;
+                       }
                }
        }
 
index 88b0c4cdffbf544f5ed12a1a5746162cdf152a6d..32999d9f0b36025e6e25acf95b1f53caf09eccad 100644 (file)
 class HideOper : public SimpleUserModeHandler
 {
  public:
+       size_t opercount;
+
        HideOper(Module* Creator) : SimpleUserModeHandler(Creator, "hideoper", 'H')
+               , opercount(0)
        {
                oper = true;
        }
+
+       ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding)
+       {
+               if (SimpleUserModeHandler::OnModeChange(source, dest, channel, parameter, adding) == MODEACTION_DENY)
+                       return MODEACTION_DENY;
+
+               if (adding)
+                       opercount++;
+               else
+                       opercount--;
+
+               return MODEACTION_ALLOW;
+       }
 };
 
 class ModuleHideOper : public Module
 {
        HideOper hm;
+       bool active;
  public:
        ModuleHideOper()
                : hm(this)
+               , active(false)
        {
        }
 
        void init()
        {
                ServerInstance->Modules->AddService(hm);
-               Implementation eventlist[] = { I_OnWhoisLine, I_OnSendWhoLine, I_OnStats };
+               Implementation eventlist[] = { I_OnWhoisLine, I_OnSendWhoLine, I_OnStats, I_OnNumeric, I_OnUserQuit };
                ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
        }
 
@@ -60,6 +78,28 @@ class ModuleHideOper : public Module
                return Version("Provides support for hiding oper status with user mode +H", VF_VENDOR);
        }
 
+       void OnUserQuit(User* user, const std::string&, const std::string&)
+       {
+               if (user->IsModeSet('H'))
+                       hm.opercount--;
+       }
+
+       ModResult OnNumeric(User* user, unsigned int numeric, const std::string& text)
+       {
+               if (numeric != 252 || active || user->HasPrivPermission("users/auspex"))
+                       return MOD_RES_PASSTHRU;
+
+               // If there are no visible operators then we shouldn't send the numeric.
+               size_t opercount = ServerInstance->Users->all_opers.size() - hm.opercount;
+               if (opercount)
+               {
+                       active = true;
+                       user->WriteNumeric(252, "%s %lu :operator(s) online", user->nick.c_str(),  static_cast<unsigned long>(opercount));
+                       active = false;
+               }
+               return MOD_RES_DENY;
+       }
+
        ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text)
        {
                /* Dont display numeric 313 (RPL_WHOISOPER) if they have +H set and the
index 2fc7ca7dea33656e4c79dfcf5c7723176daf75f1..e17bf514f0835d494e57f60074bd5e30b009a55a 100644 (file)
@@ -213,7 +213,7 @@ class ModuleHttpStats : public Module
                                        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>";
index da42d823d2678a63712a4a05ba3de3416a882cd8..b7dd0e81bbfcd1e50a00f9f5aa198ec27804d0e2 100644 (file)
@@ -222,7 +222,7 @@ class ModuleIRCv3 : public Module
                {
                        // Send the away notify line if the current member is local, has the away-notify cap and isn't excepted
                        User* member = IS_LOCAL(it->first);
-                       if ((member) && (cap_awaynotify.ext.get(member)) && (last_excepts.find(member) == last_excepts.end()))
+                       if ((member) && (cap_awaynotify.ext.get(member)) && (last_excepts.find(member) == last_excepts.end()) && (it->second != memb))
                        {
                                member->Write(line);
                        }
index dce8f0bd5dfcf2856f184cdb6495b244e636733a..44c6fc0d9fb20cfbd11c5a23015faac793c73f36 100644 (file)
@@ -161,7 +161,7 @@ class ModuleJumpServer : public Module
                        user->WriteNumeric(10, "%s %s %d :Please use this Server/Port instead",
                                user->nick.c_str(), js.redirect_to.c_str(), js.port);
                        ServerInstance->Users->QuitUser(user, js.reason);
-                       return MOD_RES_PASSTHRU;
+                       return MOD_RES_DENY;
                }
                return MOD_RES_PASSTHRU;
        }
index 4db1f70b92c78e9a0d5da781f99c0114a0eec90e..46710946b67a7adde9193e01aa4a14733a8d93d3 100644 (file)
@@ -33,7 +33,12 @@ static void DisplayList(User* user, Channel* channel)
                        continue;
                items << " +" << mh->name;
                if (mh->GetNumParams(true))
-                       items << " " << channel->GetModeParameter(letter);
+               {
+                       if ((letter == 'k') && (!channel->HasUser(user)) && (!user->HasPrivPermission("channels/auspex")))
+                               items << " <key>";
+                       else
+                               items << " " << channel->GetModeParameter(letter);
+               }
        }
        char pfx[MAXBUF];
        snprintf(pfx, MAXBUF, ":%s 961 %s %s", ServerInstance->Config->ServerName.c_str(), user->nick.c_str(), channel->name.c_str());
@@ -65,6 +70,8 @@ class CommandProp : public Command
                while (i < parameters.size())
                {
                        std::string prop = parameters[i++];
+                       if (prop.empty())
+                               continue;
                        bool plus = prop[0] != '-';
                        if (prop[0] == '+' || prop[0] == '-')
                                prop.erase(prop.begin());
index 9f1f6cc5e8f3f25863a940abde3513d133767d46..7d5e6d1181151f0cfae5c7b243205fed2d910248 100644 (file)
@@ -58,6 +58,39 @@ class OperPrefixMode : public ModeHandler
                }
 
                bool NeedsOper() { return true; }
+
+               void RemoveMode(Channel* chan, irc::modestacker* stack)
+               {
+                       irc::modestacker modestack(false);
+                       const UserMembList* users = chan->GetUsers();
+                       for (UserMembCIter i = users->begin(); i != users->end(); ++i)
+                       {
+                               if (i->second->hasMode(mode))
+                               {
+                                       if (stack)
+                                               stack->Push(this->GetModeChar(), i->first->nick);
+                                       else
+                                               modestack.Push(this->GetModeChar(), i->first->nick);
+                               }
+                       }
+
+                       if (stack)
+                               return;
+
+                       std::deque<std::string> stackresult;
+                       std::vector<std::string> mode_junk;
+                       mode_junk.push_back(chan->name);
+                       while (modestack.GetStackedLine(stackresult))
+                       {
+                               mode_junk.insert(mode_junk.end(), stackresult.begin(), stackresult.end());
+                               ServerInstance->SendMode(mode_junk, ServerInstance->FakeClient);
+                               mode_junk.erase(mode_junk.begin() + 1, mode_junk.end());
+                       }
+               }
+
+               void RemoveMode(User* user, irc::modestacker* stack)
+               {
+               }
 };
 
 class ModuleOperPrefixMode;
index e86b3cbf6d171dece2453c8e50e110680ad9c980..74a798356c1a67b8cf05aac577932d9d0afbb11e 100644 (file)
@@ -298,6 +298,12 @@ public:
 
                                ServerInstance->Logs->Log("m_permchannels", DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str());
 
+                               if (modes.find('P') == std::string::npos)
+                               {
+                                       ServerInstance->Logs->Log("m_permchannels", DEFAULT, "%s (%s) does not have +P set in <permchannels:modes>; it will be deleted when empty!",
+                                               c->name.c_str(), tag->getTagLocation().c_str());
+                               }
+
                                if (modes.empty())
                                        continue;
 
index 7dfcd8904db3b7e8531059e270274a6eac547cb5..afca49e251ba17b3294670277915a5f17b8b0bd5 100644 (file)
@@ -63,14 +63,6 @@ class CommandSakick : public Command
                        if (IS_LOCAL(dest))
                        {
                                channel->KickUser(ServerInstance->FakeClient, dest, reason);
-
-                               Channel *n = ServerInstance->FindChan(parameters[1]);
-                               if (n && n->HasUser(dest))
-                               {
-                                       /* Sort-of-bug: If the command was issued remotely, this message won't be sent */
-                                       user->WriteServ("NOTICE %s :*** Unable to kick %s from %s", user->nick.c_str(), dest->nick.c_str(), parameters[0].c_str());
-                                       return CMD_FAILURE;
-                               }
                        }
 
                        if (IS_LOCAL(user))
index 32c9afc79ec05e36be5eeecd07f91f6f75e94ca3..5afab9502147ce9e4a73e482ca222bdfc39b5445 100644 (file)
@@ -51,10 +51,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(sasl_target);
                params.push_back("SASL");
@@ -147,7 +200,7 @@ class SaslAuthenticator
 
                SendSASL(params);
 
-               if (parameters[0][0] == '*')
+               if (parameters[0].c_str()[0] == '*')
                {
                        this->Abort();
                        return false;
@@ -189,6 +242,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)
@@ -199,6 +253,9 @@ class CommandAuthenticate : public Command
                        if (!cap.ext.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]));
@@ -264,7 +321,7 @@ class ModuleSASL : public Module
        void init()
        {
                OnRehash(NULL);
-               Implementation eventlist[] = { I_OnEvent, I_OnUserRegister, I_OnRehash };
+               Implementation eventlist[] = { I_OnEvent, I_OnUserConnect, I_OnRehash };
                ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
 
                ServiceProvider* providelist[] = { &auth, &sasl, &authExt };
@@ -279,7 +336,7 @@ class ModuleSASL : public Module
                sasl_target = ServerInstance->Config->ConfValue("sasl")->getString("target", "*");
        }
 
-       ModResult OnUserRegister(LocalUser *user)
+       void OnUserConnect(LocalUser *user)
        {
                SaslAuthenticator *sasl_ = authExt.get(user);
                if (sasl_)
@@ -287,8 +344,6 @@ class ModuleSASL : public Module
                        sasl_->Abort();
                        authExt.unset(user);
                }
-
-               return MOD_RES_PASSTHRU;
        }
 
        Version GetVersion()
index 6013d1fd7543400bfcadf0a4f55f1269f8b058ad..5d11d27f7b0fa16b72a2e568d232745e279e0f42 100644 (file)
@@ -76,7 +76,7 @@ class ModuleSecureList : public Module
 
                        /* Not exempt, BOOK EM DANNO! */
                        user->WriteServ("NOTICE %s :*** You cannot list within the first %lu seconds of connecting. Please try again later.",user->nick.c_str(), (unsigned long) WaitTime);
-                       /* Some crap clients (read: mIRC, various java chat applets) muck up if they don't
+                       /* Some clients (e.g. mIRC, various java chat applets) muck up if they don't
                         * receive these numerics whenever they send LIST, so give them an empty LIST to mull over.
                         */
                        user->WriteNumeric(321, "%s Channel :Users Name",user->nick.c_str());
index 7b64358980d6bb41e49dbadeee5b437ea327fd5b..0ab815fef71e8eaef8c38516f8d6d236552071b0 100644 (file)
@@ -27,6 +27,7 @@
 #include "utils.h"
 #include "link.h"
 #include "main.h"
+#include "../hash.h"
 
 std::string TreeSocket::MyModules(int filter)
 {
@@ -134,7 +135,7 @@ void TreeSocket::SendCapabilities(int phase)
 
        std::string extra;
        /* Do we have sha256 available? If so, we send a challenge */
-       if (Utils->ChallengeResponse && (ServerInstance->Modules->Find("m_sha256.so")))
+       if (Utils->ChallengeResponse && (ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256")))
        {
                SetOurChallenge(ServerInstance->GenRandomStr(20));
                extra = " CHALLENGE=" + this->GetOurChallenge();
@@ -320,7 +321,7 @@ bool TreeSocket::Capab(const parameterlist &params)
 
                /* Challenge response, store their challenge for our password */
                std::map<std::string,std::string>::iterator n = this->capab->CapKeys.find("CHALLENGE");
-               if (Utils->ChallengeResponse && (n != this->capab->CapKeys.end()) && (ServerInstance->Modules->Find("m_sha256.so")))
+               if (Utils->ChallengeResponse && (n != this->capab->CapKeys.end()) && (ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256")))
                {
                        /* Challenge-response is on now */
                        this->SetTheirChallenge(n->second);
index 47b39452268dfa8cc34923a98cfc36184726bb25..4ec6e1dbb0f3d502209775cbde367ce325455ba3 100644 (file)
@@ -201,7 +201,7 @@ CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *src
                        }
                        else
                        {
-                               ServerInstance->Logs->Log("m_spanningtree",SPARSE, "Ignored nonexistant user %s in fjoin to %s (probably quit?)", usr, channel.c_str());
+                               ServerInstance->Logs->Log("m_spanningtree",SPARSE, "Ignored nonexistent user %s in fjoin to %s (probably quit?)", usr, channel.c_str());
                                continue;
                        }
                }
index d508c092dd00fea08c6fb87a365fb8b64e6da736..3bce90eda30895bcb1be9cf67d013ffcfe607e41 100644 (file)
@@ -140,25 +140,28 @@ void TreeSocket::SendFJoins(Channel* c)
                buffer.append(list).append("\r\n");
        }
 
-       int linesize = 1;
+       unsigned int linesize = 1;
        for (BanList::iterator b = c->bans.begin(); b != c->bans.end(); b++)
        {
-               int size = b->data.length() + 2;
-               int currsize = linesize + size;
-               if (currsize <= 350)
-               {
-                       modes.append("b");
-                       params.append(" ").append(b->data);
-                       linesize += size;
-               }
-               if ((modes.length() >= ServerInstance->Config->Limits.MaxModes) || (currsize > 350))
+               unsigned int size = b->data.length() + 2; // "b" and " "
+               unsigned int nextsize = linesize + size;
+
+               if ((modes.length() >= ServerInstance->Config->Limits.MaxModes) || (nextsize > FMODE_MAX_LENGTH))
                {
-                       /* Wrap at MAXMODES */
+                       /* Wrap */
                        buffer.append(":").append(ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params).append("\r\n");
+
                        modes.clear();
                        params.clear();
                        linesize = 1;
                }
+
+               modes.push_back('b');
+
+               params.push_back(' ');
+               params.append(b->data);
+
+               linesize += size;
        }
 
        /* Only send these if there are any */
index 471bbfcb970670c895ec304df5e30bcef15c44d2..3f5d427e169a7ca90b68e82ae0648217f191c825 100644 (file)
@@ -73,7 +73,7 @@ void SpanningTreeUtilities::RouteCommand(TreeServer* origin, const std::string &
                TreeServer* sdest = FindServer(routing.serverdest);
                if (!sdest)
                {
-                       ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Trying to route ENCAP to nonexistant server %s",
+                       ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Trying to route ENCAP to nonexistent server %s",
                                routing.serverdest.c_str());
                        return;
                }
index 3ab5dae9df0c9aa5b54fed4fc8c53e4f244bb10d..ca4147fea254807ad7006001bf98a3e357c76bb9 100644 (file)
@@ -137,9 +137,6 @@ void SpanningTreeProtocolInterface::PushToClient(User* target, const std::string
 
 void SpanningTreeProtocolInterface::SendChannel(Channel* target, char status, const std::string &text)
 {
-       std::string cname = target->name;
-       if (status)
-               cname = status + cname;
        TreeServerList list;
        CUList exempt_list;
        Utils->GetListOfServersForChannel(target,list,status,exempt_list);
@@ -154,12 +151,20 @@ void SpanningTreeProtocolInterface::SendChannel(Channel* target, char status, co
 
 void SpanningTreeProtocolInterface::SendChannelPrivmsg(Channel* target, char status, const std::string &text)
 {
-       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+target->name+" :"+text);
+       std::string cname = target->name;
+       if (status)
+               cname.insert(0, 1, status);
+
+       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+cname+" :"+text);
 }
 
 void SpanningTreeProtocolInterface::SendChannelNotice(Channel* target, char status, const std::string &text)
 {
-       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+target->name+" :"+text);
+       std::string cname = target->name;
+       if (status)
+               cname.insert(0, 1, status);
+
+       SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+cname+" :"+text);
 }
 
 void SpanningTreeProtocolInterface::SendUserPrivmsg(User* target, const std::string &text)
index abda283353def3e2fab90d2ea4cdf04593f80f76..efcce5f7a3e46463eb71eb061d0c525f06da7a1d 100644 (file)
@@ -100,6 +100,8 @@ class TreeSocket : public BufferedSocket
        int proto_version;                      /* Remote protocol version */
        bool ConnectionFailureShown; /* Set to true if a connection failure message was shown */
 
+       static const unsigned int FMODE_MAX_LENGTH = 350;
+
        /** Checks if the given servername and sid are both free
         */
        bool CheckDuplicate(const std::string& servername, const std::string& sid);
index 2bfe0e1c4e0ca285727789b722d48a4056790e6e..083ac0f0448486a212bfc53ad61adfc57a3389ed 100644 (file)
@@ -180,6 +180,9 @@ class ModuleSSLInfo : public Module
                        if (i != ServerInstance->Config->oper_blocks.end())
                        {
                                OperInfo* ifo = i->second;
+                               if (!ifo->oper_block)
+                                       return MOD_RES_PASSTHRU;
+
                                ssl_cert* cert = cmd.CertExt.get(user);
 
                                if (ifo->oper_block->getBool("sslonly") && !cert)
@@ -220,6 +223,9 @@ class ModuleSSLInfo : public Module
                for(OperIndex::iterator i = ServerInstance->Config->oper_blocks.begin(); i != ServerInstance->Config->oper_blocks.end(); i++)
                {
                        OperInfo* ifo = i->second;
+                       if (!ifo->oper_block)
+                               continue;
+
                        std::string fp = ifo->oper_block->getString("fingerprint");
                        if (fp == cert->fingerprint && ifo->oper_block->getBool("autologin"))
                                user->Oper(ifo);
index f2837777ad7ec7a3ac11e6116be84bc70ca9ca0e..d5f01734782e568d29fbf69457ed7224d1fb25bd 100644 (file)
@@ -25,7 +25,7 @@
 #include "exitcodes.h"
 #include "socketengine.h"
 #include <sys/epoll.h>
-#include <ulimit.h>
+#include <sys/resource.h>
 #include <iostream>
 #define EP_DELAY 5
 
@@ -55,10 +55,11 @@ public:
 EPollEngine::EPollEngine()
 {
        CurrentSetSize = 0;
-       int max = ulimit(4, 0);
-       if (max > 0)
+
+       struct rlimit limit;
+       if (!getrlimit(RLIMIT_NOFILE, &limit))
        {
-               MAX_DESCRIPTORS = max;
+               MAX_DESCRIPTORS = limit.rlim_cur;
        }
        else
        {
index 76446c5b57fb07371adaa9b6730e6f335d7e0805..2cb7ad51117a4743eb8835f6cd5c79dba9456d6c 100644 (file)
@@ -143,6 +143,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs
        {
                ServerInstance->Logs->Log("USERS", DEBUG,"Internal error on new connection");
                this->QuitUser(New, "Internal error handling connection");
+               return;
        }
 
        /* NOTE: even if dns lookups are *off*, we still need to display this.
index 418f2c9aa3557f187e45eb189c892a07b154970c..4dbb73a1f55ef7e4e5492784d1165d283c832c53 100644 (file)
@@ -837,6 +837,7 @@ void LocalUser::FullConnect()
 void User::InvalidateCache()
 {
        /* Invalidate cache */
+       cachedip.clear();
        cached_fullhost.clear();
        cached_hostip.clear();
        cached_makehost.clear();
@@ -1001,8 +1002,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);
 }
 
@@ -1398,6 +1398,8 @@ void User::DoHostCycle(const std::string &quitline)
 
        FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));
 
+       // Users shouldn't see themselves quitting when host cycling
+       exceptions.erase(this);
        for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
        {
                LocalUser* u = IS_LOCAL(i->first);
index 8686e33ae1f567bf0c71de2dea227468d519d8d0..74a5837590cd83da380948860d3765847838f442 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-echo "InspIRCd-2.0.20"
+echo "InspIRCd-2.0.23"
diff --git a/tools/travis-ci.sh b/tools/travis-ci.sh
new file mode 100755 (executable)
index 0000000..42b07fa
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+set -v
+if [ "$TRAVIS_OS_NAME" = "linux" ]
+then
+       sudo apt-get update --assume-yes
+       sudo apt-get install --assume-yes libgeoip-dev libgnutls-dev libldap2-dev libmysqlclient-dev libpcre3-dev libpq-dev libsqlite3-dev libssl-dev libtre-dev
+else
+       >&2 echo "'$TRAVIS_OS_NAME' is an unknown Travis CI environment!"
+       exit 1
+fi
+set -e
+./configure --enable-extras=m_geoip.cpp,m_ldapauth.cpp,m_ldapoper.cpp,m_mysql.cpp,m_pgsql.cpp,m_regex_pcre.cpp,m_regex_posix.cpp,m_regex_tre.cpp,m_sqlite3.cpp,m_ssl_gnutls.cpp,m_ssl_openssl.cpp
+./configure --with-cc=$CXX
+make -j4 install
+./run/bin/inspircd --version
index 10653cf74a13692c75f618c444341c463096275a..7be08a3fcd43f2c18d4dea2f508347af1dd863ef 100644 (file)
@@ -85,6 +85,7 @@ file(MAKE_DIRECTORY ${LOG_PATH})
 install(DIRECTORY ${LOG_PATH} 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")
index be437d4a36c37bba3bd9063782320abe6447ae69..d7ceb73aa46170a437f9468c9f958825e75bc20e 100644 (file)
@@ -63,6 +63,7 @@
 
 /* Disable the deprecation warnings.. it spams :P */
 #define _CRT_SECURE_NO_DEPRECATE
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
 
 /* Normal windows (platform-specific) includes */
 #include <winsock2.h>
@@ -90,9 +91,11 @@ CoreExport const char * insp_inet_ntop(int af, const void * src, char * dst, soc
 #define inet_pton insp_inet_pton
 #define inet_ntop insp_inet_ntop
 
-/* Safe printf functions aren't defined in VC++ */
+/* Safe printf functions aren't defined in VC++ releases older than v14 */
+#if _MSC_VER <= 1800
 #define snprintf _snprintf
 #define vsnprintf _vsnprintf
+#endif
 
 /* Unix-style sleep (argument is in seconds) */
 __inline void sleep(int seconds) { Sleep(seconds * 1000); }
@@ -136,11 +139,13 @@ struct DIR
        bool first;
 };
 
+#if _MSC_VER <= 1800
 struct timespec
 {
        time_t tv_sec;
        long tv_nsec;
 };
+#endif
 
 CoreExport DIR * opendir(const char * path);
 CoreExport dirent * readdir(DIR * handle);