/run
/bin
-/include/inspircd_config.h
-/include/inspircd_version.h
+/include/config.h
/src/modules/m_geoip.cpp
/src/modules/m_ldapauth.cpp
};
use File::Copy ();
-use Socket;
use Cwd;
use Getopt::Long;
# Utility functions for our buildsystem
use make::utilities;
use make::configure;
-use make::gnutlscert;
-use make::opensslcert;
###############################################################################################
#
#
###############################################################################################
-our ($opt_use_gnutls, $opt_rebuild, $opt_use_openssl, $opt_nointeractive, $opt_ports,
- $opt_epoll, $opt_kqueue, $opt_noports, $opt_noepoll, $opt_nokqueue,
- $opt_noipv6, $opt_maxbuf, $opt_disable_debug, $opt_freebsd_port,
- $opt_system, $opt_uid);
+our ($opt_use_gnutls, $opt_use_openssl, $opt_nointeractive, $opt_ports, $opt_epoll, $opt_kqueue,
+ $opt_noports, $opt_noepoll, $opt_nokqueue, $opt_maxbuf, $opt_freebsd_port, $opt_system, $opt_uid);
our ($opt_cc, $opt_base_dir, $opt_config_dir, $opt_module_dir, $opt_binary_dir, $opt_data_dir, $opt_log_dir);
GetOptions (
'enable-gnutls' => \$opt_use_gnutls,
- 'rebuild' => \$opt_rebuild,
'system' => \$opt_system,
'uid=s' => \$opt_uid,
'enable-openssl' => \$opt_use_openssl,
'disable-ports' => \$opt_noports,
'disable-epoll' => \$opt_noepoll,
'disable-kqueue' => \$opt_nokqueue,
- 'disable-ipv6' => \$opt_noipv6,
'with-cc=s' => \$opt_cc,
'with-maxbuf=i' => \$opt_maxbuf,
'enable-freebsd-ports-openssl' => \$opt_freebsd_port,
'binary-dir=s' => \$opt_binary_dir,
'data-dir=s' => \$opt_data_dir,
'log-dir=s' => \$opt_log_dir,
- 'disable-debuginfo' => sub { $opt_disable_debug = 1 },
'help' => sub { showhelp(); },
'update' => sub { update(); },
'clean' => sub { clean(); },
'list-extras' => sub { list_extras; exit 0; }, # This, --enable-extras, and --disable-extras are for non-interactive managing.
'enable-extras=s@' => \@opt_enableextras, # ^
'disable-extras=s@' => \@opt_disableextras, # ^
- 'generate-openssl-cert' => sub { make_openssl_cert(); exit(0); },
- 'generate-gnutls-cert' => sub { make_gnutls_cert(); exit(0); }
);
if (scalar(@opt_enableextras) + scalar(@opt_disableextras) > 0) {
(defined $opt_log_dir) ||
(defined $opt_nointeractive) ||
(defined $opt_cc) ||
- (defined $opt_noipv6) ||
(defined $opt_kqueue) ||
(defined $opt_epoll) ||
(defined $opt_ports) ||
$config{USE_OPENSSL} = "y";
}
-if (!defined $opt_disable_debug) {
- $config{OPTIMISATI} = "-g1"; # Optimisation Flag
-} else {
- $config{OPTIMISATI} = "-O2";
-}
-
-$config{HAS_STRLCPY} = "false"; # strlcpy Check.
$config{HAS_STDINT} = "false"; # stdint.h check
$config{USE_KQUEUE} = "y"; # kqueue enabled
if (defined $opt_nokqueue) {
{
$config{USE_PORTS} = "n";
}
-$config{_SOMAXCONN} = SOMAXCONN; # Max connections in accept queue
$config{OSNAME} = $^O; # Operating System Name
-$config{IS_DARWIN} = "NO"; # Is OSX?
$config{STARTSCRIPT} = "inspircd"; # start script?
$config{DESTINATION} = "BASE"; # Is target path.
if ($config{OSNAME} =~ /darwin/i)
{
- $config{IS_DARWIN} = "YES";
$config{STARTSCRIPT} = "org.inspircd.plist"; # start script for OSX.
$config{CC} = "xcrun clang++"; # C++ compiler for OSX.
}
}
if (($config{GCCVER} eq "") || ($config{GCCMINOR} eq "")) {
- if ($config{IS_DARWIN} eq "YES") {
+ if ($config{OSNAME} eq 'darwin') {
print $config{CC} . " was not found! You require clang++ (the LLVM C++ compiler, part of the OSX developer tools) to build InspIRCd!\n";
} else {
print $config{CC} . " was not found! You require g++ (the GNU C++ compiler, part of GCC) to build InspIRCd!\n";
} else {
# We've Loaded the cache file and all our variables..
print "Updating files...\n";
- if (defined($opt_disable_debug) && $opt_disable_debug == 1)
- {
- print "Disabling debug information (-g).\n";
- $config{OPTIMISATI} = "";
- }
$has_epoll = $config{HAS_EPOLL};
$has_ports = $config{HAS_PORTS};
$has_kqueue = $config{HAS_KQUEUE};
exit;
}
-
-sub test_compile {
- my $feature = shift;
- my $fail = 0;
- $fail ||= system "$config{CC} -o test_$feature make/check_$feature.cpp >/dev/null 2>&1";
- $fail ||= system "./test_$feature";
- unlink "test_$feature";
- return !$fail;
-}
-
print "Running non-interactive configure...\n" unless $interactive;
print "Checking for cache from previous configure... ";
print ($cache_loaded ? "found\n" : "not found\n");
$exec = $config{CC} . " -dumpversion | cut -c 3";
chomp($config{GCCMINOR} = `$exec`);
-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 "Checking whether <stdint.h> exists... ";
+if (test_header($config{CC}, "stdint.h")) {
+ $config{HAS_STDINT} = "true";
+ print "yes\n";
+} else {
+ $config{HAS_STDINT} = "false";
+ print "no\n";
}
-print "yes\n" if $config{HAS_STDINT} eq "true";
-print "no\n" if $config{HAS_STDINT} eq "false";
-
-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);
+
+printf "Checking whether clock_gettime() exists... ";
+if (test_file($config{CC}, "clock_gettime.cpp", "-lrt")) {
+ $config{HAS_CLOCK_GETTIME} = "true";
+ print "yes\n";
+} else {
+ $config{HAS_CLOCK_GETTIME} = "false";
+ print "no\n";
}
-print "yes\n" if $config{HAS_STRLCPY} eq "true";
-print "no\n" if $config{HAS_STRLCPY} eq "false";
-
-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);
+
+printf "Checking whether eventfd() exists... ";
+if (test_file($config{CC}, "eventfd.cpp")) {
+ $config{HAS_EVENTFD} = "true";
+ print "yes\n";
+} else {
+ $config{HAS_EVENTFD} = "false";
+ print "no\n";
+}
+
+printf "Checking if a TCP deferring mechanism is available... ";
+if (test_file($config{CC}, "tcp_defer_accept.cpp")) {
+ $config{HAS_DEFER} = "TCP_DEFER_ACCEPT";
+ print "yes (TCP_DEFER_ACCEPT)\n";
+} elsif (test_file($config{CC}, "so_acceptfilter.cpp")) {
+ $config{HAS_DEFER} = "SO_ACCEPTFILTER";
+ print "yes (SO_ACCEPTFILTER)\n";
+} else {
+ $config{HAS_DEFER} = "false";
+ print "no\n";
}
-print "yes\n" if $has_kqueue == 1;
-print "no\n" if $has_kqueue == 0;
-printf "Checking for epoll support... ";
-$has_epoll = test_compile('epoll');
+print "Checking whether epoll is available... ";
+$has_epoll = test_header($config{CC}, "sys/epoll.h");
print $has_epoll ? "yes\n" : "no\n";
-printf "Checking for eventfd support... ";
-$config{HAS_EVENTFD} = test_compile('eventfd') ? 'true' : 'false';
-print $config{HAS_EVENTFD} eq 'true' ? "yes\n" : "no\n";
-
-printf "Checking if Solaris I/O completion ports are available... ";
-$has_ports = 0;
-our $system = `uname -s`;
-chomp ($system);
-$has_ports = 1 if ($system eq "SunOS");
-
-if ($has_ports) {
- my $kernel = `uname -r`;
- chomp($kernel);
- if (($kernel !~ /^5\.1./)) {
- $has_ports = 0;
- }
-}
-print "yes\n" if $has_ports == 1;
-print "no\n" if $has_ports == 0;
+print "Checking whether Kqueue is available... ";
+$has_kqueue = test_file($config{CC}, "kqueue.cpp");
+print $has_kqueue ? "yes\n" : "no\n";
+
+print 'Checking whether Solaris IOCP is available... ';
+$has_ports = test_header($config{CC}, 'port.h');
+print $has_ports ? "yes\n" : "no\n";
$config{HAS_EPOLL} = $has_epoll;
$config{HAS_KQUEUE} = $has_kqueue;
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`);
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";
+ if ($config{GCCVER} < 4 || $config{GCCVER} == 4 && $config{GCCMINOR} < 1) {
+ print "\e[1;32mGCC 4.1 and earlier WILL NOT WORK!\e[0m. Let's try that again, shall we?\n";
}
}
else {
* few times and get that HD going :) Then answer the *
* Questions which follow. If you are unsure, just hit enter *
*************************************************************\n\n";
- $failed = make_gnutls_cert();
+ $failed = system "./tools/genssl gnutls";
if ($failed) {
print "\n\e[1;32mCertificate generation failed!\e[0m\n\n";
} else {
* Generating the certificates may take some time, go grab a *
* coffee, or something. *
*************************************************************\n\n";
- make_openssl_cert();
+ system "./tools/genssl openssl";
print "\nCertificate generation complete, copying to config directory... ";
File::Copy::move("key.pem", "$config{CONFIG_DIR}/key.pem") or print STDERR "Could not copy key.pem!\n";
File::Copy::move("cert.pem", "$config{CONFIG_DIR}/cert.pem") or print STDERR "Could not copy cert.pem!\n";
sub writefiles {
my($writeheader) = @_;
- # First File.. inspircd_config.h
+ # First File.. config.h
chomp(my $incos = `uname -n -s -r`);
chomp(my $version = `sh src/version.sh`);
chomp(my $revision2 = getrevision());
}
if ($writeheader == 1)
{
- print "Writing \e[1;32minspircd_config.h\e[0m\n";
- open(FILEHANDLE, ">include/inspircd_config.h.tmp");
+ print "Writing \e[1;32mconfig.h\e[0m\n";
+ open(FILEHANDLE, ">include/config.h.tmp");
print FILEHANDLE <<EOF;
/* Auto generated by configure, do not modify! */
-#ifndef __CONFIGURATION_AUTO__
-#define __CONFIGURATION_AUTO__
+#pragma once
-/* this is for windows support. */
-#define CoreExport /**/
-#define DllExport /**/
+#define BRANCH "$branch"
+#define VERSION "$version"
+#define REVISION "$revision2"
+#define SYSTEM "$incos"
#define CONFIG_PATH "$config{CONFIG_DIR}"
#define DATA_PATH "$config{DATA_DIR}"
#define LOG_PATH "$config{LOG_DIR}"
#define MOD_PATH "$config{MODULE_DIR}"
-#define SOMAXCONN_S "$config{_SOMAXCONN}"
-#define ENTRYPOINT int main(int argc, char** argv)
EOF
print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
if ($config{GCCVER} >= 3) {
print FILEHANDLE "#define GCC3\n";
}
- if ($config{HAS_STRLCPY} eq "true") {
- print FILEHANDLE "#define HAS_STRLCPY\n";
- }
if ($config{HAS_STDINT} eq "true") {
print FILEHANDLE "#define HAS_STDINT\n";
}
if ($config{HAS_EVENTFD} eq 'true') {
print FILEHANDLE "#define HAS_EVENTFD\n";
}
- if ($config{OSNAME} !~ /DARWIN/i) {
+ if ($config{HAS_CLOCK_GETTIME} eq 'true') {
print FILEHANDLE "#define HAS_CLOCK_GETTIME\n";
}
my $use_hiperf = 0;
$config{SOCKETENGINE} = "socketengine_select";
}
}
- print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n\n#endif\n";
- close(FILEHANDLE);
- open(FILEHANDLE, ">include/inspircd_version.h.tmp");
- print FILEHANDLE <<EOF;
-#define BRANCH "$branch"
-#define VERSION "$version"
-#define REVISION "$revision2"
-#define SYSTEM "$incos"
-EOF
- close FILEHANDLE;
-
- for my $file (qw(include/inspircd_config.h include/inspircd_version.h)) {
- my $diff = 0;
- open my $fh1, $file or $diff = 1;
- open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
- while (!$diff) {
- my $line1 = <$fh1>;
- my $line2 = <$fh2>;
- if (defined($line1) != defined($line2)) {
- $diff = 1;
- } elsif (!defined $line1) {
- last;
- } else {
- $diff = ($line1 ne $line2);
- }
- }
- if ($diff) {
- unlink $file;
- rename "$file.tmp", $file;
+ if ($config{HAS_DEFER} eq "TCP_DEFER_ACCEPT") {
+ print FILEHANDLE "#define USE_TCP_DEFER_ACCEPT";
+ } elsif ($config{HAS_DEFER} eq "SO_ACCEPTFILTER") {
+ print FILEHANDLE "#define USE_SO_ACCEPTFILTER"
+ }
+
+ print FILEHANDLE "\n#include \"threadengines/threadengine_pthread.h\"\n";
+ close(FILEHANDLE);
+
+ my $file = 'include/config.h';
+ my $diff = 0;
+ open my $fh1, $file or $diff = 1;
+ open my $fh2, $file.'.tmp' or die "Can't read $file.tmp that we just wrote: $!";
+ while (!$diff) {
+ my $line1 = <$fh1>;
+ my $line2 = <$fh2>;
+ if (defined($line1) != defined($line2)) {
+ $diff = 1;
+ } elsif (!defined $line1) {
+ last;
} else {
- unlink "$file.tmp";
+ $diff = ($line1 ne $line2);
}
}
+ if ($diff) {
+ unlink $file;
+ rename "$file.tmp", $file;
+ } else {
+ unlink "$file.tmp";
+ }
}
# Write all .in files.
channel halfoperator to remove a user. A removed user will part with
a message stating they were removed from the channel and by whom.">
+<helpop key="rmode" value="/RMODE [channel] [modeletter] {[pattern]}
+
+Removes listmodes from a channel.
+E.g. /RMODE #Chan b m:* will remove all mute extbans.">
+
<helpop key="fpart" value="/FPART [channel] [nick] {[reason]}
This behaves identically to /REMOVE, the only difference is that that
v [nickname] Gives voice to [nickname], allowing them to speak
while the channel is +m.
- h [nickname] Gives halfop status to [nickname] (this mode can
- be disabled).
+ h [nickname] Gives halfop status to [nickname] (requires
+ customprefix module).
o [nickname] Gives op status to [nickname].
a [nickname] Gives protected status to [nickname], preventing
them from them from being kicked (+q only,
- requires chanprotect module).
+ requires customprefix module).
q [nickname] Gives owner status to [nickname], preventing them
from being kicked (Services or only, requires
- chanprotect module).
+ customprefix module).
b [hostmask] Bans [hostmask] from the channel.
e [hostmask] Excepts [hostmask] from bans (requires
v [nickname] Gives voice to [nickname], allowing them to speak
while the channel is +m.
- h [nickname] Gives halfop status to [nickname] (this mode can
- be disabled).
+ h [nickname] Gives halfop status to [nickname] (requires
+ customprefix module).
o [nickname] Gives op status to [nickname].
a [nickname] Gives protected status to [nickname], preventing
them from them from being kicked (+q only,
- requires chanprotect module).
+ requires customprefix module).
q [nickname] Gives owner status to [nickname], preventing them
from being kicked (Services or only, requires
- chanprotect module).
+ customprefix module).
b [hostmask] Bans [hostmask] from the channel.
e [hostmask] Excepts [hostmask] from bans (requires
# #
########################################################################
+#-#-#-#-#-#-#-#-#-# CONFIGURATION FORMAT #-#-#-#-#-#-#-#-#-#-#-#-#-#-
+# #
+# In order to maintain compatibility with older configuration files, #
+# you can change the configuration parser to parse as it did in #
+# previous releases. When using the "compat" format, you need to use #
+# C++ escape sequences (e.g. \n) instead of XML ones (e.g. &nl;) and #
+# can not use <define> to create macros. #
+#<config format="compat">
+
#-#-#-#-#-#-#-#-#-# INCLUDE CONFIGURATION #-#-#-#-#-#-#-#-#-#-#-#-#-#
# #
# This optional tag allows you to include another config file #
# #
# Variables may be redefined and may reference other variables. #
# Value expansion happens at the time the tag is read. #
-# #
-# Using variable definitions REQUIRES that the config format be #
-# changed to "xml" from the default "compat" that uses escape #
-# sequences such as "\"" and "\n", and does not support <define> #
-<config format="xml">
<define name="bindip" value="1.2.2.3">
<define name="localips" value="&bindip;/24">
# for ssl to work. If you do not want this bind section to support ssl,
# just remove or comment out this option.
ssl="gnutls"
+
+ # defer: When this is non-zero, connections will not be handed over to
+ # the daemon from the operating system before data is ready.
+ # In Linux, the value indicates the number of seconds we'll wait for a
+ # connection to come up with data. Don't set it too low!
+ # In BSD the value is ignored; only zero and non-zero is possible.
+ # Windows ignores this parameter completely.
+ # Note: This does not take effect on rehash.
+ # To change it on a running bind, you'll have to comment it out,
+ # rehash, comment it in and rehash again.
+ defer="0"
>
<bind address="" port="6660-6669" type="clients">
# maxconnwarn: Enable warnings when localmax or globalmax is hit (defaults to on)
maxconnwarn="off"
+ # nouserdns: If enabled, no DNS lookups will be performed on connecting users
+ # in this class. This can save a lot of resources on very busy servers.
+ nouserdns="no"
+
# usednsbl: Defines whether or not users in this class are subject to DNSBL. Default is yes.
# This setting only has effect when m_dnsbl is loaded.
#usednsbl="yes"
# globalmax: Maximum global (network-wide) connections per IP.
globalmax="3"
+ # nouserdns: If enabled, no DNS lookups will be performed on connecting users
+ # in this class. This can save a lot of resources on very busy servers.
+ nouserdns="no"
+
# useident: Defines if users in this class must respond to a ident query or not.
useident="no"
# cyclehosts: If enabled, when a user gets a host set, it will cycle
# them in all their channels. If not, it will simply change their host
# without cycling them.
- cyclehosts="yes"
+ cyclehosts="no"
# cyclehostsfromuser: If enabled, the source of the mode change for
# cyclehosts will be the user who cycled. This can look nicer, but
# nosnoticestack: This prevents snotices from 'stacking' and giving you
# the message saying '(last message repeated X times)'. Defaults to no.
- nosnoticestack="no"
-
- # welcomenotice: When turned on, this sends a NOTICE to connecting users
- # with the text Welcome to <networkname>! after successful registration.
- # Defaults to yes.
- welcomenotice="yes">
+ nosnoticestack="no">
#-#-#-#-#-#-#-#-#-#-#-# PERFORMANCE CONFIGURATION #-#-#-#-#-#-#-#-#-#-#
# +C and +Q snomasks. Setting this to yes squelches those messages,
# which makes it easier for opers, but degrades the functionality of
# bots like BOPM during netsplits.
- quietbursts="yes"
-
- # nouserdns: If enabled, no DNS lookups will be performed on
- # connecting users. This can save a lot of resources on very busy servers.
- nouserdns="no">
+ quietbursts="yes">
#-#-#-#-#-#-#-#-#-#-#-# SECURITY CONFIGURATION #-#-#-#-#-#-#-#-#-#-#-#
# #
<security
+ # allowcoreunload: If this value is set to yes, Opers will be able to
+ # unload core modules (e.g. cmd_privmsg.so).
+ allowcoreunload="no"
# announceinvites: This option controls which members of the channel
# receive an announcement when someone is INVITEd. Available values:
# in a channel matching a mask like +b j:#channel*mask from joining.
#<module name="m_channelban.so">
-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
-# Chanprotect module: gives +q and +a channel modes
-#<module name="m_chanprotect.so">
-
-<chanprotect
- # noservices: With this set to yes, when a user joins a empty channel,
- # the server will set +q on them. If set to no, it will only set +o
- # on them until they register the channel.
- noservices="no"
-
- # qprefix: Prefix (symbol) to use for +q users.
- qprefix="~"
-
- # aprefix: Prefix (symbol) to use for +a users.
- aprefix="&"
-
- # deprotectself: If this value is set (true, yes or 1), it will allow
- # +a and +q users to remove the +a and +q from themselves, otherwise,
- # the status will have to be removed by services.
- deprotectself="yes"
-
- # deprotectothers: If this value is set to yes, true, or 1, then any
- # user with +q or +a may remove the +q or +a from other users.
- deprotectothers="yes">
-
-
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Check module: gives /check
# Check is useful for looking up information on channels,
# cloak prefix as shown below. The cloak key must be shared across #
# the network for correct cloaking. #
# #
-# There are four methods of cloaking: #
+# There are two methods of cloaking: #
# #
# half Cloak only the "unique" portion of a host; show #
# the last 2 parts of the domain, /16 subnet of IPv4 #
# full Cloak the users completely, using three slices for #
# common CIDR bans (IPv4: /16, /24; IPv6: /48, /64) #
# #
-# These methods use a single key that can be any length of text. #
+# The methods use a single key that can be any length of text. #
# An optional prefix may be specified to mark cloaked hosts. #
-# #
-# The following methods are maintained for backwards compatibility; #
-# they are slightly less secure, and always hide unresolved IPs #
-# #
-# compat-host InspIRCd 1.2-compatible host-based cloaking #
-# compat-ip InspIRCd 1.2-compatible ip-always cloaking #
-# #
-# If you use a compat cloaking mode then you must specify key1, key2, #
-# 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. #
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
#
#<cloak mode="half"
# quitmsg="Throttled" bootwait="10">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
-# Custom prefixes: allows for channel prefixes to be added.
-# This can replace m_chanprotect and m_halfop, except for services that
-# recognise those modules by name
+# Custom prefixes: allows for channel prefixes to be added.
#<module name="m_customprefix.so">
#
# name The name of the mode, must be unique from other modes
# ranktoset The numeric rank required to set/unset this mode. Defaults to rank.
# depriv Can you remove the mode from yourself? Defaults to yes.
#<customprefix name="founder" letter="q" prefix="~" rank="50000" ranktoset="50000">
-#<customprefix name="admin" letter="a" prefix="&" rank="40000" ranktoset="50000">
+#<customprefix name="admin" letter="a" prefix="&" rank="40000" ranktoset="50000">
#<customprefix name="halfop" letter="h" prefix="%" rank="20000" ranktoset="30000">
#<customprefix name="halfvoice" letter="V" prefix="-" rank="1" ranktoset="20000">
# must be in one of your oper class blocks.
#<module name="m_globalload.so">
-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
-# Halfop module: Provides the +h (halfops) channel status mode.
-#<module name="m_halfop.so">
-
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# HELPOP module: Provides the /HELPOP command
#<module name="m_helpop.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Anti-Auto-Rejoin: Adds support for prevention of auto-rejoin (+J)
#<module name="m_kicknorejoin.so">
-# Set the maximum time that is accepted as a parameter for +J here.
-#<kicknorejoin maxtime="1m">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Knock module: adds the /KNOCK command and +K channel mode
# use glob. For this reason, is recommended to use a real regex engine
# so that at least \s or [[:space:]] is available.
+#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
+# RMODE module: Adds the /RMODE command
+# Allows channel mods to remove list modes en masse.
+# Syntax: /rmode <channel> <mode> [pattern]
+# E.g. '/rmode #Channel b m:*' will remove all mute-extbans on the channel.
+#<module name="m_rmode.so">
+
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# SAJOIN module: Adds the /SAJOIN command
# This module is oper-only.
<module name="m_chanfilter.so">
<chanfilter hidemask="yes">
-<module name="m_chanprotect.so">
-
-<chanprotect
- noservices="no"
- qprefix="~"
- aprefix="&"
- deprotectself="yes"
- deprotectothers="yes">
-
<module name="m_check.so">
<module name="m_chghost.so">
<hostname charmap="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_/0123456789">
# - servers/auspex: allows opers with this priv to see more detail about server information than normal users.
# ACTIONS:
# - users/mass-message: allows opers with this priv to PRIVMSG and NOTICE to a server mask (e.g. NOTICE $*)
+ # - users/samode-usermodes: allows opers with this priv to change the user modes of any other user using /SAMODE
# - channels/high-join-limit: allows opers with this priv to join <channels:opers> total channels instead of <channels:users> total channels.
# PERMISSIONS:
# - users/flood/no-throttle: allows opers with this priv to send commands without being throttled (*NOTE)
*/
-#ifndef BANCACHE_H
-#define BANCACHE_H
+#pragma once
/** Stores a cached ban entry.
* Each ban has one of these hashed in a hash_map to make for faster removal
/** Reason, shown as quit message
*/
std::string Reason;
- /** IP to match against, no wildcards here (of course)
- */
- std::string IP;
/** Time that the ban expires at
*/
time_t Expiry;
- BanCacheHit(const std::string &ip, const std::string &type, const std::string &reason)
+ BanCacheHit(const std::string &type, const std::string &reason, time_t seconds)
+ : Type(type), Reason(reason), Expiry(ServerInstance->Time() + seconds)
{
- this->Type = type;
- this->Reason = reason;
- this->IP = ip;
- this->Expiry = ServerInstance->Time() + 86400; // a day. this might seem long, but entries will be removed as glines/etc expire.
}
- // overridden to allow custom time
- BanCacheHit(const std::string &ip, const std::string &type, const std::string &reason, time_t seconds)
- {
- this->Type = type;
- this->Reason = reason;
- this->IP = ip;
- this->Expiry = ServerInstance->Time() + seconds;
- }
+ bool IsPositive() const { return (!Reason.empty()); }
};
/* A container of ban cache items.
* must be defined after class BanCacheHit.
*/
-typedef nspace::hash_map<std::string, BanCacheHit*, nspace::hash<std::string> > BanCacheHash;
+typedef TR1NS::unordered_map<std::string, BanCacheHit*, TR1NS::hash<std::string> > BanCacheHash;
/** A manager for ban cache, which allocates and deallocates and checks cached bans.
*/
class CoreExport BanCacheManager
{
- private:
BanCacheHash* BanHash;
+ bool RemoveIfExpired(BanCacheHash::iterator& it);
+
public:
/** Creates and adds a Ban Cache item.
* @param ip The IP the item is for.
* @param type The type of ban cache item. std::string. .empty() means it's a negative match (user is allowed freely).
* @param reason The reason for the ban. Left .empty() if it's a negative match.
+ * @param seconds Number of seconds before nuking the bancache entry, the default is a day. This might seem long, but entries will be removed as glines/etc expire.
*/
- BanCacheHit *AddHit(const std::string &ip, const std::string &type, const std::string &reason);
-
- // Overridden to allow an optional number of seconds before expiry
- BanCacheHit *AddHit(const std::string &ip, const std::string &type, const std::string &reason, time_t seconds);
+ BanCacheHit *AddHit(const std::string &ip, const std::string &type, const std::string &reason, time_t seconds = 0);
BanCacheHit *GetHit(const std::string &ip);
- bool RemoveHit(BanCacheHit *b);
/** Removes all entries of a given type, either positive or negative. Returns the number of hits removed.
* @param type The type of bancache entries to remove (e.g. 'G')
* @param positive Remove either positive (true) or negative (false) hits.
*/
- unsigned int RemoveEntries(const std::string &type, bool positive);
+ void RemoveEntries(const std::string& type, bool positive);
BanCacheManager()
{
this->BanHash = new BanCacheHash();
}
~BanCacheManager();
- void RehashCache();
};
-
-#endif
*/
-#ifndef BASE_H
-#define BASE_H
+#pragma once
#include <map>
#include <deque>
virtual ~ServiceProvider();
};
-
-#endif
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
+ * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include "mode.h"
+#include "channels.h"
+#include "listmode.h"
+
+/** Channel mode +b
+ */
+class ModeChannelBan : public ListModeBase
+{
+ public:
+ ModeChannelBan()
+ : ListModeBase(NULL, "ban", 'b', "End of channel ban list", 367, 368, true, "maxbans")
+ {
+ }
+};
+
+/** Channel mode +i
+ */
+class ModeChannelInviteOnly : public SimpleChannelModeHandler
+{
+ public:
+ ModeChannelInviteOnly() : SimpleChannelModeHandler(NULL, "inviteonly", 'i')
+ {
+ }
+};
+
+/** Channel mode +k
+ */
+class ModeChannelKey : public ModeHandler
+{
+ public:
+ ModeChannelKey();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
+};
+
+/** Channel mode +l
+ */
+class ModeChannelLimit : public ParamChannelModeHandler
+{
+ public:
+ ModeChannelLimit();
+ bool ParamValidate(std::string& parameter);
+ bool ResolveModeConflict(std::string &their_param, const std::string &our_param, Channel* channel);
+};
+
+/** Channel mode +m
+ */
+class ModeChannelModerated : public SimpleChannelModeHandler
+{
+ public:
+ ModeChannelModerated() : SimpleChannelModeHandler(NULL, "moderated", 'm')
+ {
+ }
+};
+
+/** Channel mode +n
+ */
+class ModeChannelNoExternal : public SimpleChannelModeHandler
+{
+ public:
+ ModeChannelNoExternal() : SimpleChannelModeHandler(NULL, "noextmsg", 'n')
+ {
+ }
+};
+
+/** Channel mode +o
+ */
+class ModeChannelOp : public ModeHandler
+{
+ private:
+ public:
+ ModeChannelOp();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
+ unsigned int GetPrefixRank();
+};
+
+/** Channel mode +p
+ */
+class ModeChannelPrivate : public SimpleChannelModeHandler
+{
+ public:
+ ModeChannelPrivate() : SimpleChannelModeHandler(NULL, "private", 'p')
+ {
+ }
+};
+
+/** Channel mode +s
+ */
+class ModeChannelSecret : public SimpleChannelModeHandler
+{
+ public:
+ ModeChannelSecret() : SimpleChannelModeHandler(NULL, "secret", 's')
+ {
+ }
+};
+
+/** Channel mode +t
+ */
+class ModeChannelTopicOps : public SimpleChannelModeHandler
+{
+ public:
+ ModeChannelTopicOps() : SimpleChannelModeHandler(NULL, "topiclock", 't')
+ {
+ }
+};
+
+/** Channel mode +v
+ */
+class ModeChannelVoice : public ModeHandler
+{
+ private:
+ public:
+ ModeChannelVoice();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
+ unsigned int GetPrefixRank();
+};
+
+/** User mode +i
+ */
+class ModeUserInvisible : public SimpleUserModeHandler
+{
+ public:
+ ModeUserInvisible() : SimpleUserModeHandler(NULL, "invisible", 'i')
+ {
+ }
+};
+
+/** User mode +n
+ */
+class ModeUserServerNoticeMask : public ModeHandler
+{
+ public:
+ ModeUserServerNoticeMask();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
+ void OnParameterMissing(User* user, User* dest, Channel* channel);
+ std::string GetUserParameter(User* user);
+};
+
+/** User mode +o
+ */
+class ModeUserOperator : public ModeHandler
+{
+ public:
+ ModeUserOperator();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
+};
+
+/** User mode +w
+ */
+class ModeUserWallops : public SimpleUserModeHandler
+{
+ public:
+ ModeUserWallops() : SimpleUserModeHandler(NULL, "wallops", 'w')
+ {
+ }
+};
*
* Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
* Copyright (C) 2007 Craig Edwards <craigedwards@brainbox.cc>
+ * Copyright (C) 2012 Adam <Adam@anope.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
*/
-#ifndef CALLER_H
-#define CALLER_H
+#pragma once
+
+#if defined HAS_CXX11_VARIADIC_TEMPLATES
+
+template<typename ReturnType, typename... Args> class CoreExport Handler : public classbase
+{
+ public:
+ virtual ~Handler() { }
+ virtual ReturnType Call(Args...) = 0;
+};
+
+template<typename ReturnType, typename... Args> class CoreExport Caller
+{
+ public:
+ Handler<ReturnType, Args...>* target;
+
+ Caller(Handler<ReturnType, Args...>* initial) : target(initial) { }
+ virtual ~Caller() { }
+
+ virtual ReturnType operator()(const Args&... params)
+ {
+ return this->target->Call(params...);
+ }
+};
+
+/* Below here is compat with the old API */
+#define HandlerBase0 Handler
+#define HandlerBase1 Handler
+#define HandlerBase2 Handler
+#define HandlerBase3 Handler
+#define HandlerBase4 Handler
+#define HandlerBase5 Handler
+#define HandlerBase6 Handler
+#define HandlerBase7 Handler
+#define HandlerBase8 Handler
+
+#define caller1 Caller
+#define caller2 Caller
+#define caller3 Caller
+#define caller4 Caller
+#define caller5 Caller
+#define caller6 Caller
+#define caller7 Caller
+#define caller8 Caller
+
+#define DEFINE_HANDLER0(NAME, RETURN) \
+ class CoreExport NAME : public Handler<RETURN> { public: NAME() { } virtual RETURN Call(); }
+
+#define DEFINE_HANDLER1(NAME, RETURN, V1) \
+ class CoreExport NAME : public Handler<RETURN, V1> { public: NAME() { } virtual RETURN Call(V1); }
+
+#define DEFINE_HANDLER2(NAME, RETURN, V1, V2) \
+ class CoreExport NAME : public Handler<RETURN, V1, V2> { public: NAME() { } virtual RETURN Call(V1, V2); }
+
+#define DEFINE_HANDLER3(NAME, RETURN, V1, V2, V3) \
+ class CoreExport NAME : public Handler<RETURN, V1, V2, V3> { public: NAME() { } virtual RETURN Call(V1, V2, V3); }
+
+#define DEFINE_HANDLER4(NAME, RETURN, V1, V2, V3, V4) \
+ class CoreExport NAME : public Handler<RETURN, V1, V2, V3, V4> { public: NAME() { } virtual RETURN Call(V1, V2, V3, V4); }
+
+#define DEFINE_HANDLER5(NAME, RETURN, V1, V2, V3, V4, V5) \
+ class CoreExport NAME : public Handler<RETURN, V1, V2, V3, V4, V5> { public: NAME() { } virtual RETURN Call(V1, V2, V3, V4, V5); }
+
+#define DEFINE_HANDLER6(NAME, RETURN, V1, V2, V3, V4, V5, V6) \
+ class CoreExport NAME : public Handler<RETURN, V1, V2, V3, V4, V5, V6> { public: NAME() { } virtual RETURN Call(V1, V2, V3, V4, V5, V6); }
+
+#define DEFINE_HANDLER7(NAME, RETURN, V1, V2, V3, V4, V5, V6, V7) \
+ class CoreExport NAME : public Handler<RETURN, V1, V2, V3, V4, V5, V6, V7> { public: NAME() { } virtual RETURN Call(V1, V2, V3, V4, V5, V6, V7); }
+
+#define DEFINE_HANDLER8(NAME, RETURN, V1, V2, V3, V4, V5, V6, V7, V8) \
+ class CoreExport NAME : public Handler<RETURN, V1, V2, V3, V4, V5, V6, V7, V8> { public: NAME() { } virtual RETURN Call(V1, V2, V3, V4, V5, V6, V7, V8); }
+
+#else
/** The templates below can be auto generated by tools/create_templates.pl.
* They are used to represent a functor with a given number of parameters and
*/
-#ifndef CHANNELS_H
-#define CHANNELS_H
+#pragma once
#include "membership.h"
#include "mode.h"
/** Holds an entry for a ban list, exemption list, or invite list.
* This class contains a single element in a channel list, such as a banlist.
*/
-class HostItem
-{
- public:
- /** Time the item was added
- */
- time_t set_time;
- /** Who added the item
- */
- std::string set_by;
- /** The actual item data
- */
- std::string data;
-
- HostItem() { /* stub */ }
- virtual ~HostItem() { /* stub */ }
-};
-
-/** A subclass of HostItem designed to hold channel bans (+b)
- */
-class BanItem : public HostItem
-{
-};
/** Holds all relevent information for a channel.
* This class represents a channel, and contains its name, modes, topic, topic set time,
*/
class CoreExport Channel : public Extensible, public InviteBase
{
- /** Connect a Channel to a User
- */
- static Channel* ForceChan(Channel* Ptr, User* user, const std::string &privs, bool bursting, bool created);
-
/** Set default modes for the channel on creation
*/
void SetDefaultModes();
- /** Maximum number of bans (cached)
- */
- int maxbans;
-
/** Modes for the channel.
* This is not a null terminated string! It is a bitset where
* each item in it represents if a mode is set. For example
*/
CustomModeList custom_mode_params;
+ /** Remove the given membership from the channel's internal map of
+ * memberships and destroy the Membership object.
+ * This function does not remove the channel from User::chanlist.
+ * Since the parameter is an iterator to the target, the complexity
+ * of this function is constant.
+ * @param membiter The UserMembIter to remove, must be valid
+ */
+ void DelUser(const UserMembIter& membiter);
+
public:
/** Creates a channel record and initialises it with default values
* @throw Nothing at present.
*/
Channel(const std::string &name, time_t ts);
+ /** Checks whether the channel should be destroyed, and if yes, begins
+ * the teardown procedure.
+ *
+ * If there are users on the channel or a module vetoes the deletion
+ * (OnPreChannelDelete hook) then nothing else happens.
+ * Otherwise, first the OnChannelDelete event is fired, then the channel is
+ * removed from the channel list. All pending invites are destroyed and
+ * finally the channel is added to the cull list.
+ */
+ void CheckDestroy();
+
/** The channel's name.
*/
std::string name;
*/
std::string setby; /* 128 */
- /** The list of all bans set on the channel.
- */
- BanList bans;
-
/** Sets or unsets a custom mode in the channels info
* @param mode The mode character to set or unset
* @param value True if you want to set the mode or false if you want to remove it
int SetTopic(User *u, std::string &t, bool forceset = false);
/** Obtain the channel "user counter"
- * This returns the channel reference counter, which is initialized
- * to 0 when the channel is created and incremented/decremented
- * upon joins, parts quits and kicks.
+ * This returns the number of users on this channel
*
* @return The number of users on this channel
*/
- long GetUserCounter();
+ long GetUserCounter() const { return userlist.size(); }
/** Add a user pointer to the internal reference list
* @param user The user to add
*
* @return This function returns pointer to a map of User pointers (CUList*).
*/
- const UserMembList* GetUsers();
+ const UserMembList* GetUsers() const { return &userlist; }
/** Returns true if the user given is on the given channel.
* @param user The user to look for
* @param src The source of the kick
* @param user The user being kicked (must be on this channel)
* @param reason The reason for the kick
+ * @param srcmemb The membership of the user who does the kick, can be NULL
*/
- void KickUser(User *src, User *user, const char* reason);
+ void KickUser(User* src, User* user, const std::string& reason, Membership* srcmemb = NULL);
/** Part a user from this channel with the given reason.
* If the reason field is NULL, no reason will be sent.
*/
void PartUser(User *user, std::string &reason);
- /* Join a user to a channel. May be a channel that doesnt exist yet.
+ /** Join a local user to a channel, with or without permission checks. May be a channel that doesn't exist yet.
* @param user The user to join to the channel.
- * @param cn The channel name to join to. Does not have to exist.
+ * @param channame The channel name to join to. Does not have to exist.
* @param key The key of the channel, if given
* @param override If true, override all join restrictions such as +bkil
* @return A pointer to the Channel the user was joined to. A new Channel may have
* been created if the channel did not exist before the user was joined to it.
- * If the user could not be joined to a channel, the return value may be NULL.
+ * If the user could not be joined to a channel, the return value is NULL.
+ */
+ static Channel* JoinUser(LocalUser* user, std::string channame, bool override = false, const std::string& key = "");
+
+ /** Join a user to an existing channel, without doing any permission checks
+ * @param user The user to join to the channel
+ * @param privs Priviliges (prefix mode letters) to give to this user, may be NULL
+ * @param bursting True if this join is the result of a netburst (passed to modules in the OnUserJoin hook)
+ * @param created True if this channel was just created by a local user (passed to modules in the OnUserJoin hook)
*/
- static Channel* JoinUser(User *user, const char* cn, bool override, const char* key, bool bursting, time_t TS = 0);
+ void ForceJoin(User* user, const std::string* privs = NULL, bool bursting = false, bool created_by_local = false);
/** Write to a channel, from a user, using va_args for text
* @param user User whos details to prefix the line with
/** Write a line of text that already includes the source */
void RawWriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string& text);
- /** Returns the maximum number of bans allowed to be set on this channel
- * @return The maximum number of bans allowed
- */
- long GetMaxBans();
-
/** Return the channel's modes with parameters.
* @param showkey If this is set to true, the actual key is shown,
* otherwise it is replaced with '<KEY>'
* @return The channel mode string
*/
- char* ChanModes(bool showkey);
+ const char* ChanModes(bool showkey);
/** Spool the NAMES list for this channel to the given user
* @param user The user to spool the NAMES list to
*/
void UserList(User *user);
- /** Get the number of invisible users on this channel
- * @return Number of invisible users
- */
- int CountInvisible();
-
/** Get a users prefix on this channel in a string.
* @param user The user to look up
* @return A character array containing the prefix string.
*/
unsigned int GetPrefixValue(User* user);
- /** This method removes all prefix characters from a user.
- * It will not inform the user or the channel of the removal of prefixes,
- * and should be used when the user parts or quits.
- * @param user The user to remove all prefixes from
- */
- void RemoveAllPrefixes(User* user);
-
/** Add a prefix character to a user.
* Only the core should call this method, usually from
* within the mode parser or when the first user joins
/** Get the status of an "action" type extban
*/
ModResult GetExtBanStatus(User *u, char type);
-
- /** Clears the cached max bans value
- */
- void ResetMaxBans();
};
-#endif
+inline bool Channel::HasUser(User* user)
+{
+ return (userlist.find(user) != userlist.end());
+}
*/
-#ifndef COMMAND_PARSE_H
-#define COMMAND_PARSE_H
+#pragma once
/** This class handles command management and parsing.
* It allows you to add and remove commands from the map,
* @param user The user to parse the command for
* @param cmd The command string to process
*/
- bool ProcessCommand(LocalUser *user, std::string &cmd);
+ void ProcessCommand(LocalUser* user, std::string& cmd);
public:
/** Command list, a hash_map of command names to Command*
* @param buffer The buffer line to process
* @param user The user to whom this line belongs
*/
- bool ProcessBuffer(std::string &buffer,LocalUser *user);
+ void ProcessBuffer(std::string &buffer,LocalUser *user);
/** Add a new command to the commands hash
* @param f The new Command to add to the list
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};
-
-#endif
*/
-#ifndef CMD_WHOWAS_H
-#define CMD_WHOWAS_H
-#include "modules.h"
-
-struct WhowasRequest : public Request
-{
- /* list of available internal commands */
- enum Internals
- {
- WHOWAS_ADD = 1,
- WHOWAS_STATS = 2,
- WHOWAS_PRUNE = 3,
- WHOWAS_MAINTAIN = 4
- };
-
- const Internals type;
- std::string value;
- User* user;
-
- WhowasRequest(Module* src, Module* whowas, Internals Type) : Request(src, whowas, "WHOWAS"), type(Type)
- {}
-};
+#pragma once
-/* Forward ref for timer */
-class WhoWasMaintainTimer;
+#include "modules.h"
/* Forward ref for typedefs */
class WhoWasGroup;
-/** Timer that is used to maintain the whowas list, called once an hour
- */
-extern WhoWasMaintainTimer* timer;
-
/** A group of users related by nickname
*/
typedef std::deque<WhoWasGroup*> whowas_set;
whowas_users_fifo whowas_fifo;
public:
+ /** Max number of WhoWas entries per user.
+ */
+ int WhoWasGroupSize;
+
+ /** Max number of cumulative user-entries in WhoWas.
+ * When max reached and added to, push out oldest entry FIFO style.
+ */
+ int WhoWasMaxGroups;
+
+ /** Max seconds a user is kept in WhoWas before being pruned.
+ */
+ int WhoWasMaxKeep;
+
CommandWhowas(Module* parent);
/** Handle command.
* @param parameters The parameters to the comamnd
*/
~WhoWasGroup();
};
-
-class WhoWasMaintainTimer : public Timer
-{
- public:
- WhoWasMaintainTimer(long interval)
- : Timer(interval, ServerInstance->Time(), true)
- {
- }
- virtual void Tick(time_t TIME);
-};
-
-#endif
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013 Peter Powell <petpow@saberuk.com>
+ * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
+ * Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
+ *
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#pragma once
+
+/**
+ * Some implementations of the C++11 standard library are incomplete so we use
+ * the implementation of the same types from C++ Technical Report 1 instead.
+ */
+#if defined _LIBCPP_VERSION || defined _WIN32
+# define TR1NS std
+# include <unordered_map>
+#else
+# define TR1NS std::tr1
+# include <tr1/unordered_map>
+#endif
+
+/**
+ * This macro enables the compile-time checking of printf format strings. This
+ * makes the compiler show a warning if the format of a printf arguments are
+ * incorrect.
+ */
+#if defined __clang__ || defined __GNUC__
+# define CUSTOM_PRINTF(stringpos, firstpos) __attribute__((format(printf, stringpos, firstpos)))
+#else
+# pragma message ("Warning! CUSTOM_PRINTF() does not work on your compiler!")
+# define CUSTOM_PRINTF(stringpos, firstpos)
+#endif
+
+/**
+ * These macros enable the use of the C++11 override control keywords in
+ * compilers which support them.
+ */
+#if __cplusplus >= 201103L
+# define HAS_CXX11_FINAL_OVERRIDE
+#elif defined __clang__
+# if __has_feature(cxx_override_control)
+# define HAS_CXX11_FINAL_OVERRIDE
+# endif
+#elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
+# if defined __GXX_EXPERIMENTAL_CXX0X__
+# define HAS_CXX11_FINAL_OVERRIDE
+# endif
+#elif _MSC_VER >= 1700
+# define HAS_CXX11_FINAL_OVERRIDE
+#endif
+
+#if defined HAS_CXX11_FINAL_OVERRIDE
+# define CXX11_FINAL final
+# define CXX11_OVERRIDE override
+#else
+# define CXX11_FINAL
+# define CXX11_OVERRIDE
+#endif
+
+/**
+ * These macros enable the detection of the C++11 variadic templates in
+ * compilers which support them.
+ */
+#if __cplusplus >= 201103L
+# define HAS_CXX11_VARIADIC_TEMPLATES
+#elif defined __clang__
+# if __has_feature(cxx_variadic_templates)
+# define HAS_CXX11_VARIADIC_TEMPLATES
+# endif
+#elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
+# if defined __GXX_EXPERIMENTAL_CXX0X__
+# define HAS_CXX11_VARIADIC_TEMPLATES
+# endif
+#elif _MSC_FULL_VER >= 170051025
+# define HAS_CXX11_VARIADIC_TEMPLATES
+#endif
+
+/**
+ * This macro allows methods to be marked as deprecated. To use this, wrap the
+ * method declaration in the header file with the macro.
+ */
+#if defined __clang__ || defined __GNUC__
+# define DEPRECATED_METHOD(function) function __attribute__((deprecated))
+#elif defined _MSC_VER
+# define DEPRECATED_METHOD(function) __declspec(deprecated) function
+#else
+# pragma message ("Warning! DEPRECATED_METHOD() does not work on your compiler!")
+# define DEPRECATED_METHOD(function) function
+#endif
+
+/**
+ * Windows is very different to UNIX so we have to wrap certain features in
+ * order to build on Windows correctly.
+ */
+#if defined _WIN32
+# include "inspircd_win32wrapper.h"
+#else
+# include <unistd.h>
+# define ENTRYPOINT int main(int argc, char** argv)
+# define DllExport
+# define CoreExport
+#endif
*/
+#pragma once
+
struct fpos
{
std::string filename;
enum ParseFlags
{
- FLAG_USE_XML = 1,
+ FLAG_USE_COMPAT = 1,
FLAG_NO_EXEC = 2,
FLAG_NO_INC = 4
};
}
}
};
-
-
*/
-#ifndef INSPIRCD_CONFIGREADER
-#define INSPIRCD_CONFIGREADER
+#pragma once
#include <sstream>
#include <string>
/** Saved argv from startup
*/
char** argv;
-
- std::string startup_log;
};
class CoreExport OperInfo : public refcountbase
/** Get a configuration item, searching in the oper, type, and class blocks (in that order) */
std::string getConfig(const std::string& key);
void init();
-
- inline const char* NameStr()
- {
- return irc::Spacify(name.c_str());
- }
};
/** This class holds the bulk of the runtime configuration for the ircd.
*/
int c_ipv6_range;
- /** Max number of WhoWas entries per user.
- */
- int WhoWasGroupSize;
-
- /** Max number of cumulative user-entries in WhoWas.
- * When max reached and added to, push out oldest entry FIFO style.
- */
- int WhoWasMaxGroups;
-
- /** Max seconds a user is kept in WhoWas before being pruned.
- */
- int WhoWasMaxKeep;
-
/** Holds the server name of the local server
* as defined by the administrator.
*/
*/
std::string FixedPart;
- /** The DNS server to use for DNS queries
- */
- std::string DNSServer;
-
/** Pretend disabled commands don't exist.
*/
bool DisabledDontExist;
*/
ClassVector Classes;
- /** The 005 tokens of this server (ISUPPORT)
- * populated/repopulated upon loading or unloading
- * modules.
- */
- std::string data005;
-
- /** isupport strings
- */
- std::vector<std::string> isupport;
-
/** STATS characters in this list are available
* only to operators.
*/
*/
std::map<irc::string, bool> ulines;
- /** Max banlist sizes for channels (the std::string is a glob)
- */
- std::map<std::string, int> maxbans;
-
- /** If set to true, no user DNS lookups are to be performed
- */
- bool NoUserDns;
-
/** If set to true, provide syntax hints for unknown commands
*/
bool SyntaxHints;
/** Get server ID as string with required leading zeroes
*/
- const std::string& GetSID();
-
- /** Update the 005 vector
- */
- void Update005();
-
- /** Send the 005 numerics (ISUPPORT) to a user
- */
- void Send005(User* user);
+ const std::string& GetSID() const { return sid; }
/** Read the entire configuration into memory
* and initialize this class. All other methods
/** If this value is true, snotices will not stack when repeats are sent
*/
bool NoSnoticeStack;
-
- /** If true, a "Welcome to <networkname>!" NOTICE will be sent to
- * connecting users
- */
- bool WelcomeNotice;
};
/** The background thread for config reading, so that reading from executable includes
void Finish();
bool IsDone() { return done; }
};
-
-#endif
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CONSOLECOLORS_H
-#define CONSOLECOLORS_H
+
+#pragma once
#include <ostream>
}
#endif
-
-#endif
*/
-#ifndef CTABLES_H
-#define CTABLES_H
+#pragma once
/** Used to indicate command success codes
*/
*/
unsigned long use_count;
- /** used by /stats m
- */
- unsigned long total_bytes;
-
/** True if the command is disabled to non-opers
*/
bool disabled;
*/
Command(Module* me, const std::string &cmd, int minpara = 0, int maxpara = 0) :
ServiceProvider(me, cmd, SERVICE_COMMAND), flags_needed(0), min_params(minpara), max_params(maxpara),
- use_count(0), total_bytes(0), disabled(false), works_before_reg(false), allow_empty_last_param(true),
+ use_count(0), disabled(false), works_before_reg(false), allow_empty_last_param(true),
Penalty(1)
{
}
translation.push_back(x5);translation.push_back(x6);translation.push_back(x7);
#define TRANSLATE8(x1,x2,x3,x4,x5,x6,x7,x8) translation.push_back(x1);translation.push_back(x2);translation.push_back(x3);translation.push_back(x4);\
translation.push_back(x5);translation.push_back(x6);translation.push_back(x7);translation.push_back(x8);
-
-#endif
*/
-#ifndef CULL_LIST_H
-#define CULL_LIST_H
+#pragma once
/**
* The CullList class is used to delete objects at the end of the main loop to
void Run();
};
-
-#endif
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2005-2008 Craig Edwards <craigedwards@brainbox.cc>
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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/>.
- */
-
-
-/*
-dns.h - dns library very very loosely based on
-firedns, Copyright (C) 2002 Ian Gulliver
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of version 2 of the GNU General Public License as
-published by the Free Software Foundation.
-
-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, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#ifndef DNS_H
-#define DNS_H
-
-#include "socket.h"
-#include "hashcomp.h"
-
-/**
- * Result status, used internally
- */
-class CoreExport DNSResult
-{
- public:
- /** Result ID
- */
- int id;
- /** Result body, a hostname or IP address
- */
- std::string result;
- /** Time-to-live value of the result
- */
- unsigned long ttl;
- /** The original request, a hostname or IP address
- */
- std::string original;
-
- /** Build a DNS result.
- * @param i The request ID
- * @param res The request result, a hostname or IP
- * @param timetolive The request time-to-live
- * @param orig The original request, a hostname or IP
- */
- DNSResult(int i, const std::string &res, unsigned long timetolive, const std::string &orig) : id(i), result(res), ttl(timetolive), original(orig) { }
-};
-
-/**
- * Information on a completed lookup, used internally
- */
-typedef std::pair<unsigned char*, std::string> DNSInfo;
-
-/** Cached item stored in the query cache.
- */
-class CoreExport CachedQuery
-{
- public:
- /** The cached result data, an IP or hostname
- */
- std::string data;
- /** The time when the item is due to expire
- */
- time_t expires;
-
- /** Build a cached query
- * @param res The result data, an IP or hostname
- * @param ttl The time-to-live value of the query result
- */
- CachedQuery(const std::string &res, unsigned int ttl);
-
- /** Returns the number of seconds remaining before this
- * cache item has expired and should be removed.
- */
- int CalcTTLRemaining();
-};
-
-/** DNS cache information. Holds IPs mapped to hostnames, and hostnames mapped to IPs.
- */
-typedef nspace::hash_map<irc::string, CachedQuery, irc::hash> dnscache;
-
-/**
- * Error types that class Resolver can emit to its error method.
- */
-enum ResolverError
-{
- RESOLVER_NOERROR = 0,
- RESOLVER_NSDOWN = 1,
- RESOLVER_NXDOMAIN = 2,
- RESOLVER_BADIP = 3,
- RESOLVER_TIMEOUT = 4,
- RESOLVER_FORCEUNLOAD = 5
-};
-
-/**
- * Query and resource record types
- */
-enum QueryType
-{
- /** Uninitialized Query */
- DNS_QUERY_NONE = 0,
- /** 'A' record: an ipv4 address */
- DNS_QUERY_A = 1,
- /** 'CNAME' record: An alias */
- DNS_QUERY_CNAME = 5,
- /** 'PTR' record: a hostname */
- DNS_QUERY_PTR = 12,
- /** 'AAAA' record: an ipv6 address */
- DNS_QUERY_AAAA = 28,
-
- /** Force 'PTR' to use IPV4 scemantics */
- DNS_QUERY_PTR4 = 0xFFFD,
- /** Force 'PTR' to use IPV6 scemantics */
- DNS_QUERY_PTR6 = 0xFFFE
-};
-
-/**
- * Used internally to force PTR lookups to use a certain protocol scemantics,
- * e.g. x.x.x.x.in-addr.arpa for v4, and *.ip6.arpa for v6.
- */
-enum ForceProtocol
-{
- /** Forced to use ipv4 */
- PROTOCOL_IPV4 = 0,
- /** Forced to use ipv6 */
- PROTOCOL_IPV6 = 1
-};
-
-/**
- * The Resolver class is a high-level abstraction for resolving DNS entries.
- * It can do forward and reverse IPv4 lookups, and where IPv6 is supported, will
- * also be able to do those, transparent of protocols. Module developers must
- * extend this class via inheritence, and then insert a pointer to their derived
- * class into the core using Server::AddResolver(). Once you have done this,
- * the class will be able to receive callbacks. There are two callbacks which
- * can occur by calling virtual methods, one is a success situation, and the other
- * an error situation.
- */
-class CoreExport Resolver
-{
- protected:
- /**
- * Pointer to creator module (if any, or NULL)
- */
- ModuleRef Creator;
- /**
- * The input data, either a host or an IP address
- */
- std::string input;
- /**
- * True if a forward lookup is being performed, false if otherwise
- */
- QueryType querytype;
- /**
- * The DNS erver being used for lookups. If this is an empty string,
- * the value of ServerConfig::DNSServer is used instead.
- */
- std::string server;
- /**
- * The ID allocated to your lookup. This is a pseudo-random number
- * between 0 and 65535, a value of -1 indicating a failure.
- * The core uses this to route results to the correct objects.
- */
- int myid;
-
- /**
- * Cached result, if there is one
- */
- CachedQuery *CQ;
-
- /**
- * Time left before cache expiry
- */
- int time_left;
-
- public:
- /**
- * Initiate DNS lookup. Your class should not attempt to delete or free these
- * objects, as the core will do this for you. They must always be created upon
- * the heap using new, as you cannot be sure at what time they will be deleted.
- * Allocating them on the stack or attempting to delete them yourself could cause
- * the object to go 'out of scope' and cause a segfault in the core if the result
- * arrives at a later time.
- * @param source The IP or hostname to resolve
- * @param qt The query type to perform. Resolution of 'A', 'AAAA', 'PTR' and 'CNAME' records
- * is supported. Use one of the QueryType enum values to initiate this type of
- * lookup. Resolution of 'AAAA' ipv6 records is always supported, regardless of
- * wether InspIRCd is built with ipv6 support.
- * To look up reverse records, specify one of DNS_QUERY_PTR4 or DNS_QUERY_PTR6 depending
- * on the type of address you are looking up.
- * @param cached The constructor will set this boolean to true or false depending
- * on whether the DNS lookup you are attempting is cached (and not expired) or not.
- * If the value is cached, upon return this will be set to true, otherwise it will
- * be set to false. You should pass this value to InspIRCd::AddResolver(), which
- * will then influence the behaviour of the method and determine whether a cached
- * or non-cached result is obtained. The value in this variable is always correct
- * for the given request when the constructor exits.
- * @param creator See the note below.
- * @throw ModuleException This class may throw an instance of ModuleException, in the
- * event a lookup could not be allocated, or a similar hard error occurs such as
- * the network being down. This will also be thrown if an invalid IP address is
- * passed when resolving a 'PTR' record.
- *
- * NOTE: If you are instantiating your DNS lookup from a module, you should set the
- * value of creator to point at your Module class. This way if your module is unloaded
- * whilst lookups are in progress, they can be safely removed and your module will not
- * crash the server.
- */
- Resolver(const std::string &source, QueryType qt, bool &cached, Module* creator);
-
- /**
- * The default destructor does nothing.
- */
- virtual ~Resolver();
-
- /**
- * When your lookup completes, this method will be called.
- * @param result The resulting DNS lookup, either an IP address or a hostname.
- * @param ttl The time-to-live value of the result, in the instance of a cached
- * result, this is the number of seconds remaining before refresh/expiry.
- * @param cached True if the result is a cached result, false if it was requested
- * from the DNS server.
- */
- virtual void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached) = 0;
-
- /**
- * If an error occurs (such as NXDOMAIN, no domain name found) then this method
- * will be called.
- * @param e A ResolverError enum containing the error type which has occured.
- * @param errormessage The error text of the error that occured.
- */
- virtual void OnError(ResolverError e, const std::string &errormessage);
-
- /**
- * Returns the id value of this class. This is primarily used by the core
- * to determine where in various tables to place a pointer to your class, but it
- * is safe to call and use this method.
- * As specified in RFC1035, each dns request has a 16 bit ID value, ranging
- * from 0 to 65535. If there is an issue and the core cannot send your request,
- * this method will return -1.
- */
- int GetId();
-
- /**
- * Returns the creator module, or NULL
- */
- Module* GetCreator();
-
- /**
- * If the result is a cached result, this triggers the objects
- * OnLookupComplete. This is done because it is not safe to call
- * the abstract virtual method from the constructor.
- */
- void TriggerCachedResult();
-};
-
-/** DNS is a singleton class used by the core to dispatch dns
- * requests to the dns server, and route incoming dns replies
- * back to Resolver objects, based upon the request ID. You
- * should never use this class yourself.
- */
-class CoreExport DNS : public EventHandler
-{
- private:
-
- /**
- * The maximum value of a dns request id,
- * 16 bits wide, 0xFFFF.
- */
- static const int MAX_REQUEST_ID = 0xFFFF;
-
- /**
- * Currently cached items
- */
- dnscache* cache;
-
- /** A timer which ticks every hour to remove expired
- * items from the DNS cache.
- */
- class CacheTimer* PruneTimer;
-
- /**
- * Build a dns packet payload
- */
- int MakePayload(const char* name, const QueryType rr, const unsigned short rr_class, unsigned char* payload);
-
- public:
-
- irc::sockets::sockaddrs myserver;
-
- /**
- * Currently active Resolver classes
- */
- Resolver* Classes[MAX_REQUEST_ID];
-
- /**
- * Requests that are currently 'in flight'
- */
- DNSRequest* requests[MAX_REQUEST_ID];
-
- /**
- * The port number DNS requests are made on,
- * and replies have as a source-port number.
- */
- static const int QUERY_PORT = 53;
-
- /**
- * Fill an rr (resource record) with data from input
- */
- static void FillResourceRecord(ResourceRecord* rr, const unsigned char* input);
-
- /**
- * Fill a header with data from input limited by a length
- */
- static void FillHeader(DNSHeader *header, const unsigned char *input, const int length);
-
- /**
- * Empty out a header into a data stream ready for transmission "on the wire"
- */
- static void EmptyHeader(unsigned char *output, const DNSHeader *header, const int length);
-
- /**
- * Start the lookup of an ipv4 from a hostname
- */
- int GetIP(const char* name);
-
- /**
- * Start lookup of a hostname from an ip, but
- * force a specific protocol to be used for the lookup
- * for example to perform an ipv6 reverse lookup.
- */
- int GetNameForce(const char *ip, ForceProtocol fp);
-
- /**
- * Start lookup of an ipv6 from a hostname
- */
- int GetIP6(const char *name);
-
- /**
- * Start lookup of a CNAME from another hostname
- */
- int GetCName(const char* alias);
-
- /**
- * Fetch the result string (an ip or host)
- * and/or an error message to go with it.
- */
- DNSResult GetResult();
-
- /**
- * Handle a SocketEngine read event
- * Inherited from EventHandler
- */
- void HandleEvent(EventType et, int errornum = 0);
-
- /**
- * Add a Resolver* to the list of active classes
- */
- bool AddResolverClass(Resolver* r);
-
- /**
- * Add a query to the list to be sent
- */
- DNSRequest* AddQuery(DNSHeader *header, int &id, const char* original);
-
- /**
- * The constructor initialises the dns socket,
- * and clears the request lists.
- */
- DNS();
-
- /**
- * Re-initialize the DNS subsystem.
- */
- void Rehash();
-
- /**
- * Destructor
- */
- ~DNS();
-
- /**
- * Turn an in6_addr into a .ip6.arpa domain
- */
- static void MakeIP6Int(char* query, const in6_addr *ip);
-
- /**
- * Clean out all dns resolvers owned by a particular
- * module, to make unloading a module safe if there
- * are dns requests currently in progress.
- */
- void CleanResolvers(Module* module);
-
- /** Return the cached value of an IP or hostname
- * @param source An IP or hostname to find in the cache.
- * @return A pointer to a CachedQuery if the item exists,
- * otherwise NULL.
- */
- CachedQuery* GetCache(const std::string &source);
-
- /** Delete a cached item from the DNS cache.
- * @param source An IP or hostname to remove
- */
- void DelCache(const std::string &source);
-
- /** Clear all items from the DNS cache immediately.
- */
- int ClearCache();
-
- /** Prune the DNS cache, e.g. remove all expired
- * items and rehash the cache buckets, but leave
- * items in the hash which are still valid.
- */
- int PruneCache();
-};
-
-#endif
-
*/
-#ifndef DLL_H
-#define DLL_H
+#pragma once
/** The DLLManager class is able to load a module file by filename,
* and locate its init_module symbol.
/** Get detailed version information from the module file */
std::string GetVersion();
};
-
-#endif
-
*/
-#ifndef EXITCODE_H
-#define EXITCODE_H
+#pragma once
/** Valid exit codes to be used with InspIRCd::Exit()
*/
* human-readable strings to be shown on shutdown.
*/
extern const char * ExitCodes[];
-
-#endif
-
*/
-#ifndef EXTENSIBLE_H
-#define EXTENSIBLE_H
+#pragma once
#include <stdint.h>
void unset(Extensible* container);
void free(void* item);
};
-
-#endif
*/
-#ifndef FILELOGGER_H
-#define FILELOGGER_H
+#pragma once
#include "logger.h"
-/** Debug levels for use with InspIRCd::Log()
- * */
-enum DebugLevel
-{
- RAWIO = 5,
- DEBUG = 10,
- VERBOSE = 20,
- DEFAULT = 30,
- SPARSE = 40,
- NONE = 50
-};
-
-
-/* Forward declaration -- required */
-class InspIRCd;
-
/** A logging class which logs to a streamed file.
*/
class CoreExport FileLogStream : public LogStream
private:
FileWriter *f;
public:
- FileLogStream(int loglevel, FileWriter *fw);
+ FileLogStream(LogLevel loglevel, FileWriter *fw);
virtual ~FileLogStream();
- virtual void OnLog(int loglevel, const std::string &type, const std::string &msg);
+ virtual void OnLog(LogLevel loglevel, const std::string &type, const std::string &msg);
};
-
-#endif
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Robin Burchell <robin+git@viroteck.net>
- * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
- * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
- * Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.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/>.
- */
-
-
-#ifndef INSPIRCD_HASHMAP_H
-#define INSPIRCD_HASHMAP_H
-
- /** Where hash_map is varies from compiler to compiler
- * as it is not standard unless we have tr1.
- *
- * TODO: in 2.2 if we drop support for libstdc++ older than 3.4.7 and GCC older
- * than 4.1 this can be cleaned up massively.
- */
- #ifndef _WIN32
- #if __GLIBCXX__ > 20060309
- // GCC4+ has deprecated hash_map and uses tr1. But of course, uses a different include to MSVC. FOR FUCKS SAKE.
- #include <tr1/unordered_map>
- #define HAS_TR1_UNORDERED
- #define HASHMAP_DEPRECATED
- #else
- #include <ext/hash_map>
- /** Oddball linux namespace for hash_map */
- #define nspace __gnu_cxx
- #define BEGIN_HASHMAP_NAMESPACE namespace nspace {
- #define END_HASHMAP_NAMESPACE }
- #endif
- #else
- #include <unordered_map>
- #define HAS_TR1_UNORDERED
- #define HASHMAP_DEPRECATED
- #endif
-
- // tr1: restoring sanity to our headers. now if only compiler vendors could agree on a FUCKING INCLUDE FILE.
- #ifdef HAS_TR1_UNORDERED
- #define hash_map unordered_map
- #define nspace std::tr1
- #define BEGIN_HASHMAP_NAMESPACE namespace std { namespace tr1 {
- #define END_HASHMAP_NAMESPACE } }
- #endif
-
-#endif
*/
-#ifndef HASHCOMP_H
-#define HASHCOMP_H
+#pragma once
#include <cstring>
#include <string>
#include <deque>
#include <map>
#include <set>
-#include "hash_map.h"
+#include "inspircd.h"
/*******************************************************
* This file contains classes and templates that deal
bool operator()(const std::string& s1, const std::string& s2) const;
};
+ struct insensitive
+ {
+ size_t CoreExport operator()(const std::string &s) const;
+ };
+
/** The irc_char_traits class is used for RFC-style comparison of strings.
* This class is used to implement irc::string, a case-insensitive, RFC-
* comparing string class.
static CoreExport const char* find(const char* s1, int n, char c);
};
- /** Compose a hex string from raw data.
- * @param raw The raw data to compose hex from
- * @param rawsz The size of the raw data buffer
- * @return The hex string.
- */
- CoreExport std::string hex(const unsigned char *raw, size_t rawsz);
-
/** This typedef declares irc::string based upon irc_char_traits.
*/
typedef std::basic_string<char, irc_char_traits, std::allocator<char> > string;
/** irc::stringjoiner joins string lists into a string, using
- * the given seperator string.
+ * the given separator string.
* This class can join a vector of std::string, a deque of
* std::string, or a const char* const* array, using overloaded
* constructors.
public:
/** Join elements of a vector, between (and including) begin and end
- * @param seperator The string to seperate values with
- * @param sequence One or more items to seperate
- * @param begin The starting element in the sequence to be joined
- * @param end The ending element in the sequence to be joined
- */
- stringjoiner(const std::string &seperator, const std::vector<std::string> &sequence, int begin, int end);
-
- /** Join elements of a deque, between (and including) begin and end
- * @param seperator The string to seperate values with
- * @param sequence One or more items to seperate
- * @param begin The starting element in the sequence to be joined
- * @param end The ending element in the sequence to be joined
- */
- stringjoiner(const std::string &seperator, const std::deque<std::string> &sequence, int begin, int end);
-
- /** Join elements of an array of char arrays, between (and including) begin and end
- * @param seperator The string to seperate values with
+ * @param separator The string to seperate values with
* @param sequence One or more items to seperate
* @param begin The starting element in the sequence to be joined
* @param end The ending element in the sequence to be joined
*/
- stringjoiner(const std::string &seperator, const char* const* sequence, int begin, int end);
+ stringjoiner(const std::string& separator, const std::vector<std::string>& sequence, unsigned int begin, unsigned int end);
/** Get the joined sequence
- * @return A reference to the joined string
+ * @return A constant reference to the joined string
*/
- std::string& GetJoined();
+ const std::string& GetJoined() const { return joined; }
};
/** irc::modestacker stacks mode sequences into a list.
*/
int GetStackedLine(std::vector<std::string> &result, int max_line_size = 360);
- /** deprecated compatability interface - TODO remove */
- int GetStackedLine(std::deque<std::string> &result, int max_line_size = 360) {
- std::vector<std::string> r;
- int n = GetStackedLine(r, max_line_size);
- result.clear();
- result.insert(result.end(), r.begin(), r.end());
- return n;
- }
- };
-
- /** irc::tokenstream reads a string formatted as per RFC1459 and RFC2812.
- * It will split the string into 'tokens' each containing one parameter
- * from the string.
- * For instance, if it is instantiated with the string:
- * "PRIVMSG #test :foo bar baz qux"
- * then each successive call to tokenstream::GetToken() will return
- * "PRIVMSG", "#test", "foo bar baz qux", "".
- * Note that if the whole string starts with a colon this is not taken
- * to mean the string is all one parameter, and the first item in the
- * list will be ":item". This is to allow for parsing 'source' fields
- * from data.
- */
- class CoreExport tokenstream
- {
- private:
-
- /** Original string
- */
- std::string tokens;
-
- /** Last position of a seperator token
- */
- std::string::iterator last_starting_position;
-
- /** Current string position
- */
- std::string::iterator n;
-
- /** True if the last value was an ending value
- */
- bool last_pushed;
- public:
-
- /** Create a tokenstream and fill it with the provided data
- */
- tokenstream(const std::string &source);
-
- /** Destructor
- */
- ~tokenstream();
-
- /** Fetch the next token from the stream as a std::string
- * @param token The next token available, or an empty string if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(std::string &token);
-
- /** Fetch the next token from the stream as an irc::string
- * @param token The next token available, or an empty string if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(irc::string &token);
-
- /** Fetch the next token from the stream as an integer
- * @param token The next token available, or undefined if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(int &token);
-
- /** Fetch the next token from the stream as a long integer
- * @param token The next token available, or undefined if none remain
- * @return True if tokens are left to be read, false if the last token was just retrieved.
- */
- bool GetToken(long &token);
};
/** irc::sepstream allows for splitting token seperated lists.
*/
class CoreExport sepstream
{
- private:
+ protected:
/** Original string.
*/
std::string tokens;
- /** Last position of a seperator token
+ /** Separator value
*/
- std::string::iterator last_starting_position;
+ char sep;
/** Current string position
*/
- std::string::iterator n;
- /** Seperator value
+ size_t pos;
+ /** If set then GetToken() can return an empty string
*/
- char sep;
+ bool allow_empty;
public:
/** Create a sepstream and fill it with the provided data
*/
- sepstream(const std::string &source, char seperator);
-
- /** Destructor
- */
- virtual ~sepstream();
+ sepstream(const std::string &source, char separator, bool allowempty = false);
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
*/
- virtual bool GetToken(std::string &token);
+ bool GetToken(std::string& token);
/** Fetch the entire remaining stream, without tokenizing
* @return The remaining part of the stream
*/
- virtual const std::string GetRemaining();
+ const std::string GetRemaining();
/** Returns true if the end of the stream has been reached
* @return True if the end of the stream has been reached, otherwise false
*/
- virtual bool StreamEnd();
+ bool StreamEnd();
};
/** A derived form of sepstream, which seperates on commas
class CoreExport commasepstream : public sepstream
{
public:
- /** Initialize with comma seperator
+ /** Initialize with comma separator
*/
- commasepstream(const std::string &source) : sepstream(source, ',')
+ commasepstream(const std::string &source, bool allowempty = false) : sepstream(source, ',', allowempty)
{
}
};
class CoreExport spacesepstream : public sepstream
{
public:
- /** Initialize with space seperator
+ /** Initialize with space separator
*/
- spacesepstream(const std::string &source) : sepstream(source, ' ')
+ spacesepstream(const std::string &source, bool allowempty = false) : sepstream(source, ' ', allowempty)
{
}
};
+ /** irc::tokenstream reads a string formatted as per RFC1459 and RFC2812.
+ * It will split the string into 'tokens' each containing one parameter
+ * from the string.
+ * For instance, if it is instantiated with the string:
+ * "PRIVMSG #test :foo bar baz qux"
+ * then each successive call to tokenstream::GetToken() will return
+ * "PRIVMSG", "#test", "foo bar baz qux", "".
+ * Note that if the whole string starts with a colon this is not taken
+ * to mean the string is all one parameter, and the first item in the
+ * list will be ":item". This is to allow for parsing 'source' fields
+ * from data.
+ */
+ class CoreExport tokenstream : private spacesepstream
+ {
+ public:
+ /** Create a tokenstream and fill it with the provided data
+ */
+ tokenstream(const std::string &source);
+
+ /** Fetch the next token from the stream as a std::string
+ * @param token The next token available, or an empty string if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(std::string &token);
+
+ /** Fetch the next token from the stream as an irc::string
+ * @param token The next token available, or an empty string if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(irc::string &token);
+
+ /** Fetch the next token from the stream as an integer
+ * @param token The next token available, or undefined if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(int &token);
+
+ /** Fetch the next token from the stream as a long integer
+ * @param token The next token available, or undefined if none remain
+ * @return True if tokens are left to be read, false if the last token was just retrieved.
+ */
+ bool GetToken(long &token);
+ };
+
/** The portparser class seperates out a port range into integers.
* A port range may be specified in the input string in the form
* "6660,6661,6662-6669,7020". The end of the stream is indicated by
long GetToken();
};
- /** Turn _ characters in a string into spaces
- * @param n String to translate
- * @return The new value with _ translated to space.
- */
- CoreExport const char* Spacify(const char* n);
-
struct hash
{
/** Hash an irc::string using RFC1459 case sensitivity rules
return str;
}
-
-/** Hashing stuff is totally different on vc++'s hash_map implementation, so to save a buttload of
- * \#ifdefs we'll just do it all at once. Except, of course, with TR1, when it's the same as GCC.
- */
-BEGIN_HASHMAP_NAMESPACE
-
- /** Hashing function to hash irc::string
- */
-#if defined(_WIN32) && !defined(HAS_TR1_UNORDERED)
- template<> class CoreExport hash_compare<irc::string, std::less<irc::string> >
- {
- public:
- enum { bucket_size = 4, min_buckets = 8 }; /* Got these numbers from the CRT source, if anyone wants to change them feel free. */
-
- /** Compare two irc::string values for hashing in hash_map
- */
- bool operator()(const irc::string & s1, const irc::string & s2) const
- {
- if(s1.length() != s2.length()) return true;
- return (irc::irc_char_traits::compare(s1.c_str(), s2.c_str(), (size_t)s1.length()) < 0);
- }
-
- /** Hash an irc::string value for hash_map
- */
- size_t operator()(const irc::string & s) const;
- };
-
- template<> class CoreExport hash_compare<std::string, std::less<std::string> >
- {
- public:
- enum { bucket_size = 4, min_buckets = 8 }; /* Again, from the CRT source */
-
- /** Compare two std::string values for hashing in hash_map
- */
- bool operator()(const std::string & s1, const std::string & s2) const
- {
- if(s1.length() != s2.length()) return true;
- return (irc::irc_char_traits::compare(s1.c_str(), s2.c_str(), (size_t)s1.length()) < 0);
- }
-
- /** Hash a std::string using RFC1459 case sensitivity rules
- * @param s A string to hash
- * @return The hash value
- */
- size_t operator()(const std::string & s) const;
- };
-#else
-
- /* XXX FIXME: Implement a hash function overriding std::string's that works with TR1! */
-
-#ifdef HASHMAP_DEPRECATED
- struct insensitive
-#else
- CoreExport template<> struct hash<std::string>
-#endif
- {
- size_t CoreExport operator()(const std::string &s) const;
- };
-
-#endif
-
- /** Convert a string to lower case respecting RFC1459
- * @param n A string to lowercase
- */
- void strlower(char *n);
-
-END_HASHMAP_NAMESPACE
-
-#endif
*/
-#ifndef INSPIRCD_H
-#define INSPIRCD_H
+#pragma once
-#define _FILE_OFFSET_BITS 64
-#ifndef _LARGEFILE_SOURCE
-#define _LARGEFILE_SOURCE
-#endif
-
-#ifndef _WIN32
-#define DllExport
-#define CoreExport
-#else
-#include "inspircd_win32wrapper.h"
-/** Windows defines these already */
-#undef ERROR
-#endif
-
-#ifdef __GNUC__
-#define CUSTOM_PRINTF(STRING, FIRST) __attribute__((format(printf, STRING, FIRST)))
-#else
-#define CUSTOM_PRINTF(STRING, FIRST)
-#endif
-
-// Required system headers.
-#include <ctime>
-#include <cstdarg>
-#include <algorithm>
-#include <cmath>
-#include <cstring>
#include <climits>
+#include <cmath>
+#include <csignal>
+#include <cstdarg>
#include <cstdio>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
+#include <cstring>
+#include <ctime>
-#include <sstream>
-#include <string>
-#include <vector>
-#include <list>
+#include <algorithm>
+#include <bitset>
#include <deque>
+#include <list>
#include <map>
-#include <bitset>
#include <set>
-#include <time.h>
-#include "inspircd_config.h"
-#include "inspircd_version.h"
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "compat.h"
#include "typedefs.h"
-#include "consolecolors.h"
CoreExport extern InspIRCd* ServerInstance;
+#include "config.h"
+#include "consolecolors.h"
#include "caller.h"
#include "cull_list.h"
#include "extensible.h"
#include "inspstring.h"
#include "protocol.h"
-#ifndef PATH_MAX
-#warning Potentially broken system, PATH_MAX undefined
-#define PATH_MAX 4096
-#endif
-
-/**
- * Used to define the maximum number of parameters a command may have.
- */
-#define MAXPARAMETERS 127
-
/** Returned by some functions to indicate failure.
*/
#define ERROR -1
-/** Support for librodent -
- * see http://www.chatspike.net/index.php?z=64
- */
-#define ETIREDHAMSTERS EAGAIN
-
/** Template function to convert any input type to std::string
*/
template<typename T> inline std::string ConvNumeric(const T &in)
}
};
-DEFINE_HANDLER2(IsNickHandler, bool, const char*, size_t);
+/** This class manages the generation and transmission of ISUPPORT. */
+class CoreExport ISupportManager
+{
+private:
+ /** The generated lines which are sent to clients. */
+ std::vector<std::string> Lines;
+
+public:
+ /** (Re)build the ISUPPORT vector. */
+ void Build();
+
+ /** Returns the std::vector of ISUPPORT lines. */
+ const std::vector<std::string>& GetLines()
+ {
+ return this->Lines;
+ }
+
+ /** Send the 005 numerics (ISUPPORT) to a user. */
+ void SendTo(LocalUser* user);
+};
+
+DEFINE_HANDLER1(IsNickHandler, bool, const std::string&);
DEFINE_HANDLER2(GenRandomHandler, void, char*, size_t);
-DEFINE_HANDLER1(IsIdentHandler, bool, const char*);
-DEFINE_HANDLER1(FloodQuitUserHandler, void, User*);
-DEFINE_HANDLER2(IsChannelHandler, bool, const char*, size_t);
-DEFINE_HANDLER1(IsSIDHandler, bool, const std::string&);
+DEFINE_HANDLER1(IsIdentHandler, bool, const std::string&);
+DEFINE_HANDLER1(IsChannelHandler, bool, const std::string&);
DEFINE_HANDLER1(RehashHandler, void, const std::string&);
DEFINE_HANDLER3(OnCheckExemptionHandler, ModResult, User*, Channel*, const std::string&);
-class TestSuite;
-
/** The main class of the irc server.
* This class contains instances of all the other classes in this software.
* Amongst other things, it contains a ModeParser, a DNS object, a CommandParser
class CoreExport InspIRCd
{
private:
- /** Holds the current UID. Used to generate the next one.
- */
- char current_uid[UUID_LENGTH];
-
/** Set up the signal handlers
*/
void SetSignals();
*/
void DoSocketTimeouts(time_t TIME);
- /** Increments the current UID by one.
- */
- void IncrementUID(int pos);
-
/** Perform background user events such as PING checks
*/
void DoBackgroundUserStuff();
public:
+ UIDGenerator UIDGen;
+
/** Global cull list, will be processed on next iteration
*/
CullList GlobalCulls;
IsNickHandler HandleIsNick;
IsIdentHandler HandleIsIdent;
- FloodQuitUserHandler HandleFloodQuitUser;
OnCheckExemptionHandler HandleOnCheckExemption;
IsChannelHandler HandleIsChannel;
- IsSIDHandler HandleIsSID;
RehashHandler HandleRehash;
GenRandomHandler HandleGenRandom;
*/
FakeUser* FakeClient;
- /** Returns the next available UID for this server.
- */
- std::string GetUID();
-
- static const char LogHeader[];
-
/** Find a user in the UUID hash
* @param uid The UUID to find
* @return A pointer to the user, or NULL if the user does not exist
*/
User* FindUUID(const std::string &uid);
- /** Find a user in the UUID hash
- * @param uid The UUID to find
- * @return A pointer to the user, or NULL if the user does not exist
- */
- User* FindUUID(const char *uid);
-
- /** Build the ISUPPORT string by triggering all modules On005Numeric events
- */
- void BuildISupport();
-
/** Time this ircd was booted
*/
time_t startup_time;
*/
SnomaskManager* SNO;
- /** DNS class, provides resolver facilities to the core and modules
- */
- DNS* Res;
-
/** Timer manager class, triggers Timer timer events
*/
TimerManager* Timers;
/** Set to the current signal recieved
*/
- int s_signal;
+ static sig_atomic_t s_signal;
/** Protocol interface, overridden by server protocol modules
*/
ProtocolInterface* PI;
- /** Holds extensible for user nickforced
- */
- LocalIntExt NICKForced;
-
/** Holds extensible for user operquit
*/
LocalStringExt OperQuit;
+ /** Manages the generation and transmission of ISUPPORT. */
+ ISupportManager ISupport;
+
/** Get the current time
* Because this only calls time() once every time around the mainloop,
* it is much faster than calling time() directly.
*/
User* FindNick(const std::string &nick);
- /** Find a user in the nick hash.
- * If the user cant be found in the nick hash check the uuid hash
- * @param nick The nickname to find
- * @return A pointer to the user, or NULL if the user does not exist
- */
- User* FindNick(const char* nick);
-
- /** Find a user in the nick hash ONLY
- */
- User* FindNickOnly(const char* nick);
-
/** Find a user in the nick hash ONLY
*/
User* FindNickOnly(const std::string &nick);
*/
Channel* FindChan(const std::string &chan);
- /** Find a channel in the channels hash
- * @param chan The channel to find
- * @return A pointer to the channel, or NULL if the channel does not exist
- */
- Channel* FindChan(const char* chan);
-
/** Check we aren't running as root, and exit if we are
* @return Depending on the configuration, this function may never return
*/
void CheckRoot();
- /** Determine the right path for, and open, the logfile
- * @param argv The argv passed to main() initially, used to calculate program path
- * @param argc The argc passed to main() initially, used to calculate program path
- * @return True if the log could be opened, false if otherwise
- */
- bool OpenLog(char** argv, int argc);
-
/** Return true if a channel name is valid
* @param chname A channel name to verify
* @return True if the name is valid
*/
- caller2<bool, const char*, size_t> IsChannel;
+ caller1<bool, const std::string&> IsChannel;
/** Return true if str looks like a server ID
* @param string to check against
*/
- caller1<bool, const std::string&> IsSID;
+ static bool IsSID(const std::string& sid);
/** Rehash the local server
*/
/** Causes the server to exit immediately with exit code 0.
* The status code is required for signal handlers, and ignored.
*/
+
+ /** Printf-wrapper.
+ * @param How you want it formatted
+ * @param ...
+ * @return The formatted string
+ */
+ static const char* Format(const char* formatString, ...) CUSTOM_PRINTF(1, 2);
+ static const char* Format(va_list &vaList, const char* formatString) CUSTOM_PRINTF(2, 0);
+
static void QuickExit(int status);
/** Return a count of channels on the network
* @return The number of channels
*/
- long ChannelCount();
+ long ChannelCount() const { return chanlist->size(); }
/** Send an error notice to all local users, opered and unopered
* @param s The error string to send
* @param n A nickname to verify
* @return True if the nick is valid
*/
- caller2<bool, const char*, size_t> IsNick;
+ caller1<bool, const std::string&> IsNick;
/** Return true if an ident is valid
* @param An ident to verify
* @return True if the ident is valid
*/
- caller1<bool, const char*> IsIdent;
-
- /** Add a dns Resolver class to this server's active set
- * @param r The resolver to add
- * @param cached If this value is true, then the cache will
- * be searched for the DNS result, immediately. If the value is
- * false, then a request will be sent to the nameserver, and the
- * result will not be immediately available. You should usually
- * use the boolean value which you passed to the Resolver
- * constructor, which Resolver will set appropriately depending
- * on if cached results are available and haven't expired. It is
- * however safe to force this value to false, forcing a remote DNS
- * lookup, but not an update of the cache.
- * @return True if the operation completed successfully. Note that
- * if this method returns true, you should not attempt to access
- * the resolver class you pass it after this call, as depending upon
- * the request given, the object may be deleted!
- */
- bool AddResolver(Resolver* r, bool cached);
+ caller1<bool, const std::string&> IsIdent;
/** Add a command to this server's command parser
* @param f A Command command handler object to add
* @param map The character map to use when matching.
*/
static bool Match(const std::string &str, const std::string &mask, unsigned const char *map = NULL);
- static bool Match(const char *str, const char *mask, unsigned const char *map = NULL);
+ static bool Match(const char *str, const char *mask, unsigned const char *map = NULL);
/** Match two strings using pattern matching, optionally, with a map
* to check case against (may be NULL). If map is null, match will be case insensitive.
* @param map The character map to use when matching.
*/
static bool MatchCIDR(const std::string &str, const std::string &mask, unsigned const char *map = NULL);
- static bool MatchCIDR(const char *str, const char *mask, unsigned const char *map = NULL);
-
- /** Call the handler for a given command.
- * @param commandname The command whos handler you wish to call
- * @param parameters The mode parameters
- * @param user The user to execute the command as
- * @return True if the command handler was called successfully
- */
- CmdResult CallCommandHandler(const std::string &commandname, const std::vector<std::string>& parameters, User* user);
+ static bool MatchCIDR(const char *str, const char *mask, unsigned const char *map = NULL);
- /** Return true if the command is a module-implemented command and the given parameters are valid for it
- * @param commandname The command name to check
- * @param pcnt The parameter count
- * @param user The user to test-execute the command as
- * @return True if the command handler is a module command, and there are enough parameters and the user has permission to the command
+ /** Matches a hostname and IP against a space delimited list of hostmasks.
+ * @param masks The space delimited masks to match against.
+ * @param hostname The hostname to try and match.
+ * @param ipaddr The IP address to try and match.
*/
- bool IsValidModuleCommand(const std::string &commandname, int pcnt, User* user);
+ static bool MatchMask(const std::string& masks, const std::string& hostname, const std::string& ipaddr);
/** Return true if the given parameter is a valid nick!user\@host mask
* @param mask A nick!user\@host masak to match against
* (one year, two weeks, three days, four hours, six minutes and five seconds)
* @return The total number of seconds
*/
- long Duration(const std::string &str);
+ static unsigned long Duration(const std::string& str);
/** Attempt to compare a password to a string from the config file.
* This will be passed to handling modules which will compare the data
/** Returns the full version string of this ircd
* @return The version string
*/
- std::string GetVersionString(bool rawversion = false);
+ std::string GetVersionString(bool getFullVersion = false);
/** Attempt to write the process id to a given file
* @param filename The PID file to attempt to write to
*/
void SendWhoisLine(User* user, User* dest, int numeric, const char* format, ...) CUSTOM_PRINTF(5, 6);
- /** Handle /WHOIS
- */
- void DoWhois(User* user, User* dest,unsigned long signon, unsigned long idle, const char* nick);
-
- /** Quit a user for excess flood, and if they are not
- * fully registered yet, temporarily zline their IP.
- * @param current user to quit
- */
- caller1<void, User*> FloodQuitUser;
-
/** Called to check whether a channel restriction mode applies to a user
* @param User that is attempting some action
* @param Channel that the action is being performed on
*/
void Cleanup();
- /** This copies the user and channel hash_maps into new hash maps.
- * This frees memory used by the hash_map allocator (which it neglects
- * to free, most of the time, using tons of ram)
- */
- void RehashUsersAndChans();
-
- /** Resets the cached max bans value on all channels.
- * Called by rehash.
- */
- void ResetMaxBans();
-
/** Return a time_t as a human-readable string.
*/
std::string TimeString(time_t curtime);
*/
int Run();
- /** Adds an extban char to the 005 token.
- */
- void AddExtBanChar(char c);
-
char* GetReadBuffer()
{
return this->ReadBuffer;
}
-
- friend class TestSuite;
};
ENTRYPOINT;
}
};
-#endif
+inline void InspIRCd::SendMode(const std::vector<std::string>& parameters, User* user)
+{
+ this->Modes->Process(parameters, user);
+}
*/
-#ifndef INSPSOCKET_H
-#define INSPSOCKET_H
+#pragma once
#include "timer.h"
/** Handle tick event
*/
- virtual void Tick(time_t now);
+ virtual bool Tick(time_t now);
};
/**
inline Module* StreamSocket::GetIOHook() { return IOHook; }
inline void StreamSocket::AddIOHook(Module* m) { IOHook = m; }
inline void StreamSocket::DelIOHook() { IOHook = NULL; }
-#endif
*/
-#ifndef INSPSTRING_H
-#define INSPSTRING_H
+#pragma once
-// This (inspircd_config) is needed as inspstring doesn't pull in the central header
-#include "inspircd_config.h"
+// This (config) is needed as inspstring doesn't pull in the central header
+#include "config.h"
#include <cstring>
-//#include <cstddef>
-#ifndef HAS_STRLCPY
-/** strlcpy() implementation for systems that don't have it (linux) */
-CoreExport size_t strlcpy(char *dst, const char *src, size_t siz);
-/** strlcat() implementation for systems that don't have it (linux) */
-CoreExport size_t strlcat(char *dst, const char *src, size_t siz);
-#endif
-
-/** charlcat() will append one character to a string using the same
- * safety scemantics as strlcat().
- * @param x The string to operate on
- * @param y the character to append to the end of x
- * @param z The maximum allowed length for z including null terminator
- */
-CoreExport int charlcat(char* x,char y,int z);
-/** charremove() will remove all instances of a character from a string
- * @param mp The string to operate on
- * @param remove The character to remove
+/** Sets ret to the formated string. last is the last parameter before ..., and format is the format in printf-style */
+#define VAFORMAT(ret, last, format) \
+ do { \
+ va_list _vaList; \
+ va_start(_vaList, last); \
+ ret = InspIRCd::Format(_vaList, format); \
+ va_end(_vaList); \
+ } while (false);
+
+/** Compose a hex string from raw data.
+ * @param raw The raw data to compose hex from (can be NULL if rawsize is 0)
+ * @param rawsize The size of the raw data buffer
+ * @return The hex string
*/
-CoreExport bool charremove(char* mp, char remove);
+CoreExport std::string BinToHex(const void* raw, size_t rawsize);
-/** Binary to hexadecimal conversion */
-CoreExport std::string BinToHex(const std::string& data);
/** Base64 encode */
CoreExport std::string BinToBase64(const std::string& data, const char* table = NULL, char pad = 0);
/** Base64 decode */
CoreExport std::string Base64ToBin(const std::string& data, const char* table = NULL);
-#endif
-
+/** Compose a hex string from the data in a std::string.
+ * @param data The data to compose hex from
+ * @return The hex string.
+ */
+inline std::string BinToHex(const std::string& data)
+{
+ return BinToHex(data.data(), data.size());
+}
--- /dev/null
+/*
+ * 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
+ * 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/>.
+ */
+
+
+#pragma once
+
+/** The base class for list modes, should be inherited.
+ */
+class CoreExport ListModeBase : public ModeHandler
+{
+ public:
+ /** An item in a listmode's list
+ */
+ struct ListItem
+ {
+ std::string setter;
+ std::string mask;
+ time_t time;
+ ListItem(const std::string& Mask, const std::string& Setter, time_t Time)
+ : setter(Setter), mask(Mask), time(Time) { }
+ };
+
+ /** Items stored in the channel's list
+ */
+ typedef std::list<ListItem> ModeList;
+
+ private:
+ class ChanData
+ {
+ public:
+ ModeList list;
+ int maxitems;
+
+ ChanData() : maxitems(-1) { }
+ };
+
+ /** The number of items a listmode's list may contain
+ */
+ struct ListLimit
+ {
+ std::string mask;
+ unsigned int limit;
+ ListLimit(const std::string& Mask, unsigned int Limit) : mask(Mask), limit(Limit) { }
+ bool operator==(const ListLimit& other) const { return (this->mask == other.mask && this->limit == other.limit); }
+ };
+
+ /** Max items per channel by name
+ */
+ typedef std::vector<ListLimit> limitlist;
+
+ /** Finds the limit of modes that can be placed on the given channel name according to the config
+ * @param channame The channel name to find the limit for
+ * @return The maximum number of modes of this type that we allow to be set on the given channel name
+ */
+ unsigned int FindLimit(const std::string& channame);
+
+ /** Returns the limit on the given channel for this mode.
+ * If the limit is cached then the cached value is returned,
+ * otherwise the limit is determined using FindLimit() and cached
+ * for later queries before it is returned
+ * @param channame The channel name to find the limit for
+ * @param cd The ChanData associated with channel channame
+ * @return The maximum number of modes of this type that we allow to be set on the given channel
+ */
+ unsigned int GetLimitInternal(const std::string& channame, ChanData* cd);
+
+ protected:
+ /** Numeric to use when outputting the list
+ */
+ unsigned int listnumeric;
+ /** Numeric to indicate end of list
+ */
+ unsigned int endoflistnumeric;
+ /** String to send for end of list
+ */
+ std::string endofliststring;
+ /** Automatically tidy up entries
+ */
+ bool tidy;
+ /** Config tag to check for max items per channel
+ */
+ std::string configtag;
+ /** Limits on a per-channel basis read from the tag
+ * specified in ListModeBase::configtag
+ */
+ limitlist chanlimits;
+
+ /** Storage key
+ */
+ SimpleExtItem<ChanData> extItem;
+
+ public:
+ /** Constructor.
+ * @param Instance The creator of this class
+ * @param modechar Mode character
+ * @param eolstr End of list string
+ * @param lnum List numeric
+ * @param eolnum End of list numeric
+ * @param autotidy Automatically tidy list entries on add
+ * @param ctag Configuration tag to get limits from
+ */
+ ListModeBase(Module* Creator, const std::string& Name, char modechar, const std::string &eolstr, unsigned int lnum, unsigned int eolnum, bool autotidy, const std::string &ctag = "banlist");
+
+ /** Get limit of this mode on a channel
+ * @param channel The channel to inspect
+ * @return Maximum number of modes of this type that can be placed on the given channel
+ */
+ unsigned int GetLimit(Channel* channel);
+
+ /** Retrieves the list of all modes set on the given channel
+ * @param channel Channel to get the list from
+ * @return A list with all modes of this type set on the given channel, can be NULL
+ */
+ ModeList* GetList(Channel* channel);
+
+ /** Display the list for this mode
+ * See mode.h
+ * @param user The user to send the list to
+ * @param channel The channel the user is requesting the list for
+ */
+ virtual void DisplayList(User* user, Channel* channel);
+
+ /** Tell a user that a list contains no elements.
+ * Sends 'eolnum' numeric with text 'eolstr', unless overridden (see constructor)
+ * @param user The user issuing the command
+ * @param channel The channel that has the empty list
+ * See mode.h
+ */
+ virtual void DisplayEmptyList(User* user, Channel* channel);
+
+ /** Remove all instances of the mode from a channel.
+ * Populates the given modestack with modes that remove every instance of
+ * this mode from the channel.
+ * See mode.h for more details.
+ * @param channel The channel to remove all instances of the mode from
+ * @param stack The mode stack to add the mode change to
+ */
+ virtual void RemoveMode(Channel* channel, irc::modestacker& stack);
+
+ /** Perform a rehash of this mode's configuration data
+ */
+ virtual void DoRehash();
+
+ /** Populate the Implements list with the correct events for a List Mode
+ */
+ virtual void DoImplements(Module* m);
+
+ /** Handle the list mode.
+ * See mode.h
+ */
+ virtual ModeAction OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding);
+
+ /** Syncronize channel item list with another server.
+ * See modules.h
+ * @param chan Channel to syncronize
+ * @param proto Protocol module pointer
+ * @param opaque Opaque connection handle
+ */
+ virtual void DoSyncChannel(Channel* chan, Module* proto, void* opaque);
+
+ /** Validate parameters.
+ * Overridden by implementing module.
+ * @param source Source user adding the parameter
+ * @param channel Channel the parameter is being added to
+ * @param parameter The actual parameter being added
+ * @return true if the parameter is valid
+ */
+ virtual bool ValidateParam(User* user, Channel* channel, std::string& parameter);
+
+ /** Tell the user the list is too long.
+ * Overridden by implementing module.
+ * @param source Source user adding the parameter
+ * @param channel Channel the parameter is being added to
+ * @param parameter The actual parameter being added
+ */
+ virtual void TellListTooLong(User* source, Channel* channel, std::string& parameter);
+
+ /** Tell the user an item is already on the list.
+ * Overridden by implementing module.
+ * @param source Source user adding the parameter
+ * @param channel Channel the parameter is being added to
+ * @param parameter The actual parameter being added
+ */
+ virtual void TellAlreadyOnList(User* source, Channel* channel, std::string& parameter);
+
+ /** Tell the user that the parameter is not in the list.
+ * Overridden by implementing module.
+ * @param source Source user removing the parameter
+ * @param channel Channel the parameter is being removed from
+ * @param parameter The actual parameter being removed
+ */
+ virtual void TellNotSet(User* source, Channel* channel, std::string& parameter);
+};
+
+inline ListModeBase::ModeList* ListModeBase::GetList(Channel* channel)
+{
+ ChanData* cd = extItem.get(channel);
+ if (!cd)
+ return NULL;
+
+ return &cd->list;
+}
*/
-#ifndef LOGGER_H
-#define LOGGER_H
+#pragma once
+
+/** Levels at which messages can be logged. */
+enum LogLevel
+{
+ LOG_RAWIO = 5,
+ LOG_DEBUG = 10,
+ LOG_VERBOSE = 20,
+ LOG_DEFAULT = 30,
+ LOG_SPARSE = 40,
+ LOG_NONE = 50
+};
/** Simple wrapper providing periodic flushing to a disk-backed file.
*/
class CoreExport LogStream : public classbase
{
protected:
- int loglvl;
+ LogLevel loglvl;
public:
- LogStream(int loglevel) : loglvl(loglevel)
+ static const char LogHeader[];
+
+ LogStream(LogLevel loglevel) : loglvl(loglevel)
{
}
/** Changes the loglevel for this LogStream on-the-fly.
* This is needed for -nofork. But other LogStreams could use it to change loglevels.
*/
- void ChangeLevel(int lvl) { this->loglvl = lvl; }
+ void ChangeLevel(LogLevel lvl) { this->loglvl = lvl; }
/** Called when there is stuff to log for this particular logstream. The derived class may take no action with it, or do what it
* wants with the output, basically. loglevel and type are primarily for informational purposes (the level and type of the event triggered)
* and msg is, of course, the actual message to log.
*/
- virtual void OnLog(int loglevel, const std::string &type, const std::string &msg) = 0;
+ virtual void OnLog(LogLevel loglevel, const std::string &type, const std::string &msg) = 0;
};
typedef std::map<FileWriter*, int> FileLogMap;
FileLogMap FileLogs;
public:
-
LogManager();
~LogManager();
/** Logs an event, sending it to all LogStreams registered for the type.
* @param type Log message type (ex: "USERINPUT", "MODULE", ...)
- * @param loglevel Log message level (DEBUG, VERBOSE, DEFAULT, SPARSE, NONE)
+ * @param loglevel Log message level (LOG_DEBUG, LOG_VERBOSE, LOG_DEFAULT, LOG_SPARSE, LOG_NONE)
* @param msg The message to be logged (literal).
*/
- void Log(const std::string &type, int loglevel, const std::string &msg);
+ void Log(const std::string &type, LogLevel loglevel, const std::string &msg);
/** Logs an event, sending it to all LogStreams registered for the type.
* @param type Log message type (ex: "USERINPUT", "MODULE", ...)
- * @param loglevel Log message level (DEBUG, VERBOSE, DEFAULT, SPARSE, NONE)
+ * @param loglevel Log message level (LOG_DEBUG, LOG_VERBOSE, LOG_DEFAULT, LOG_SPARSE, LOG_NONE)
* @param fmt The format of the message to be logged. See your C manual on printf() for details.
*/
- void Log(const std::string &type, int loglevel, const char *fmt, ...) CUSTOM_PRINTF(4, 5);
+ void Log(const std::string &type, LogLevel loglevel, const char *fmt, ...) CUSTOM_PRINTF(4, 5);
};
-
-#endif
*/
-#ifndef MEMBERSHIP_H
-#define MEMBERSHIP_H
+#pragma once
class CoreExport Membership : public Extensible
{
friend class Invitation;
};
-class Invitation : public classbase
+class CoreExport Invitation : public classbase
{
Invitation(Channel* c, LocalUser* u, time_t timeout) : user(u), chan(c), expiry(timeout) {}
static void Create(Channel* c, LocalUser* u, time_t timeout);
static Invitation* Find(Channel* c, LocalUser* u, bool check_expired = true);
};
-
-#endif
*/
-#ifndef MODE_H
-#define MODE_H
+#pragma once
#include "ctables.h"
*/
class CoreExport ModeHandler : public ServiceProvider
{
+ /**
+ * Removes this prefix mode from all users on the given channel
+ * @param channel The channel which the server wants to remove your mode from
+ * @param stack The mode stack to add the mode change to
+ */
+ void RemovePrefixMode(Channel* chan, irc::modestacker& stack);
+
protected:
/**
* The mode parameter translation type
/**
* Returns true if the mode is a list mode
*/
- bool IsListMode();
+ bool IsListMode() const { return list; }
/**
* Mode prefix or 0. If this is defined, you should
* also implement GetPrefixRank() to return an integer
virtual bool ResolveModeConflict(std::string &their_param, const std::string &our_param, Channel* channel);
/**
- * When a MODETYPE_USER mode handler is being removed, the server will call this method for every user on the server.
- * Your mode handler should remove its user mode from the user by sending the appropriate server modes using
- * InspIRCd::SendMode(). The default implementation of this method can remove simple modes which have no parameters,
- * and can be used when your mode is of this type, otherwise you must implement a more advanced version of it to remove
- * your mode properly from each user.
+ * When a MODETYPE_USER mode handler is being removed, the core will call this method for every user on the server.
+ * The usermode will be removed using the appropiate server mode using InspIRCd::SendMode().
* @param user The user which the server wants to remove your mode from
- * @param stack The mode stack to add the mode change to
*/
- virtual void RemoveMode(User* user, irc::modestacker* stack = NULL);
+ void RemoveMode(User* user);
/**
* When a MODETYPE_CHANNEL mode handler is being removed, the server will call this method for every channel on the server.
- * Your mode handler should remove its user mode from the channel by sending the appropriate server modes using
- * InspIRCd::SendMode(). The default implementation of this method can remove simple modes which have no parameters,
- * and can be used when your mode is of this type, otherwise you must implement a more advanced version of it to remove
- * your mode properly from each channel. Note that in the case of listmodes, you should remove the entire list of items.
+ * The mode handler has to populate the given modestacker with mode changes that remove the mode from the channel.
+ * The default implementation of this method can remove all kinds of channel modes except listmodes.
+ * In the case of listmodes, the entire list of items must be added to the modestacker (which is handled by ListModeBase,
+ * so if you inherit from it or your mode can be removed by the default implementation then you do not have to implement
+ * this function).
* @param channel The channel which the server wants to remove your mode from
* @param stack The mode stack to add the mode change to
*/
- virtual void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
+ virtual void RemoveMode(Channel* channel, irc::modestacker& stack);
inline unsigned int GetLevelRequired() const { return levelrequired; }
};
*/
class CoreExport ModeWatcher : public classbase
{
- protected:
+ private:
/**
- * The mode letter this class is watching
+ * The mode name this class is watching
*/
- char mode;
+ const std::string mode;
+
/**
* The mode type being watched (user or channel)
*/
/**
* The constructor initializes the mode and the mode type
*/
- ModeWatcher(Module* creator, char modeletter, ModeType type);
+ ModeWatcher(Module* creator, const std::string& modename, ModeType type);
/**
* The default destructor does nothing.
*/
virtual ~ModeWatcher();
/**
- * Get the mode character being watched
- * @return The mode character being watched
+ * Get the mode name being watched
+ * @return The mode name being watched
*/
- char GetModeChar();
+ const std::string& GetModeName() const { return mode; }
+
/**
* Get the mode type being watched
* @return The mode type being watched (user or channel)
* If you alter the parameter you are given, the mode handler will see your atered version
* when it handles the mode.
* @param adding True if the mode is being added and false if it is being removed
- * @param type The mode type, either MODETYPE_USER or MODETYPE_CHANNEL
* @return True to allow the mode change to go ahead, false to abort it. If you abort the
* change, the mode handler (and ModeWatcher::AfterMode()) will never see the mode change.
*/
- virtual bool BeforeMode(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, ModeType type);
+ virtual bool BeforeMode(User* source, User* dest, Channel* channel, std::string& parameter, bool adding);
/**
* After the mode character has been processed by the ModeHandler, this method will be called.
* @param source The sender of the mode
* @param parameter The parameter of the mode, if the mode is supposed to have a parameter.
* You cannot alter the parameter here, as the mode handler has already processed it.
* @param adding True if the mode is being added and false if it is being removed
- * @param type The mode type, either MODETYPE_USER or MODETYPE_CHANNEL
*/
- virtual void AfterMode(User* source, User* dest, Channel* channel, const std::string ¶meter, bool adding, ModeType type);
+ virtual void AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding);
};
-typedef std::vector<ModeWatcher*>::iterator ModeWatchIter;
+typedef std::multimap<std::string, ModeWatcher*>::iterator ModeWatchIter;
/** The mode parser handles routing of modes and handling of mode strings.
* It marshalls, controls and maintains both ModeWatcher and ModeHandler classes,
* or a channel mode, so we have 256 of them not 64.
*/
ModeHandler* modehandlers[256];
- /** Mode watcher classes arranged in the same way as the
- * mode handlers, except for instead of having 256 of them
- * we have 256 lists of them.
+
+ /** Mode watcher classes
*/
- std::vector<ModeWatcher*> modewatchers[256];
+ std::multimap<std::string, ModeWatcher*> modewatchermap;
+
/** Displays the current modes of a channel or user.
* Used by ModeParser::Process.
*/
*/
ModeAction TryMode(User* user, User* targu, Channel* targc, bool adding, unsigned char mode, std::string ¶m, bool SkipACL);
+ /** Returns a list of user or channel mode characters.
+ * Used for constructing the parts of the mode list in the 004 numeric.
+ * @param mt Controls whether to list user modes or channel modes
+ * @param needparam Return modes only if they require a parameter to be set
+ * @return The available mode letters that satisfy the given conditions
+ */
+ std::string CreateModeList(ModeType mt, bool needparam = false);
+
+ /** Recreate the cached mode list that is displayed in the 004 numeric
+ * in Cached004ModeList.
+ * Called when a mode handler is added or removed.
+ */
+ void RecreateModeListFor004Numeric();
+
/** The string representing the last set of modes to be parsed.
* Use GetLastParse() to get this value, to be used for display purposes.
*/
unsigned int seq;
- public:
-
- /** The constructor initializes all the RFC basic modes by using ModeParserAddMode().
+ /** Cached mode list for use in 004 numeric
*/
+ std::string Cached004ModeList;
+
+ public:
ModeParser();
~ModeParser();
- /** Used to check if user 'd' should be allowed to do operation 'MASK' on channel 'chan'.
- * for example, should 'user A' be able to 'op' on 'channel B'.
+ /** Initialize all built-in modes
*/
- User* SanityChecks(User *user,const char *dest,Channel *chan,int status);
+ static void InitBuiltinModes();
+
/** Tidy a banmask. This makes a banmask 'acceptable' if fields are left out.
* E.g.
*
* may be different to what you sent after it has been 'cleaned up' by the parser.
* @return Last parsed string, as seen by users.
*/
- const std::string& GetLastParse();
+ const std::string& GetLastParse() const { return LastParse; }
const std::vector<std::string>& GetLastParseParams() { return LastParseParams; }
const std::vector<TranslateType>& GetLastParseTranslate() { return LastParseTranslate; }
/** Add a mode to the mode parser.
* triggered. See the documentation of class ModeWatcher for more
* information.
* @param mw The ModeWatcher you want to add
- * @return True if the ModeWatcher was added correctly
*/
- bool AddModeWatcher(ModeWatcher* mw);
+ void AddModeWatcher(ModeWatcher* mw);
+
/** Delete a mode watcher.
* A mode watcher is triggered before and after a mode handler is
* triggered. See the documentation of class ModeWatcher for more
*/
ModeHandler* FindPrefix(unsigned const char pfxletter);
- /** Returns a list of mode characters which are usermodes.
- * This is used in the 004 numeric when users connect.
- */
- std::string UserModeList();
-
- /** Returns a list of channel mode characters which are listmodes.
- * This is used in the 004 numeric when users connect.
+ /** Returns a list of modes, space seperated by type:
+ * 1. User modes
+ * 2. Channel modes
+ * 3. Channel modes that require a parameter when set
+ * This is sent to users as the last part of the 004 numeric
*/
- std::string ChannelModeList();
-
- /** Returns a list of channel mode characters which take parameters.
- * This is used in the 004 numeric when users connect.
- */
- std::string ParaModeList();
+ const std::string& GetModeListFor004Numeric();
/** Generates a list of modes, comma seperated by type:
* 1; Listmodes EXCEPT those with a prefix
*/
std::string GiveModeList(ModeMasks m);
- static bool PrefixComparison(ModeHandler* one, ModeHandler* two);
-
/** This returns the PREFIX=(ohv)@%+ section of the 005 numeric, or
* just the "@%+" part if the parameter false
*/
std::string BuildPrefixes(bool lettersAndModes = true);
};
-#endif
+inline const std::string& ModeParser::GetModeListFor004Numeric()
+{
+ return Cached004ModeList;
+}
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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 "mode.h"
-#include "channels.h"
-
-class InspIRCd;
-
-/** Channel mode +b
- */
-class ModeChannelBan : public ModeHandler
-{
- private:
- BanItem b;
- public:
- ModeChannelBan();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
- std::string& AddBan(User *user,std::string& dest,Channel *chan,int status);
- std::string& DelBan(User *user,std::string& dest,Channel *chan,int status);
- void DisplayList(User* user, Channel* channel);
- void DisplayEmptyList(User* user, Channel* channel);
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
-};
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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 "mode.h"
-
-class InspIRCd;
-
-/** Channel mode +k
- */
-class ModeChannelKey : public ModeHandler
-{
- public:
- ModeChannelKey();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
-};
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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 "mode.h"
-
-/** Channel mode +l
- */
-class ModeChannelLimit : public ParamChannelModeHandler
-{
- public:
- ModeChannelLimit();
- bool ParamValidate(std::string& parameter);
- bool ResolveModeConflict(std::string &their_param, const std::string &our_param, Channel* channel);
-};
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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 "mode.h"
-#include "channels.h"
-
-class InspIRCd;
-
-/** Channel mode +o
- */
-class ModeChannelOp : public ModeHandler
-{
- private:
- public:
- ModeChannelOp();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
- unsigned int GetPrefixRank();
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
-};
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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 "mode.h"
-#include "channels.h"
-
-class InspIRCd;
-
-/** Channel mode +v
- */
-class ModeChannelVoice : public ModeHandler
-{
- private:
- public:
- ModeChannelVoice();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
- unsigned int GetPrefixRank();
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
-};
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
- * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
- *
- * 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 "mode.h"
-
-/** Channel mode +i
- */
-class ModeChannelInviteOnly : public SimpleChannelModeHandler
-{
- public:
- ModeChannelInviteOnly() : SimpleChannelModeHandler(NULL, "inviteonly", 'i')
- {
- }
-};
-
-/** Channel mode +m
- */
-class ModeChannelModerated : public SimpleChannelModeHandler
-{
- public:
- ModeChannelModerated() : SimpleChannelModeHandler(NULL, "moderated", 'm')
- {
- }
-};
-
-/** Channel mode +n
- */
-class ModeChannelNoExternal : public SimpleChannelModeHandler
-{
- public:
- ModeChannelNoExternal() : SimpleChannelModeHandler(NULL, "noextmsg", 'n')
- {
- }
-};
-
-/** Channel mode +p
- */
-class ModeChannelPrivate : public SimpleChannelModeHandler
-{
- public:
- ModeChannelPrivate() : SimpleChannelModeHandler(NULL, "private", 'p')
- {
- }
-};
-
-/** Channel mode +s
- */
-class ModeChannelSecret : public SimpleChannelModeHandler
-{
- public:
- ModeChannelSecret() : SimpleChannelModeHandler(NULL, "secret", 's')
- {
- }
-};
-
-/** Channel mode +t
- */
-class ModeChannelTopicOps : public SimpleChannelModeHandler
-{
- public:
- ModeChannelTopicOps() : SimpleChannelModeHandler(NULL, "topiclock", 't')
- {
- }
-};
-
-/** User mode +i
- */
-class ModeUserInvisible : public SimpleUserModeHandler
-{
- public:
- ModeUserInvisible() : SimpleUserModeHandler(NULL, "invisible", 'i')
- {
- }
-};
-
-/** User mode +w
- */
-class ModeUserWallops : public SimpleUserModeHandler
-{
- public:
- ModeUserWallops() : SimpleUserModeHandler(NULL, "wallops", 'w')
- {
- }
-};
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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 "mode.h"
-
-class InspIRCd;
-
-/** User mode +o
- */
-class ModeUserOperator : public ModeHandler
-{
- public:
- ModeUserOperator();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
-};
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2008 Robin Burchell <robin+git@viroteck.net>
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * 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 "mode.h"
-
-class InspIRCd;
-
-/** User mode +n
- */
-class ModeUserServerNoticeMask : public ModeHandler
-{
- public:
- ModeUserServerNoticeMask();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
- void OnParameterMissing(User* user, User* dest, Channel* channel);
- std::string GetUserParameter(User* user);
-};
*/
-#ifndef MODULES_H
-#define MODULES_H
+#pragma once
#include "dynamic.h"
#include "base.h"
#include <sstream>
#include "timer.h"
#include "mode.h"
-#include "dns.h"
/** Used to define a set of behavior bits for a module
*/
/** InspIRCd major version.
* 1.2 -> 102; 2.1 -> 201; 2.12 -> 212
*/
-#define INSPIRCD_VERSION_MAJ 200
+#define INSPIRCD_VERSION_MAJ 202
/** InspIRCd API version.
* If you change any API elements, increment this value. This counter should be
* reset whenever the major version is changed. Modules can use these two values
* and numerical comparisons in preprocessor macros if they wish to support
* multiple versions of InspIRCd in one file.
*/
-#define INSPIRCD_VERSION_API 6
+#define INSPIRCD_VERSION_API 1
/**
* This #define allows us to call a method in all
} \
catch (CoreException& modexcept) \
{ \
- ServerInstance->Logs->Log("MODULE",DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Exception caught: %s",modexcept.GetReason()); \
} \
_i = safei; \
} \
} \
catch (CoreException& except_ ## n) \
{ \
- ServerInstance->Logs->Log("MODULE",DEFAULT,"Exception caught: %s", (except_ ## n).GetReason()); \
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Exception caught: %s", (except_ ## n).GetReason()); \
(void) mod_ ## n; /* catch mismatched pairs */ \
} \
} \
{
private:
std::string name;
+ void resolve();
protected:
- DataProvider* value;
+ ServiceProvider* value;
public:
ModuleRef creator;
dynamic_reference_base(Module* Creator, const std::string& Name);
~dynamic_reference_base();
- inline void ClearCache() { value = NULL; }
inline const std::string& GetProvider() { return name; }
void SetProvider(const std::string& newname);
- void lookup();
- operator bool();
+ void check();
+ operator bool() { return (value != NULL); }
static void reset_all();
};
+inline void dynamic_reference_base::check()
+{
+ if (!value)
+ throw ModuleException("Dynamic reference to '" + name + "' failed to resolve");
+}
+
template<typename T>
class dynamic_reference : public dynamic_reference_base
{
public:
dynamic_reference(Module* Creator, const std::string& Name)
: dynamic_reference_base(Creator, Name) {}
+
inline T* operator->()
{
- if (!value)
- lookup();
+ check();
return static_cast<T*>(value);
}
+
+ T* operator*()
+ {
+ return operator->();
+ }
+};
+
+template<typename T>
+class dynamic_reference_nocheck : public dynamic_reference_base
+{
+ public:
+ dynamic_reference_nocheck(Module* Creator, const std::string& Name)
+ : dynamic_reference_base(Creator, Name) {}
+
+ T* operator->()
+ {
+ return static_cast<T*>(value);
+ }
+
+ T* operator*()
+ {
+ return operator->();
+ }
+};
+
+class ModeReference : public dynamic_reference_nocheck<ModeHandler>
+{
+ public:
+ ModeReference(Module* mod, const std::string& modename)
+ : dynamic_reference_nocheck<ModeHandler>(mod, "mode/" + modename) {}
};
/** Priority types which can be used by Module::Prioritize()
I_BEGIN,
I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash,
I_OnSendSnotice, I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo, I_OnWhois,
- I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreNick,
- I_OnUserMessage, I_OnUserNotice, I_OnMode, I_OnGetServerDescription, I_OnSyncUser,
- I_OnSyncChannel, I_OnDecodeMetaData, I_OnWallops, I_OnAcceptConnection, I_OnUserInit,
+ I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNick,
+ I_OnUserMessage, I_OnMode, I_OnGetServerDescription, I_OnSyncUser,
+ I_OnSyncChannel, I_OnDecodeMetaData, I_OnAcceptConnection, I_OnUserInit,
I_OnChangeHost, I_OnChangeName, I_OnAddLine, I_OnDelLine, I_OnExpireLine,
I_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule,
I_OnUnloadModule, I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite,
I_OnRawMode, I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnCheckChannelBan, I_OnExtBanCheck,
I_OnStats, I_OnChangeLocalUserHost, I_OnPreTopicChange,
- I_OnPostTopicChange, I_OnEvent, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan,
- I_OnDelBan, I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
+ I_OnPostTopicChange, I_OnEvent, I_OnGlobalOper, I_OnPostConnect,
+ I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnPostCommand, I_OnPostJoin,
I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect, I_OnSetConnectClass,
I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO,
* @param keygiven The key given to join the channel, or an empty string if none was provided
* @return 1 To prevent the join, 0 to allow it.
*/
- virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven);
+ virtual ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven);
/** Called whenever a user is about to be kicked.
* Returning a value of 1 from this function stops the process immediately, causing no
* @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone.
* @param exempt_list A list of users not to send to. For channel messages, this will usually contain just the sender.
* It will be ignored for private messages.
+ * @param msgtype The message type, MSG_PRIVMSG for PRIVMSGs, MSG_NOTICE for NOTICEs
* @return 1 to deny the message, 0 to allow it
*/
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
-
- /** Called whenever a user is about to NOTICE A user or a channel, before any processing is done.
- * Returning any nonzero value from this function stops the process immediately, causing no
- * output to be sent to the user by the core. If you do this you must produce your own numerics,
- * notices etc. This is useful for modules which may want to filter or redirect messages.
- * target_type can be one of TYPE_USER or TYPE_CHANNEL. If the target_type value is a user,
- * you must cast dest to a User* otherwise you must cast it to a Channel*, this is the details
- * of where the message is destined to be sent.
- * You may alter the message text as you wish before relinquishing control to the next module
- * in the chain, and if no other modules block the text this altered form of the text will be sent out
- * to the user and possibly to other servers.
- * @param user The user sending the message
- * @param dest The target of the message (Channel* or User*)
- * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
- * @param text Changeable text being sent by the user
- * @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone.
- * @param exempt_list A list of users not to send to. For channel notices, this will usually contain just the sender.
- * It will be ignored for private notices.
- * @return 1 to deny the NOTICE, 0 to allow it
- */
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
+ virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list, MessageType msgtype);
/** Called when sending a message to all "neighbors" of a given user -
* that is, all users that share a common channel. This is used in
* @param text the text being sent by the user
* @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone.
* @param exempt_list A list of users to not send to.
+ * @param msgtype The message type, MSG_PRIVMSG for PRIVMSGs, MSG_NOTICE for NOTICEs
*/
- virtual void OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list);
-
- /** Called after any NOTICE sent from a user.
- * The dest variable contains a User* if target_type is TYPE_USER and a Channel*
- * if target_type is TYPE_CHANNEL.
- * @param user The user sending the message
- * @param dest The target of the message
- * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
- * @param text the text being sent by the user
- * @param status The status being used, e.g. NOTICE @#chan has status== '@', 0 to send to everyone.
- * @param exempt_list A list of users to not send to.
- */
- virtual void OnUserNotice(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list);
+ virtual void OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list, MessageType msgtype);
/** Called immediately before any NOTICE or PRIVMSG sent from a user, local or remote.
* The dest variable contains a User* if target_type is TYPE_USER and a Channel*
* if target_type is TYPE_CHANNEL.
- * The difference between this event and OnUserPreNotice/OnUserPreMessage is that delivery is gauranteed,
+ * The difference between this event and OnUserPreMessage is that delivery is gauranteed,
* the message has already been vetted. In the case of the other two methods, a later module may stop your
* message. This also differs from OnUserMessage which occurs AFTER the message has been sent.
* @param user The user sending the message
* (see below). This function will be called for every user visible on your side
* of the burst, allowing you to for example set modes, etc.
*
- * For a good example of how to use this function, please see src/modules/m_chanprotect.cpp
- *
* @param chan The channel being syncronized
* @param proto A pointer to the module handling network protocol
* @param opaque An opaque pointer set by the protocol module, should not be modified!
* down the network link as a broadcast, without a module calling it having to know the format
* of the MODE command before the actual mode string.
*
- * More documentation to follow soon. Please see src/modules/m_chanprotect.cpp for examples
- * of how to use this function.
- *
* @param opaque An opaque pointer set by the protocol module, should not be modified!
* @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL
* @param target The Channel* or User* that modes should be sent for
*/
virtual void ProtoSendMetaData(void* opaque, Extensible* target, const std::string &extname, const std::string &extdata);
- /** Called after every WALLOPS command.
- * @param user The user sending the WALLOPS
- * @param text The content of the WALLOPS message
- */
- virtual void OnWallops(User* user, const std::string &text);
-
/** Called whenever a user's hostname is changed.
* This event triggers after the host has been set.
* @param user The user whos host is being changed
/** Called when a 005 numeric is about to be output.
* The module should modify the 005 numeric if needed to indicate its features.
- * @param output The 005 string to be modified if neccessary.
- */
- virtual void On005Numeric(std::string &output);
+ * @param output The 005 map to be modified if neccessary.
+ */
+ virtual void On005Numeric(std::map<std::string, std::string>& tokens);
/** Called when a client is disconnected by KILL.
* If a client is killed by a server, e.g. a nickname collision or protocol error,
*/
virtual void OnPostConnect(User* user);
- /** Called whenever a ban is added to a channel's list.
- * Return a non-zero value to 'eat' the mode change and prevent the ban from being added.
- * @param source The user adding the ban
- * @param channel The channel the ban is being added to
- * @param banmask The ban mask being added
- * @return 1 to block the ban, 0 to continue as normal
- */
- virtual ModResult OnAddBan(User* source, Channel* channel,const std::string &banmask);
-
- /** Called whenever a ban is removed from a channel's list.
- * Return a non-zero value to 'eat' the mode change and prevent the ban from being removed.
- * @param source The user deleting the ban
- * @param channel The channel the ban is being deleted from
- * @param banmask The ban mask being deleted
- * @return 1 to block the unban, 0 to continue as normal
- */
- virtual ModResult OnDelBan(User* source, Channel* channel,const std::string &banmask);
-
/** Called to install an I/O hook on an event handler
* @param user The socket to possibly install the I/O hook on
* @param via The port that the user connected on
virtual void OnSetUserIP(LocalUser* user);
};
-
-#define CONF_NO_ERROR 0x000000
-#define CONF_NOT_A_NUMBER 0x000010
-#define CONF_INT_NEGATIVE 0x000080
-#define CONF_VALUE_NOT_FOUND 0x000100
-#define CONF_FILE_NOT_FOUND 0x000200
-
-
-/** Allows reading of values from configuration files
- * This class allows a module to read from either the main configuration file (inspircd.conf) or from
- * a module-specified configuration file. It may either be instantiated with one parameter or none.
- * Constructing the class using one parameter allows you to specify a path to your own configuration
- * file, otherwise, inspircd.conf is read.
- */
-class CoreExport ConfigReader : public interfacebase
-{
- protected:
- /** Error code
- */
- long error;
-
- public:
- /** Default constructor.
- * This constructor initialises the ConfigReader class to read the inspircd.conf file
- * as specified when running ./configure.
- */
- ConfigReader();
- /** Default destructor.
- * This method destroys the ConfigReader class.
- */
- ~ConfigReader();
-
- /** Retrieves a value from the config file.
- * This method retrieves a value from the config file. Where multiple copies of the tag
- * exist in the config file, index indicates which of the values to retrieve.
- */
- std::string ReadValue(const std::string &tag, const std::string &name, int index, bool allow_linefeeds = false);
- /** Retrieves a value from the config file.
- * This method retrieves a value from the config file. Where multiple copies of the tag
- * exist in the config file, index indicates which of the values to retrieve. If the
- * tag is not found the default value is returned instead.
- */
- std::string ReadValue(const std::string &tag, const std::string &name, const std::string &default_value, int index, bool allow_linefeeds = false);
-
- /** Retrieves a boolean value from the config file.
- * This method retrieves a boolean value from the config file. Where multiple copies of the tag
- * exist in the config file, index indicates which of the values to retrieve. The values "1", "yes"
- * and "true" in the config file count as true to ReadFlag, and any other value counts as false.
- */
- bool ReadFlag(const std::string &tag, const std::string &name, int index);
- /** Retrieves a boolean value from the config file.
- * This method retrieves a boolean value from the config file. Where multiple copies of the tag
- * exist in the config file, index indicates which of the values to retrieve. The values "1", "yes"
- * and "true" in the config file count as true to ReadFlag, and any other value counts as false.
- * If the tag is not found, the default value is used instead.
- */
- bool ReadFlag(const std::string &tag, const std::string &name, const std::string &default_value, int index);
-
- /** Retrieves an integer value from the config file.
- * This method retrieves an integer value from the config file. Where multiple copies of the tag
- * exist in the config file, index indicates which of the values to retrieve. Any invalid integer
- * values in the tag will cause the objects error value to be set, and any call to GetError() will
- * return CONF_INVALID_NUMBER to be returned. need_positive is set if the number must be non-negative.
- * If a negative number is placed into a tag which is specified positive, 0 will be returned and GetError()
- * will return CONF_INT_NEGATIVE. Note that need_positive is not suitable to get an unsigned int - you
- * should cast the result to achieve that effect.
- */
- int ReadInteger(const std::string &tag, const std::string &name, int index, bool need_positive);
- /** Retrieves an integer value from the config file.
- * This method retrieves an integer value from the config file. Where multiple copies of the tag
- * exist in the config file, index indicates which of the values to retrieve. Any invalid integer
- * values in the tag will cause the objects error value to be set, and any call to GetError() will
- * return CONF_INVALID_NUMBER to be returned. needs_unsigned is set if the number must be unsigned.
- * If a signed number is placed into a tag which is specified unsigned, 0 will be returned and GetError()
- * will return CONF_NOT_UNSIGNED. If the tag is not found, the default value is used instead.
- */
- int ReadInteger(const std::string &tag, const std::string &name, const std::string &default_value, int index, bool need_positive);
-
- /** Returns the last error to occur.
- * Valid errors can be found by looking in modules.h. Any nonzero value indicates an error condition.
- * A call to GetError() resets the error flag back to 0.
- */
- long GetError();
-
- /** Counts the number of times a given tag appears in the config file.
- * This method counts the number of times a tag appears in a config file, for use where
- * there are several tags of the same kind, e.g. with opers and connect types. It can be
- * used with the index value of ConfigReader::ReadValue to loop through all copies of a
- * multiple instance tag.
- */
- int Enumerate(const std::string &tag);
-};
-
-
-
-/** Caches a text file into memory and can be used to retrieve lines from it.
- * This class contains methods for read-only manipulation of a text file in memory.
- * Either use the constructor type with one parameter to load a file into memory
- * at construction, or use the LoadFile method to load a file.
- */
+/** Provides an easy method of reading a text file into memory. */
class CoreExport FileReader : public classbase
{
- /** The file contents
+ /** The lines of text in the file.
*/
- std::vector<std::string> fc;
+ std::vector<std::string> lines;
/** Content size in bytes
*/
- unsigned long contentsize;
-
- /** Calculate content size in bytes
- */
- void CalcSize();
+ unsigned long totalSize;
public:
- /** Default constructor.
- * This method does not load any file into memory, you must use the LoadFile method
- * after constructing the class this way.
+ /** Initializes a new file reader.
*/
- FileReader();
+ FileReader() : totalSize(0) { }
- /** Secondary constructor.
- * This method initialises the class with a file loaded into it ready for GetLine and
- * and other methods to be called. If the file could not be loaded, FileReader::FileSize
- * returns 0.
+ /** Initializes a new file reader and reads the specified file.
+ * @param file The file to read into memory.
*/
- FileReader(const std::string &filename);
+ FileReader(const std::string& filename);
- /** Default destructor.
- * This deletes the memory allocated to the file.
- */
- ~FileReader();
-
- /** Used to load a file.
- * This method loads a file into the class ready for GetLine and
- * and other methods to be called. If the file could not be loaded, FileReader::FileSize
- * returns 0.
- */
- void LoadFile(const std::string &filename);
-
- /** Returns the whole content of the file as std::string
+ /** Loads a text file from disk.
+ * @param filename The file to read into memory.
+ * @throw CoreException The file can not be loaded.
*/
- std::string Contents();
+ void Load(const std::string& filename);
- /** Returns the entire size of the file as std::string
+ /** Retrieves the entire contents of the file cache as a single string.
*/
- unsigned long ContentSize();
+ std::string GetString();
- /** Returns true if the file exists
- * This function will return false if the file could not be opened.
+ /** Retrieves the entire contents of the file cache as a vector of strings.
*/
- bool Exists();
+ const std::vector<std::string>& GetVector() { return lines; }
- /** Retrieve one line from the file.
- * This method retrieves one line from the text file. If an empty non-NULL string is returned,
- * the index was out of bounds, or the line had no data on it.
- */
- std::string GetLine(int x);
-
- /** Returns the size of the file in lines.
- * This method returns the number of lines in the read file. If it is 0, no lines have been
- * read into memory, either because the file is empty or it does not exist, or cannot be
- * opened due to permission problems.
- */
- int FileSize();
+ unsigned long TotalSize() { return totalSize; }
};
/** A list of modules
#define COMMAND_INIT(c) MODULE_INIT(CommandModule<c>)
#endif
-
-#endif
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
+ *
+ * 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/>.
+ */
+
+
+#pragma once
+
+#include <map>
+#include <string>
+
+class AccountEvent : public Event
+{
+ public:
+ User* const user;
+ const std::string account;
+ AccountEvent(Module* me, User* u, const std::string& name)
+ : Event(me, "account_login"), user(u), account(name)
+ {
+ }
+};
+
+typedef StringExtItem AccountExtItem;
+
+inline AccountExtItem* GetAccountExtItem()
+{
+ return static_cast<AccountExtItem*>(ServerInstance->Extensions.GetItem("accountname"));
+}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
+ *
+ * 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/>.
+ */
+
+
+#pragma once
+
+class CapEvent : public Event
+{
+ public:
+ enum CapEventType
+ {
+ CAPEVENT_REQ,
+ CAPEVENT_LS,
+ CAPEVENT_LIST,
+ CAPEVENT_CLEAR
+ };
+
+ CapEventType type;
+ std::vector<std::string> wanted;
+ std::vector<std::string> ack;
+ User* user;
+ CapEvent(Module* sender, User* u, CapEventType capevtype) : Event(sender, "cap_request"), type(capevtype), user(u) {}
+};
+
+class GenericCap
+{
+ public:
+ LocalIntExt ext;
+ const std::string cap;
+ GenericCap(Module* parent, const std::string &Cap) : ext("cap_" + Cap, parent), cap(Cap)
+ {
+ ServerInstance->Modules->AddService(ext);
+ }
+
+ void HandleEvent(Event& ev)
+ {
+ if (ev.id != "cap_request")
+ return;
+
+ CapEvent *data = static_cast<CapEvent*>(&ev);
+ if (data->type == CapEvent::CAPEVENT_REQ)
+ {
+ for (std::vector<std::string>::iterator it = data->wanted.begin(); it != data->wanted.end(); ++it)
+ {
+ if (it->empty())
+ continue;
+ bool enablecap = ((*it)[0] != '-');
+ if (((enablecap) && (*it == cap)) || (*it == "-" + cap))
+ {
+ // 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);
+ break;
+ }
+ }
+ }
+ else if (data->type == CapEvent::CAPEVENT_LS)
+ {
+ data->wanted.push_back(cap);
+ }
+ else if (data->type == CapEvent::CAPEVENT_LIST)
+ {
+ if (ext.get(data->user))
+ data->wanted.push_back(cap);
+ }
+ else if (data->type == CapEvent::CAPEVENT_CLEAR)
+ {
+ data->ack.push_back("-" + cap);
+ ext.set(data->user, 0);
+ }
+ }
+};
+
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013 Adam <Adam@anope.org>
+ * Copyright (C) 2003-2013 Anope Team <team@anope.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
+ * 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/>.
+ */
+
+#pragma once
+
+namespace DNS
+{
+ /** Valid query types
+ */
+ enum QueryType
+ {
+ /* Nothing */
+ QUERY_NONE,
+ /* A simple A lookup */
+ QUERY_A = 1,
+ /* A CNAME lookup */
+ QUERY_CNAME = 5,
+ /* Reverse DNS lookup */
+ QUERY_PTR = 12,
+ /* IPv6 AAAA lookup */
+ QUERY_AAAA = 28
+ };
+
+ /** Flags that can be AND'd into DNSPacket::flags to receive certain values
+ */
+ enum
+ {
+ QUERYFLAGS_QR = 0x8000,
+ QUERYFLAGS_OPCODE = 0x7800,
+ QUERYFLAGS_AA = 0x400,
+ QUERYFLAGS_TC = 0x200,
+ QUERYFLAGS_RD = 0x100,
+ QUERYFLAGS_RA = 0x80,
+ QUERYFLAGS_Z = 0x70,
+ QUERYFLAGS_RCODE = 0xF
+ };
+
+ enum Error
+ {
+ ERROR_NONE,
+ ERROR_UNKNOWN,
+ ERROR_UNLOADED,
+ ERROR_TIMEDOUT,
+ ERROR_NOT_AN_ANSWER,
+ ERROR_NONSTANDARD_QUERY,
+ ERROR_FORMAT_ERROR,
+ ERROR_SERVER_FAILURE,
+ ERROR_DOMAIN_NOT_FOUND,
+ ERROR_NOT_IMPLEMENTED,
+ ERROR_REFUSED,
+ ERROR_NO_RECORDS,
+ ERROR_INVALIDTYPE
+ };
+
+ const int PORT = 53;
+
+ /**
+ * The maximum value of a dns request id,
+ * 16 bits wide, 0xFFFF.
+ */
+ const int MAX_REQUEST_ID = 0xFFFF;
+
+ class Exception : public ModuleException
+ {
+ public:
+ Exception(const std::string& message) : ModuleException(message) { }
+ };
+
+ struct Question
+ {
+ std::string name;
+ QueryType type;
+ unsigned short qclass;
+
+ Question() : type(QUERY_NONE), qclass(0) { }
+ Question(const std::string& n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { }
+ inline bool operator==(const Question& other) const { return name == other.name && type == other.type && qclass == other.qclass; }
+
+ struct hash
+ {
+ size_t operator()(const Question& question) const
+ {
+ return irc::insensitive()(question.name);
+ }
+ };
+ };
+
+ struct ResourceRecord : Question
+ {
+ unsigned int ttl;
+ std::string rdata;
+ time_t created;
+
+ ResourceRecord(const std::string& n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(ServerInstance->Time()) { }
+ ResourceRecord(const Question& question) : Question(question), ttl(0), created(ServerInstance->Time()) { }
+ };
+
+ struct Query
+ {
+ std::vector<Question> questions;
+ std::vector<ResourceRecord> answers;
+ Error error;
+ bool cached;
+
+ Query() : error(ERROR_NONE), cached(false) { }
+ Query(const Question& question) : error(ERROR_NONE), cached(false) { questions.push_back(question); }
+ };
+
+ class ReplySocket;
+ class Request;
+
+ /** DNS manager
+ */
+ class Manager : public DataProvider
+ {
+ public:
+ Manager(Module* mod) : DataProvider(mod, "DNS") { }
+
+ virtual void Process(Request* req) = 0;
+ virtual void RemoveRequest(Request* req) = 0;
+ virtual std::string GetErrorStr(Error) = 0;
+ };
+
+ /** A DNS query.
+ */
+ class Request : public Timer, public Question
+ {
+ protected:
+ Manager* const manager;
+ public:
+ /* Use result cache if available */
+ bool use_cache;
+ /* Request id */
+ unsigned short id;
+ /* Creator of this request */
+ Module* const creator;
+
+ Request(Manager* mgr, Module* mod, const std::string& addr, QueryType qt, bool usecache = true)
+ : Timer((ServerInstance->Config->dns_timeout ? ServerInstance->Config->dns_timeout : 5), ServerInstance->Time())
+ , Question(addr, qt)
+ , manager(mgr)
+ , use_cache(usecache)
+ , id(0)
+ , creator(mod)
+ {
+ ServerInstance->Timers->AddTimer(this);
+ }
+
+ virtual ~Request()
+ {
+ manager->RemoveRequest(this);
+ }
+
+ /** Called when this request succeeds
+ * @param r The query sent back from the nameserver
+ */
+ virtual void OnLookupComplete(const Query* req) = 0;
+
+ /** Called when this request fails or times out.
+ * @param r The query sent back from the nameserver, check the error code.
+ */
+ virtual void OnError(const Query* req) { }
+
+ /** Used to time out the query, calls OnError and asks the TimerManager
+ * to delete this request
+ */
+ bool Tick(time_t now)
+ {
+ Query rr(*this);
+ rr.error = ERROR_TIMEDOUT;
+ this->OnError(&rr);
+ return false;
+ }
+ };
+
+} // namespace DNS
+
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 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
+ * 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/>.
+ */
+
+
+#pragma once
+
+#include "modules.h"
+
+class HashProvider : public DataProvider
+{
+ public:
+ const unsigned int out_size;
+ const unsigned int block_size;
+ HashProvider(Module* mod, const std::string& Name, int osiz, int bsiz)
+ : DataProvider(mod, Name), out_size(osiz), block_size(bsiz) {}
+ virtual std::string sum(const std::string& data) = 0;
+ inline std::string hexsum(const std::string& data)
+ {
+ return BinToHex(sum(data));
+ }
+
+ inline std::string b64sum(const std::string& data)
+ {
+ return BinToBase64(sum(data), NULL, 0);
+ }
+
+ /** HMAC algorithm, RFC 2104 */
+ std::string hmac(const std::string& key, const std::string& msg)
+ {
+ std::string hmac1, hmac2;
+ std::string kbuf = key.length() > block_size ? sum(key) : key;
+ kbuf.resize(block_size);
+
+ for (size_t n = 0; n < block_size; n++)
+ {
+ hmac1.push_back(static_cast<char>(kbuf[n] ^ 0x5C));
+ hmac2.push_back(static_cast<char>(kbuf[n] ^ 0x36));
+ }
+ hmac2.append(msg);
+ hmac1.append(sum(hmac2));
+ return sum(hmac1);
+ }
+};
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
+ * Copyright (C) 2007 John Brooks <john.brooks@dereferenced.net>
+ * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
+ *
+ * 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/>.
+ */
+
+
+#pragma once
+
+#include "base.h"
+
+#include <string>
+#include <sstream>
+#include <map>
+
+/** A modifyable list of HTTP header fields
+ */
+class HTTPHeaders
+{
+ protected:
+ std::map<std::string,std::string> headers;
+ public:
+
+ /** Set the value of a header
+ * Sets the value of the named header. If the header is already present, it will be replaced
+ */
+ void SetHeader(const std::string &name, const std::string &data)
+ {
+ headers[name] = data;
+ }
+
+ /** Set the value of a header, only if it doesn't exist already
+ * Sets the value of the named header. If the header is already present, it will NOT be updated
+ */
+ void CreateHeader(const std::string &name, const std::string &data)
+ {
+ if (!IsSet(name))
+ SetHeader(name, data);
+ }
+
+ /** Remove the named header
+ */
+ void RemoveHeader(const std::string &name)
+ {
+ headers.erase(name);
+ }
+
+ /** Remove all headers
+ */
+ void Clear()
+ {
+ headers.clear();
+ }
+
+ /** Get the value of a header
+ * @return The value of the header, or an empty string
+ */
+ std::string GetHeader(const std::string &name)
+ {
+ std::map<std::string,std::string>::iterator it = headers.find(name);
+ if (it == headers.end())
+ return std::string();
+
+ return it->second;
+ }
+
+ /** Check if the given header is specified
+ * @return true if the header is specified
+ */
+ bool IsSet(const std::string &name)
+ {
+ std::map<std::string,std::string>::iterator it = headers.find(name);
+ return (it != headers.end());
+ }
+
+ /** Get all headers, formatted by the HTTP protocol
+ * @return Returns all headers, formatted according to the HTTP protocol. There is no request terminator at the end
+ */
+ std::string GetFormattedHeaders()
+ {
+ std::string re;
+
+ for (std::map<std::string,std::string>::iterator i = headers.begin(); i != headers.end(); i++)
+ re += i->first + ": " + i->second + "\r\n";
+
+ return re;
+ }
+};
+
+class HttpServerSocket;
+
+/** This class represents a HTTP request.
+ */
+class HTTPRequest : public Event
+{
+ protected:
+ std::string type;
+ std::string document;
+ std::string ipaddr;
+ std::string postdata;
+
+ public:
+
+ HTTPHeaders *headers;
+ int errorcode;
+
+ /** A socket pointer, which you must return in your HTTPDocument class
+ * if you reply to this request.
+ */
+ HttpServerSocket* sock;
+
+ /** Initialize HTTPRequest.
+ * This constructor is called by m_httpd.so to initialize the class.
+ * @param request_type The request type, e.g. GET, POST, HEAD
+ * @param uri The URI, e.g. /page
+ * @param hdr The headers sent with the request
+ * @param opaque An opaque pointer used internally by m_httpd, which you must pass back to the module in your reply.
+ * @param ip The IP address making the web request.
+ * @param pdata The post data (content after headers) received with the request, up to Content-Length in size
+ */
+ HTTPRequest(Module* me, const std::string &eventid, const std::string &request_type, const std::string &uri,
+ HTTPHeaders* hdr, HttpServerSocket* socket, const std::string &ip, const std::string &pdata)
+ : Event(me, eventid), type(request_type), document(uri), ipaddr(ip), postdata(pdata), headers(hdr), sock(socket)
+ {
+ }
+
+ /** Get the post data (request content).
+ * All post data will be returned, including carriage returns and linefeeds.
+ * @return The postdata
+ */
+ std::string& GetPostData()
+ {
+ return postdata;
+ }
+
+ /** Get the request type.
+ * Any request type can be intercepted, even ones which are invalid in the HTTP/1.1 spec.
+ * @return The request type, e.g. GET, POST, HEAD
+ */
+ std::string& GetType()
+ {
+ return type;
+ }
+
+ /** Get URI.
+ * The URI string (URL minus hostname and scheme) will be provided by this function.
+ * @return The URI being requested
+ */
+ std::string& GetURI()
+ {
+ return document;
+ }
+
+ /** Get IP address of requester.
+ * The requesting system's ip address will be returned.
+ * @return The IP address as a string
+ */
+ std::string& GetIP()
+ {
+ return ipaddr;
+ }
+};
+
+/** You must return a HTTPDocument to the httpd module by using the Request class.
+ * When you initialize this class you may initialize it with all components required to
+ * form a valid HTTP response, including document data, headers, and a response code.
+ */
+class HTTPDocumentResponse : public Request
+{
+ public:
+ std::stringstream* document;
+ int responsecode;
+ HTTPHeaders headers;
+ HTTPRequest& src;
+
+ /** Initialize a HTTPRequest ready for sending to m_httpd.so.
+ * @param opaque The socket pointer you obtained from the HTTPRequest at an earlier time
+ * @param doc A stringstream containing the document body
+ * @param response A valid HTTP/1.0 or HTTP/1.1 response code. The response text will be determined for you
+ * based upon the response code.
+ * @param extra Any extra headers to include with the defaults, seperated by carriage return and linefeed.
+ */
+ HTTPDocumentResponse(Module* me, HTTPRequest& req, std::stringstream* doc, int response)
+ : Request(me, req.source, "HTTP-DOC"), document(doc), responsecode(response), src(req)
+ {
+ }
+};
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2008 Thomas Stagner <aquanight@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
+ * 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/>.
+ */
+
+
+#pragma once
+
+#include "inspircd.h"
+
+class Regex : public classbase
+{
+protected:
+ std::string regex_string; // The raw uncompiled regex string.
+
+ // Constructor may as well be protected, as this class is abstract.
+ Regex(const std::string& rx) : regex_string(rx)
+ {
+ }
+
+public:
+
+ virtual ~Regex()
+ {
+ }
+
+ virtual bool Matches(const std::string& text) = 0;
+
+ const std::string& GetRegexString() const
+ {
+ return regex_string;
+ }
+};
+
+class RegexFactory : public DataProvider
+{
+ public:
+ RegexFactory(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) {}
+
+ virtual Regex* Create(const std::string& expr) = 0;
+};
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 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
+ * 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/>.
+ */
+
+
+#pragma once
+
+class SASLFallback : public Event
+{
+ public:
+ const parameterlist& params;
+ SASLFallback(Module* me, const parameterlist& p)
+ : Event(me, "sasl_fallback"), params(p)
+ {
+ Send();
+ }
+};
--- /dev/null
+/*
+ * 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
+ * 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/>.
+ */
+
+
+#pragma once
+
+struct AddServerEvent : public Event
+{
+ const std::string servername;
+ AddServerEvent(Module* me, const std::string& name)
+ : Event(me, "new_server"), servername(name)
+ {
+ Send();
+ }
+};
+
+struct DelServerEvent : public Event
+{
+ const std::string servername;
+ DelServerEvent(Module* me, const std::string& name)
+ : Event(me, "lost_server"), servername(name)
+ {
+ Send();
+ }
+};
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 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
+ * 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/>.
+ */
+
+
+#pragma once
+
+/** Defines the error types which SQLerror may be set to
+ */
+enum SQLerrorNum { SQL_NO_ERROR, SQL_BAD_DBID, SQL_BAD_CONN, SQL_QSEND_FAIL, SQL_QREPLY_FAIL };
+
+/** A list of format parameters for an SQLquery object.
+ */
+typedef std::vector<std::string> ParamL;
+
+typedef std::map<std::string, std::string> ParamM;
+
+class SQLEntry
+{
+ public:
+ std::string value;
+ bool nul;
+ SQLEntry() : nul(true) {}
+ SQLEntry(const std::string& v) : value(v), nul(false) {}
+ inline operator std::string&() { return value; }
+};
+
+typedef std::vector<SQLEntry> SQLEntries;
+
+/**
+ * Result of an SQL query. Only valid inside OnResult
+ */
+class SQLResult : public classbase
+{
+ public:
+ /**
+ * Return the number of rows in the result.
+ *
+ * Note that if you have perfomed an INSERT or UPDATE query or other
+ * query which will not return rows, this will return the number of
+ * affected rows. In this case you SHOULD NEVER access any of the result
+ * set rows, as there aren't any!
+ * @returns Number of rows in the result set.
+ */
+ virtual int Rows() = 0;
+
+ /**
+ * Return a single row (result of the query). The internal row counter
+ * is incremented by one.
+ *
+ * @param result Storage for the result data.
+ * @returns true if there was a row, false if no row exists (end of
+ * iteration)
+ */
+ virtual bool GetRow(SQLEntries& result) = 0;
+
+ /** Returns column names for the items in this row
+ */
+ virtual void GetCols(std::vector<std::string>& result) = 0;
+};
+
+/** SQLerror holds the error state of a request.
+ * The error string varies from database software to database software
+ * and should be used to display informational error messages to users.
+ */
+class SQLerror
+{
+ public:
+ /** The error id
+ */
+ SQLerrorNum id;
+
+ /** The error string
+ */
+ std::string str;
+
+ /** Initialize an SQLerror
+ * @param i The error ID to set
+ * @param s The (optional) error string to set
+ */
+ SQLerror(SQLerrorNum i, const std::string &s = "")
+ : id(i), str(s)
+ {
+ }
+
+ /** Return the error string for an error
+ */
+ const char* Str()
+ {
+ if(str.length())
+ return str.c_str();
+
+ switch(id)
+ {
+ case SQL_BAD_DBID:
+ return "Invalid database ID";
+ case SQL_BAD_CONN:
+ return "Invalid connection";
+ case SQL_QSEND_FAIL:
+ return "Sending query failed";
+ case SQL_QREPLY_FAIL:
+ return "Getting query result failed";
+ default:
+ return "Unknown error";
+ }
+ }
+};
+
+/**
+ * Object representing an SQL query. This should be allocated on the heap and
+ * passed to an SQLProvider, which will free it when the query is complete or
+ * when the querying module is unloaded.
+ *
+ * You should store whatever information is needed to have the callbacks work in
+ * this object (UID of user, channel name, etc).
+ */
+class SQLQuery : public classbase
+{
+ public:
+ ModuleRef creator;
+
+ SQLQuery(Module* Creator) : creator(Creator) {}
+ virtual ~SQLQuery() {}
+
+ virtual void OnResult(SQLResult& result) = 0;
+ /**
+ * Called when the query fails
+ */
+ virtual void OnError(SQLerror& error) { }
+};
+
+/**
+ * Provider object for SQL servers
+ */
+class SQLProvider : public DataProvider
+{
+ public:
+ SQLProvider(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) {}
+ /** Submit an asynchronous SQL request
+ * @param callback The result reporting point
+ * @param query The hardcoded query string. If you have parameters to substitute, see below.
+ */
+ virtual void submit(SQLQuery* callback, const std::string& query) = 0;
+
+ /** Submit an asynchronous SQL request
+ * @param callback The result reporting point
+ * @param format The simple parameterized query string ('?' parameters)
+ * @param p Parameters to fill in for the '?' entries
+ */
+ virtual void submit(SQLQuery* callback, const std::string& format, const ParamL& p) = 0;
+
+ /** Submit an asynchronous SQL request.
+ * @param callback The result reporting point
+ * @param format The parameterized query string ('$name' parameters)
+ * @param p Parameters to fill in for the '$name' entries
+ */
+ virtual void submit(SQLQuery* callback, const std::string& format, const ParamM& p) = 0;
+
+ /** Convenience function to prepare a map from a User* */
+ void PopulateUserInfo(User* user, ParamM& userinfo)
+ {
+ userinfo["nick"] = user->nick;
+ userinfo["host"] = user->host;
+ userinfo["ip"] = user->GetIPString();
+ userinfo["gecos"] = user->fullname;
+ userinfo["ident"] = user->ident;
+ userinfo["server"] = user->server;
+ userinfo["uuid"] = user->uuid;
+ }
+};
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
+ * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
+ *
+ * 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/>.
+ */
+
+
+#pragma once
+
+#include <map>
+#include <string>
+
+/** ssl_cert is a class which abstracts SSL certificate
+ * and key information.
+ *
+ * Because gnutls and openssl represent key information in
+ * wildly different ways, this class allows it to be accessed
+ * in a unified manner. These classes are attached to ssl-
+ * connected local users using SSLCertExt
+ */
+class ssl_cert : public refcountbase
+{
+ public:
+ std::string dn;
+ std::string issuer;
+ std::string error;
+ std::string fingerprint;
+ bool trusted, invalid, unknownsigner, revoked;
+
+ ssl_cert() : trusted(false), invalid(true), unknownsigner(true), revoked(false) {}
+
+ /** Get certificate distinguished name
+ * @return Certificate DN
+ */
+ const std::string& GetDN()
+ {
+ return dn;
+ }
+
+ /** Get Certificate issuer
+ * @return Certificate issuer
+ */
+ const std::string& GetIssuer()
+ {
+ return issuer;
+ }
+
+ /** Get error string if an error has occured
+ * @return The error associated with this users certificate,
+ * or an empty string if there is no error.
+ */
+ const std::string& GetError()
+ {
+ return error;
+ }
+
+ /** Get key fingerprint.
+ * @return The key fingerprint as a hex string.
+ */
+ const std::string& GetFingerprint()
+ {
+ return fingerprint;
+ }
+
+ /** Get trust status
+ * @return True if this is a trusted certificate
+ * (the certificate chain validates)
+ */
+ bool IsTrusted()
+ {
+ return trusted;
+ }
+
+ /** Get validity status
+ * @return True if the certificate itself is
+ * correctly formed.
+ */
+ bool IsInvalid()
+ {
+ return invalid;
+ }
+
+ /** Get signer status
+ * @return True if the certificate appears to be
+ * self-signed.
+ */
+ bool IsUnknownSigner()
+ {
+ return unknownsigner;
+ }
+
+ /** Get revokation status.
+ * @return True if the certificate is revoked.
+ * Note that this only works properly for GnuTLS
+ * right now.
+ */
+ bool IsRevoked()
+ {
+ return revoked;
+ }
+
+ bool IsCAVerified()
+ {
+ return trusted && !invalid && !revoked && !unknownsigner && error.empty();
+ }
+
+ std::string GetMetaLine()
+ {
+ std::stringstream value;
+ bool hasError = !error.empty();
+ value << (IsInvalid() ? "v" : "V") << (IsTrusted() ? "T" : "t") << (IsRevoked() ? "R" : "r")
+ << (IsUnknownSigner() ? "s" : "S") << (hasError ? "E" : "e") << " ";
+ if (hasError)
+ value << GetError();
+ else
+ value << GetFingerprint() << " " << GetDN() << " " << GetIssuer();
+ return value.str();
+ }
+};
+
+/** Get certificate from a socket (only useful with an SSL module) */
+struct SocketCertificateRequest : public Request
+{
+ StreamSocket* const sock;
+ ssl_cert* cert;
+
+ SocketCertificateRequest(StreamSocket* ss, Module* Me)
+ : Request(Me, ss->GetIOHook(), "GET_SSL_CERT"), sock(ss), cert(NULL)
+ {
+ Send();
+ }
+
+ std::string GetFingerprint()
+ {
+ if (cert)
+ return cert->GetFingerprint();
+ return "";
+ }
+};
+
+/** Get certificate from a user (requires m_sslinfo) */
+struct UserCertificateRequest : public Request
+{
+ User* const user;
+ ssl_cert* cert;
+
+ UserCertificateRequest(User* u, Module* Me, Module* info = ServerInstance->Modules->Find("m_sslinfo.so"))
+ : Request(Me, info, "GET_USER_CERT"), user(u), cert(NULL)
+ {
+ Send();
+ }
+
+ std::string GetFingerprint()
+ {
+ if (cert)
+ return cert->GetFingerprint();
+ return "";
+ }
+};
*/
-#ifndef NUMERICS_H
-#define NUMERICS_H
+#pragma once
/*
* This file is aimed providing a string that is easier to use than using the numeric
ERR_CANTLOADMODULE = 974, // insp-specific
RPL_LOADEDMODULE = 975 // insp-specific
};
-
-#endif
*/
-#ifndef PROTOCOL_H
-#define PROTOCOL_H
+#pragma once
#include "hashcomp.h"
*/
virtual void GetServerList(ProtoServerList &sl) { }
};
-
-#endif
-
*/
-#ifndef SNOMASKS_H
-#define SNOMASKS_H
+#pragma once
class Snomask
{
*/
void FlushSnotices();
};
-
-#endif
*/
-#ifndef INSPIRCD_SOCKET_H
-#define INSPIRCD_SOCKET_H
+#pragma once
#ifndef _WIN32
*/
CoreExport bool MatchCIDR(const std::string &address, const std::string &cidr_mask, bool match_with_username);
- /** Return the size of the structure for syscall passing */
- inline int sa_size(const irc::sockets::sockaddrs& sa) { return sa.sa_size(); }
-
/** Convert an address-port pair into a binary sockaddr
* @param addr The IP address, IPv4 or IPv6
* @param port The port, 0 for unspecified
*/
void AcceptInternal();
};
-
-#endif
-
*/
-#ifndef SOCKETENGINE_H
-#define SOCKETENGINE_H
+#pragma once
#include <vector>
#include <string>
#include <map>
-#include "inspircd_config.h"
+#include "config.h"
#include "socket.h"
#include "base.h"
/** Add a trial write. During the next DispatchEvents invocation, this
* will call HandleEvent with EVENT_WRITE unless writes are known to be
* blocking.
- *
+ *
* This could be used to group several writes together into a single
* send() syscall, or to ensure that writes are blocking when attempting
* to use FD_WANT_FAST_WRITE.
/** Assert that writes are known to block. This cancels FD_ADD_TRIAL_WRITE.
* Reset by SE before running EVENT_WRITE
*/
- FD_WRITE_WILL_BLOCK = 0x8000,
+ FD_WRITE_WILL_BLOCK = 0x8000,
/** Mask for trial read/trial write */
FD_TRIAL_NOTE_MASK = 0x5000
* @param buf The buffer in which the data that is sent is stored.
* @param len The size of the buffer.
* @param flags A flag value that controls the sending of the data.
- * @param to The remote IP address and port.
+ * @param to The remote IP address and port.
* @param tolen The size of the to parameter.
* @return This method should return exactly the same values as the system call it emulates.
*/
}
SocketEngine* CreateSocketEngine();
-
-#endif
-
*/
-#ifndef TESTSUITE_H
-#define TESTSUITE_H
+#pragma once
class TestSuite
{
- bool RealGenerateUIDTests();
public:
TestSuite();
~TestSuite();
bool DoSpaceSepStreamTests();
bool DoGenerateUIDTests();
};
-
-#endif
*/
-#ifndef THREADENGINE_H
-#define THREADENGINE_H
+#pragma once
#include <vector>
#include <string>
#include <map>
-#include "inspircd_config.h"
+#include "config.h"
#include "base.h"
class ThreadData;
*/
virtual void OnNotify() = 0;
};
-
-#endif
-
*/
-#ifndef THREADENGINE_PTHREAD_H
-#define THREADENGINE_PTHREAD_H
+#pragma once
#include <pthread.h>
#include "typedefs.h"
public:
ThreadSignalSocket* sock;
};
-
-
-#endif
*/
-#ifndef THREADENGINE_WIN32_H
-#define THREADENGINE_WIN32_H
+#pragma once
-#include "inspircd_config.h"
+#include "config.h"
#include "base.h"
class Thread;
connFD = -1;
}
};
-
-#endif
-
*/
-#ifndef INSPIRCD_TIMER_H
-#define INSPIRCD_TIMER_H
+#pragma once
+
+class Module;
/** Timer class for one-second resolution timers
* Timer provides a facility which allows module
* resolution. To use Timer, inherit a class from
* Timer, then insert your inherited class into the
* queue using Server::AddTimer(). The Tick() method of
- * your object (which you should override) will be called
+ * your object (which you have to override) will be called
* at the given time.
*/
class CoreExport Timer
{
- private:
/** The triggering time
*/
time_t trigger;
+
/** Number of seconds between triggers
*/
- long secs;
+ unsigned int secs;
+
/** True if this is a repeating timer
*/
bool repeat;
+
public:
/** Default constructor, initializes the triggering time
+ * @param mod The module that created this timer
* @param secs_from_now The number of seconds from now to trigger the timer
* @param now The time now
* @param repeating Repeat this timer every secs_from_now seconds if set to true
*/
- Timer(long secs_from_now, time_t now, bool repeating = false)
+ Timer(unsigned int secs_from_now, time_t now, bool repeating = false)
{
trigger = now + secs_from_now;
secs = secs_from_now;
repeat = repeating;
}
- /** Default destructor, does nothing.
+ /** Default destructor, removes the timer from the timer manager
*/
- virtual ~Timer() { }
+ virtual ~Timer();
/** Retrieve the current triggering time
*/
- virtual time_t GetTimer()
+ time_t GetTrigger() const
{
return trigger;
}
/** Sets the trigger timeout to a new value
+ * This does not update the bookkeeping in TimerManager, use SetInterval()
+ * to change the interval between ticks while keeping TimerManager updated
*/
- virtual void SetTimer(time_t t)
+ void SetTrigger(time_t nexttrigger)
{
- trigger = t;
+ trigger = nexttrigger;
}
+ /** Sets the interval between two ticks.
+ */
+ void SetInterval(time_t interval);
+
/** Called when the timer ticks.
* You should override this method with some useful code to
* handle the tick event.
*/
- virtual void Tick(time_t TIME) = 0;
+ virtual bool Tick(time_t TIME) = 0;
/** Returns true if this timer is set to repeat
*/
- bool GetRepeat()
+ bool GetRepeat() const
{
return repeat;
}
/** Returns the interval (number of seconds between ticks)
* of this timer object.
*/
- long GetSecs()
+ unsigned int GetInterval() const
{
return secs;
}
/** Cancels the repeat state of a repeating timer.
* If you call this method, then the next time your
* timer ticks, it will be removed immediately after.
- * You should use this method call to remove a recurring
- * timer if you wish to do so within the timer's Tick
- * event, as calling TimerManager::DelTimer() from within
- * the Timer::Tick() method is dangerous and may
- * cause a segmentation fault. Calling CancelRepeat()
- * is safe in this case.
*/
void CancelRepeat()
{
}
};
+typedef std::multimap<time_t, Timer*> TimerMap;
/** This class manages sets of Timers, and triggers them at their defined times.
* This will ensure timers are not missed, as well as removing timers that have
*/
class CoreExport TimerManager
{
- protected:
/** A list of all pending timers
*/
- std::vector<Timer *> Timers;
+ TimerMap Timers;
public:
- /** Constructor
- */
- TimerManager();
- ~TimerManager();
-
/** Tick all pending Timers
* @param TIME the current system time
*/
*/
void AddTimer(Timer *T);
- /** Delete an Timer
- * @param T an Timer derived class to delete
+ /** Remove a Timer
+ * @param T an Timer derived class to remove
*/
void DelTimer(Timer* T);
-
- /** Compares two timers
- */
- static bool TimerComparison( Timer *one, Timer*two);
};
-
-#endif
-
*/
-#ifndef TYPEDEFS_H
-#define TYPEDEFS_H
+#pragma once
class BanCacheManager;
class BanItem;
class Command;
class ConfigReader;
class ConfigTag;
-class DNSHeader;
-class DNSRequest;
class Extensible;
class FakeUser;
class InspIRCd;
class ServerLimits;
class Thread;
class User;
-class UserResolver;
class XLine;
class XLineManager;
class XLineFactory;
struct ConnectClass;
struct ModResult;
-struct ResourceRecord;
#include "hashcomp.h"
#include "base.h"
-#ifdef HASHMAP_DEPRECATED
- typedef nspace::hash_map<std::string, User*, nspace::insensitive, irc::StrHashComp> user_hash;
- typedef nspace::hash_map<std::string, Channel*, nspace::insensitive, irc::StrHashComp> chan_hash;
-#else
- typedef nspace::hash_map<std::string, User*, nspace::hash<std::string>, irc::StrHashComp> user_hash;
- typedef nspace::hash_map<std::string, Channel*, nspace::hash<std::string>, irc::StrHashComp> chan_hash;
-#endif
+typedef TR1NS::unordered_map<std::string, User*, irc::insensitive, irc::StrHashComp> user_hash;
+typedef TR1NS::unordered_map<std::string, Channel*, irc::insensitive, irc::StrHashComp> chan_hash;
/** A list holding local users, this is the type of UserManager::local_users
*/
/** A hash of commands used by the core
*/
-typedef nspace::hash_map<std::string,Command*> Commandtable;
+typedef TR1NS::unordered_map<std::string, Command*> Commandtable;
/** Membership list of a channel */
typedef std::map<User*, Membership*> UserMembList;
/** An interator in an XLineLookup
*/
typedef XLineLookup::iterator LookupIter;
-
-
-#endif
-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#pragma once
-/**
- * This is the maximum length of a UUID (unique user identifier).
- * This length is set in compliance with TS6 protocol, and really should not be changed. Ever.
- * It allows for a lot of clients as-is. -- w00t.
- */
-#define UUID_LENGTH 10
+class TestSuite;
+
+class CoreExport UIDGenerator
+{
+ friend class TestSuite;
+
+ /** Holds the current UID. Used to generate the next one.
+ */
+ std::string current_uid;
+
+ /** Increments the current UID by one.
+ */
+ void IncrementUID(unsigned int pos);
+
+ public:
+ /**
+ * This is the maximum length of a UUID (unique user identifier).
+ * This length is set in compliance with TS6 protocol, and really should not be changed. Ever.
+ * It allows for a lot of clients as-is. -- w00t.
+ */
+ static const unsigned int UUID_LENGTH = 9;
+
+ /** Initializes this UID generator with the given SID
+ * @param sid SID that conforms to InspIRCd::IsSID()
+ */
+ void init(const std::string& sid);
+ /** Returns the next available UID for this server.
+ */
+ std::string GetUID();
+ /** Generates a pseudorandom SID based on a servername and a description
+ * Guaranteed to return the same if invoked with the same parameters
+ * @param servername The server name to use as seed
+ * @param serverdesc The server description to use as seed
+ * @return A valid SID
+ */
+ static std::string GenerateSID(const std::string& servername, const std::string& serverdesc);
+};
*/
-#ifndef USERMANAGER_H
-#define USERMANAGER_H
+#pragma once
#include <list>
*/
clonemap global_clones;
+ /**
+ * Reset the already_sent IDs so we don't wrap it around and drop a message
+ * Also removes all expired invites
+ */
+ void GarbageCollect();
+
/** Add a client to the system.
* This will create a new User, insert it into the user_hash,
* initialize it as not yet registered, and add it to the socket engine.
*/
unsigned int LocalUserCount();
-
-
-
/** Number of users with a certain mode set on them
*/
int ModeCount(const char mode);
* @param ... The format arguments
*/
void ServerNoticeAll(const char* text, ...) CUSTOM_PRINTF(2, 3);
-
- /** Send a server message (PRIVMSG) to all local users
- * @param text The text format string to send
- * @param ... The format arguments
- */
- void ServerPrivmsgAll(const char* text, ...) CUSTOM_PRINTF(2, 3);
};
-
-#endif
*/
-#ifndef USERS_H
-#define USERS_H
+#pragma once
#include "socket.h"
#include "inspsocket.h"
-#include "dns.h"
#include "mode.h"
#include "membership.h"
*/
unsigned long limit;
+ /** If set to true, no user DNS lookups are to be performed
+ */
+ bool nouserdns;
+
/** Create a new connect class with no settings.
*/
ConnectClass(ConfigTag* tag, char type, const std::string& mask);
*/
time_t signon;
- /** Time that the connection last sent a message, used to calculate idle time
- */
- time_t idle_lastmsg;
-
/** Client address that the user is connected from.
* Do not modify this value directly, use SetClientIP() to change it.
* Port is not valid for remote users.
std::string awaymsg;
/** Time the user last went away.
- * This is ONLY RELIABLE if user IS_AWAY()!
+ * This is ONLY RELIABLE if user IsAway()!
*/
time_t awaytime;
*/
unsigned int registered:3;
- /** True when DNS lookups are completed.
- * The UserResolver classes res_forward and res_reverse will
- * set this value once they complete.
- */
- unsigned int dns_done:1;
-
/** Whether or not to send an snotice about this user's quitting
*/
unsigned int quietquit:1;
*/
unsigned int quitting:1;
- /** Recursion fix: user is out of SendQ and will be quit as soon as possible.
- * This can't be handled normally because QuitUser itself calls Write on other
- * users, which could trigger their SendQ to overrun.
- */
- unsigned int quitting_sendq:1;
-
- /** This is true if the user matched an exception (E:Line). It is used to save time on ban checks.
- */
- unsigned int exempt:1;
-
- /** has the user responded to their previous ping?
- */
- unsigned int lastping:1;
-
/** What type of user is this? */
const unsigned int usertype:2;
/** Get client IP string from sockaddr, using static internal buffer
* @return The IP string
*/
- const char* GetIPString();
+ const std::string& GetIPString();
/** Get CIDR mask, using default range, for this user
*/
*/
User(const std::string &uid, const std::string& srv, int objtype);
- /** Check if the user matches a G or K line, and disconnect them if they do.
- * @param doZline True if ZLines should be checked (if IP has changed since initial connect)
- * Returns true if the user matched a ban, false else.
- */
- bool CheckLines(bool doZline = false);
-
/** Returns the full displayed host of the user
* This member function returns the hostname of the user as seen by other users
* on the server, in nick!ident\@host form.
*/
std::string ProcessNoticeMasks(const char *sm);
+ /** Returns whether this user is currently away or not. If true,
+ * further information can be found in User::awaymsg and User::awaytime
+ * @return True if the user is away, false otherwise
+ */
+ bool IsAway() const { return (!awaymsg.empty()); }
+
+ /** Returns whether this user is an oper or not. If true,
+ * oper information can be obtained from User::oper
+ * @return True if the user is an oper, false otherwise
+ */
+ bool IsOper() const { return oper; }
+
/** Returns true if a notice mask is set
* @param sm A notice mask character to check
* @return True if the notice mask is set
*/
const std::string& MakeHostIP();
- /** Add the user to WHOWAS system
- */
- void AddToWhoWas();
-
/** Oper up the user using the given opertype.
* This will also give the +o usermode.
*/
* @param newnick The nickname to change to
* @return True if the nickchange was successful.
*/
- inline bool ForceNickChange(const char* newnick) { return ChangeNick(newnick, true); }
+ bool ForceNickChange(const std::string& newnick) { return ChangeNick(newnick, true); }
/** Oper down.
* This will clear the +o usermode and unset the user's oper type
*/
void WriteServ(const char* text, ...) CUSTOM_PRINTF(2, 3);
+ /** Sends a server notice to this user.
+ * @param text The contents of the message to send.
+ */
+ void WriteNotice(const std::string& text);
+
void WriteNumeric(unsigned int numeric, const char* text, ...) CUSTOM_PRINTF(3, 4);
void WriteNumeric(unsigned int numeric, const std::string &text);
*/
void SendAll(const char* command, const char* text, ...) CUSTOM_PRINTF(3, 4);
- /** Compile a channel list for this user. Used internally by WHOIS
- * @param source The user to prepare the channel list for
- * @param spy Whether to return the spy channel list rather than the normal one
- * @return This user's channel list
- */
- std::string ChannelList(User* source, bool spy);
-
- /** Split the channel list in cl which came from dest, and spool it to this user
- * Used internally by WHOIS
- * @param dest The user the original channel list came from
- * @param cl The channel list as a string obtained from User::ChannelList()
- */
- void SplitChanList(User* dest, const std::string &cl);
-
/** Remove this user from all channels they are on, and delete any that are now empty.
* This is used by QUIT, and will not send part messages!
*/
*/
int GetServerPort();
+ /** Recursion fix: user is out of SendQ and will be quit as soon as possible.
+ * This can't be handled normally because QuitUser itself calls Write on other
+ * users, which could trigger their SendQ to overrun.
+ */
+ unsigned int quitting_sendq:1;
+
+ /** has the user responded to their previous ping?
+ */
+ unsigned int lastping:1;
+
+ /** This is true if the user matched an exception (E:Line). It is used to save time on ban checks.
+ */
+ unsigned int exempt:1;
+
/** Used by PING checking code
*/
time_t nping;
+ /** Time that the connection last sent a message, used to calculate idle time
+ */
+ time_t idle_lastmsg;
+
/** This value contains how far into the penalty threshold the user is.
* This is used either to enable fake lag or for excess flood quits
*/
static already_sent_t already_sent_id;
already_sent_t already_sent;
- /** Stored reverse lookup from res_forward. Should not be used after resolution.
- */
- std::string stored_host;
-
- /** Starts a DNS lookup of the user's IP.
- * This will cause two UserResolver classes to be instantiated.
- * When complete, these objects set User::dns_done to true.
+ /** Check if the user matches a G or K line, and disconnect them if they do.
+ * @param doZline True if ZLines should be checked (if IP has changed since initial connect)
+ * Returns true if the user matched a ban, false else.
*/
- void StartDNSLookup();
+ bool CheckLines(bool doZline = false);
/** Use this method to fully connect a user.
* This will send the message of the day, check G/K/E lines, etc.
InviteList& GetInviteList();
/** Returns true if a user is invited to a channel.
- * @param channel A channel name to look up
+ * @param channel A channel to look up
* @return True if the user is invited to the given channel
*/
- bool IsInvited(const irc::string &channel);
-
- /** Adds a channel to a users invite list (invites them to a channel)
- * @param channel A channel name to add
- * @param timeout When the invite should expire (0 == never)
- */
- void InviteTo(const irc::string &channel, time_t timeout);
+ bool IsInvited(Channel* chan) { return (Invitation::Find(chan, this) != NULL); }
/** Removes a channel from a users invite list.
* This member function is called on successfully joining an invite only channel
* to which the user has previously been invited, to clear the invitation.
* @param channel The channel to remove the invite to
+ * @return True if the user was invited to the channel and the invite was erased, false if the user wasn't invited
*/
- void RemoveInvite(const irc::string &channel);
+ bool RemoveInvite(Channel* chan);
void RemoveExpiredInvites();
{
return u->usertype == USERTYPE_SERVER ? static_cast<FakeUser*>(u) : NULL;
}
-/** Is an oper */
-#define IS_OPER(x) (x->oper)
-/** Is away */
-#define IS_AWAY(x) (!x->awaymsg.empty())
-/** Derived from Resolver, and performs user forward/reverse lookups.
- */
-class CoreExport UserResolver : public Resolver
-{
- private:
- /** UUID we are looking up */
- std::string uuid;
- /** True if the lookup is forward, false if is a reverse lookup
- */
- bool fwd;
- public:
- /** Create a resolver.
- * @param user The user to begin lookup on
- * @param to_resolve The IP or host to resolve
- * @param qt The query type
- * @param cache Modified by the constructor if the result was cached
- */
- UserResolver(LocalUser* user, std::string to_resolve, QueryType qt, bool &cache);
-
- /** Called on successful lookup
- * @param result Result string
- * @param ttl Time to live for result
- * @param cached True if the result was found in the cache
- */
- void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached);
-
- /** Called on failed lookup
- * @param e Error code
- * @param errormessage Error message string
- */
- void OnError(ResolverError e, const std::string &errormessage);
-};
-
-#endif
*/
-#ifndef XLINE_H
-#define XLINE_H
+#pragma once
/** XLine is the base class for ban lines such as G lines and K lines.
* Modules may derive from this, and their xlines will automatically be
* line. Usually a line in the form 'expiring Xline blah, set by...'
* see the DisplayExpiry methods of GLine, ELine etc.
*/
- virtual void DisplayExpiry() = 0;
+ virtual void DisplayExpiry();
/** Returns the displayable form of the pattern for this xline,
* e.g. '*\@foo' or '*baz*'. This must always return the full pattern
* in a form which can be used to construct an entire derived xline,
* even if it is stored differently internally (e.g. GLine stores the
* ident and host parts seperately but will still return ident\@host
- * for its Displayable() method)
+ * for its Displayable() method).
*/
- virtual const char* Displayable() = 0;
+ virtual const std::string& Displayable() = 0;
/** Called when the xline has just been added.
*/
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
virtual bool IsBurstable();
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** Ident mask (ident part only)
*/
virtual void Unset();
- virtual void DisplayExpiry();
-
virtual void OnAdd();
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** Ident mask (ident part only)
*/
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** IP mask (no ident part)
*/
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** Nickname mask
*/
void InvokeStats(const std::string &type, int numeric, User* user, string_list &results);
};
-#endif
while (<$in>) {
if (/^\s*#\s*include\s*"([^"]+)"/) {
my $inc = $1;
- next if $inc eq 'inspircd_version.h' && $f eq '../include/inspircd.h';
+ next if $inc eq 'config.h' && $f eq '../include/inspircd.h';
my $found = 0;
for my $loc ("$basedir/$inc", "../include/$inc") {
next unless -e $loc;
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- *
- * 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/epoll.h>
-
-int main() {
- int fd = epoll_create(1);
- return (fd < 0);
-}
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- *
- * 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/eventfd.h>
-
-int main() {
- eventfd_t efd_data;
- int fd;
-
- fd = eventfd(0, EFD_NONBLOCK);
- eventfd_read(fd, &efd_data);
-
- return (fd < 0);
-}
use Exporter 'import';
use POSIX;
use make::utilities;
-our @EXPORT = qw(promptnumeric dumphash is_dir getmodules getrevision getcompilerflags getlinkerflags getdependencies nopedantic resolve_directory yesno showhelp promptstring_s module_installed);
+our @EXPORT = qw(test_file test_header promptnumeric dumphash is_dir getmodules getrevision getcompilerflags getlinkerflags getdependencies nopedantic resolve_directory yesno showhelp promptstring_s module_installed);
my $no_git = 0;
+sub test_file($$;$) {
+ my ($cc, $file, $args) = @_;
+ my $status = 0;
+ $args ||= '';
+ $status ||= system "$cc -o __test_$file make/test/$file $args >/dev/null 2>&1";
+ $status ||= system "./__test_$file >/dev/null 2>&1";
+ unlink "./__test_$file";
+ return !$status;
+}
+
+sub test_header($$;$) {
+ my ($cc, $header, $args) = @_;
+ $args ||= '';
+ open(CC, "| $cc -E - $args >/dev/null 2>&1") or return 0;
+ print CC "#include <$header>";
+ close(CC);
+ return !$?;
+}
+
sub yesno {
my ($flag,$prompt) = @_;
print "$prompt [\e[1;32m$main::config{$flag}\e[0m] -> ";
to select() [not set]
--disable-kqueue Do not enable kqueue(), fall back
to select() [not set]
- --disable-ipv6 Do not build IPv6 native InspIRCd [not set]
--with-cc=[filename] Use an alternative compiler to
build InspIRCd [g++]
--with-maxbuf=[n] Change the per message buffer size [512]
+++ /dev/null
-#
-# InspIRCd -- Internet Relay Chat Daemon
-#
-# Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
-# Copyright (C) 2007 Craig Edwards <craigedwards@brainbox.cc>
-#
-# 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/>.
-#
-
-
-package make::gnutlscert;
-
-require 5.8.0;
-
-use strict;
-use warnings FATAL => qw(all);
-
-use Exporter 'import';
-use make::configure;
-our @EXPORT = qw(make_gnutls_cert);
-
-
-sub make_gnutls_cert()
-{
- open (FH, ">certtool.template");
- my $timestr = time();
- my $org = promptstring_s("Please enter the organization name", "My IRC Network");
- my $unit = promptstring_s("Please enter the unit Name", "Server Admins");
- my $state = promptstring_s("Please enter your state (two letter code)", "CA");
- my $country = promptstring_s("Please enter your country", "Oompa Loompa Land");
- my $commonname = promptstring_s("Please enter the certificate common name (hostname)", "irc.mynetwork.com");
- my $email = promptstring_s("Please enter a contact email address", "oompa\@loompa.com");
- print FH <<__END__;
-# X.509 Certificate options
-#
-# DN options
-
-# The organization of the subject.
-organization = "$org"
-
-# The organizational unit of the subject.
-unit = "$unit"
-
-# The locality of the subject.
-# locality =
-
-# The state of the certificate owner.
-state = "$state"
-
-# The country of the subject. Two letter code.
-country = $country
-
-# The common name of the certificate owner.
-cn = "$commonname"
-
-# A user id of the certificate owner.
-#uid = "clauper"
-
-# If the supported DN OIDs are not adequate you can set
-# any OID here.
-# For example set the X.520 Title and the X.520 Pseudonym
-# by using OID and string pairs.
-#dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal"
-
-# This is deprecated and should not be used in new
-# certificates.
-# pkcs9_email = "none\@none.org"
-
-# The serial number of the certificate
-serial = $timestr
-
-# In how many days, counting from today, this certificate will expire.
-expiration_days = 700
-
-# X.509 v3 extensions
-
-# A dnsname in case of a WWW server.
-#dns_name = "www.none.org"
-
-# An IP address in case of a server.
-#ip_address = "192.168.1.1"
-
-# An email in case of a person
-email = "$email"
-
-# An URL that has CRLs (certificate revocation lists)
-# available. Needed in CA certificates.
-#crl_dist_points = "http://www.getcrl.crl/getcrl/"
-
-# Whether this is a CA certificate or not
-#ca
-
-# Whether this certificate will be used for a TLS client
-tls_www_client
-
-# Whether this certificate will be used for a TLS server
-tls_www_server
-
-# Whether this certificate will be used to sign data (needed
-# in TLS DHE ciphersuites).
-signing_key
-
-# Whether this certificate will be used to encrypt data (needed
-# in TLS RSA ciphersuites). Note that it is prefered to use different
-# keys for encryption and signing.
-encryption_key
-
-# Whether this key will be used to sign other certificates.
-cert_signing_key
-
-# Whether this key will be used to sign CRLs.
-crl_signing_key
-
-# Whether this key will be used to sign code.
-code_signing_key
-
-# Whether this key will be used to sign OCSP data.
-ocsp_signing_key
-
-# Whether this key will be used for time stamping.
-time_stamping_key
-__END__
-close(FH);
-my $certtool = "certtool";
-if (`uname -s` eq "Darwin\n") {
- # On OS X the certtool binary name is different to prevent
- # collisions with the system certtool from NSS.
- $certtool = "gnutls-certtool";
-}
-if ( (my $status = system("$certtool --generate-privkey --outfile key.pem")) ne 0) { return 1; }
-if ( (my $status = system("$certtool --generate-self-signed --load-privkey key.pem --outfile cert.pem --template certtool.template")) ne 0) { return 1; }
-unlink("certtool.template");
-return 0;
-}
-
-1;
-
+++ /dev/null
-#
-# InspIRCd -- Internet Relay Chat Daemon
-#
-# Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
-# Copyright (C) 2007 Craig Edwards <craigedwards@brainbox.cc>
-#
-# 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/>.
-#
-
-
-package make::opensslcert;
-
-require 5.8.0;
-
-use strict;
-use warnings FATAL => qw(all);
-
-use Exporter 'import';
-use make::configure;
-our @EXPORT = qw(make_openssl_cert);
-
-
-sub make_openssl_cert()
-{
- open (FH, ">openssl.template");
- my $org = promptstring_s("Please enter the organization name", "My IRC Network");
- my $unit = promptstring_s("Please enter the unit Name", "Server Admins");
- my $country = promptstring_s("Please enter your country (two letter code)", "US");
- my $state = promptstring_s("Please enter your state or locality name", "Alaska");
- my $city = promptstring_s("Please enter your city", "Factory Town");
- my $email = promptstring_s("Please enter a contact email address", "oompa\@loompa.com");
- my $commonname = promptstring_s("Please enter the common name (domain name) of the irc server", "example.inspircd.org");
- print FH <<__END__;
-$country
-$state
-$city
-$org
-$unit
-$commonname
-$email
-__END__
-close(FH);
-
-my $time = promptstring_s("Please enter the number of days that this certificate is valid for","365");
-
-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");
-unlink("openssl.template");
-}
-
-1;
[ $(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_BIN) tools/genssl $(BINPATH)/inspircd-genssl 2>/dev/null
-$(INSTALL) -m $(INSTMODE_LIB) tools/gdbargs $(BASE)/.gdbargs 2>/dev/null
-$(INSTALL) -m $(INSTMODE_LIB) docs/conf/*.example $(CONPATH)/examples
-$(INSTALL) -m $(INSTMODE_LIB) docs/conf/aliases/*.example $(CONPATH)/examples/aliases
rm -f .config.cache
rm -f BSDmakefile
rm -f GNUmakefile
- rm -f include/inspircd_config.h
- rm -f include/inspircd_version.h
+ rm -f include/config.h
rm -f inspircd
-rm -f org.inspircd.plist
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *
+ * 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 <time.h>
+
+int main() {
+ timespec time_spec;
+ clock_gettime(CLOCK_REALTIME, &time_spec);
+ return 0;
+}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *
+ * 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/eventfd.h>
+
+int main() {
+ eventfd_t efd_data;
+ int fd;
+
+ fd = eventfd(0, EFD_NONBLOCK);
+ eventfd_read(fd, &efd_data);
+
+ return (fd < 0);
+}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *
+ * 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);
+}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *
+ * 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/socket.h>
+
+#ifndef SO_ACCEPTFILTER
+ #error
+#endif
+
+int main()
+{
+ return 0;
+}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *
+ * 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 <netinet/tcp.h>
+
+#ifndef TCP_DEFER_ACCEPT
+ #error
+#endif
+
+int main()
+{
+ return 0;
+}
#include "inspircd.h"
#include "bancache.h"
-BanCacheHit *BanCacheManager::AddHit(const std::string &ip, const std::string &type, const std::string &reason)
-{
- BanCacheHit *b;
-
- if (this->BanHash->find(ip) != this->BanHash->end()) // can't have two cache entries on the same IP, sorry..
- return NULL;
-
- b = new BanCacheHit(ip, type, reason);
-
- this->BanHash->insert(std::make_pair(ip, b));
- return b;
-}
-
BanCacheHit *BanCacheManager::AddHit(const std::string &ip, const std::string &type, const std::string &reason, time_t seconds)
{
- BanCacheHit *b;
-
- if (this->BanHash->find(ip) != this->BanHash->end()) // can't have two cache entries on the same IP, sorry..
+ BanCacheHit*& b = (*BanHash)[ip];
+ if (b != NULL) // can't have two cache entries on the same IP, sorry..
return NULL;
- b = new BanCacheHit(ip, type, reason, seconds);
-
- this->BanHash->insert(std::make_pair(ip, b));
+ b = new BanCacheHit(type, reason, (seconds ? seconds : 86400));
return b;
}
if (i == this->BanHash->end())
return NULL; // free and safe
- else
- {
- if (ServerInstance->Time() > i->second->Expiry)
- {
- ServerInstance->Logs->Log("BANCACHE", DEBUG, "Hit on " + ip + " is out of date, removing!");
- RemoveHit(i->second);
- return NULL; // out of date
- }
- return i->second; // hit.
- }
+ if (RemoveIfExpired(i))
+ return NULL; // expired
+
+ return i->second; // hit.
}
-bool BanCacheManager::RemoveHit(BanCacheHit *b)
+bool BanCacheManager::RemoveIfExpired(BanCacheHash::iterator& it)
{
- BanCacheHash::iterator i;
-
- if (!b)
- return false; // I don't think so.
-
- i = this->BanHash->find(b->IP);
-
- if (i == this->BanHash->end())
- {
- // err..
- ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCacheManager::RemoveHit(): I got asked to remove a hit that wasn't in the hash(?)");
- }
- else
- {
- this->BanHash->erase(i);
- }
+ if (ServerInstance->Time() < it->second->Expiry)
+ return false;
- delete b;
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "Hit on " + it->first + " is out of date, removing!");
+ delete it->second;
+ it = BanHash->erase(it);
return true;
}
-unsigned int BanCacheManager::RemoveEntries(const std::string &type, bool positive)
+void BanCacheManager::RemoveEntries(const std::string& type, bool positive)
{
- int removed = 0;
-
- BanCacheHash::iterator safei;
-
if (positive)
- ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCacheManager::RemoveEntries(): Removing positive hits for " + type);
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCacheManager::RemoveEntries(): Removing positive hits for " + type);
else
- ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCacheManager::RemoveEntries(): Removing negative hits for " + type);
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCacheManager::RemoveEntries(): Removing all negative hits");
- for (BanCacheHash::iterator n = BanHash->begin(); n != BanHash->end(); )
+ for (BanCacheHash::iterator i = BanHash->begin(); i != BanHash->end(); )
{
- safei = n;
- safei++;
+ if (RemoveIfExpired(i))
+ continue; // updates the iterator if expired
- BanCacheHit *b = n->second;
+ BanCacheHit* b = i->second;
+ bool remove = false;
- /* Safe to delete items here through iterator 'n' */
- if (b->Type == type || !positive) // if removing negative hits, ignore type..
+ if (positive)
{
- if ((positive && !b->Reason.empty()) || b->Reason.empty())
- {
- /* we need to remove this one. */
- ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCacheManager::RemoveEntries(): Removing a hit on " + b->IP);
- delete b;
- BanHash->erase(n); // WORD TO THE WISE: don't use RemoveHit here, because we MUST remove the iterator in a safe way.
- removed++;
- }
+ // when removing positive hits, remove only if the type matches
+ remove = b->IsPositive() && (b->Type == type);
+ }
+ else
+ {
+ // when removing negative hits, remove all of them
+ remove = !b->IsPositive();
}
- /* End of safe section */
- n = safei;
- }
-
-
- return removed;
-}
-
-void BanCacheManager::RehashCache()
-{
- BanCacheHash* NewHash = new BanCacheHash();
-
- BanCacheHash::iterator safei;
- for (BanCacheHash::iterator n = BanHash->begin(); n != BanHash->end(); )
- {
- safei = n;
- safei++;
-
- /* Safe to delete items here through iterator 'n' */
- BanCacheHit *b = n->second;
-
- if (ServerInstance->Time() > b->Expiry)
+ if (remove)
{
/* we need to remove this one. */
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCacheManager::RemoveEntries(): Removing a hit on " + i->first);
delete b;
- BanHash->erase(n); // WORD TO THE WISE: don't use RemoveHit here, because we MUST remove the iterator in a safe way.
+ i = BanHash->erase(i);
}
else
- {
- /* Actually inserts a std::pair */
- NewHash->insert(*n);
- }
-
- /* End of safe section */
-
- n = safei;
+ ++i;
}
-
- delete BanHash;
- BanHash = NewHash;
}
BanCacheManager::~BanCacheManager()
classbase::classbase()
{
if (ServerInstance && ServerInstance->Logs)
- ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::+ @%p", (void*)this);
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::+ @%p", (void*)this);
}
CullResult classbase::cull()
{
if (ServerInstance && ServerInstance->Logs)
- ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::-%s @%p",
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::-%s @%p",
typeid(*this).name(), (void*)this);
return CullResult();
}
classbase::~classbase()
{
if (ServerInstance && ServerInstance->Logs)
- ServerInstance->Logs->Log("CULLLIST", DEBUG, "classbase::~ @%p", (void*)this);
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "classbase::~ @%p", (void*)this);
}
CullResult::CullResult()
refcountbase::~refcountbase()
{
if (refcount && ServerInstance && ServerInstance->Logs)
- ServerInstance->Logs->Log("CULLLIST", DEBUG, "refcountbase::~ @%p with refcount %d",
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "refcountbase::~ @%p with refcount %d",
(void*)this, refcount);
}
usecountbase::~usecountbase()
{
if (usecount && ServerInstance && ServerInstance->Logs)
- ServerInstance->Logs->Log("CULLLIST", DEBUG, "usecountbase::~ @%p with refcount %d",
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "usecountbase::~ @%p with refcount %d",
(void*)this, usecount);
}
Extensible::~Extensible()
{
if (!extensions.empty() && ServerInstance && ServerInstance->Logs)
- ServerInstance->Logs->Log("CULLLIST", DEBUG,
- "Extensible destructor called without cull @%p", (void*)this);
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "Extensible destructor called without cull @%p", (void*)this);
}
LocalExtItem::LocalExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
/* $Core */
#include "inspircd.h"
+#include "listmode.h"
#include <cstdarg>
#include "mode.h"
+static ModeReference ban(NULL, "ban");
+
Channel::Channel(const std::string &cname, time_t ts)
{
if (!ServerInstance->chanlist->insert(std::make_pair(cname, this)).second)
this->name = cname;
this->age = ts ? ts : ServerInstance->Time();
- maxbans = topicset = 0;
+ topicset = 0;
modes.reset();
}
int Channel::SetTopic(User *u, std::string &ntopic, bool forceset)
{
- if (!u)
- u = ServerInstance->FakeClient;
if (IS_LOCAL(u) && !forceset)
{
ModResult res;
}
this->topic.assign(ntopic, 0, ServerInstance->Config->Limits.MaxTopic);
- if (u)
- {
- this->setby.assign(ServerInstance->Config->FullHostInTopic ? u->GetFullHost() : u->nick, 0, 128);
- this->WriteChannel(u, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
- }
- else
- {
- this->setby.assign(ServerInstance->Config->ServerName);
- this->WriteChannelWithServ(ServerInstance->Config->ServerName, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
- }
-
+ this->setby.assign(ServerInstance->Config->FullHostInTopic ? u->GetFullHost() : u->nick, 0, 128);
+ this->WriteChannel(u, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
this->topicset = ServerInstance->Time();
FOREACH_MOD(I_OnPostTopicChange,OnPostTopicChange(u, this, this->topic));
return CMD_SUCCESS;
}
-long Channel::GetUserCounter()
-{
- return userlist.size();
-}
-
Membership* Channel::AddUser(User* user)
{
- Membership* memb = new Membership(user, this);
- userlist[user] = memb;
+ Membership*& memb = userlist[user];
+ if (memb)
+ return NULL;
+
+ memb = new Membership(user, this);
return memb;
}
void Channel::DelUser(User* user)
{
- UserMembIter a = userlist.find(user);
+ UserMembIter it = userlist.find(user);
+ if (it != userlist.end())
+ DelUser(it);
+}
- if (a != userlist.end())
- {
- a->second->cull();
- delete a->second;
- userlist.erase(a);
- }
+void Channel::CheckDestroy()
+{
+ if (!userlist.empty())
+ return;
- if (userlist.empty())
- {
- ModResult res;
- FIRST_MOD_RESULT(OnChannelPreDelete, res, (this));
- if (res == MOD_RES_DENY)
- return;
- chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
- /* kill the record */
- if (iter != ServerInstance->chanlist->end())
- {
- FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
- ServerInstance->chanlist->erase(iter);
- }
+ ModResult res;
+ FIRST_MOD_RESULT(OnChannelPreDelete, res, (this));
+ if (res == MOD_RES_DENY)
+ return;
- ClearInvites();
- ServerInstance->GlobalCulls.AddItem(this);
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
+ /* kill the record */
+ if (iter != ServerInstance->chanlist->end())
+ {
+ FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
+ ServerInstance->chanlist->erase(iter);
}
+
+ ClearInvites();
+ ServerInstance->GlobalCulls.AddItem(this);
}
-bool Channel::HasUser(User* user)
+void Channel::DelUser(const UserMembIter& membiter)
{
- return (userlist.find(user) != userlist.end());
+ Membership* memb = membiter->second;
+ memb->cull();
+ delete memb;
+ userlist.erase(membiter);
+
+ // If this channel became empty then it should be removed
+ CheckDestroy();
}
Membership* Channel::GetUser(User* user)
return i->second;
}
-const UserMembList* Channel::GetUsers()
-{
- return &userlist;
-}
-
void Channel::SetDefaultModes()
{
- ServerInstance->Logs->Log("CHANNELS", DEBUG, "SetDefaultModes %s",
+ ServerInstance->Logs->Log("CHANNELS", LOG_DEBUG, "SetDefaultModes %s",
ServerInstance->Config->DefaultModes.c_str());
irc::spacesepstream list(ServerInstance->Config->DefaultModes);
std::string modeseq;
* add a channel to a user, creating the record for it if needed and linking
* it to the user record
*/
-Channel* Channel::JoinUser(User *user, const char* cn, bool override, const char* key, bool bursting, time_t TS)
+Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, const std::string& key)
{
- // Fix: unregistered users could be joined using /SAJOIN
- if (!user || !cn || user->registered != REG_ALL)
+ if (user->registered != REG_ALL)
+ {
+ ServerInstance->Logs->Log("CHANNELS", LOG_DEBUG, "Attempted to join unregistered user " + user->uuid + " to channel " + cname);
return NULL;
-
- std::string privs;
- Channel *Ptr;
+ }
/*
* We don't restrict the number of channels that remote users or users that are override-joining may be in.
* We restrict local operators to OperMaxChans channels.
* This is a lot more logical than how it was formerly. -- w00t
*/
- if (IS_LOCAL(user) && !override)
+ if (!override)
{
if (user->HasPrivPermission("channels/high-join-limit"))
{
if (user->chans.size() >= ServerInstance->Config->OperMaxChans)
{
- user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
+ user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cname.c_str());
return NULL;
}
}
maxchans = ServerInstance->Config->MaxChans;
if (user->chans.size() >= maxchans)
{
- user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
+ user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cname.c_str());
return NULL;
}
}
}
- std::string cname;
- cname.assign(std::string(cn), 0, ServerInstance->Config->Limits.ChanMax);
- Ptr = ServerInstance->FindChan(cname);
- bool created_by_local = false;
+ // Crop channel name if it's too long
+ if (cname.length() > ServerInstance->Config->Limits.ChanMax)
+ cname.resize(ServerInstance->Config->Limits.ChanMax);
+
+ Channel* chan = ServerInstance->FindChan(cname);
+ bool created_by_local = (chan == NULL); // Flag that will be passed to modules in the OnUserJoin() hook later
+ std::string privs; // Prefix mode(letter)s to give to the joining user
- if (!Ptr)
+ if (!chan)
{
- /*
- * Fix: desync bug was here, don't set @ on remote users - spanningtree handles their permissions. bug #358. -- w00t
- */
- if (!IS_LOCAL(user))
- {
- if (!TS)
- ServerInstance->Logs->Log("CHANNELS",DEBUG,"*** BUG *** Channel::JoinUser called for REMOTE user '%s' on channel '%s' but no TS given!", user->nick.c_str(), cn);
- }
- else
- {
- privs = "o";
- created_by_local = true;
- }
+ privs = "o";
- if (IS_LOCAL(user) && override == false)
+ if (override == false)
{
+ // Ask the modules whether they're ok with the join, pass NULL as Channel* as the channel is yet to be created
ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, NULL, cname.c_str(), privs, key ? key : ""));
+ FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, NULL, cname, privs, key));
if (MOD_RESULT == MOD_RES_DENY)
- return NULL;
+ return NULL; // A module wasn't happy with the join, abort
}
- Ptr = new Channel(cname, TS);
+ chan = new Channel(cname, ServerInstance->Time());
+ // Set the default modes on the channel (<options:defaultmodes>)
+ chan->SetDefaultModes();
}
else
{
/* Already on the channel */
- if (Ptr->HasUser(user))
+ if (chan->HasUser(user))
return NULL;
- /*
- * remote users are allowed us to bypass channel modes
- * and bans (used by servers)
- */
- if (IS_LOCAL(user) && override == false)
+ if (override == false)
{
ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, Ptr, cname.c_str(), privs, key ? key : ""));
+ FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, chan, cname, privs, key));
+
+ // A module explicitly denied the join and (hopefully) generated a message
+ // describing the situation, so we may stop here without sending anything
if (MOD_RESULT == MOD_RES_DENY)
- {
return NULL;
- }
- else if (MOD_RESULT == MOD_RES_PASSTHRU)
+
+ // If no module returned MOD_RES_DENY or MOD_RES_ALLOW (which is the case
+ // most of the time) then proceed to check channel modes +k, +i, +l and bans,
+ // in this order.
+ // If a module explicitly allowed the join (by returning MOD_RES_ALLOW),
+ // then this entire section is skipped
+ if (MOD_RESULT == MOD_RES_PASSTHRU)
{
- std::string ckey = Ptr->GetModeParameter('k');
- bool invited = IS_LOCAL(user)->IsInvited(Ptr->name.c_str());
+ std::string ckey = chan->GetModeParameter('k');
+ bool invited = user->IsInvited(chan);
bool can_bypass = ServerInstance->Config->InvBypassModes && invited;
if (!ckey.empty())
{
- FIRST_MOD_RESULT(OnCheckKey, MOD_RESULT, (user, Ptr, key ? key : ""));
- if (!MOD_RESULT.check((key && ckey == key) || can_bypass))
+ FIRST_MOD_RESULT(OnCheckKey, MOD_RESULT, (user, chan, key));
+ if (!MOD_RESULT.check((ckey == key) || can_bypass))
{
// If no key provided, or key is not the right one, and can't bypass +k (not invited or option not enabled)
- user->WriteNumeric(ERR_BADCHANNELKEY, "%s %s :Cannot join channel (Incorrect channel key)",user->nick.c_str(), Ptr->name.c_str());
+ user->WriteNumeric(ERR_BADCHANNELKEY, "%s %s :Cannot join channel (Incorrect channel key)",user->nick.c_str(), chan->name.c_str());
return NULL;
}
}
- if (Ptr->IsModeSet('i'))
+ if (chan->IsModeSet('i'))
{
- FIRST_MOD_RESULT(OnCheckInvite, MOD_RESULT, (user, Ptr));
+ FIRST_MOD_RESULT(OnCheckInvite, MOD_RESULT, (user, chan));
if (!MOD_RESULT.check(invited))
{
- user->WriteNumeric(ERR_INVITEONLYCHAN, "%s %s :Cannot join channel (Invite only)",user->nick.c_str(), Ptr->name.c_str());
+ user->WriteNumeric(ERR_INVITEONLYCHAN, "%s %s :Cannot join channel (Invite only)",user->nick.c_str(), chan->name.c_str());
return NULL;
}
}
- std::string limit = Ptr->GetModeParameter('l');
+ std::string limit = chan->GetModeParameter('l');
if (!limit.empty())
{
- FIRST_MOD_RESULT(OnCheckLimit, MOD_RESULT, (user, Ptr));
- if (!MOD_RESULT.check((Ptr->GetUserCounter() < atol(limit.c_str()) || can_bypass)))
+ FIRST_MOD_RESULT(OnCheckLimit, MOD_RESULT, (user, chan));
+ if (!MOD_RESULT.check((chan->GetUserCounter() < atol(limit.c_str()) || can_bypass)))
{
- user->WriteNumeric(ERR_CHANNELISFULL, "%s %s :Cannot join channel (Channel is full)",user->nick.c_str(), Ptr->name.c_str());
+ user->WriteNumeric(ERR_CHANNELISFULL, "%s %s :Cannot join channel (Channel is full)",user->nick.c_str(), chan->name.c_str());
return NULL;
}
}
- if (Ptr->IsBanned(user) && !can_bypass)
+ if (chan->IsBanned(user) && !can_bypass)
{
- user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)",user->nick.c_str(), Ptr->name.c_str());
+ user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)",user->nick.c_str(), chan->name.c_str());
return NULL;
}
*/
if (invited)
{
- IS_LOCAL(user)->RemoveInvite(Ptr->name.c_str());
+ user->RemoveInvite(chan);
}
}
}
}
- if (created_by_local)
- {
- /* As spotted by jilles, dont bother to set this on remote users */
- Ptr->SetDefaultModes();
- }
-
- return Channel::ForceChan(Ptr, user, privs, bursting, created_by_local);
+ // We figured that this join is allowed and also created the
+ // channel if it didn't exist before, now do the actual join
+ chan->ForceJoin(user, &privs, false, created_by_local);
+ return chan;
}
-Channel* Channel::ForceChan(Channel* Ptr, User* user, const std::string &privs, bool bursting, bool created)
+void Channel::ForceJoin(User* user, const std::string* privs, bool bursting, bool created_by_local)
{
- std::string nick = user->nick;
+ Membership* memb = this->AddUser(user);
+ if (!memb)
+ return; // Already on the channel
+
+ if (IS_SERVER(user))
+ {
+ ServerInstance->Logs->Log("CHANNELS", LOG_DEBUG, "Attempted to join server user " + user->uuid + " to channel " + this->name);
+ return;
+ }
- Membership* memb = Ptr->AddUser(user);
- user->chans.insert(Ptr);
+ user->chans.insert(this);
- for (std::string::const_iterator x = privs.begin(); x != privs.end(); x++)
+ if (privs)
{
- const char status = *x;
- ModeHandler* mh = ServerInstance->Modes->FindMode(status, MODETYPE_CHANNEL);
- if (mh)
+ // If the user was granted prefix modes (in the OnUserPreJoin hook, or he's a
+ // remote user and his own server set the modes), then set them internally now
+ memb->modes = *privs;
+ for (std::string::const_iterator i = privs->begin(); i != privs->end(); ++i)
{
- /* Set, and make sure that the mode handler knows this mode was now set */
- Ptr->SetPrefix(user, mh->GetModeChar(), true);
- mh->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, Ptr, nick, true);
+ ModeHandler* mh = ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL);
+ if (mh)
+ {
+ std::string nick = user->nick;
+ /* Set, and make sure that the mode handler knows this mode was now set */
+ this->SetPrefix(user, mh->GetModeChar(), true);
+ mh->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, nick, true);
+ }
}
}
+ // Tell modules about this join, they have the chance now to populate except_list with users we won't send the JOIN (and possibly MODE) to
CUList except_list;
- FOREACH_MOD(I_OnUserJoin,OnUserJoin(memb, bursting, created, except_list));
+ FOREACH_MOD(I_OnUserJoin,OnUserJoin(memb, bursting, created_by_local, except_list));
- Ptr->WriteAllExcept(user, false, 0, except_list, "JOIN :%s", Ptr->name.c_str());
+ this->WriteAllExcept(user, false, 0, except_list, "JOIN :%s", this->name.c_str());
/* Theyre not the first ones in here, make sure everyone else sees the modes we gave the user */
- if ((Ptr->GetUserCounter() > 1) && (!memb->modes.empty()))
+ if ((GetUserCounter() > 1) && (!memb->modes.empty()))
{
std::string ms = memb->modes;
for(unsigned int i=0; i < memb->modes.length(); i++)
ms.append(" ").append(user->nick);
except_list.insert(user);
- Ptr->WriteAllExcept(user, !ServerInstance->Config->CycleHostsFromUser, 0, except_list, "MODE %s +%s", Ptr->name.c_str(), ms.c_str());
+ this->WriteAllExcept(user, !ServerInstance->Config->CycleHostsFromUser, 0, except_list, "MODE %s +%s", this->name.c_str(), ms.c_str());
}
if (IS_LOCAL(user))
{
- if (Ptr->topicset)
+ if (this->topicset)
{
- user->WriteNumeric(RPL_TOPIC, "%s %s :%s", user->nick.c_str(), Ptr->name.c_str(), Ptr->topic.c_str());
- user->WriteNumeric(RPL_TOPICTIME, "%s %s %s %lu", user->nick.c_str(), Ptr->name.c_str(), Ptr->setby.c_str(), (unsigned long)Ptr->topicset);
+ user->WriteNumeric(RPL_TOPIC, "%s %s :%s", user->nick.c_str(), this->name.c_str(), this->topic.c_str());
+ user->WriteNumeric(RPL_TOPICTIME, "%s %s %s %lu", user->nick.c_str(), this->name.c_str(), this->setby.c_str(), (unsigned long)this->topicset);
}
- Ptr->UserList(user);
+ this->UserList(user);
}
+
FOREACH_MOD(I_OnPostJoin,OnPostJoin(memb));
- return Ptr;
}
bool Channel::IsBanned(User* user)
if (result != MOD_RES_PASSTHRU)
return (result == MOD_RES_DENY);
- for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++)
+ ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
+ const ListModeBase::ModeList* bans = banlm->GetList(this);
+ if (bans)
{
- if (CheckBan(user, i->data))
- return true;
+ for (ListModeBase::ModeList::const_iterator it = bans->begin(); it != bans->end(); it++)
+ {
+ if (CheckBan(user, it->mask))
+ return true;
+ }
}
return false;
}
if (at == std::string::npos)
return false;
- char tomatch[MAXBUF];
- snprintf(tomatch, MAXBUF, "%s!%s", user->nick.c_str(), user->ident.c_str());
+ const std::string nickIdent = user->nick + "!" + user->ident;
std::string prefix = mask.substr(0, at);
- if (InspIRCd::Match(tomatch, prefix, NULL))
+ if (InspIRCd::Match(nickIdent, prefix, NULL))
{
std::string suffix = mask.substr(at + 1);
if (InspIRCd::Match(user->host, suffix, NULL) ||
FIRST_MOD_RESULT(OnExtBanCheck, rv, (user, this, type));
if (rv != MOD_RES_PASSTHRU)
return rv;
- for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++)
+
+ ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
+ const ListModeBase::ModeList* bans = banlm->GetList(this);
+ if (bans)
+
{
- if (i->data[0] == type && i->data[1] == ':')
+ for (ListModeBase::ModeList::const_iterator it = bans->begin(); it != bans->end(); ++it)
{
- std::string val = i->data.substr(2);
- if (CheckBan(user, val))
+ if (CheckBan(user, it->mask))
return MOD_RES_DENY;
}
}
}
/* Channel::PartUser
- * remove a channel from a users record, and return the number of users left.
- * Therefore, if this function returns 0 the caller should delete the Channel.
+ * Remove a channel from a users record, remove the reference to the Membership object
+ * from the channel and destroy it.
*/
void Channel::PartUser(User *user, std::string &reason)
{
- if (!user)
- return;
-
- Membership* memb = GetUser(user);
+ UserMembIter membiter = userlist.find(user);
- if (memb)
+ if (membiter != userlist.end())
{
+ Membership* memb = membiter->second;
CUList except_list;
FOREACH_MOD(I_OnUserPart,OnUserPart(memb, reason, except_list));
WriteAllExcept(user, false, 0, except_list, "PART %s%s%s", this->name.c_str(), reason.empty() ? "" : " :", reason.c_str());
+ // Remove this channel from the user's chanlist
user->chans.erase(this);
- this->RemoveAllPrefixes(user);
+ // Remove the Membership from this channel's userlist and destroy it
+ this->DelUser(membiter);
}
-
- this->DelUser(user);
}
-void Channel::KickUser(User *src, User *user, const char* reason)
+void Channel::KickUser(User* src, User* victim, const std::string& reason, Membership* srcmemb)
{
- if (!src || !user || !reason)
+ UserMembIter victimiter = userlist.find(victim);
+ Membership* memb = ((victimiter != userlist.end()) ? victimiter->second : NULL);
+
+ if (!memb)
+ {
+ src->WriteNumeric(ERR_USERNOTINCHANNEL, "%s %s %s :They are not on that channel",src->nick.c_str(), victim->nick.c_str(), this->name.c_str());
return;
+ }
- Membership* memb = GetUser(user);
+ // Do the following checks only if the KICK is done by a local user;
+ // each server enforces its own rules.
if (IS_LOCAL(src))
{
- if (!memb)
- {
- src->WriteNumeric(ERR_USERNOTINCHANNEL, "%s %s %s :They are not on that channel",src->nick.c_str(), user->nick.c_str(), this->name.c_str());
- return;
- }
- if ((ServerInstance->ULine(user->server)) && (!ServerInstance->ULine(src->server)))
- {
- src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only a u-line may kick a u-line from a channel.",src->nick.c_str(), this->name.c_str());
- return;
- }
-
+ // Modules are allowed to explicitly allow or deny kicks done by local users
ModResult res;
- if (ServerInstance->ULine(src->server))
- res = MOD_RES_ALLOW;
- else
- FIRST_MOD_RESULT(OnUserPreKick, res, (src,memb,reason));
-
+ FIRST_MOD_RESULT(OnUserPreKick, res, (src,memb,reason));
if (res == MOD_RES_DENY)
return;
if (res == MOD_RES_PASSTHRU)
{
- unsigned int them = this->GetPrefixValue(src);
+ if (!srcmemb)
+ srcmemb = GetUser(src);
+ unsigned int them = srcmemb ? srcmemb->getRank() : 0;
unsigned int req = HALFOP_VALUE;
for (std::string::size_type i = 0; i < memb->modes.length(); i++)
{
}
}
- if (memb)
- {
- CUList except_list;
- FOREACH_MOD(I_OnUserKick,OnUserKick(src, memb, reason, except_list));
-
- WriteAllExcept(src, false, 0, except_list, "KICK %s %s :%s", name.c_str(), user->nick.c_str(), reason);
+ CUList except_list;
+ FOREACH_MOD(I_OnUserKick,OnUserKick(src, memb, reason, except_list));
- user->chans.erase(this);
- this->RemoveAllPrefixes(user);
- }
+ WriteAllExcept(src, false, 0, except_list, "KICK %s %s :%s", name.c_str(), victim->nick.c_str(), reason.c_str());
- this->DelUser(user);
+ victim->chans.erase(this);
+ this->DelUser(victimiter);
}
void Channel::WriteChannel(User* user, const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- if (!user || !text)
- return;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteChannel(user, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteChannel(user, textbuffer);
}
void Channel::WriteChannel(User* user, const std::string &text)
{
- char tb[MAXBUF];
-
- if (!user)
- return;
-
- snprintf(tb,MAXBUF,":%s %s", user->GetFullHost().c_str(), text.c_str());
- std::string out = tb;
+ const std::string message = ":" + user->GetFullHost() + " " + text;
for (UserMembIter i = userlist.begin(); i != userlist.end(); i++)
{
if (IS_LOCAL(i->first))
- i->first->Write(out);
+ i->first->Write(message);
}
}
void Channel::WriteChannelWithServ(const std::string& ServName, const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- if (!text)
- return;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteChannelWithServ(ServName, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteChannelWithServ(ServName, textbuffer);
}
void Channel::WriteChannelWithServ(const std::string& ServName, const std::string &text)
{
- char tb[MAXBUF];
-
- snprintf(tb,MAXBUF,":%s %s", ServName.empty() ? ServerInstance->Config->ServerName.c_str() : ServName.c_str(), text.c_str());
- std::string out = tb;
+ const std::string message = ":" + (ServName.empty() ? ServerInstance->Config->ServerName : ServName) + " " + text;
for (UserMembIter i = userlist.begin(); i != userlist.end(); i++)
{
if (IS_LOCAL(i->first))
- i->first->Write(out);
+ i->first->Write(message);
}
}
* for the sender (for privmsg etc) */
void Channel::WriteAllExceptSender(User* user, bool serversource, char status, const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- if (!text)
- return;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteAllExceptSender(user, serversource, status, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteAllExceptSender(user, serversource, status, textbuffer);
}
void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- if (!text)
- return;
-
- int offset = snprintf(textbuffer,MAXBUF,":%s ", serversource ? ServerInstance->Config->ServerName.c_str() : user->GetFullHost().c_str());
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer + offset, MAXBUF - offset, text, argsPtr);
- va_end(argsPtr);
-
- this->RawWriteAllExcept(user, serversource, status, except_list, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ textbuffer = ":" + (serversource ? ServerInstance->Config->ServerName : user->GetFullHost()) + " " + textbuffer;
+ this->RawWriteAllExcept(user, serversource, status, except_list, textbuffer);
}
void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &text)
{
- char tb[MAXBUF];
-
- snprintf(tb,MAXBUF,":%s %s", serversource ? ServerInstance->Config->ServerName.c_str() : user->GetFullHost().c_str(), text.c_str());
-
- this->RawWriteAllExcept(user, serversource, status, except_list, std::string(tb));
+ const std::string message = ":" + (serversource ? ServerInstance->Config->ServerName : user->GetFullHost()) + " " + text;
+ this->RawWriteAllExcept(user, serversource, status, except_list, message);
}
void Channel::RawWriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &out)
this->WriteAllExcept(user, serversource, status, except_list, std::string(text));
}
-/*
- * return a count of the users on a specific channel accounting for
- * invisible users who won't increase the count. e.g. for /LIST
- */
-int Channel::CountInvisible()
-{
- int count = 0;
- for (UserMembIter i = userlist.begin(); i != userlist.end(); i++)
- {
- if (!i->first->quitting && !i->first->IsModeSet('i'))
- count++;
- }
-
- return count;
-}
-
-char* Channel::ChanModes(bool showkey)
+const char* Channel::ChanModes(bool showkey)
{
- static char scratch[MAXBUF];
- static char sparam[MAXBUF];
- char* offset = scratch;
- std::string extparam;
+ static std::string scratch;
+ std::string sparam;
- *scratch = '\0';
- *sparam = '\0';
+ scratch.clear();
/* This was still iterating up to 190, Channel::modes is only 64 elements -- Om */
for(int n = 0; n < 64; n++)
{
if(this->modes[n])
{
- *offset++ = n + 65;
- extparam.clear();
+ scratch.push_back(n + 65);
if (n == 'k' - 65 && !showkey)
{
- extparam = "<key>";
+ sparam += " <key>";
}
else
{
- extparam = this->GetModeParameter(n + 65);
- }
- if (!extparam.empty())
- {
- charlcat(sparam,' ',MAXBUF);
- strlcat(sparam,extparam.c_str(),MAXBUF);
+ const std::string param = this->GetModeParameter(n + 65);
+ if (!param.empty())
+ {
+ sparam += ' ';
+ sparam += param;
+ }
}
}
}
- /* Null terminate scratch */
- *offset = '\0';
- strlcat(scratch,sparam,MAXBUF);
- return scratch;
+ scratch += sparam;
+ return scratch.c_str();
}
/* compile a userlist of a channel into a string, each nick seperated by
*/
void Channel::UserList(User *user)
{
- char list[MAXBUF];
- size_t dlen, curlen;
-
- if (!IS_LOCAL(user))
- return;
-
if (this->IsModeSet('s') && !this->HasUser(user) && !user->HasPrivPermission("channels/auspex"))
{
user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), this->name.c_str());
return;
}
- dlen = curlen = snprintf(list,MAXBUF,"%s %c %s :", user->nick.c_str(), this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name.c_str());
+ std::string list = user->nick;
+ list.push_back(' ');
+ list.push_back(this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=');
+ list.push_back(' ');
+ list.append(this->name).append(" :");
+ std::string::size_type pos = list.size();
- int numusers = 0;
- char* ptr = list + dlen;
+ bool has_one = false;
/* Improvement by Brain - this doesnt change in value, so why was it inside
* the loop?
*/
bool has_user = this->HasUser(user);
- for (UserMembIter i = userlist.begin(); i != userlist.end(); i++)
+ std::string prefixlist;
+ std::string nick;
+ for (UserMembIter i = userlist.begin(); i != userlist.end(); ++i)
{
if (i->first->quitting)
continue;
continue;
}
- std::string prefixlist = this->GetPrefixChar(i->first);
- std::string nick = i->first->nick;
+ prefixlist = this->GetPrefixChar(i->first);
+ nick = i->first->nick;
FOREACH_MOD(I_OnNamesListItem, OnNamesListItem(user, i->second, prefixlist, nick));
if (nick.empty())
continue;
- size_t ptrlen = 0;
-
- if (curlen + prefixlist.length() + nick.length() + 1 > 480)
+ if (list.size() + prefixlist.length() + nick.length() + 1 > 480)
{
/* list overflowed into multiple numerics */
- user->WriteNumeric(RPL_NAMREPLY, std::string(list));
-
- /* reset our lengths */
- dlen = curlen = snprintf(list,MAXBUF,"%s %c %s :", user->nick.c_str(), this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name.c_str());
- ptr = list + dlen;
+ user->WriteNumeric(RPL_NAMREPLY, list);
- numusers = 0;
+ // Erase all nicks, keep the constant part
+ list.erase(pos);
+ has_one = false;
}
- ptrlen = snprintf(ptr, MAXBUF, "%s%s ", prefixlist.c_str(), nick.c_str());
+ list.append(prefixlist).append(nick).push_back(' ');
- curlen += ptrlen;
- ptr += ptrlen;
-
- numusers++;
+ has_one = true;
}
/* if whats left in the list isnt empty, send it */
- if (numusers)
+ if (has_one)
{
- user->WriteNumeric(RPL_NAMREPLY, std::string(list));
+ user->WriteNumeric(RPL_NAMREPLY, list);
}
user->WriteNumeric(RPL_ENDOFNAMES, "%s %s :End of /NAMES list.", user->nick.c_str(), this->name.c_str());
}
-long Channel::GetMaxBans()
-{
- /* Return the cached value if there is one */
- if (this->maxbans)
- return this->maxbans;
-
- /* If there isnt one, we have to do some O(n) hax to find it the first time. (ick) */
- for (std::map<std::string,int>::iterator n = ServerInstance->Config->maxbans.begin(); n != ServerInstance->Config->maxbans.end(); n++)
- {
- if (InspIRCd::Match(this->name, n->first, NULL))
- {
- this->maxbans = n->second;
- return n->second;
- }
- }
-
- /* Screw it, just return the default of 64 */
- this->maxbans = 64;
- return this->maxbans;
-}
-
-void Channel::ResetMaxBans()
-{
- this->maxbans = 0;
-}
-
/* returns the status character for a given user on a channel, e.g. @ for op,
* % for halfop etc. If the user has several modes set, the highest mode
* the user has must be returned.
return adding;
}
-void Channel::RemoveAllPrefixes(User* user)
-{
- UserMembIter m = userlist.find(user);
- if (m != userlist.end())
- {
- m->second->modes.clear();
- }
-}
-
void Invitation::Create(Channel* c, LocalUser* u, time_t timeout)
{
if ((timeout != 0) && (ServerInstance->Time() >= timeout))
// Expired, don't bother
return;
- ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Create chan=%s user=%s", c->name.c_str(), u->uuid.c_str());
+ ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Create chan=%s user=%s", c->name.c_str(), u->uuid.c_str());
Invitation* inv = Invitation::Find(c, u, false);
if (inv)
if ((inv->expiry == 0) || (inv->expiry > timeout))
return;
inv->expiry = timeout;
- ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Create changed expiry in existing invitation %p", (void*) inv);
+ ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Create changed expiry in existing invitation %p", (void*) inv);
}
else
{
inv = new Invitation(c, u, timeout);
c->invites.push_back(inv);
u->invites.push_back(inv);
- ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Create created new invitation %p", (void*) inv);
+ ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Create created new invitation %p", (void*) inv);
}
}
Invitation* Invitation::Find(Channel* c, LocalUser* u, bool check_expired)
{
- ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find chan=%s user=%s check_expired=%d", c ? c->name.c_str() : "NULL", u ? u->uuid.c_str() : "NULL", check_expired);
+ ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Find chan=%s user=%s check_expired=%d", c ? c->name.c_str() : "NULL", u ? u->uuid.c_str() : "NULL", check_expired);
if (!u || u->invites.empty())
return NULL;
{
/* Expired invite, remove it. */
std::string expiration = ServerInstance->TimeString(inv->expiry);
- ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find ecountered expired entry: %p expired %s", (void*) inv, expiration.c_str());
+ ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Find ecountered expired entry: %p expired %s", (void*) inv, expiration.c_str());
i = locallist.erase(i);
inv->cull();
delete inv;
}
locallist.swap(u->invites);
- ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find result=%p", (void*) result);
+ ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Find result=%p", (void*) result);
return result;
}
void InviteBase::ClearInvites()
{
- ServerInstance->Logs->Log("INVITEBASE", DEBUG, "InviteBase::ClearInvites %p", (void*) this);
+ ServerInstance->Logs->Log("INVITEBASE", LOG_DEBUG, "InviteBase::ClearInvites %p", (void*) this);
InviteList locallist;
locallist.swap(invites);
for (InviteList::const_iterator i = locallist.begin(); i != locallist.end(); ++i)
return CMD_INVALID;
}
-bool CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
+void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd)
{
std::vector<std::string> command_p;
irc::tokenstream tokens(cmd);
if (command[0] == ':')
tokens.GetToken(command);
- while (tokens.GetToken(token) && (command_p.size() <= MAXPARAMETERS))
+ while (tokens.GetToken(token))
command_p.push_back(token);
std::transform(command.begin(), command.end(), command.begin(), ::toupper);
/* find the command, check it exists */
- Commandtable::iterator cm = cmdlist.find(command);
+ Command* handler = GetHandler(command);
/* Modify the user's penalty regardless of whether or not the command exists */
- bool do_more = true;
if (!user->HasPrivPermission("users/flood/no-throttle"))
{
// If it *doesn't* exist, give it a slightly heftier penalty than normal to deter flooding us crap
- user->CommandFloodPenalty += cm != cmdlist.end() ? cm->second->Penalty * 1000 : 2000;
+ user->CommandFloodPenalty += handler ? handler->Penalty * 1000 : 2000;
}
-
- if (cm == cmdlist.end())
+ if (!handler)
{
ModResult MOD_RESULT;
FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, command_p, user, false, cmd));
if (MOD_RESULT == MOD_RES_DENY)
- return true;
+ return;
/*
* This double lookup is in case a module (abbreviation) wishes to change a command.
* Thanks dz for making me actually understand why this is necessary!
* -- w00t
*/
- cm = cmdlist.find(command);
- if (cm == cmdlist.end())
+ handler = GetHandler(command);
+ if (!handler)
{
if (user->registered == REG_ALL)
user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s %s :Unknown command",user->nick.c_str(),command.c_str());
ServerInstance->stats->statsUnknown++;
- return true;
+ return;
}
}
- if (cm->second->max_params && command_p.size() > cm->second->max_params)
+ // If we were given more parameters than max_params then append the excess parameter(s)
+ // to command_p[maxparams-1], i.e. to the last param that is still allowed
+ if (handler->max_params && command_p.size() > handler->max_params)
{
/*
* command_p input (assuming max_params 1):
* a
* test
*/
- std::string lparam;
- /*
- * The '-1' here is a clever trick, we'll go backwards throwing everything into a temporary param
- * and then just toss that into the array.
- * -- w00t
- */
- while (command_p.size() > (cm->second->max_params - 1))
- {
- // BE CAREFUL: .end() returns past the end of the vector, hence decrement.
- std::vector<std::string>::iterator it = --command_p.end();
+ // Iterator to the last parameter that will be kept
+ const std::vector<std::string>::iterator lastkeep = command_p.begin() + (handler->max_params - 1);
+ // Iterator to the first excess parameter
+ const std::vector<std::string>::iterator firstexcess = lastkeep + 1;
- lparam.insert(0, " " + *(it));
- command_p.erase(it); // remove last element
+ // Append all excess parameter(s) to the last parameter, seperated by spaces
+ for (std::vector<std::string>::const_iterator i = firstexcess; i != command_p.end(); ++i)
+ {
+ lastkeep->push_back(' ');
+ lastkeep->append(*i);
}
- /* we now have (each iteration):
- * ' test'
- * ' a test'
- * ' is a test' <-- final string
- * ...now remove the ' ' at the start...
- */
- lparam.erase(lparam.begin());
-
- /* param is now 'is a test', which is exactly what we wanted! */
- command_p.push_back(lparam);
+ // Erase the excess parameter(s)
+ command_p.erase(firstexcess, command_p.end());
}
/*
ModResult MOD_RESULT;
FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, command_p, user, false, cmd));
if (MOD_RESULT == MOD_RES_DENY)
- return true;
+ return;
/* activity resets the ping pending timer */
user->nping = ServerInstance->Time() + user->MyClass->GetPingTime();
- if (cm->second->flags_needed)
+ if (handler->flags_needed)
{
- if (!user->IsModeSet(cm->second->flags_needed))
+ if (!user->IsModeSet(handler->flags_needed))
{
user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - You do not have the required operator privileges",user->nick.c_str());
- return do_more;
+ return;
}
+
if (!user->HasPermission(command))
{
user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to command %s",
- user->nick.c_str(), user->oper->NameStr(), command.c_str());
- return do_more;
+ user->nick.c_str(), user->oper->name.c_str(), command.c_str());
+ return;
}
}
- if ((user->registered == REG_ALL) && (!IS_OPER(user)) && (cm->second->IsDisabled()))
+
+ if ((user->registered == REG_ALL) && (!user->IsOper()) && (handler->IsDisabled()))
{
/* command is disabled! */
if (ServerInstance->Config->DisabledDontExist)
ServerInstance->SNO->WriteToSnoMask('t', "%s denied for %s (%s@%s)",
command.c_str(), user->nick.c_str(), user->ident.c_str(), user->host.c_str());
- return do_more;
+ return;
}
- if ((!command_p.empty()) && (command_p.back().empty()) && (!cm->second->allow_empty_last_param))
+ if ((!command_p.empty()) && (command_p.back().empty()) && (!handler->allow_empty_last_param))
command_p.pop_back();
- if (command_p.size() < cm->second->min_params)
+ if (command_p.size() < handler->min_params)
{
user->WriteNumeric(ERR_NEEDMOREPARAMS, "%s %s :Not enough parameters.", user->nick.c_str(), command.c_str());
- if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (cm->second->syntax.length()))
- user->WriteNumeric(RPL_SYNTAX, "%s :SYNTAX %s %s", user->nick.c_str(), cm->second->name.c_str(), cm->second->syntax.c_str());
- return do_more;
+ if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (handler->syntax.length()))
+ user->WriteNumeric(RPL_SYNTAX, "%s :SYNTAX %s %s", user->nick.c_str(), handler->name.c_str(), handler->syntax.c_str());
+ return;
}
- if ((user->registered != REG_ALL) && (!cm->second->WorksBeforeReg()))
+
+ if ((user->registered != REG_ALL) && (!handler->WorksBeforeReg()))
{
user->WriteNumeric(ERR_NOTREGISTERED, "%s :You have not registered",command.c_str());
- return do_more;
}
else
{
/* passed all checks.. first, do the (ugly) stats counters. */
- cm->second->use_count++;
- cm->second->total_bytes += cmd.length();
+ handler->use_count++;
/* module calls too */
FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, command_p, user, true, cmd));
if (MOD_RESULT == MOD_RES_DENY)
- return do_more;
+ return;
/*
* WARNING: be careful, the user may be deleted soon
*/
- CmdResult result = cm->second->Handle(command_p, user);
+ CmdResult result = handler->Handle(command_p, user);
FOREACH_MOD(I_OnPostCommand,OnPostCommand(command, command_p, user, result,cmd));
- return do_more;
}
}
ServerInstance->Parser->RemoveCommand(this);
}
-bool CommandParser::ProcessBuffer(std::string &buffer,LocalUser *user)
+void CommandParser::ProcessBuffer(std::string &buffer,LocalUser *user)
{
if (!user || buffer.empty())
- return true;
+ return;
- ServerInstance->Logs->Log("USERINPUT", RAWIO, "C[%s] I :%s %s",
+ ServerInstance->Logs->Log("USERINPUT", LOG_RAWIO, "C[%s] I :%s %s",
user->uuid.c_str(), user->nick.c_str(), buffer.c_str());
- return ProcessCommand(user,buffer);
+ ProcessCommand(user,buffer);
}
bool CommandParser::AddCommand(Command *f)
return HandleRemote(parms, IS_REMOTE(u));
if (IS_SERVER(u))
return HandleServer(parms, IS_SERVER(u));
- ServerInstance->Logs->Log("COMMAND", DEFAULT, "Unknown user type in command (uuid=%s)!", u->uuid.c_str());
+ ServerInstance->Logs->Log("COMMAND", LOG_DEFAULT, "Unknown user type in command (uuid=%s)!", u->uuid.c_str());
return CMD_INVALID;
}
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
- *
- * This file is part of InspIRCd. InspIRCd is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "inspircd.h"
-
-/** Handle /CLEARCACHE. These command handlers can be reloaded by the core,
- * and handle basic RFC1459 commands. Commands within modules work
- * the same way, however, they can be fully unloaded, where these
- * may not.
- */
-class CommandClearcache : public Command
-{
- public:
- /** Constructor for clearcache.
- */
- CommandClearcache ( Module* parent) : Command(parent,"CLEARCACHE",0) { flags_needed = 'o'; }
- /** Handle command.
- * @param parameters The parameters to the comamnd
- * @param pcnt The number of parameters passed to teh command
- * @param user The user issuing the command
- * @return A value from CmdResult to indicate command success or failure.
- */
- CmdResult Handle(const std::vector<std::string>& parameters, User *user);
-};
-
-/** Handle /CLEARCACHE
- */
-CmdResult CommandClearcache::Handle (const std::vector<std::string>& parameters, User *user)
-{
- int n = ServerInstance->Res->ClearCache();
- user->WriteServ("NOTICE %s :*** Cleared DNS cache of %d items.", user->nick.c_str(), n);
- return CMD_SUCCESS;
-}
-
-COMMAND_INIT(CommandClearcache)
{
{
std::string diebuf = "*** DIE command from " + user->GetFullHost() + ". Terminating.";
- ServerInstance->Logs->Log("COMMAND",SPARSE, diebuf);
+ ServerInstance->Logs->Log("COMMAND", LOG_SPARSE, diebuf);
ServerInstance->SendError(diebuf);
}
}
else
{
- ServerInstance->Logs->Log("COMMAND",SPARSE, "Failed /DIE command from %s", user->GetFullRealHost().c_str());
+ ServerInstance->Logs->Log("COMMAND", LOG_SPARSE, "Failed /DIE command from %s", user->GetFullRealHost().c_str());
ServerInstance->SNO->WriteGlobalSno('a', "Failed DIE Command from %s.", user->GetFullRealHost().c_str());
return CMD_FAILURE;
}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013 Adam <Adam@anope.org>
+ * Copyright (C) 2003-2013 Anope Team <team@anope.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
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "inspircd.h"
+#include "modules/dns.h"
+#include <iostream>
+#include <fstream>
+
+#ifdef _WIN32
+#include <Iphlpapi.h>
+#pragma comment(lib, "Iphlpapi.lib")
+#endif
+
+using namespace DNS;
+
+/** A full packet sent or recieved to/from the nameserver
+ */
+class Packet : public Query
+{
+ void PackName(unsigned char* output, unsigned short output_size, unsigned short& pos, const std::string& name)
+ {
+ if (pos + name.length() + 2 > output_size)
+ throw Exception("Unable to pack name");
+
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Packing name " + name);
+
+ irc::sepstream sep(name, '.');
+ std::string token;
+
+ while (sep.GetToken(token))
+ {
+ output[pos++] = token.length();
+ memcpy(&output[pos], token.data(), token.length());
+ pos += token.length();
+ }
+
+ output[pos++] = 0;
+ }
+
+ std::string UnpackName(const unsigned char* input, unsigned short input_size, unsigned short& pos)
+ {
+ std::string name;
+ unsigned short pos_ptr = pos, lowest_ptr = input_size;
+ bool compressed = false;
+
+ if (pos_ptr >= input_size)
+ throw Exception("Unable to unpack name - no input");
+
+ while (input[pos_ptr] > 0)
+ {
+ unsigned short offset = input[pos_ptr];
+
+ if (offset & POINTER)
+ {
+ if ((offset & POINTER) != POINTER)
+ throw Exception("Unable to unpack name - bogus compression header");
+ if (pos_ptr + 1 >= input_size)
+ throw Exception("Unable to unpack name - bogus compression header");
+
+ /* Place pos at the second byte of the first (farthest) compression pointer */
+ if (compressed == false)
+ {
+ ++pos;
+ compressed = true;
+ }
+
+ pos_ptr = (offset & LABEL) << 8 | input[pos_ptr + 1];
+
+ /* Pointers can only go back */
+ if (pos_ptr >= lowest_ptr)
+ throw Exception("Unable to unpack name - bogus compression pointer");
+ lowest_ptr = pos_ptr;
+ }
+ else
+ {
+ if (pos_ptr + offset + 1 >= input_size)
+ throw Exception("Unable to unpack name - offset too large");
+ if (!name.empty())
+ name += ".";
+ for (unsigned i = 1; i <= offset; ++i)
+ name += input[pos_ptr + i];
+
+ pos_ptr += offset + 1;
+ if (compressed == false)
+ /* Move up pos */
+ pos = pos_ptr;
+ }
+ }
+
+ /* +1 pos either to one byte after the compression pointer or one byte after the ending \0 */
+ ++pos;
+
+ if (name.empty())
+ throw Exception("Unable to unpack name - no name");
+
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Unpack name " + name);
+
+ return name;
+ }
+
+ Question UnpackQuestion(const unsigned char* input, unsigned short input_size, unsigned short& pos)
+ {
+ Question question;
+
+ question.name = this->UnpackName(input, input_size, pos);
+
+ if (pos + 4 > input_size)
+ throw Exception("Unable to unpack question");
+
+ question.type = static_cast<QueryType>(input[pos] << 8 | input[pos + 1]);
+ pos += 2;
+
+ question.qclass = input[pos] << 8 | input[pos + 1];
+ pos += 2;
+
+ return question;
+ }
+
+ ResourceRecord UnpackResourceRecord(const unsigned char* input, unsigned short input_size, unsigned short& pos)
+ {
+ ResourceRecord record = static_cast<ResourceRecord>(this->UnpackQuestion(input, input_size, pos));
+
+ if (pos + 6 > input_size)
+ throw Exception("Unable to unpack resource record");
+
+ record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3];
+ pos += 4;
+
+ //record.rdlength = input[pos] << 8 | input[pos + 1];
+ pos += 2;
+
+ switch (record.type)
+ {
+ case QUERY_A:
+ {
+ if (pos + 4 > input_size)
+ throw Exception("Unable to unpack resource record");
+
+ irc::sockets::sockaddrs addrs;
+ memset(&addrs, 0, sizeof(addrs));
+
+ addrs.in4.sin_family = AF_INET;
+ addrs.in4.sin_addr.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24);
+ pos += 4;
+
+ record.rdata = addrs.addr();
+ break;
+ }
+ case QUERY_AAAA:
+ {
+ if (pos + 16 > input_size)
+ throw Exception("Unable to unpack resource record");
+
+ irc::sockets::sockaddrs addrs;
+ memset(&addrs, 0, sizeof(addrs));
+
+ addrs.in6.sin6_family = AF_INET6;
+ for (int j = 0; j < 16; ++j)
+ addrs.in6.sin6_addr.s6_addr[j] = input[pos + j];
+ pos += 16;
+
+ record.rdata = addrs.addr();
+
+ break;
+ }
+ case QUERY_CNAME:
+ case QUERY_PTR:
+ {
+ record.rdata = this->UnpackName(input, input_size, pos);
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (!record.name.empty() && !record.rdata.empty())
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: " + record.name + " -> " + record.rdata);
+
+ return record;
+ }
+
+ public:
+ static const int POINTER = 0xC0;
+ static const int LABEL = 0x3F;
+ static const int HEADER_LENGTH = 12;
+
+ /* ID for this packet */
+ unsigned short id;
+ /* Flags on the packet */
+ unsigned short flags;
+
+ Packet() : id(0), flags(0)
+ {
+ }
+
+ void Fill(const unsigned char* input, const unsigned short len)
+ {
+ if (len < HEADER_LENGTH)
+ throw Exception("Unable to fill packet");
+
+ unsigned short packet_pos = 0;
+
+ this->id = (input[packet_pos] << 8) | input[packet_pos + 1];
+ packet_pos += 2;
+
+ if (this->id >= MAX_REQUEST_ID)
+ throw Exception("Query ID too large?");
+
+ this->flags = (input[packet_pos] << 8) | input[packet_pos + 1];
+ packet_pos += 2;
+
+ unsigned short qdcount = (input[packet_pos] << 8) | input[packet_pos + 1];
+ packet_pos += 2;
+
+ unsigned short ancount = (input[packet_pos] << 8) | input[packet_pos + 1];
+ packet_pos += 2;
+
+ unsigned short nscount = (input[packet_pos] << 8) | input[packet_pos + 1];
+ packet_pos += 2;
+
+ unsigned short arcount = (input[packet_pos] << 8) | input[packet_pos + 1];
+ packet_pos += 2;
+
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: qdcount: " + ConvToStr(qdcount) + " ancount: " + ConvToStr(ancount) + " nscount: " + ConvToStr(nscount) + " arcount: " + ConvToStr(arcount));
+
+ for (unsigned i = 0; i < qdcount; ++i)
+ this->questions.push_back(this->UnpackQuestion(input, len, packet_pos));
+
+ for (unsigned i = 0; i < ancount; ++i)
+ this->answers.push_back(this->UnpackResourceRecord(input, len, packet_pos));
+ }
+
+ unsigned short Pack(unsigned char* output, unsigned short output_size)
+ {
+ if (output_size < HEADER_LENGTH)
+ throw Exception("Unable to pack packet");
+
+ unsigned short pos = 0;
+
+ output[pos++] = this->id >> 8;
+ output[pos++] = this->id & 0xFF;
+ output[pos++] = this->flags >> 8;
+ output[pos++] = this->flags & 0xFF;
+ output[pos++] = this->questions.size() >> 8;
+ output[pos++] = this->questions.size() & 0xFF;
+ output[pos++] = this->answers.size() >> 8;
+ output[pos++] = this->answers.size() & 0xFF;
+ output[pos++] = 0;
+ output[pos++] = 0;
+ output[pos++] = 0;
+ output[pos++] = 0;
+
+ for (unsigned i = 0; i < this->questions.size(); ++i)
+ {
+ Question& q = this->questions[i];
+
+ if (q.type == QUERY_PTR)
+ {
+ irc::sockets::sockaddrs ip;
+ irc::sockets::aptosa(q.name, 0, ip);
+
+ if (q.name.find(':') != std::string::npos)
+ {
+ static const char* const hex = "0123456789abcdef";
+ char reverse_ip[128];
+ unsigned reverse_ip_count = 0;
+ for (int j = 15; j >= 0; --j)
+ {
+ reverse_ip[reverse_ip_count++] = hex[ip.in6.sin6_addr.s6_addr[j] & 0xF];
+ reverse_ip[reverse_ip_count++] = '.';
+ reverse_ip[reverse_ip_count++] = hex[ip.in6.sin6_addr.s6_addr[j] >> 4];
+ reverse_ip[reverse_ip_count++] = '.';
+ }
+ reverse_ip[reverse_ip_count++] = 0;
+
+ q.name = reverse_ip;
+ q.name += "ip6.arpa";
+ }
+ else
+ {
+ unsigned long forward = ip.in4.sin_addr.s_addr;
+ ip.in4.sin_addr.s_addr = forward << 24 | (forward & 0xFF00) << 8 | (forward & 0xFF0000) >> 8 | forward >> 24;
+
+ q.name = ip.addr() + ".in-addr.arpa";
+ }
+ }
+
+ this->PackName(output, output_size, pos, q.name);
+
+ if (pos + 4 >= output_size)
+ throw Exception("Unable to pack packet");
+
+ short s = htons(q.type);
+ memcpy(&output[pos], &s, 2);
+ pos += 2;
+
+ s = htons(q.qclass);
+ memcpy(&output[pos], &s, 2);
+ pos += 2;
+ }
+
+ for (unsigned int i = 0; i < answers.size(); i++)
+ {
+ ResourceRecord& rr = answers[i];
+
+ this->PackName(output, output_size, pos, rr.name);
+
+ if (pos + 8 >= output_size)
+ throw Exception("Unable to pack packet");
+
+ short s = htons(rr.type);
+ memcpy(&output[pos], &s, 2);
+ pos += 2;
+
+ s = htons(rr.qclass);
+ memcpy(&output[pos], &s, 2);
+ pos += 2;
+
+ long l = htonl(rr.ttl);
+ memcpy(&output[pos], &l, 4);
+ pos += 4;
+
+ switch (rr.type)
+ {
+ case QUERY_A:
+ {
+ if (pos + 6 > output_size)
+ throw Exception("Unable to pack packet");
+
+ irc::sockets::sockaddrs a;
+ irc::sockets::aptosa(rr.rdata, 0, a);
+
+ s = htons(4);
+ memcpy(&output[pos], &s, 2);
+ pos += 2;
+
+ memcpy(&output[pos], &a.in4.sin_addr, 4);
+ pos += 4;
+ break;
+ }
+ case QUERY_AAAA:
+ {
+ if (pos + 18 > output_size)
+ throw Exception("Unable to pack packet");
+
+ irc::sockets::sockaddrs a;
+ irc::sockets::aptosa(rr.rdata, 0, a);
+
+ s = htons(16);
+ memcpy(&output[pos], &s, 2);
+ pos += 2;
+
+ memcpy(&output[pos], &a.in6.sin6_addr, 16);
+ pos += 16;
+ break;
+ }
+ case QUERY_CNAME:
+ case QUERY_PTR:
+ {
+ if (pos + 2 >= output_size)
+ throw Exception("Unable to pack packet");
+
+ unsigned short packet_pos_save = pos;
+ pos += 2;
+
+ this->PackName(output, output_size, pos, rr.rdata);
+
+ s = htons(pos - packet_pos_save - 2);
+ memcpy(&output[packet_pos_save], &s, 2);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return pos;
+ }
+};
+
+class MyManager : public Manager, public Timer, public EventHandler
+{
+ typedef TR1NS::unordered_map<Question, Query, Question::hash> cache_map;
+ cache_map cache;
+
+ irc::sockets::sockaddrs myserver;
+
+ static bool IsExpired(const Query& record, time_t now = ServerInstance->Time())
+ {
+ const ResourceRecord& req = record.answers[0];
+ return (req.created + static_cast<time_t>(req.ttl) < now);
+ }
+
+ /** Check the DNS cache to see if request can be handled by a cached result
+ * @return true if a cached result was found.
+ */
+ bool CheckCache(DNS::Request* req, const DNS::Question& question)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: cache: Checking cache for " + question.name);
+
+ cache_map::iterator it = this->cache.find(question);
+ if (it == this->cache.end())
+ return false;
+
+ Query& record = it->second;
+ if (IsExpired(record))
+ {
+ this->cache.erase(it);
+ return false;
+ }
+
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: Using cached result for " + question.name);
+ record.cached = true;
+ req->OnLookupComplete(&record);
+ return true;
+ }
+
+ /** Add a record to the dns cache
+ * @param r The record
+ */
+ void AddCache(Query& r)
+ {
+ const ResourceRecord& rr = r.answers[0];
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: added cache for " + rr.name + " -> " + rr.rdata + " ttl: " + ConvToStr(rr.ttl));
+ this->cache[r.questions[0]] = r;
+ }
+
+ public:
+ DNS::Request* requests[MAX_REQUEST_ID];
+
+ MyManager(Module* c) : Manager(c), Timer(3600, ServerInstance->Time(), true)
+ {
+ for (int i = 0; i < MAX_REQUEST_ID; ++i)
+ requests[i] = NULL;
+ ServerInstance->Timers->AddTimer(this);
+ }
+
+ ~MyManager()
+ {
+ for (int i = 0; i < MAX_REQUEST_ID; ++i)
+ {
+ DNS::Request* request = requests[i];
+ if (!request)
+ continue;
+
+ Query rr(*request);
+ rr.error = ERROR_UNKNOWN;
+ request->OnError(&rr);
+
+ delete request;
+ }
+ }
+
+ void Process(DNS::Request* req)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Processing request to lookup " + req->name + " of type " + ConvToStr(req->type) + " to " + this->myserver.addr());
+
+ /* Create an id */
+ unsigned int tries = 0;
+ do
+ {
+ req->id = ServerInstance->GenRandomInt(DNS::MAX_REQUEST_ID);
+
+ if (++tries == DNS::MAX_REQUEST_ID*5)
+ {
+ // If we couldn't find an empty slot this many times, do a sequential scan as a last
+ // resort. If an empty slot is found that way, go on, otherwise throw an exception
+ req->id = 0;
+ for (int i = 1; i < DNS::MAX_REQUEST_ID; i++)
+ {
+ if (!this->requests[i])
+ {
+ req->id = i;
+ break;
+ }
+ }
+
+ if (req->id == 0)
+ throw Exception("DNS: All ids are in use");
+
+ break;
+ }
+ }
+ while (!req->id || this->requests[req->id]);
+
+ this->requests[req->id] = req;
+
+ Packet p;
+ p.flags = QUERYFLAGS_RD;
+ p.id = req->id;
+ p.questions.push_back(*req);
+
+ unsigned char buffer[524];
+ unsigned short len = p.Pack(buffer, sizeof(buffer));
+
+ /* Note that calling Pack() above can actually change the contents of p.questions[0].name, if the query is a PTR,
+ * to contain the value that would be in the DNS cache, which is why this is here.
+ */
+ if (req->use_cache && this->CheckCache(req, p.questions[0]))
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Using cached result");
+ delete req;
+ return;
+ }
+
+ if (ServerInstance->SE->SendTo(this, buffer, len, 0, &this->myserver.sa, this->myserver.sa_size()) != len)
+ throw Exception("DNS: Unable to send query");
+ }
+
+ void RemoveRequest(DNS::Request* req)
+ {
+ this->requests[req->id] = NULL;
+ }
+
+ std::string GetErrorStr(Error e)
+ {
+ switch (e)
+ {
+ case ERROR_UNLOADED:
+ return "Module is unloading";
+ case ERROR_TIMEDOUT:
+ return "Request timed out";
+ case ERROR_NOT_AN_ANSWER:
+ case ERROR_NONSTANDARD_QUERY:
+ case ERROR_FORMAT_ERROR:
+ return "Malformed answer";
+ case ERROR_SERVER_FAILURE:
+ case ERROR_NOT_IMPLEMENTED:
+ case ERROR_REFUSED:
+ case ERROR_INVALIDTYPE:
+ return "Nameserver failure";
+ case ERROR_DOMAIN_NOT_FOUND:
+ case ERROR_NO_RECORDS:
+ return "Domain not found";
+ case ERROR_NONE:
+ case ERROR_UNKNOWN:
+ default:
+ return "Unknown error";
+ }
+ }
+
+ void HandleEvent(EventType et, int)
+ {
+ if (et == EVENT_ERROR)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: UDP socket got an error event");
+ return;
+ }
+
+ unsigned char buffer[524];
+ irc::sockets::sockaddrs from;
+ socklen_t x = sizeof(from);
+
+ int length = ServerInstance->SE->RecvFrom(this, buffer, sizeof(buffer), 0, &from.sa, &x);
+
+ if (length < Packet::HEADER_LENGTH)
+ return;
+
+ Packet recv_packet;
+
+ try
+ {
+ recv_packet.Fill(buffer, length);
+ }
+ catch (Exception& ex)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, std::string(ex.GetReason()));
+ return;
+ }
+
+ if (myserver != from)
+ {
+ std::string server1 = from.str();
+ std::string server2 = myserver.str();
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Got a result from the wrong server! Bad NAT or DNS forging attempt? '%s' != '%s'",
+ server1.c_str(), server2.c_str());
+ return;
+ }
+
+ DNS::Request* request = this->requests[recv_packet.id];
+ if (request == NULL)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Received an answer for something we didn't request");
+ return;
+ }
+
+ if (recv_packet.flags & QUERYFLAGS_OPCODE)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Received a nonstandard query");
+ ServerInstance->stats->statsDnsBad++;
+ recv_packet.error = ERROR_NONSTANDARD_QUERY;
+ request->OnError(&recv_packet);
+ }
+ else if (recv_packet.flags & QUERYFLAGS_RCODE)
+ {
+ Error error = ERROR_UNKNOWN;
+
+ switch (recv_packet.flags & QUERYFLAGS_RCODE)
+ {
+ case 1:
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: format error");
+ error = ERROR_FORMAT_ERROR;
+ break;
+ case 2:
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: server error");
+ error = ERROR_SERVER_FAILURE;
+ break;
+ case 3:
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: domain not found");
+ error = ERROR_DOMAIN_NOT_FOUND;
+ break;
+ case 4:
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: not implemented");
+ error = ERROR_NOT_IMPLEMENTED;
+ break;
+ case 5:
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: refused");
+ error = ERROR_REFUSED;
+ break;
+ default:
+ break;
+ }
+
+ ServerInstance->stats->statsDnsBad++;
+ recv_packet.error = error;
+ request->OnError(&recv_packet);
+ }
+ else if (recv_packet.questions.empty() || recv_packet.answers.empty())
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: No resource records returned");
+ ServerInstance->stats->statsDnsBad++;
+ recv_packet.error = ERROR_NO_RECORDS;
+ request->OnError(&recv_packet);
+ }
+ else
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: Lookup complete for " + request->name);
+ ServerInstance->stats->statsDnsGood++;
+ request->OnLookupComplete(&recv_packet);
+ this->AddCache(recv_packet);
+ }
+
+ ServerInstance->stats->statsDns++;
+
+ /* Request's destructor removes it from the request map */
+ delete request;
+ }
+
+ bool Tick(time_t now)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolver: cache: purging DNS cache");
+
+ for (cache_map::iterator it = this->cache.begin(); it != this->cache.end(); )
+ {
+ const Query& query = it->second;
+ if (IsExpired(query, now))
+ this->cache.erase(it++);
+ else
+ ++it;
+ }
+ return true;
+ }
+
+ void Rehash(const std::string& dnsserver)
+ {
+ if (this->GetFd() > -1)
+ {
+ ServerInstance->SE->DelFd(this);
+ ServerInstance->SE->Shutdown(this, 2);
+ ServerInstance->SE->Close(this);
+ this->SetFd(-1);
+
+ /* Remove expired entries from the cache */
+ this->Tick(ServerInstance->Time());
+ }
+
+ irc::sockets::aptosa(dnsserver, DNS::PORT, myserver);
+
+ /* Initialize mastersocket */
+ int s = socket(myserver.sa.sa_family, SOCK_DGRAM, 0);
+ this->SetFd(s);
+
+ /* Have we got a socket? */
+ if (this->GetFd() != -1)
+ {
+ ServerInstance->SE->SetReuse(s);
+ ServerInstance->SE->NonBlocking(s);
+
+ irc::sockets::sockaddrs bindto;
+ memset(&bindto, 0, sizeof(bindto));
+ bindto.sa.sa_family = myserver.sa.sa_family;
+
+ if (ServerInstance->SE->Bind(this->GetFd(), bindto) < 0)
+ {
+ /* Failed to bind */
+ ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Error binding dns socket - hostnames will NOT resolve");
+ ServerInstance->SE->Close(this);
+ this->SetFd(-1);
+ }
+ else if (!ServerInstance->SE->AddFd(this, FD_WANT_POLL_READ | FD_WANT_NO_WRITE))
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Internal error starting DNS - hostnames will NOT resolve.");
+ ServerInstance->SE->Close(this);
+ this->SetFd(-1);
+ }
+ }
+ else
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_SPARSE, "Resolver: Error creating DNS socket - hostnames will NOT resolve");
+ }
+ }
+};
+
+class ModuleDNS : public Module
+{
+ MyManager manager;
+ std::string DNSServer;
+
+ void FindDNSServer()
+ {
+#ifdef _WIN32
+ // attempt to look up their nameserver from the system
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: <dns:server> not defined, attempting to find a working server in the system settings...");
+
+ PFIXED_INFO pFixedInfo;
+ DWORD dwBufferSize = sizeof(FIXED_INFO);
+ pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, sizeof(FIXED_INFO));
+
+ if (pFixedInfo)
+ {
+ if (GetNetworkParams(pFixedInfo, &dwBufferSize) == ERROR_BUFFER_OVERFLOW)
+ {
+ HeapFree(GetProcessHeap(), 0, pFixedInfo);
+ pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
+ }
+
+ if (pFixedInfo)
+ {
+ if (GetNetworkParams(pFixedInfo, &dwBufferSize) == NO_ERROR)
+ DNSServer = pFixedInfo->DnsServerList.IpAddress.String;
+
+ HeapFree(GetProcessHeap(), 0, pFixedInfo);
+ }
+
+ if (!DNSServer.empty())
+ {
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "<dns:server> set to '%s' as first active resolver in the system settings.", DNSServer.c_str());
+ return;
+ }
+ }
+
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "No viable nameserver found! Defaulting to nameserver '127.0.0.1'!");
+#else
+ // attempt to look up their nameserver from /etc/resolv.conf
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
+
+ std::ifstream resolv("/etc/resolv.conf");
+
+ while (resolv >> DNSServer)
+ {
+ if (DNSServer == "nameserver")
+ {
+ resolv >> DNSServer;
+ if (DNSServer.find_first_not_of("0123456789.") == std::string::npos)
+ {
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",DNSServer.c_str());
+ return;
+ }
+ }
+ }
+
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
+#endif
+ DNSServer = "127.0.0.1";
+ }
+
+ public:
+ ModuleDNS() : manager(this)
+ {
+ }
+
+ void init()
+ {
+ Implementation i[] = { I_OnRehash, I_OnUnloadModule };
+ ServerInstance->Modules->Attach(i, this, sizeof(i) / sizeof(Implementation));
+
+ ServerInstance->Modules->AddService(this->manager);
+
+ this->OnRehash(NULL);
+ }
+
+ void OnRehash(User* user)
+ {
+ std::string oldserver = DNSServer;
+ DNSServer = ServerInstance->Config->ConfValue("dns")->getString("server");
+ if (DNSServer.empty())
+ FindDNSServer();
+
+ if (oldserver != DNSServer)
+ this->manager.Rehash(DNSServer);
+ }
+
+ void OnUnloadModule(Module* mod)
+ {
+ for (int i = 0; i < MAX_REQUEST_ID; ++i)
+ {
+ DNS::Request* req = this->manager.requests[i];
+ if (!req)
+ continue;
+
+ if (req->creator == mod)
+ {
+ Query rr(*req);
+ rr.error = ERROR_UNLOADED;
+ req->OnError(&rr);
+
+ delete req;
+ }
+ }
+ }
+
+ Version GetVersion()
+ {
+ return Version("DNS support", VF_CORE|VF_VENDOR);
+ }
+};
+
+MODULE_INIT(ModuleDNS)
+
else
ih = ServerInstance->XLines->IdentSplit(target);
- if (ih.first.empty())
- {
- user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
- return CMD_FAILURE;
- }
+ if (ih.first.empty())
+ {
+ user->WriteNotice("*** Target not found");
+ return CMD_FAILURE;
+ }
if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
return CMD_FAILURE;
- long duration = ServerInstance->Duration(parameters[1].c_str());
-
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
ELine* el = new ELine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
if (ServerInstance->XLines->AddLine(el, user))
{
else
{
delete el;
- user->WriteServ("NOTICE %s :*** E-Line for %s already exists",user->nick.c_str(),target.c_str());
+ user->WriteNotice("*** E-Line for " + target + " already exists");
}
}
else
}
else
{
- user->WriteServ("NOTICE %s :*** E-Line %s not found in list, try /stats e.",user->nick.c_str(),target.c_str());
+ user->WriteNotice("*** E-Line " + target + " not found in list, try /stats e");
}
}
if (ih.first.empty())
{
- user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
+ user->WriteNotice("*** Target not found");
return CMD_FAILURE;
}
else if (target.find('!') != std::string::npos)
{
- user->WriteServ("NOTICE %s :*** G-Line cannot operate on nick!user@host masks",user->nick.c_str());
+ user->WriteNotice("*** G-Line cannot operate on nick!user@host masks");
return CMD_FAILURE;
}
- long duration = ServerInstance->Duration(parameters[1].c_str());
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
GLine* gl = new GLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
if (ServerInstance->XLines->AddLine(gl, user))
{
else
{
delete gl;
- user->WriteServ("NOTICE %s :*** G-Line for %s already exists",user->nick.c_str(),target.c_str());
+ user->WriteNotice("** G-Line for " + target + " already exists");
}
}
}
else
{
- user->WriteServ("NOTICE %s :*** G-line %s not found in list, try /stats g.",user->nick.c_str(),target.c_str());
+ user->WriteNotice("*** G-Line " + target + " not found in list, try /stats g.");
}
}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013 Adam <Adam@anope.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
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "inspircd.h"
+#include "modules/dns.h"
+
+namespace
+{
+ LocalIntExt* dl;
+ LocalStringExt* ph;
+}
+
+/** Derived from Resolver, and performs user forward/reverse lookups.
+ */
+class UserResolver : public DNS::Request
+{
+ /** UUID we are looking up */
+ const std::string uuid;
+
+ /** True if the lookup is forward, false if is a reverse lookup
+ */
+ const bool fwd;
+
+ public:
+ /** Create a resolver.
+ * @param mgr DNS Manager
+ * @param me this module
+ * @param user The user to begin lookup on
+ * @param to_resolve The IP or host to resolve
+ * @param qt The query type
+ */
+ UserResolver(DNS::Manager* mgr, Module* me, LocalUser* user, const std::string& to_resolve, DNS::QueryType qt)
+ : DNS::Request(mgr, me, to_resolve, qt)
+ , uuid(user->uuid)
+ , fwd(qt == DNS::QUERY_A || qt == DNS::QUERY_AAAA)
+ {
+ }
+
+ /** Called on successful lookup
+ * if a previous result has already come back.
+ * @param r The finished query
+ */
+ void OnLookupComplete(const DNS::Query* r)
+ {
+ LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
+ if (!bound_user)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Resolution finished for user '%s' who is gone", uuid.c_str());
+ return;
+ }
+
+ const DNS::ResourceRecord& ans_record = r->answers[0];
+
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "DNS result for %s: '%s' -> '%s'", uuid.c_str(), ans_record.name.c_str(), ans_record.rdata.c_str());
+
+ if (!fwd)
+ {
+ // first half of resolution is done. We now need to verify that the host matches.
+ ph->set(bound_user, ans_record.rdata);
+
+ UserResolver* res_forward;
+ if (bound_user->client_sa.sa.sa_family == AF_INET6)
+ {
+ /* IPV6 forward lookup */
+ res_forward = new UserResolver(this->manager, this->creator, bound_user, ans_record.rdata, DNS::QUERY_AAAA);
+ }
+ else
+ {
+ /* IPV4 lookup */
+ res_forward = new UserResolver(this->manager, this->creator, bound_user, ans_record.rdata, DNS::QUERY_A);
+ }
+ try
+ {
+ this->manager->Process(res_forward);
+ }
+ catch (DNS::Exception& e)
+ {
+ delete res_forward;
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEBUG, "Error in resolver: %s",e.GetReason());
+
+ bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead.");
+ dl->set(bound_user, 0);
+ }
+ }
+ else
+ {
+ /* Both lookups completed */
+
+ irc::sockets::sockaddrs* user_ip = &bound_user->client_sa;
+ bool rev_match = false;
+ if (user_ip->sa.sa_family == AF_INET6)
+ {
+ struct in6_addr res_bin;
+ if (inet_pton(AF_INET6, ans_record.rdata.c_str(), &res_bin))
+ {
+ rev_match = !memcmp(&user_ip->in6.sin6_addr, &res_bin, sizeof(res_bin));
+ }
+ }
+ else
+ {
+ struct in_addr res_bin;
+ if (inet_pton(AF_INET, ans_record.rdata.c_str(), &res_bin))
+ {
+ rev_match = !memcmp(&user_ip->in4.sin_addr, &res_bin, sizeof(res_bin));
+ }
+ }
+
+ dl->set(bound_user, 0);
+
+ if (rev_match)
+ {
+ std::string* hostname = ph->get(bound_user);
+
+ if (hostname == NULL)
+ {
+ ServerInstance->Logs->Log("RESOLVER", LOG_DEFAULT, "ERROR: User has no hostname attached when doing a forward lookup");
+ bound_user->WriteNotice("*** There was an internal error resolving your host, using your IP address (" + bound_user->GetIPString() + ") instead.");
+ return;
+ }
+ else if (hostname->length() < 65)
+ {
+ /* Hostnames starting with : are not a good thing (tm) */
+ if ((*hostname)[0] == ':')
+ hostname->insert(0, "0");
+
+ bound_user->WriteNotice("*** Found your hostname (" + *hostname + (r->cached ? ") -- cached" : ")"));
+ bound_user->host.assign(*hostname, 0, 64);
+ bound_user->dhost = bound_user->host;
+
+ /* Invalidate cache */
+ bound_user->InvalidateCache();
+ }
+ else
+ {
+ bound_user->WriteNotice("*** Your hostname is longer than the maximum of 64 characters, using your IP address (" + bound_user->GetIPString() + ") instead.");
+ }
+
+ ph->unset(bound_user);
+ }
+ else
+ {
+ bound_user->WriteNotice("*** Your hostname does not match up with your IP address. Sorry, using your IP address (" + bound_user->GetIPString() + ") instead.");
+ }
+ }
+ }
+
+ /** Called on failed lookup
+ * @param query The errored query
+ */
+ void OnError(const DNS::Query* query)
+ {
+ LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
+ if (bound_user)
+ {
+ bound_user->WriteNotice("*** Could not resolve your hostname: " + this->manager->GetErrorStr(query->error) + "; using your IP address (" + bound_user->GetIPString() + ") instead.");
+ dl->set(bound_user, 0);
+ ServerInstance->stats->statsDnsBad++;
+ }
+ }
+};
+
+class ModuleHostnameLookup : public Module
+{
+ LocalIntExt dnsLookup;
+ LocalStringExt ptrHosts;
+ dynamic_reference<DNS::Manager> DNS;
+
+ public:
+ ModuleHostnameLookup()
+ : dnsLookup("dnsLookup", this)
+ , ptrHosts("ptrHosts", this)
+ , DNS(this, "DNS")
+ {
+ dl = &dnsLookup;
+ ph = &ptrHosts;
+ }
+
+ void init()
+ {
+ OnRehash(NULL);
+ ServerInstance->Modules->AddService(this->dnsLookup);
+ ServerInstance->Modules->AddService(this->ptrHosts);
+
+ Implementation i[] = { I_OnUserInit, I_OnCheckReady };
+ ServerInstance->Modules->Attach(i, this, sizeof(i) / sizeof(Implementation));
+ }
+
+ void OnUserInit(LocalUser *user)
+ {
+ if (!DNS || user->MyClass->nouserdns)
+ {
+ user->WriteNotice("*** Skipping host resolution (disabled by server administrator)");
+ return;
+ }
+
+ user->WriteNotice("*** Looking up your hostname...");
+
+ UserResolver* res_reverse = new UserResolver(*this->DNS, this, user, user->GetIPString(), DNS::QUERY_PTR);
+ try
+ {
+ /* If both the reverse and forward queries are cached, the user will be able to pass DNS completely
+ * before Process() completes, which is why dnsLookup.set() is here, before Process()
+ */
+ this->dnsLookup.set(user, 1);
+ this->DNS->Process(res_reverse);
+ }
+ catch (DNS::Exception& e)
+ {
+ this->dnsLookup.set(user, 0);
+ delete res_reverse;
+ ServerInstance->Logs->Log("USERS", LOG_DEBUG, "Error in resolver: %s", e.GetReason());
+ ServerInstance->stats->statsDnsBad++;
+ }
+ }
+
+ ModResult OnCheckReady(LocalUser* user)
+ {
+ return this->dnsLookup.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU;
+ }
+
+ Version GetVersion()
+ {
+ return Version("Provides support for DNS lookups on connecting clients", VF_CORE|VF_VENDOR);
+ }
+};
+
+MODULE_INIT(ModuleHostnameLookup)
if (parameters.size() == 3)
{
if (IS_LOCAL(user))
- timeout = ServerInstance->Time() + ServerInstance->Duration(parameters[2]);
+ timeout = ServerInstance->Time() + InspIRCd::Duration(parameters[1]);
else
timeout = ConvToInt(parameters[2]);
}
}
if (IS_LOCAL(u))
- IS_LOCAL(u)->InviteTo(c->name.c_str(), timeout);
- u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str());
- user->WriteNumeric(RPL_INVITING, "%s %s %s",user->nick.c_str(),u->nick.c_str(),c->name.c_str());
+ {
+ Invitation::Create(c, IS_LOCAL(u), timeout);
+ u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str());
+ }
+
+ if (IS_LOCAL(user))
+ user->WriteNumeric(RPL_INVITING, "%s %s %s",user->nick.c_str(),u->nick.c_str(),c->name.c_str());
+
if (ServerInstance->Config->AnnounceInvites != ServerConfig::INVITE_ANNOUNCE_NONE)
{
char prefix;
* the same way, however, they can be fully unloaded, where these
* may not.
*/
-class CommandJoin : public Command
+class CommandJoin : public SplitCommand
{
public:
/** Constructor for join.
*/
- CommandJoin ( Module* parent) : Command(parent,"JOIN", 1, 2) { syntax = "<channel>{,<channel>} {<key>{,<key>}}"; Penalty = 2; }
+ CommandJoin(Module* parent)
+ : SplitCommand(parent, "JOIN", 1, 2)
+ {
+ syntax = "<channel>{,<channel>} {<key>{,<key>}}";
+ Penalty = 2;
+ }
+
/** Handle command.
* @param parameters The parameters to the comamnd
* @param pcnt The number of parameters passed to teh command
* @param user The user issuing the command
* @return A value from CmdResult to indicate command success or failure.
*/
- CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+ CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user);
};
/** Handle /JOIN
*/
-CmdResult CommandJoin::Handle (const std::vector<std::string>& parameters, User *user)
+CmdResult CommandJoin::HandleLocal(const std::vector<std::string>& parameters, LocalUser *user)
{
if (parameters.size() > 1)
{
if (ServerInstance->Parser->LoopCall(user, this, parameters, 0, 1, false))
return CMD_SUCCESS;
- if (ServerInstance->IsChannel(parameters[0].c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (ServerInstance->IsChannel(parameters[0]))
{
- Channel::JoinUser(user, parameters[0].c_str(), false, parameters[1].c_str(), false);
+ Channel::JoinUser(user, parameters[0], false, parameters[1]);
return CMD_SUCCESS;
}
}
if (ServerInstance->Parser->LoopCall(user, this, parameters, 0, -1, false))
return CMD_SUCCESS;
- if (ServerInstance->IsChannel(parameters[0].c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (ServerInstance->IsChannel(parameters[0]))
{
- Channel::JoinUser(user, parameters[0].c_str(), false, "", false);
+ Channel::JoinUser(user, parameters[0]);
return CMD_SUCCESS;
}
}
return CMD_FAILURE;
}
- if ((IS_LOCAL(user)) && (!c->HasUser(user)) && (!ServerInstance->ULine(user->server)))
+ Membership* srcmemb = NULL;
+ if (IS_LOCAL(user))
{
- user->WriteServ( "442 %s %s :You're not on that channel!", user->nick.c_str(), parameters[0].c_str());
- return CMD_FAILURE;
+ srcmemb = c->GetUser(user);
+ if (!srcmemb)
+ {
+ user->WriteServ( "442 %s %s :You're not on that channel!", user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
+ if (ServerInstance->ULine(u->server))
+ {
+ user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You may not kick a u-lined client", user->nick.c_str(), c->name.c_str());
+ return CMD_FAILURE;
+ }
}
if (parameters.size() > 2)
reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick);
}
- c->KickUser(user, u, reason.c_str());
+ c->KickUser(user, u, reason, srcmemb);
return CMD_SUCCESS;
}
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());
+ ServerInstance->Logs->Log("KILL", LOG_DEFAULT, "LOCAL KILL: %s :%s!%s!%s (%s)", u->nick.c_str(), ServerInstance->Config->ServerName.c_str(), user->dhost.c_str(), user->nick.c_str(), parameters[1].c_str());
/* 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
*/
if (ih.first.empty())
{
- user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
+ user->WriteNotice("*** Target not found");
return CMD_FAILURE;
}
if (target.find('!') != std::string::npos)
{
- user->WriteServ("NOTICE %s :*** K-Line cannot operate on nick!user@host masks",user->nick.c_str());
+ user->WriteNotice("*** K-Line cannot operate on nick!user@host masks");
return CMD_FAILURE;
}
- long duration = ServerInstance->Duration(parameters[1].c_str());
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
KLine* kl = new KLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
if (ServerInstance->XLines->AddLine(kl,user))
{
else
{
delete kl;
- user->WriteServ("NOTICE %s :*** K-Line for %s already exists",user->nick.c_str(),target.c_str());
+ user->WriteNotice("*** K-Line for " + target + " already exists");
}
}
else
}
else
{
- user->WriteServ("NOTICE %s :*** K-Line %s not found in list, try /stats k.",user->nick.c_str(),target.c_str());
+ user->WriteNotice("*** K-Line " + target + " not found in list, try /stats k.");
}
}
unsigned int& invisible;
public:
InvisibleWatcher(Module* mod, unsigned int& Invisible)
- : ModeWatcher(mod, 'i', MODETYPE_USER), invisible(Invisible)
+ : ModeWatcher(mod, "invisible", MODETYPE_USER), invisible(Invisible)
{
}
- void AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding, ModeType type)
+ void AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding)
{
if (dest->registered != REG_ALL)
return;
// module to override its behaviour and display something
// better.
- if (IS_OPER(user))
+ if (user->IsOper())
{
user->WriteNumeric(006, "%s :%s [%s]", user->nick.c_str(), ServerInstance->Config->ServerName.c_str(), ServerInstance->Config->GetSID().c_str());
user->WriteNumeric(007, "%s :End of /MAP", user->nick.c_str());
{
newnick = user->uuid;
}
- else if (!ServerInstance->IsNick(newnick.c_str(), ServerInstance->Config->Limits.NickMax))
+ else if (!ServerInstance->IsNick(newnick))
{
user->WriteNumeric(432, "%s %s :Erroneous Nickname", user->nick.c_str(),newnick.c_str());
return CMD_FAILURE;
CUList exempt_list;
- user->idle_lastmsg = ServerInstance->Time();
+ LocalUser* localuser = IS_LOCAL(user);
+ if (localuser)
+ localuser->idle_lastmsg = ServerInstance->Time();
if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
ModResult MOD_RESULT;
std::string temp = parameters[1];
- FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list));
+ FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list, MSG_NOTICE));
if (MOD_RESULT == MOD_RES_DENY)
return CMD_FAILURE;
const char* text = temp.c_str();
{
user->SendAll("NOTICE", "%s", text);
}
- FOREACH_MOD(I_OnUserNotice,OnUserNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list, MSG_NOTICE));
return CMD_SUCCESS;
}
char status = 0;
if (chan)
{
- if (IS_LOCAL(user))
+ if (localuser)
{
if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
{
ModResult MOD_RESULT;
std::string temp = parameters[1];
- FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status, exempt_list));
+ FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status, exempt_list, MSG_NOTICE));
if (MOD_RESULT == MOD_RES_DENY)
return CMD_FAILURE;
chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
}
- FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,text,status,exempt_list,MSG_NOTICE));
}
else
{
const char* destnick = parameters[0].c_str();
- if (IS_LOCAL(user))
+ if (localuser)
{
const char* targetserver = strchr(destnick, '@');
ModResult MOD_RESULT;
std::string temp = parameters[1];
- FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,dest,TYPE_USER,temp,0,exempt_list));
+ FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, exempt_list, MSG_NOTICE));
if (MOD_RESULT == MOD_RES_DENY) {
return CMD_FAILURE;
}
user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
}
- FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
+ FOREACH_MOD(I_OnUserMessage, OnUserMessage(user, dest, TYPE_USER, text, 0, exempt_list, MSG_NOTICE));
}
else
{
#include "inspircd.h"
-bool OneOfMatches(const char* host, const char* ip, const char* hostlist);
-
/** Handle /OPER. These command handlers can be reloaded by the core,
* and handle basic RFC1459 commands. Commands within modules work
* the same way, however, they can be fully unloaded, where these
CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser *user);
};
-bool OneOfMatches(const char* host, const char* ip, const std::string& hostlist)
-{
- std::stringstream hl(hostlist);
- std::string xhost;
- while (hl >> xhost)
- {
- if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
- {
- return true;
- }
- }
- return false;
-}
-
CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, LocalUser *user)
{
- char TheHost[MAXBUF];
- char TheIP[MAXBUF];
bool match_login = false;
bool match_pass = false;
bool match_hosts = false;
- snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str());
- snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
+ const std::string userHost = user->ident + "@" + user->host;
+ const std::string userIP = user->ident + "@" + user->GetIPString();
OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]);
if (i != ServerInstance->Config->oper_blocks.end())
ConfigTag* tag = ifo->oper_block;
match_login = true;
match_pass = !ServerInstance->PassCompare(user, tag->getString("password"), parameters[1], tag->getString("hash"));
- match_hosts = OneOfMatches(TheHost,TheIP,tag->getString("host"));
+ match_hosts = InspIRCd::MatchMask(tag->getString("host"), userHost, userIP);
if (match_pass && match_hosts)
{
user->CommandFloodPenalty += 10000;
ServerInstance->SNO->WriteGlobalSno('o', "WARNING! Failed oper attempt by %s using login '%s': The following fields do not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str());
- ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s using login '%s': The following fields did not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str());
+ ServerInstance->Logs->Log("OPER", LOG_DEFAULT, "OPER: Failed oper attempt by %s using login '%s': The following fields did not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str());
return CMD_FAILURE;
}
Channel *chan;
CUList except_list;
- user->idle_lastmsg = ServerInstance->Time();
+ LocalUser* localuser = IS_LOCAL(user);
+ if (localuser)
+ localuser->idle_lastmsg = ServerInstance->Time();
if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
ModResult MOD_RESULT;
std::string temp = parameters[1];
- FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list));
+ FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list, MSG_PRIVMSG));
if (MOD_RESULT == MOD_RES_DENY)
return CMD_FAILURE;
{
user->SendAll("PRIVMSG", "%s", text);
}
- FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list, MSG_PRIVMSG));
return CMD_SUCCESS;
}
char status = 0;
if (chan)
{
- if (IS_LOCAL(user) && chan->GetPrefixValue(user) < VOICE_VALUE)
+ if (localuser && chan->GetPrefixValue(user) < VOICE_VALUE)
{
if (chan->IsModeSet('n') && !chan->HasUser(user))
{
ModResult MOD_RESULT;
std::string temp = parameters[1];
- FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status,except_list));
+ FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, chan, TYPE_CHANNEL, temp, status, except_list, MSG_PRIVMSG));
if (MOD_RESULT == MOD_RES_DENY)
return CMD_FAILURE;
chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %s :%s", chan->name.c_str(), text);
}
- FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,text,status,except_list));
+ FOREACH_MOD(I_OnUserMessage, OnUserMessage(user,chan, TYPE_CHANNEL, text, status, except_list, MSG_PRIVMSG));
}
else
{
const char* destnick = parameters[0].c_str();
- if (IS_LOCAL(user))
+ if (localuser)
{
const char* targetserver = strchr(destnick, '@');
return CMD_FAILURE;
}
- if (IS_AWAY(dest))
+ if (dest->IsAway())
{
/* auto respond with aweh msg */
user->WriteNumeric(301, "%s %s :%s", user->nick.c_str(), dest->nick.c_str(), dest->awaymsg.c_str());
ModResult MOD_RESULT;
std::string temp = parameters[1];
- FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, except_list));
+ FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, except_list, MSG_PRIVMSG));
if (MOD_RESULT == MOD_RES_DENY)
return CMD_FAILURE;
user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick.c_str(), text);
}
- FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, dest, TYPE_USER, text, 0, except_list));
+ FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, dest, TYPE_USER, text, 0, except_list, MSG_PRIVMSG));
}
else
{
if (parameters[0].find('@') != std::string::npos || parameters[0].find('!') != std::string::npos || parameters[0].find('.') != std::string::npos)
{
- user->WriteServ("NOTICE %s :*** A Q-Line only bans a nick pattern, not a nick!user@host pattern.",user->nick.c_str());
+ user->WriteNotice("*** A Q-Line only bans a nick pattern, not a nick!user@host pattern.");
return CMD_FAILURE;
}
- long duration = ServerInstance->Duration(parameters[1].c_str());
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
QLine* ql = new QLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
if (ServerInstance->XLines->AddLine(ql,user))
{
else
{
delete ql;
- user->WriteServ("NOTICE %s :*** Q-Line for %s already exists",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNotice("*** Q-Line for " + parameters[0] + " already exists");
}
}
else
}
else
{
- user->WriteServ("NOTICE %s :*** Q-Line %s not found in list, try /stats q.",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNotice("*** Q-Line " + parameters[0] + " not found in list, try /stats q.");
return CMD_FAILURE;
}
}
/* Don't do anything with the logs here -- logs are restarted
* after the config thread has completed.
*/
- ServerInstance->RehashUsersAndChans();
FOREACH_MOD(I_OnGarbageCollect, OnGarbageCollect());
* XXX, todo: we should find some way to kill runaway rehashes that are blocking, this is a major problem for unrealircd users
*/
if (IS_LOCAL(user))
- user->WriteServ("NOTICE %s :*** Could not rehash: A rehash is already in progress.", user->nick.c_str());
+ user->WriteNotice("*** Could not rehash: A rehash is already in progress.");
else
ServerInstance->PI->SendUserNotice(user, "*** Could not rehash: A rehash is already in progress.");
}
CmdResult CommandRestart::Handle (const std::vector<std::string>& parameters, User *user)
{
- ServerInstance->Logs->Log("COMMAND",DEFAULT,"Restart: %s",user->nick.c_str());
+ ServerInstance->Logs->Log("COMMAND", LOG_DEFAULT, "Restart: %s",user->nick.c_str());
if (!ServerInstance->PassCompare(user, ServerInstance->Config->restartpass, parameters[0].c_str(), ServerInstance->Config->powerhash))
{
ServerInstance->SNO->WriteGlobalSno('a', "RESTART command from %s, restarting server.", user->GetFullRealHost().c_str());
#include "inspircd.h"
#include "xline.h"
-#include "commands/cmd_whowas.h"
#ifdef _WIN32
#include <psapi.h>
std::string sn(ServerInstance->Config->ServerName);
bool isPublic = ServerInstance->Config->UserStats.find(statschar) != std::string::npos;
- bool isRemoteOper = IS_REMOTE(user) && IS_OPER(user);
+ bool isRemoteOper = IS_REMOTE(user) && (user->IsOper());
bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex");
if (!isPublic && !isRemoteOper && !isLocalOperWithPrivs)
User* oper = *i;
if (!ServerInstance->ULine(oper->server))
{
+ LocalUser* lu = IS_LOCAL(oper);
results.push_back(sn+" 249 " + user->nick + " :" + oper->nick + " (" + oper->ident + "@" + oper->dhost + ") Idle: " +
- (IS_LOCAL(oper) ? ConvToStr(ServerInstance->Time() - oper->idle_lastmsg) + " secs" : "unavailable"));
+ (lu ? ConvToStr(ServerInstance->Time() - lu->idle_lastmsg) + " secs" : "unavailable"));
idx++;
}
}
if (i->second->use_count)
{
/* RPL_STATSCOMMANDS */
- results.push_back(sn+" 212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count)+" "+ConvToStr(i->second->total_bytes));
+ results.push_back(sn+" 212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count));
}
}
break;
results.push_back(sn+" 249 "+user->nick+" :Channels: "+ConvToStr(ServerInstance->chanlist->size()));
results.push_back(sn+" 249 "+user->nick+" :Commands: "+ConvToStr(ServerInstance->Parser->cmdlist.size()));
- if (!ServerInstance->Config->WhoWasGroupSize == 0 && !ServerInstance->Config->WhoWasMaxGroups == 0)
- {
- Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so");
- if (whowas)
- {
- WhowasRequest req(NULL, whowas, WhowasRequest::WHOWAS_STATS);
- req.user = user;
- req.Send();
- results.push_back(sn+" 249 "+user->nick+" :"+req.value);
- }
- }
-
float kbitpersec_in, kbitpersec_out, kbitpersec_total;
char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30];
double n_eaten = (double)( ( (uint64_t)(KernelTime.dwHighDateTime - ServerInstance->stats->LastCPU.dwHighDateTime) << 32 ) + (uint64_t)(KernelTime.dwLowDateTime - ServerInstance->stats->LastCPU.dwLowDateTime) )/100000;
double n_elapsed = (double)(ThisSample.QuadPart - ServerInstance->stats->LastSampled.QuadPart) / ServerInstance->stats->QPFrequency.QuadPart;
double per = (n_eaten/n_elapsed);
-
+
char percent[30];
snprintf(percent, 30, "%03.5f%%", per);
if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A'])
cmodes.push_back(c);
}
- results.push_back(sn+" 243 "+user->nick+" O "+tag->NameStr() + " " + umodes + " " + cmodes);
+ results.push_back(sn+" 243 "+user->nick+" O "+tag->name.c_str() + " " + umodes + " " + cmodes);
}
}
break;
{
if (parameters.size() > 0 && parameters[0] != ServerInstance->Config->ServerName)
return CMD_SUCCESS;
- struct tm* timeinfo;
- time_t local = ServerInstance->Time();
-
- timeinfo = localtime(&local);
- char tms[26];
- snprintf(tms,26,"%s",asctime(timeinfo));
- tms[24] = 0;
+ time_t local = ServerInstance->Time();
+ struct tm* timeinfo = localtime(&local);
+ const std::string& humanTime = asctime(timeinfo);
- user->SendText(":%s %03d %s %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_TIME, user->nick.c_str(),ServerInstance->Config->ServerName.c_str(),tms);
+ user->SendText(":%s %03d %s %s :%s", ServerInstance->Config->ServerName.c_str(), RPL_TIME, user->nick.c_str(),
+ ServerInstance->Config->ServerName.c_str(), humanTime.c_str());
return CMD_SUCCESS;
}
CmdResult CommandUnloadmodule::Handle (const std::vector<std::string>& parameters, User *user)
{
+ if (!ServerInstance->Config->ConfValue("security")->getBool("allowcoreunload") &&
+ InspIRCd::Match(parameters[0], "cmd_*.so", ascii_case_insensitive_map))
+ {
+ user->WriteNumeric(972, "%s %s :You cannot unload core commands!", user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
if (parameters[0] == "cmd_unloadmodule.so" || parameters[0] == "cmd_loadmodule.so")
{
user->WriteNumeric(972, "%s %s :You cannot unload module loading commands!", user->nick.c_str(), parameters[0].c_str());
return CMD_FAILURE;
}
-
+
Module* m = ServerInstance->Modules->Find(parameters[0]);
if (m && ServerInstance->Modules->Unload(m))
{
{
retbuf = retbuf + u->nick;
- if (IS_OPER(u))
+ if (u->IsOper())
retbuf = retbuf + "*";
retbuf = retbuf + "=";
- if (IS_AWAY(u))
+ if (u->IsAway())
retbuf += "-";
else
retbuf += "+";
CmdResult CommandVersion::Handle (const std::vector<std::string>&, User *user)
{
- std::string version = ServerInstance->GetVersionString(IS_OPER(user));
+ std::string version = ServerInstance->GetVersionString((user->IsOper()));
user->WriteNumeric(RPL_VERSION, "%s :%s", user->nick.c_str(), version.c_str());
- ServerInstance->Config->Send005(user);
+ LocalUser *lu = IS_LOCAL(user);
+ if (lu != NULL)
+ {
+ ServerInstance->ISupport.SendTo(lu);
+ }
return CMD_SUCCESS;
}
* @return A value from CmdResult to indicate command success or failure.
*/
CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+
+ RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
+ {
+ return ROUTE_BROADCAST;
+ }
};
CmdResult CommandWallops::Handle (const std::vector<std::string>& parameters, User *user)
user->WriteTo(t,wallop);
}
- FOREACH_MOD(I_OnWallops,OnWallops(user,parameters[0]));
return CMD_SUCCESS;
}
match = InspIRCd::Match(user->awaymsg, matchtext);
else if (opt_time)
{
- long seconds = ServerInstance->Duration(matchtext);
+ long seconds = InspIRCd::Duration(matchtext);
// Okay, so time matching, we want all users connected `seconds' ago
if (user->age >= ServerInstance->Time() - seconds)
wholine.append(ServerInstance->Config->HideWhoisServer);
else
wholine.append(u->server);
-
+
wholine.append(" " + u->nick + " ");
/* away? */
- if (IS_AWAY(u))
+ if (u->IsAway())
{
wholine.append("G");
}
}
/* oper? */
- if (IS_OPER(u))
+ if (u->IsOper())
{
wholine.push_back('*');
}
opt_far = false;
opt_time = false;
- Channel *ch = NULL;
std::vector<std::string> whoresults;
std::string initial = "352 " + user->nick + " ";
- char matchtext[MAXBUF];
- bool usingwildcards = false;
-
/* Change '0' into '*' so the wildcard matcher can grok it */
- if (parameters[0] == "0")
- strlcpy(matchtext, "*", MAXBUF);
- else
- strlcpy(matchtext, parameters[0].c_str(), MAXBUF);
+ std::string matchtext = ((parameters[0] == "0") ? "*" : parameters[0]);
- for (const char* check = matchtext; *check; check++)
- {
- if (*check == '*' || *check == '?' || *check == '.')
- {
- usingwildcards = true;
- break;
- }
- }
+ // WHO flags count as a wildcard
+ bool usingwildcards = ((parameters.size() > 1) || (matchtext.find_first_of("*?.") != std::string::npos));
if (parameters.size() > 1)
{
- /* Fix for bug #444, WHO flags count as a wildcard */
- usingwildcards = true;
-
for (std::string::const_iterator iter = parameters[1].begin(); iter != parameters[1].end(); ++iter)
{
switch (*iter)
/* who on a channel? */
- ch = ServerInstance->FindChan(matchtext);
+ Channel* ch = ServerInstance->FindChan(matchtext);
if (ch)
{
if (user != i->first)
{
/* opers only, please */
- if (opt_viewopersonly && !IS_OPER(i->first))
+ if (opt_viewopersonly && !i->first->IsOper())
continue;
/* If we're not inside the channel, hide +i users */
{
User* oper = *i;
- if (whomatch(user, oper, matchtext))
+ if (whomatch(user, oper, matchtext.c_str()))
{
if (!user->SharesChannelWith(oper))
{
{
for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++)
{
- if (whomatch(user, i->second, matchtext))
+ if (whomatch(user, i->second, matchtext.c_str()))
{
if (!user->SharesChannelWith(i->second))
{
* the same way, however, they can be fully unloaded, where these
* may not.
*/
-class CommandWhois : public Command
+class CommandWhois : public SplitCommand
{
+ void SplitChanList(User* source, User* dest, const std::string& cl);
+ void DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle);
+ std::string ChannelList(User* source, User* dest, bool spy);
+
public:
/** Constructor for whois.
*/
- CommandWhois ( Module* parent) : Command(parent,"WHOIS",1) { Penalty = 2; syntax = "<nick>{,<nick>}"; }
+ CommandWhois ( Module* parent) : SplitCommand(parent,"WHOIS", 1) { Penalty = 2; syntax = "<nick>{,<nick>}"; }
/** Handle command.
* @param parameters The parameters to the comamnd
* @param pcnt The number of parameters passed to teh command
* @param user The user issuing the command
* @return A value from CmdResult to indicate command success or failure.
*/
- CmdResult Handle(const std::vector<std::string>& parameters, User *user);
+ CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user);
+ CmdResult HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target);
};
+std::string CommandWhois::ChannelList(User* source, User* dest, bool spy)
+{
+ std::string list;
+
+ for (UCListIter i = dest->chans.begin(); i != dest->chans.end(); i++)
+ {
+ Channel* c = *i;
+ /* If the target is the sender, neither +p nor +s is set, or
+ * the channel contains the user, it is not a spy channel
+ */
+ if (spy != (source == dest || !(c->IsModeSet('p') || c->IsModeSet('s')) || c->HasUser(source)))
+ list.append(c->GetPrefixChar(dest)).append(c->name).append(" ");
+ }
+
+ return list;
+}
-CmdResult CommandWhois::Handle (const std::vector<std::string>& parameters, User *user)
+void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl)
+{
+ std::string line;
+ std::ostringstream prefix;
+ std::string::size_type start, pos, length;
+
+ prefix << source->nick << " " << dest->nick << " :";
+ line = prefix.str();
+ int namelen = ServerInstance->Config->ServerName.length() + 6;
+
+ for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
+ {
+ length = (pos == std::string::npos) ? cl.length() : pos;
+
+ if (line.length() + namelen + length - start > 510)
+ {
+ ServerInstance->SendWhoisLine(source, dest, 319, "%s", line.c_str());
+ line = prefix.str();
+ }
+
+ if(pos == std::string::npos)
+ {
+ line.append(cl.substr(start, length - start));
+ break;
+ }
+ else
+ {
+ line.append(cl.substr(start, length - start + 1));
+ }
+ }
+
+ if (line.length() != prefix.str().length())
+ {
+ ServerInstance->SendWhoisLine(source, dest, 319, "%s", line.c_str());
+ }
+}
+
+void CommandWhois::DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle)
+{
+ ServerInstance->SendWhoisLine(user, dest, 311, "%s %s %s %s * :%s",user->nick.c_str(), dest->nick.c_str(), dest->ident.c_str(), dest->dhost.c_str(), dest->fullname.c_str());
+ if (user == dest || user->HasPrivPermission("users/auspex"))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 378, "%s %s :is connecting from %s@%s %s", user->nick.c_str(), dest->nick.c_str(), dest->ident.c_str(), dest->host.c_str(), dest->GetIPString().c_str());
+ }
+
+ std::string cl = ChannelList(user, dest, false);
+ const ServerConfig::OperSpyWhoisState state = user->HasPrivPermission("users/auspex") ? ServerInstance->Config->OperSpyWhois : ServerConfig::SPYWHOIS_NONE;
+
+ if (state == ServerConfig::SPYWHOIS_SINGLEMSG)
+ cl.append(ChannelList(user, dest, true));
+
+ SplitChanList(user, dest, cl);
+
+ if (state == ServerConfig::SPYWHOIS_SPLITMSG)
+ {
+ std::string scl = ChannelList(user, dest, true);
+ if (scl.length())
+ {
+ ServerInstance->SendWhoisLine(user, dest, 336, "%s %s :is on private/secret channels:",user->nick.c_str(), dest->nick.c_str());
+ SplitChanList(user, dest, scl);
+ }
+ }
+ if (user != dest && !ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 312, "%s %s %s :%s",user->nick.c_str(), dest->nick.c_str(), ServerInstance->Config->HideWhoisServer.c_str(), ServerInstance->Config->Network.c_str());
+ }
+ else
+ {
+ std::string serverdesc = ServerInstance->GetServerDescription(dest->server);
+ ServerInstance->SendWhoisLine(user, dest, 312, "%s %s %s :%s",user->nick.c_str(), dest->nick.c_str(), dest->server.c_str(), serverdesc.c_str());
+ }
+
+ if (dest->IsAway())
+ {
+ ServerInstance->SendWhoisLine(user, dest, 301, "%s %s :%s",user->nick.c_str(), dest->nick.c_str(), dest->awaymsg.c_str());
+ }
+
+ if (dest->IsOper())
+ {
+ if (ServerInstance->Config->GenericOper)
+ ServerInstance->SendWhoisLine(user, dest, 313, "%s %s :is an IRC operator",user->nick.c_str(), dest->nick.c_str());
+ else
+ ServerInstance->SendWhoisLine(user, dest, 313, "%s %s :is %s %s on %s",user->nick.c_str(), dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->name.c_str(), ServerInstance->Config->Network.c_str());
+ }
+
+ if (user == dest || user->HasPrivPermission("users/auspex"))
+ {
+ if (dest->IsModeSet('s') != 0)
+ {
+ ServerInstance->SendWhoisLine(user, dest, 379, "%s %s :is using modes +%s +%s", user->nick.c_str(), dest->nick.c_str(), dest->FormatModes(), dest->FormatNoticeMasks());
+ }
+ else
+ {
+ ServerInstance->SendWhoisLine(user, dest, 379, "%s %s :is using modes +%s", user->nick.c_str(), dest->nick.c_str(), dest->FormatModes());
+ }
+ }
+
+ FOREACH_MOD(I_OnWhois,OnWhois(user,dest));
+
+ /*
+ * We only send these if we've been provided them. That is, if hidewhois is turned off, and user is local, or
+ * if remote whois is queried, too. This is to keep the user hidden, and also since you can't reliably tell remote time. -- w00t
+ */
+ if ((idle) || (signon))
+ {
+ ServerInstance->SendWhoisLine(user, dest, 317, "%s %s %lu %lu :seconds idle, signon time",user->nick.c_str(), dest->nick.c_str(), idle, signon);
+ }
+
+ ServerInstance->SendWhoisLine(user, dest, 318, "%s %s :End of /WHOIS list.",user->nick.c_str(), dest->nick.c_str());
+}
+
+CmdResult CommandWhois::HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target)
+{
+ if (parameters.size() < 2)
+ return CMD_FAILURE;
+
+ User* user = ServerInstance->FindUUID(parameters[0]);
+ if (!user)
+ return CMD_FAILURE;
+
+ unsigned long idle = ConvToInt(parameters[1]);
+ DoWhois(user, target, target->signon, idle);
+
+ return CMD_SUCCESS;
+}
+
+CmdResult CommandWhois::HandleLocal(const std::vector<std::string>& parameters, LocalUser* user)
{
User *dest;
int userindex = 0;
if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
return CMD_SUCCESS;
-
/*
* If 2 paramters are specified (/whois nick nick), ignore the first one like spanningtree
* does, and use the second one, otherwise, use the only paramter. -- djGrrr
if (parameters.size() > 1)
userindex = 1;
- if (IS_LOCAL(user))
- dest = ServerInstance->FindNickOnly(parameters[userindex]);
- else
- dest = ServerInstance->FindNick(parameters[userindex]);
+ dest = ServerInstance->FindNickOnly(parameters[userindex]);
if ((dest) && (dest->registered == REG_ALL))
{
* For remote users (/w remoteuser remoteuser), spanningtree will handle calling do_whois, so we can ignore this case.
* Thanks to djGrrr for not being impatient while I have a crap day coding. :p -- w00t
*/
- if (IS_LOCAL(dest) && (ServerInstance->Config->HideWhoisServer.empty() || parameters.size() > 1))
+ LocalUser* localuser = IS_LOCAL(dest);
+ if (localuser && (ServerInstance->Config->HideWhoisServer.empty() || parameters.size() > 1))
{
- idle = abs((long)((dest->idle_lastmsg)-ServerInstance->Time()));
+ idle = abs((long)((localuser->idle_lastmsg)-ServerInstance->Time()));
signon = dest->signon;
}
- ServerInstance->DoWhois(user,dest,signon,idle,parameters[userindex].c_str());
+ DoWhois(user,dest,signon,idle);
}
else
{
return CMD_SUCCESS;
}
-
-
COMMAND_INIT(CommandWhois)
#include "inspircd.h"
#include "commands/cmd_whowas.h"
-WhoWasMaintainTimer * timer;
-
-CommandWhowas::CommandWhowas( Module* parent) : Command(parent, "WHOWAS", 1)
+CommandWhowas::CommandWhowas( Module* parent)
+ : Command(parent, "WHOWAS", 1), WhoWasGroupSize(0), WhoWasMaxGroups(0), WhoWasMaxKeep(0)
{
syntax = "<nick>{,<nick>}";
Penalty = 2;
- timer = new WhoWasMaintainTimer(3600);
- ServerInstance->Timers->AddTimer(timer);
}
CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, User* user)
{
/* if whowas disabled in config */
- if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
+ if (this->WhoWasGroupSize == 0 || this->WhoWasMaxGroups == 0)
{
user->WriteNumeric(421, "%s %s :This command has been disabled.",user->nick.c_str(),name.c_str());
return CMD_FAILURE;
void CommandWhowas::AddToWhoWas(User* user)
{
/* if whowas disabled */
- if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
+ if (this->WhoWasGroupSize == 0 || this->WhoWasMaxGroups == 0)
{
return;
}
whowas[user->nick.c_str()] = n;
whowas_fifo.push_back(std::make_pair(ServerInstance->Time(),user->nick.c_str()));
- if ((int)(whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
+ if ((int)(whowas.size()) > this->WhoWasMaxGroups)
{
whowas_users::iterator iter2 = whowas.find(whowas_fifo[0].second);
if (iter2 != whowas.end())
WhoWasGroup *a = new WhoWasGroup(user);
group->push_back(a);
- if ((int)(group->size()) > ServerInstance->Config->WhoWasGroupSize)
+ if ((int)(group->size()) > this->WhoWasGroupSize)
{
WhoWasGroup *a2 = (WhoWasGroup*)*(group->begin());
delete a2;
void CommandWhowas::PruneWhoWas(time_t t)
{
/* config values */
- int groupsize = ServerInstance->Config->WhoWasGroupSize;
- int maxgroups = ServerInstance->Config->WhoWasMaxGroups;
- int maxkeep = ServerInstance->Config->WhoWasMaxKeep;
+ int groupsize = this->WhoWasGroupSize;
+ int maxgroups = this->WhoWasMaxGroups;
+ int maxkeep = this->WhoWasMaxKeep;
/* first cut the list to new size (maxgroups) and also prune entries that are timed out. */
whowas_users::iterator iter;
if (iter == whowas.end())
{
/* this should never happen, if it does maps are corrupt */
- ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (1)");
+ ServerInstance->Logs->Log("WHOWAS", LOG_DEFAULT, "BUG: Whowas maps got corrupted! (1)");
return;
}
if (iter == whowas.end())
{
/* this should never happen, if it does maps are corrupt */
- ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (2)");
+ ServerInstance->Logs->Log("WHOWAS", LOG_DEFAULT, "BUG: Whowas maps got corrupted! (2)");
return;
}
whowas_set* n = (whowas_set*)iter->second;
whowas_set* n = (whowas_set*)iter->second;
if (n->size())
{
- while ((n->begin() != n->end()) && ((*n->begin())->signon < t - ServerInstance->Config->WhoWasMaxKeep))
+ while ((n->begin() != n->end()) && ((*n->begin())->signon < t - this->WhoWasMaxKeep))
{
WhoWasGroup *a = *(n->begin());
delete a;
CommandWhowas::~CommandWhowas()
{
- if (timer)
- {
- ServerInstance->Timers->DelTimer(timer);
- }
-
whowas_users::iterator iter;
int fifosize;
while ((fifosize = (int)whowas_fifo.size()) > 0)
if (iter == whowas.end())
{
/* this should never happen, if it does maps are corrupt */
- ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (3)");
+ ServerInstance->Logs->Log("WHOWAS", LOG_DEFAULT, "BUG: Whowas maps got corrupted! (3)");
return;
}
{
}
-/* every hour, run this function which removes all entries older than Config->WhoWasMaxKeep */
-void WhoWasMaintainTimer::Tick(time_t)
+class ModuleWhoWas : public Module
{
- Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so");
- if (whowas)
+ CommandWhowas cmd;
+
+ void RangeCheck(int& value, int min, int max, int def, const char* msg)
{
- WhowasRequest(whowas, whowas, WhowasRequest::WHOWAS_MAINTAIN).Send();
+ // From ConfigReader
+ if (value >= min && value <= max)
+ return;
+
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: %s value of %d is not between %d and %d; set to %d.", msg, value, min, max, def);
+ value = def;
}
-}
-class ModuleWhoWas : public Module
-{
- CommandWhowas cmd;
public:
ModuleWhoWas() : cmd(this)
{
void init()
{
ServerInstance->Modules->AddService(cmd);
+ Implementation eventlist[] = { I_OnGarbageCollect, I_OnUserQuit, I_OnStats, I_OnRehash };
+ ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
+ OnRehash(NULL);
}
- void OnRequest(Request& request)
+ void OnGarbageCollect()
{
- WhowasRequest& req = static_cast<WhowasRequest&>(request);
- switch (req.type)
- {
- case WhowasRequest::WHOWAS_ADD:
- cmd.AddToWhoWas(req.user);
- break;
- case WhowasRequest::WHOWAS_STATS:
- req.value = cmd.GetStats();
- break;
- case WhowasRequest::WHOWAS_PRUNE:
- cmd.PruneWhoWas(ServerInstance->Time());
- break;
- case WhowasRequest::WHOWAS_MAINTAIN:
- cmd.MaintainWhoWas(ServerInstance->Time());
- break;
- }
+ /* Removes all entries older than WhoWasMaxKeep */
+ cmd.MaintainWhoWas(ServerInstance->Time());
+ }
+
+ void OnUserQuit(User* user, const std::string& message, const std::string& oper_message)
+ {
+ cmd.AddToWhoWas(user);
+ }
+
+ ModResult OnStats(char symbol, User* user, string_list &results)
+ {
+ if (symbol == 'z')
+ results.push_back(ServerInstance->Config->ServerName+" 249 "+user->nick+" :"+cmd.GetStats());
+
+ return MOD_RES_PASSTHRU;
+ }
+
+ void OnRehash(User* user)
+ {
+ ConfigTag* tag = ServerInstance->Config->ConfValue("whowas");
+ int NewGroupSize = tag->getInt("groupsize");
+ int NewMaxGroups = tag->getInt("maxgroups");
+ int NewMaxKeep = InspIRCd::Duration(tag->getString("maxkeep"));
+
+ RangeCheck(NewGroupSize, 0, 10000, 10, "<whowas:groupsize>");
+ RangeCheck(NewMaxGroups, 0, 1000000, 10240, "<whowas:maxgroups>");
+ RangeCheck(NewMaxKeep, 3600, INT_MAX, 3600, "<whowas:maxkeep>");
+
+ if ((NewGroupSize == cmd.WhoWasGroupSize) && (NewMaxGroups == cmd.WhoWasMaxGroups) && (NewMaxKeep == cmd.WhoWasMaxKeep))
+ return;
+
+ cmd.WhoWasGroupSize = NewGroupSize;
+ cmd.WhoWasMaxGroups = NewMaxGroups;
+ cmd.WhoWasMaxKeep = NewMaxKeep;
+ cmd.PruneWhoWas(ServerInstance->Time());
}
Version GetVersion()
{
- return Version("WHOWAS Command", VF_VENDOR);
+ return Version("WHOWAS", VF_VENDOR);
}
};
{
if (target.find('!') != std::string::npos)
{
- user->WriteServ("NOTICE %s :*** You cannot include a nickname in a zline, a zline must ban only an IP mask",user->nick.c_str());
+ user->WriteNotice("*** You cannot include a nickname in a zline, a zline must ban only an IP mask");
return CMD_FAILURE;
}
if (ServerInstance->IPMatchesEveryone(ipaddr,user))
return CMD_FAILURE;
- long duration = ServerInstance->Duration(parameters[1].c_str());
-
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr);
if (ServerInstance->XLines->AddLine(zl,user))
{
else
{
delete zl;
- user->WriteServ("NOTICE %s :*** Z-Line for %s already exists",user->nick.c_str(),ipaddr);
+ user->WriteNotice("*** Z-Line for " + std::string(ipaddr) + " already exists");
}
}
else
}
else
{
- user->WriteServ("NOTICE %s :*** Z-Line %s not found in list, try /stats Z.",user->nick.c_str(),target.c_str());
+ user->WriteNotice("*** Z-Line " + target + " not found in list, try /stats Z.");
return CMD_FAILURE;
}
}
while (1)
{
ch = next();
- if (ch == '&' && (flags & FLAG_USE_XML))
+ if (ch == '&' && !(flags & FLAG_USE_COMPAT))
{
std::string varname;
while (1)
throw CoreException("Undefined XML entity reference '&" + varname + ";'");
value.append(var->second);
}
- else if (ch == '\\' && !(flags & FLAG_USE_XML))
+ else if (ch == '\\' && (flags & FLAG_USE_COMPAT))
{
int esc = next();
if (esc == 'n')
}
else if (name == "define")
{
- if (!(flags & FLAG_USE_XML))
+ if (flags & FLAG_USE_COMPAT)
throw CoreException("<define> tags may only be used in XML-style config (add <config format=\"xml\">)");
std::string varname = tag->getString("name");
std::string value = tag->getString("value");
{
std::string format = tag->getString("format");
if (format == "xml")
- flags |= FLAG_USE_XML;
+ flags &= ~FLAG_USE_COMPAT;
else if (format == "compat")
- flags &= ~FLAG_USE_XML;
+ flags |= FLAG_USE_COMPAT;
else if (!format.empty())
throw CoreException("Unknown configuration format " + format);
}
bool ParseStack::ParseFile(const std::string& name, int flags, const std::string& mandatory_tag)
{
- ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading file %s", name.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Reading file %s", name.c_str());
for (unsigned int t = 0; t < reading.size(); t++)
{
if (std::string(name) == reading[t])
bool ParseStack::ParseExec(const std::string& name, int flags, const std::string& mandatory_tag)
{
- ServerInstance->Logs->Log("CONFIG", DEBUG, "Reading executable %s", name.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Reading executable %s", name.c_str());
for (unsigned int t = 0; t < reading.size(); t++)
{
if (std::string(name) == reading[t])
value = j->second;
if (!allow_lf && (value.find('\n') != std::string::npos))
{
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() +
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() +
" contains a linefeed, and linefeeds in this value are not permitted -- stripped to spaces.");
for (std::string::iterator n = value.begin(); n != value.end(); n++)
if (*n == '\n')
if (result == "no" || result == "false" || result == "0" || result == "off")
return false;
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() +
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() +
" is not valid, ignoring");
return def;
}
#include "inspircd.h"
-#include <fstream>
#include "xline.h"
+#include "listmode.h"
#include "exitcodes.h"
-#include "commands/cmd_whowas.h"
#include "configparser.h"
#include <iostream>
-#ifdef _WIN32
-#include <Iphlpapi.h>
-#pragma comment(lib, "Iphlpapi.lib")
-#endif
ServerConfig::ServerConfig()
{
- WhoWasGroupSize = WhoWasMaxGroups = WhoWasMaxKeep = 0;
- RawLog = NoUserDns = HideBans = HideSplits = UndernetMsgPrefix = false;
+ RawLog = HideBans = HideSplits = UndernetMsgPrefix = false;
WildcardIPv6 = CycleHosts = InvBypassModes = true;
dns_timeout = 5;
MaxTargets = 20;
c_ipv6_range = 128;
}
-void ServerConfig::Update005()
-{
- std::stringstream out(data005);
- std::vector<std::string> data;
- std::string token;
- while (out >> token)
- data.push_back(token);
- sort(data.begin(), data.end());
-
- std::string line5;
- isupport.clear();
- for(unsigned int i=0; i < data.size(); i++)
- {
- token = data[i];
- line5 = line5 + token + " ";
- if (i % 13 == 12)
- {
- line5.append(":are supported by this server");
- isupport.push_back(line5);
- line5.clear();
- }
- }
- if (!line5.empty())
- {
- line5.append(":are supported by this server");
- isupport.push_back(line5);
- }
-}
-
-void ServerConfig::Send005(User* user)
-{
- for (std::vector<std::string>::iterator line = ServerInstance->Config->isupport.begin(); line != ServerInstance->Config->isupport.end(); line++)
- user->WriteNumeric(RPL_ISUPPORT, "%s %s", user->nick.c_str(), line->c_str());
-}
-
template<typename T, typename V>
static void range(T& value, V min, V max, V def, const char* msg)
{
if (value >= (T)min && value <= (T)max)
return;
- ServerInstance->Logs->Log("CONFIG", DEFAULT,
- "WARNING: %s value of %ld is not between %ld and %ld; set to %ld.",
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "WARNING: %s value of %ld is not between %ld and %ld; set to %ld.",
msg, (long)value, (long)min, (long)max, (long)def);
value = def;
}
-
-static void ValidIP(const std::string& ip, const std::string& key)
-{
- irc::sockets::sockaddrs dummy;
- if (!irc::sockets::aptosa(ip, 0, dummy))
- throw CoreException("The value of "+key+" is not an IP address");
-}
-
static void ValidHost(const std::string& p, const std::string& msg)
{
int num_dots = 0;
return true;
}
-static void FindDNS(std::string& server)
-{
- if (!server.empty())
- return;
-#ifdef _WIN32
- // attempt to look up their nameserver from the system
- ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <dns:server> not defined, attempting to find a working server in the system settings...");
-
- PFIXED_INFO pFixedInfo;
- DWORD dwBufferSize = sizeof(FIXED_INFO);
- pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, sizeof(FIXED_INFO));
-
- if(pFixedInfo)
- {
- if (GetNetworkParams(pFixedInfo, &dwBufferSize) == ERROR_BUFFER_OVERFLOW) {
- HeapFree(GetProcessHeap(), 0, pFixedInfo);
- pFixedInfo = (PFIXED_INFO) HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
- }
-
- if(pFixedInfo) {
- if (GetNetworkParams(pFixedInfo, &dwBufferSize) == NO_ERROR)
- server = pFixedInfo->DnsServerList.IpAddress.String;
-
- HeapFree(GetProcessHeap(), 0, pFixedInfo);
- }
-
- if(!server.empty())
- {
- ServerInstance->Logs->Log("CONFIG",DEFAULT,"<dns:server> set to '%s' as first active resolver in the system settings.", server.c_str());
- return;
- }
- }
-
- ServerInstance->Logs->Log("CONFIG",DEFAULT,"No viable nameserver found! Defaulting to nameserver '127.0.0.1'!");
-#else
- // attempt to look up their nameserver from /etc/resolv.conf
- ServerInstance->Logs->Log("CONFIG",DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
-
- std::ifstream resolv("/etc/resolv.conf");
-
- while (resolv >> server)
- {
- if (server == "nameserver")
- {
- resolv >> server;
- if (server.find_first_not_of("0123456789.") == std::string::npos)
- {
- ServerInstance->Logs->Log("CONFIG",DEFAULT,"<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",server.c_str());
- return;
- }
- }
- }
-
- ServerInstance->Logs->Log("CONFIG",DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
-#endif
- server = "127.0.0.1";
-}
-
static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::string& key, XLineFactory* make)
{
ConfigTagList tags = conf->ConfTags(tag);
std::string name = tag->getString("name");
if (name.empty())
throw CoreException("<type:name> is missing from tag at " + tag->getTagLocation());
- if (!ServerInstance->IsNick(name.c_str(), Limits.NickMax))
- throw CoreException("<type:name> is invalid (value '" + name + "')");
if (oper_blocks.find(" " + name) != oper_blocks.end())
throw CoreException("Duplicate type block with name " + name + " at " + tag->getTagLocation());
me->maxchans = tag->getInt("maxchans", me->maxchans);
me->maxconnwarn = tag->getBool("maxconnwarn", me->maxconnwarn);
me->limit = tag->getInt("limit", me->limit);
+ me->nouserdns = tag->getBool("nouserdns", me->nouserdns);
ClassMap::iterator oldMask = oldBlocksByMask.find(typeMask);
if (oldMask != oldBlocksByMask.end())
/** Represents a deprecated configuration tag.
*/
-struct Deprecated
+struct DeprecatedConfig
{
- /** Tag name
- */
- const char* tag;
- /** Tag value
- */
- const char* value;
- /** Reason for deprecation
- */
- const char* reason;
+ /** Tag name. */
+ std::string tag;
+
+ /** Attribute key. */
+ std::string key;
+
+ /** Attribute value. */
+ std::string value;
+
+ /** Reason for deprecation. */
+ std::string reason;
};
-static const Deprecated ChangedConfig[] = {
- {"options", "hidelinks", "has been moved to <security:hidelinks> as of 1.2a3"},
- {"options", "hidewhois", "has been moved to <security:hidewhois> as of 1.2a3"},
- {"options", "userstats", "has been moved to <security:userstats> as of 1.2a3"},
- {"options", "customversion", "has been moved to <security:customversion> as of 1.2a3"},
- {"options", "hidesplits", "has been moved to <security:hidesplits> as of 1.2a3"},
- {"options", "hidebans", "has been moved to <security:hidebans> as of 1.2a3"},
- {"options", "hidekills", "has been moved to <security:hidekills> as of 1.2a3"},
- {"options", "operspywhois", "has been moved to <security:operspywhois> as of 1.2a3"},
- {"options", "announceinvites", "has been moved to <security:announceinvites> as of 1.2a3"},
- {"options", "hidemodes", "has been moved to <security:hidemodes> as of 1.2a3"},
- {"options", "maxtargets", "has been moved to <security:maxtargets> as of 1.2a3"},
- {"options", "nouserdns", "has been moved to <performance:nouserdns> as of 1.2a3"},
- {"options", "maxwho", "has been moved to <performance:maxwho> as of 1.2a3"},
- {"options", "softlimit", "has been moved to <performance:softlimit> as of 1.2a3"},
- {"options", "somaxconn", "has been moved to <performance:somaxconn> as of 1.2a3"},
- {"options", "netbuffersize", "has been moved to <performance:netbuffersize> as of 1.2a3"},
- {"options", "maxwho", "has been moved to <performance:maxwho> as of 1.2a3"},
- {"options", "loglevel", "1.2+ does not use the loglevel value. Please define <log> tags instead."},
- {"die", "value", "you need to reread your config"},
- {"bind", "transport", "has been moved to <bind:ssl> as of 2.0a1"},
- {"link", "transport", "has been moved to <link:ssl> as of 2.0a1"},
- {"link", "autoconnect", "2.0+ does not use the autoconnect value. Please define <autoconnect> tags instead."},
+static const DeprecatedConfig ChangedConfig[] = {
+ { "bind", "transport", "", "has been moved to <bind:ssl> as of 2.0" },
+ { "die", "value", "", "you need to reread your config" },
+ { "link", "autoconnect", "", "2.0+ does not use this attribute - define <autoconnect> tags instead" },
+ { "link", "transport", "", "has been moved to <link:ssl> as of 2.0" },
+ { "module", "name", "m_chanprotect.so", "has been replaced with m_customprefix as of 2.2" },
+ { "module", "name", "m_halfop.so", "has been replaced with m_customprefix as of 2.2" },
+ { "performance", "nouserdns", "", "has been moved to <connect:nouserdns> as of 2.2" }
};
void ServerConfig::Fill()
ServerName = ConfValue("server")->getString("name");
sid = ConfValue("server")->getString("id");
ValidHost(ServerName, "<server:name>");
- if (!sid.empty() && !ServerInstance->IsSID(sid))
+ if (!sid.empty() && !InspIRCd::IsSID(sid))
throw CoreException(sid + " is not a valid server ID. A server ID must be 3 characters long, with the first character a digit and the next two characters a digit or letter.");
}
else
HideKillsServer = security->getString("hidekills");
RestrictBannedUsers = security->getBool("restrictbannedusers", true);
GenericOper = security->getBool("genericoper");
- NoUserDns = ConfValue("performance")->getBool("nouserdns");
SyntaxHints = options->getBool("syntaxhints");
CycleHosts = options->getBool("cyclehosts");
CycleHostsFromUser = options->getBool("cyclehostsfromuser");
MaxTargets = security->getInt("maxtargets", 20);
DefaultModes = options->getString("defaultmodes", "nt");
PID = ConfValue("pid")->getString("file");
- WhoWasGroupSize = ConfValue("whowas")->getInt("groupsize");
- WhoWasMaxGroups = ConfValue("whowas")->getInt("maxgroups");
- WhoWasMaxKeep = ServerInstance->Duration(ConfValue("whowas")->getString("maxkeep"));
MaxChans = ConfValue("channels")->getInt("users", 20);
OperMaxChans = ConfValue("channels")->getInt("opers", 60);
c_ipv4_range = ConfValue("cidr")->getInt("ipv4clone", 32);
Limits.MaxAway = ConfValue("limits")->getInt("maxaway", 200);
InvBypassModes = options->getBool("invitebypassmodes", true);
NoSnoticeStack = options->getBool("nosnoticestack", false);
- WelcomeNotice = options->getBool("welcomenotice", true);
range(SoftLimit, 10, ServerInstance->SE->GetMaxFds(), ServerInstance->SE->GetMaxFds(), "<performance:softlimit>");
if (ConfValue("performance")->getBool("limitsomaxconn", true))
range(MaxConn, 0, SOMAXCONN, SOMAXCONN, "<performance:somaxconn>");
range(MaxTargets, 1, 31, 20, "<security:maxtargets>");
range(NetBufferSize, 1024, 65534, 10240, "<performance:netbuffersize>");
- range(WhoWasGroupSize, 0, 10000, 10, "<whowas:groupsize>");
- range(WhoWasMaxGroups, 0, 1000000, 10240, "<whowas:maxgroups>");
- range(WhoWasMaxKeep, 3600, INT_MAX, 3600, "<whowas:maxkeep>");
-
- ValidIP(DNSServer, "<dns:server>");
std::string defbind = options->getString("defaultbind");
if (assign(defbind) == "ipv4")
ulines[assign(server)] = tag->getBool("silent");
}
- tags = ConfTags("banlist");
- for(ConfigIter i = tags.first; i != tags.second; ++i)
- {
- ConfigTag* tag = i->second;
- std::string chan;
- if (!tag->readString("chan", chan))
- throw CoreException("<banlist> tag missing chan at " + tag->getTagLocation());
- maxbans[chan] = tag->getInt("limit");
- }
-
ReadXLine(this, "badip", "ipmask", ServerInstance->XLines->GetFactory("Z"));
ReadXLine(this, "badnick", "nick", ServerInstance->XLines->GetFactory("Q"));
ReadXLine(this, "badhost", "host", ServerInstance->XLines->GetFactory("K"));
valid = false;
errstr << err.GetReason();
}
- if (valid)
- {
- DNSServer = ConfValue("dns")->getString("server");
- FindDNS(DNSServer);
- }
}
void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
/* The stuff in here may throw CoreException, be sure we're in a position to catch it. */
try
{
- for (int Index = 0; Index * sizeof(Deprecated) < sizeof(ChangedConfig); Index++)
+ for (int index = 0; index * sizeof(DeprecatedConfig) < sizeof(ChangedConfig); index++)
{
- std::string dummy;
- ConfigTagList tags = ConfTags(ChangedConfig[Index].tag);
+ std::string value;
+ ConfigTagList tags = ConfTags(ChangedConfig[index].tag);
for(ConfigIter i = tags.first; i != tags.second; ++i)
{
- if (i->second->readString(ChangedConfig[Index].value, dummy, true))
- errstr << "Your configuration contains a deprecated value: <"
- << ChangedConfig[Index].tag << ":" << ChangedConfig[Index].value << "> - " << ChangedConfig[Index].reason
- << " (at " << i->second->getTagLocation() << ")\n";
+ if (i->second->readString(ChangedConfig[index].key, value, true)
+ && (ChangedConfig[index].value.empty() || value == ChangedConfig[index].value))
+ {
+ errstr << "Your configuration contains a deprecated value: <" << ChangedConfig[index].tag;
+ if (ChangedConfig[index].value.empty())
+ {
+ errstr << ':' << ChangedConfig[index].key;
+ }
+ else
+ {
+ errstr << ' ' << ChangedConfig[index].key << "=\"" << ChangedConfig[index].value << "\"";
+ }
+ errstr << "> - " << ChangedConfig[index].reason << " (at " << i->second->getTagLocation() << ")\n";
+ }
}
}
ServerInstance->BindPorts(pl);
if (pl.size())
{
- errstr << "Not all your client ports could be bound.\nThe following port(s) failed to bind:\n";
+ errstr << "Not all your client ports could be bound." << std::endl
+ << "The following port(s) failed to bind:" << std::endl;
int j = 1;
for (FailedPortList::iterator i = pl.begin(); i != pl.end(); i++, j++)
{
- char buf[MAXBUF];
- snprintf(buf, MAXBUF, "%d. Address: %s Reason: %s\n", j, i->first.empty() ? "<all>" : i->first.c_str(), i->second.c_str());
- errstr << buf;
+ errstr << j << ".\tAddress: " << (i->first.empty() ? "<all>" : i->first.c_str()) << "\tReason: "
+ << i->second << std::endl;
}
}
}
User* user = useruid.empty() ? NULL : ServerInstance->FindNick(useruid);
if (!valid)
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "There were errors in your configuration file:");
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "There were errors in your configuration file:");
while (errstr.good())
{
void ServerConfig::ApplyModules(User* user)
{
- Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so");
- if (whowas)
- WhowasRequest(NULL, whowas, WhowasRequest::WHOWAS_PRUNE).Send();
-
const std::vector<std::string> v = ServerInstance->Modules->GetAllModuleNames(0);
std::vector<std::string> added_modules;
std::set<std::string> removed_modules(v.begin(), v.end());
ConfigTag* rv = found.first->second;
found.first++;
if (found.first != found.second)
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "Multiple <" + tag + "> tags found; only first will be used "
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "Multiple <" + tag + "> tags found; only first will be used "
"(first at " + rv->getTagLocation() + "; second at " + found.first->second->getTagLocation() + ")");
return rv;
}
return (p != name ? ++p : p);
}
-const std::string& ServerConfig::GetSID()
-{
- return sid;
-}
-
void ConfigReaderThread::Run()
{
Config->Read();
void ConfigReaderThread::Finish()
{
ServerConfig* old = ServerInstance->Config;
- ServerInstance->Logs->Log("CONFIG",DEBUG,"Switching to new configuration...");
+ ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Switching to new configuration...");
ServerInstance->Config = this->Config;
Config->Apply(old, TheUserUID);
*/
ServerInstance->XLines->CheckELines();
ServerInstance->XLines->ApplyLines();
- ServerInstance->Res->Rehash();
- ServerInstance->ResetMaxBans();
+ ModeReference ban(NULL, "ban");
+ static_cast<ListModeBase*>(*ban)->DoRehash();
Config->ApplyDisabledCommands(Config->DisabledCommands);
User* user = ServerInstance->FindNick(TheUserUID);
FOREACH_MOD(I_OnRehash, OnRehash(user));
- ServerInstance->BuildISupport();
+ ServerInstance->ISupport.Build();
ServerInstance->Logs->CloseLogs();
ServerInstance->Logs->OpenFileLogs();
classbase* c = list[i];
if (gone.insert(c).second)
{
- ServerInstance->Logs->Log("CULLLIST", DEBUG, "Deleting %s @%p", typeid(*c).name(),
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "Deleting %s @%p", typeid(*c).name(),
(void*)c);
c->cull();
queue.push_back(c);
}
else
{
- ServerInstance->Logs->Log("CULLLIST",DEBUG, "WARNING: Object @%p culled twice!",
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "WARNING: Object @%p culled twice!",
(void*)c);
}
}
}
if (list.size())
{
- ServerInstance->Logs->Log("CULLLIST",DEBUG, "WARNING: Objects added to cull list in a destructor");
+ ServerInstance->Logs->Log("CULLLIST", LOG_DEBUG, "WARNING: Objects added to cull list in a destructor");
Apply();
}
}
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2012 William Pitcock <nenolod@dereferenced.org>
- * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2006, 2009 Robin Burchell <robin+git@viroteck.net>
- * Copyright (C) 2007, 2009 Dennis Friis <peavey@inspircd.org>
- * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
- * Copyright (C) 2005-2007 Craig Edwards <craigedwards@brainbox.cc>
- *
- * 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/>.
- */
-
-
-/* $Core */
-
-/*
-dns.cpp - Nonblocking DNS functions.
-Very very loosely based on the firedns library,
-Copyright (C) 2002 Ian Gulliver. This file is no
-longer anything like firedns, there are many major
-differences between this code and the original.
-Please do not assume that firedns works like this,
-looks like this, walks like this or tastes like this.
-*/
-
-#ifndef _WIN32
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#else
-#include "inspircd_win32wrapper.h"
-#endif
-
-#include "inspircd.h"
-#include "socketengine.h"
-#include "configreader.h"
-#include "socket.h"
-
-#define DN_COMP_BITMASK 0xC000 /* highest 6 bits in a DN label header */
-
-/** Masks to mask off the responses we get from the DNSRequest methods
- */
-enum QueryInfo
-{
- ERROR_MASK = 0x10000 /* Result is an error */
-};
-
-/** Flags which can be ORed into a request or reply for different meanings
- */
-enum QueryFlags
-{
- FLAGS_MASK_RD = 0x01, /* Recursive */
- FLAGS_MASK_TC = 0x02,
- FLAGS_MASK_AA = 0x04, /* Authoritative */
- FLAGS_MASK_OPCODE = 0x78,
- FLAGS_MASK_QR = 0x80,
- FLAGS_MASK_RCODE = 0x0F, /* Request */
- FLAGS_MASK_Z = 0x70,
- FLAGS_MASK_RA = 0x80
-};
-
-
-/** Represents a dns resource record (rr)
- */
-struct ResourceRecord
-{
- QueryType type; /* Record type */
- unsigned int rr_class; /* Record class */
- unsigned long ttl; /* Time to live */
- unsigned int rdlength; /* Record length */
-};
-
-/** Represents a dns request/reply header, and its payload as opaque data.
- */
-class DNSHeader
-{
- public:
- unsigned char id[2]; /* Request id */
- unsigned int flags1; /* Flags */
- unsigned int flags2; /* Flags */
- unsigned int qdcount;
- unsigned int ancount; /* Answer count */
- unsigned int nscount; /* Nameserver count */
- unsigned int arcount;
- unsigned char payload[512]; /* Packet payload */
-};
-
-class DNSRequest
-{
- public:
- unsigned char id[2]; /* Request id */
- unsigned char* res; /* Result processing buffer */
- unsigned int rr_class; /* Request class */
- QueryType type; /* Request type */
- DNS* dnsobj; /* DNS caller (where we get our FD from) */
- unsigned long ttl; /* Time to live */
- std::string orig; /* Original requested name/ip */
-
- DNSRequest(DNS* dns, int id, const std::string &original);
- ~DNSRequest();
- DNSInfo ResultIsReady(DNSHeader &h, unsigned length);
- int SendRequests(const DNSHeader *header, const int length, QueryType qt);
-};
-
-class CacheTimer : public Timer
-{
- private:
- DNS* dns;
- public:
- CacheTimer(DNS* thisdns)
- : Timer(3600, ServerInstance->Time(), true), dns(thisdns) { }
-
- virtual void Tick(time_t)
- {
- dns->PruneCache();
- }
-};
-
-class RequestTimeout : public Timer
-{
- DNSRequest* watch;
- int watchid;
- public:
- RequestTimeout(unsigned long n, DNSRequest* watching, int id) : Timer(n, ServerInstance->Time()), watch(watching), watchid(id)
- {
- }
- ~RequestTimeout()
- {
- if (ServerInstance->Res)
- Tick(0);
- }
-
- void Tick(time_t)
- {
- if (ServerInstance->Res->requests[watchid] == watch)
- {
- /* Still exists, whack it */
- if (ServerInstance->Res->Classes[watchid])
- {
- ServerInstance->Res->Classes[watchid]->OnError(RESOLVER_TIMEOUT, "Request timed out");
- delete ServerInstance->Res->Classes[watchid];
- ServerInstance->Res->Classes[watchid] = NULL;
- }
- ServerInstance->Res->requests[watchid] = NULL;
- delete watch;
- }
- }
-};
-
-CachedQuery::CachedQuery(const std::string &res, unsigned int ttl) : data(res)
-{
- expires = ServerInstance->Time() + ttl;
-}
-
-int CachedQuery::CalcTTLRemaining()
-{
- int n = expires - ServerInstance->Time();
- return (n < 0 ? 0 : n);
-}
-
-/* Allocate the processing buffer */
-DNSRequest::DNSRequest(DNS* dns, int rid, const std::string &original) : dnsobj(dns)
-{
- /* hardening against overflow here: make our work buffer twice the theoretical
- * maximum size so that hostile input doesn't screw us over.
- */
- res = new unsigned char[sizeof(DNSHeader) * 2];
- *res = 0;
- orig = original;
- RequestTimeout* RT = new RequestTimeout(ServerInstance->Config->dns_timeout ? ServerInstance->Config->dns_timeout : 5, this, rid);
- ServerInstance->Timers->AddTimer(RT); /* The timer manager frees this */
-}
-
-/* Deallocate the processing buffer */
-DNSRequest::~DNSRequest()
-{
- delete[] res;
-}
-
-/** Fill a ResourceRecord class based on raw data input */
-inline void DNS::FillResourceRecord(ResourceRecord* rr, const unsigned char *input)
-{
- rr->type = (QueryType)((input[0] << 8) + input[1]);
- rr->rr_class = (input[2] << 8) + input[3];
- rr->ttl = (input[4] << 24) + (input[5] << 16) + (input[6] << 8) + input[7];
- rr->rdlength = (input[8] << 8) + input[9];
-}
-
-/** Fill a DNSHeader class based on raw data input of a given length */
-inline void DNS::FillHeader(DNSHeader *header, const unsigned char *input, const int length)
-{
- header->id[0] = input[0];
- header->id[1] = input[1];
- header->flags1 = input[2];
- header->flags2 = input[3];
- header->qdcount = (input[4] << 8) + input[5];
- header->ancount = (input[6] << 8) + input[7];
- header->nscount = (input[8] << 8) + input[9];
- header->arcount = (input[10] << 8) + input[11];
- memcpy(header->payload,&input[12],length);
-}
-
-/** Empty a DNSHeader class out into raw data, ready for transmission */
-inline void DNS::EmptyHeader(unsigned char *output, const DNSHeader *header, const int length)
-{
- output[0] = header->id[0];
- output[1] = header->id[1];
- output[2] = header->flags1;
- output[3] = header->flags2;
- output[4] = header->qdcount >> 8;
- output[5] = header->qdcount & 0xFF;
- output[6] = header->ancount >> 8;
- output[7] = header->ancount & 0xFF;
- output[8] = header->nscount >> 8;
- output[9] = header->nscount & 0xFF;
- output[10] = header->arcount >> 8;
- output[11] = header->arcount & 0xFF;
- memcpy(&output[12],header->payload,length);
-}
-
-/** Send requests we have previously built down the UDP socket */
-int DNSRequest::SendRequests(const DNSHeader *header, const int length, QueryType qt)
-{
- ServerInstance->Logs->Log("RESOLVER", DEBUG,"DNSRequest::SendRequests");
-
- unsigned char payload[sizeof(DNSHeader)];
-
- this->rr_class = 1;
- this->type = qt;
-
- DNS::EmptyHeader(payload,header,length);
-
- if (ServerInstance->SE->SendTo(dnsobj, payload, length + 12, 0, &(dnsobj->myserver.sa), sa_size(dnsobj->myserver)) != length+12)
- return -1;
-
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"Sent OK");
- return 0;
-}
-
-/** Add a query with a predefined header, and allocate an ID for it. */
-DNSRequest* DNS::AddQuery(DNSHeader *header, int &id, const char* original)
-{
- /* Is the DNS connection down? */
- if (this->GetFd() == -1)
- return NULL;
-
- /* Create an id */
- unsigned int tries = 0;
- do {
- id = ServerInstance->GenRandomInt(DNS::MAX_REQUEST_ID);
- if (++tries == DNS::MAX_REQUEST_ID*5)
- {
- // If we couldn't find an empty slot this many times, do a sequential scan as a last
- // resort. If an empty slot is found that way, go on, otherwise throw an exception
- id = -1;
- for (int i = 0; i < DNS::MAX_REQUEST_ID; i++)
- {
- if (!requests[i])
- {
- id = i;
- break;
- }
- }
-
- if (id == -1)
- throw ModuleException("DNS: All ids are in use");
-
- break;
- }
- } while (requests[id]);
-
- DNSRequest* req = new DNSRequest(this, id, original);
-
- header->id[0] = req->id[0] = id >> 8;
- header->id[1] = req->id[1] = id & 0xFF;
- header->flags1 = FLAGS_MASK_RD;
- header->flags2 = 0;
- header->qdcount = 1;
- header->ancount = 0;
- header->nscount = 0;
- header->arcount = 0;
-
- /* At this point we already know the id doesnt exist,
- * so there needs to be no second check for the ::end()
- */
- requests[id] = req;
-
- /* According to the C++ spec, new never returns NULL. */
- return req;
-}
-
-int DNS::ClearCache()
-{
- /* This ensures the buckets are reset to sane levels */
- int rv = this->cache->size();
- delete this->cache;
- this->cache = new dnscache();
- return rv;
-}
-
-int DNS::PruneCache()
-{
- int n = 0;
- dnscache* newcache = new dnscache();
- for (dnscache::iterator i = this->cache->begin(); i != this->cache->end(); i++)
- /* Dont include expired items (theres no point) */
- if (i->second.CalcTTLRemaining())
- newcache->insert(*i);
- else
- n++;
-
- delete this->cache;
- this->cache = newcache;
- return n;
-}
-
-void DNS::Rehash()
-{
- if (this->GetFd() > -1)
- {
- ServerInstance->SE->DelFd(this);
- ServerInstance->SE->Shutdown(this, 2);
- ServerInstance->SE->Close(this);
- this->SetFd(-1);
-
- /* Rehash the cache */
- this->PruneCache();
- }
- else
- {
- /* Create initial dns cache */
- this->cache = new dnscache();
- }
-
- irc::sockets::aptosa(ServerInstance->Config->DNSServer, DNS::QUERY_PORT, myserver);
-
- /* Initialize mastersocket */
- int s = socket(myserver.sa.sa_family, SOCK_DGRAM, 0);
- this->SetFd(s);
-
- /* Have we got a socket and is it nonblocking? */
- if (this->GetFd() != -1)
- {
- ServerInstance->SE->SetReuse(s);
- ServerInstance->SE->NonBlocking(s);
- irc::sockets::sockaddrs bindto;
- memset(&bindto, 0, sizeof(bindto));
- bindto.sa.sa_family = myserver.sa.sa_family;
- if (ServerInstance->SE->Bind(this->GetFd(), bindto) < 0)
- {
- /* Failed to bind */
- ServerInstance->Logs->Log("RESOLVER",SPARSE,"Error binding dns socket - hostnames will NOT resolve");
- ServerInstance->SE->Shutdown(this, 2);
- ServerInstance->SE->Close(this);
- this->SetFd(-1);
- }
- else if (!ServerInstance->SE->AddFd(this, FD_WANT_POLL_READ | FD_WANT_NO_WRITE))
- {
- ServerInstance->Logs->Log("RESOLVER",SPARSE,"Internal error starting DNS - hostnames will NOT resolve.");
- ServerInstance->SE->Shutdown(this, 2);
- ServerInstance->SE->Close(this);
- this->SetFd(-1);
- }
- }
- else
- {
- ServerInstance->Logs->Log("RESOLVER",SPARSE,"Error creating DNS socket - hostnames will NOT resolve");
- }
-}
-
-/** Initialise the DNS UDP socket so that we can send requests */
-DNS::DNS()
-{
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS::DNS");
- /* Clear the Resolver class table */
- memset(Classes,0,sizeof(Classes));
-
- /* Clear the requests class table */
- memset(requests,0,sizeof(requests));
-
- /* DNS::Rehash() sets this to a valid ptr
- */
- this->cache = NULL;
-
- /* Again, DNS::Rehash() sets this to a
- * valid value
- */
- this->SetFd(-1);
-
- /* Actually read the settings
- */
- this->Rehash();
-
- this->PruneTimer = new CacheTimer(this);
-
- ServerInstance->Timers->AddTimer(this->PruneTimer);
-}
-
-/** Build a payload to be placed after the header, based upon input data, a resource type, a class and a pointer to a buffer */
-int DNS::MakePayload(const char * const name, const QueryType rr, const unsigned short rr_class, unsigned char * const payload)
-{
- short payloadpos = 0;
- const char* tempchr, *tempchr2 = name;
- unsigned short length;
-
- /* split name up into labels, create query */
- while ((tempchr = strchr(tempchr2,'.')) != NULL)
- {
- length = tempchr - tempchr2;
- if (payloadpos + length + 1 > 507)
- return -1;
- payload[payloadpos++] = length;
- memcpy(&payload[payloadpos],tempchr2,length);
- payloadpos += length;
- tempchr2 = &tempchr[1];
- }
- length = strlen(tempchr2);
- if (length)
- {
- if (payloadpos + length + 2 > 507)
- return -1;
- payload[payloadpos++] = length;
- memcpy(&payload[payloadpos],tempchr2,length);
- payloadpos += length;
- payload[payloadpos++] = 0;
- }
- if (payloadpos > 508)
- return -1;
- length = htons(rr);
- memcpy(&payload[payloadpos],&length,2);
- length = htons(rr_class);
- memcpy(&payload[payloadpos + 2],&length,2);
- return payloadpos + 4;
-}
-
-/** Start lookup of an hostname to an IP address */
-int DNS::GetIP(const char *name)
-{
- DNSHeader h;
- int id;
- int length;
-
- if ((length = this->MakePayload(name, DNS_QUERY_A, 1, (unsigned char*)&h.payload)) == -1)
- return -1;
-
- DNSRequest* req = this->AddQuery(&h, id, name);
-
- if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_A) == -1))
- return -1;
-
- return id;
-}
-
-/** Start lookup of an hostname to an IPv6 address */
-int DNS::GetIP6(const char *name)
-{
- DNSHeader h;
- int id;
- int length;
-
- if ((length = this->MakePayload(name, DNS_QUERY_AAAA, 1, (unsigned char*)&h.payload)) == -1)
- return -1;
-
- DNSRequest* req = this->AddQuery(&h, id, name);
-
- if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_AAAA) == -1))
- return -1;
-
- return id;
-}
-
-/** Start lookup of a cname to another name */
-int DNS::GetCName(const char *alias)
-{
- DNSHeader h;
- int id;
- int length;
-
- if ((length = this->MakePayload(alias, DNS_QUERY_CNAME, 1, (unsigned char*)&h.payload)) == -1)
- return -1;
-
- DNSRequest* req = this->AddQuery(&h, id, alias);
-
- if ((!req) || (req->SendRequests(&h, length, DNS_QUERY_CNAME) == -1))
- return -1;
-
- return id;
-}
-
-/** Start lookup of an IP address to a hostname */
-int DNS::GetNameForce(const char *ip, ForceProtocol fp)
-{
- char query[128];
- DNSHeader h;
- int id;
- int length;
-
- if (fp == PROTOCOL_IPV6)
- {
- in6_addr i;
- if (inet_pton(AF_INET6, ip, &i) > 0)
- {
- DNS::MakeIP6Int(query, &i);
- }
- else
- {
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS::GetNameForce IPv6 bad format for '%s'", ip);
- /* Invalid IP address */
- return -1;
- }
- }
- else
- {
- in_addr i;
- if (inet_aton(ip, &i))
- {
- unsigned char* c = (unsigned char*)&i.s_addr;
- sprintf(query,"%d.%d.%d.%d.in-addr.arpa",c[3],c[2],c[1],c[0]);
- }
- else
- {
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS::GetNameForce IPv4 bad format for '%s'", ip);
- /* Invalid IP address */
- return -1;
- }
- }
-
- length = this->MakePayload(query, DNS_QUERY_PTR, 1, (unsigned char*)&h.payload);
- if (length == -1)
- {
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS::GetNameForce can't query '%s' using '%s' because it's too long", ip, query);
- return -1;
- }
-
- DNSRequest* req = this->AddQuery(&h, id, ip);
-
- if (!req)
- {
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS::GetNameForce can't add query (resolver down?)");
- return -1;
- }
-
- if (req->SendRequests(&h, length, DNS_QUERY_PTR) == -1)
- {
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS::GetNameForce can't send (firewall?)");
- return -1;
- }
-
- return id;
-}
-
-/** Build an ipv6 reverse domain from an in6_addr
- */
-void DNS::MakeIP6Int(char* query, const in6_addr *ip)
-{
- const char* hex = "0123456789abcdef";
- for (int index = 31; index >= 0; index--) /* for() loop steps twice per byte */
- {
- if (index % 2)
- /* low nibble */
- *query++ = hex[ip->s6_addr[index / 2] & 0x0F];
- else
- /* high nibble */
- *query++ = hex[(ip->s6_addr[index / 2] & 0xF0) >> 4];
- *query++ = '.'; /* Seperator */
- }
- strcpy(query,"ip6.arpa"); /* Suffix the string */
-}
-
-/** Return the next id which is ready, and the result attached to it */
-DNSResult DNS::GetResult()
-{
- /* Fetch dns query response and decide where it belongs */
- DNSHeader header;
- DNSRequest *req;
- unsigned char buffer[sizeof(DNSHeader)];
- irc::sockets::sockaddrs from;
- memset(&from, 0, sizeof(from));
- socklen_t x = sizeof(from);
-
- int length = ServerInstance->SE->RecvFrom(this, (char*)buffer, sizeof(DNSHeader), 0, &from.sa, &x);
-
- /* Did we get the whole header? */
- if (length < 12)
- {
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"GetResult didn't get a full packet (len=%d)", length);
- /* Nope - something screwed up. */
- return DNSResult(-1,"",0,"");
- }
-
- /* Check wether the reply came from a different DNS
- * server to the one we sent it to, or the source-port
- * is not 53.
- * A user could in theory still spoof dns packets anyway
- * but this is less trivial than just sending garbage
- * to the server, which is possible without this check.
- *
- * -- Thanks jilles for pointing this one out.
- */
- if (from != myserver)
- {
- std::string server1 = from.str();
- std::string server2 = myserver.str();
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"Got a result from the wrong server! Bad NAT or DNS forging attempt? '%s' != '%s'",
- server1.c_str(), server2.c_str());
- return DNSResult(-1,"",0,"");
- }
-
- /* Put the read header info into a header class */
- DNS::FillHeader(&header,buffer,length - 12);
-
- /* Get the id of this request.
- * Its a 16 bit value stored in two char's,
- * so we use logic shifts to create the value.
- */
- unsigned long this_id = header.id[1] + (header.id[0] << 8);
-
- /* Do we have a pending request matching this id? */
- if (!requests[this_id])
- {
- /* Somehow we got a DNS response for a request we never made... */
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"Hmm, got a result that we didn't ask for (id=%lx). Ignoring.", this_id);
- return DNSResult(-1,"",0,"");
- }
- else
- {
- /* Remove the query from the list of pending queries */
- req = requests[this_id];
- requests[this_id] = NULL;
- }
-
- /* Inform the DNSRequest class that it has a result to be read.
- * When its finished it will return a DNSInfo which is a pair of
- * unsigned char* resource record data, and an error message.
- */
- DNSInfo data = req->ResultIsReady(header, length);
- std::string resultstr;
-
- /* Check if we got a result, if we didnt, its an error */
- if (data.first == NULL)
- {
- /* An error.
- * Mask the ID with the value of ERROR_MASK, so that
- * the dns_deal_with_classes() function knows that its
- * an error response and needs to be treated uniquely.
- * Put the error message in the second field.
- */
- std::string ro = req->orig;
- delete req;
- return DNSResult(this_id | ERROR_MASK, data.second, 0, ro);
- }
- else
- {
- unsigned long ttl = req->ttl;
- char formatted[128];
-
- /* Forward lookups come back as binary data. We must format them into ascii */
- switch (req->type)
- {
- case DNS_QUERY_A:
- snprintf(formatted,16,"%u.%u.%u.%u",data.first[0],data.first[1],data.first[2],data.first[3]);
- resultstr = formatted;
- break;
-
- case DNS_QUERY_AAAA:
- {
- inet_ntop(AF_INET6, data.first, formatted, sizeof(formatted));
- char* c = strstr(formatted,":0:");
- if (c != NULL)
- {
- memmove(c+1,c+2,strlen(c+2) + 1);
- c += 2;
- while (memcmp(c,"0:",2) == 0)
- memmove(c,c+2,strlen(c+2) + 1);
- if (memcmp(c,"0",2) == 0)
- *c = 0;
- if (memcmp(formatted,"0::",3) == 0)
- memmove(formatted,formatted + 1, strlen(formatted + 1) + 1);
- }
- resultstr = formatted;
-
- /* Special case. Sending ::1 around between servers
- * and to clients is dangerous, because the : on the
- * start makes the client or server interpret the IP
- * as the last parameter on the line with a value ":1".
- */
- if (*formatted == ':')
- resultstr.insert(0, "0");
- }
- break;
-
- case DNS_QUERY_CNAME:
- /* Identical handling to PTR */
-
- case DNS_QUERY_PTR:
- /* Reverse lookups just come back as char* */
- resultstr = std::string((const char*)data.first);
- break;
-
- default:
- break;
- }
-
- /* Build the reply with the id and hostname/ip in it */
- std::string ro = req->orig;
- delete req;
- return DNSResult(this_id,resultstr,ttl,ro);
- }
-}
-
-/** A result is ready, process it */
-DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
-{
- unsigned i = 0, o;
- int q = 0;
- int curanswer;
- ResourceRecord rr;
- unsigned short ptr;
-
- /* This is just to keep _FORTIFY_SOURCE happy */
- rr.type = DNS_QUERY_NONE;
- rr.rdlength = 0;
- rr.ttl = 1; /* GCC is a whiney bastard -- see the XXX below. */
- rr.rr_class = 0; /* Same for VC++ */
-
- if (!(header.flags1 & FLAGS_MASK_QR))
- return std::make_pair((unsigned char*)NULL,"Not a query result");
-
- if (header.flags1 & FLAGS_MASK_OPCODE)
- return std::make_pair((unsigned char*)NULL,"Unexpected value in DNS reply packet");
-
- if (header.flags2 & FLAGS_MASK_RCODE)
- return std::make_pair((unsigned char*)NULL,"Domain name not found");
-
- if (header.ancount < 1)
- return std::make_pair((unsigned char*)NULL,"No resource records returned");
-
- /* Subtract the length of the header from the length of the packet */
- length -= 12;
-
- while ((unsigned int)q < header.qdcount && i < length)
- {
- if (header.payload[i] > 63)
- {
- i += 6;
- q++;
- }
- else
- {
- if (header.payload[i] == 0)
- {
- q++;
- i += 5;
- }
- else i += header.payload[i] + 1;
- }
- }
- curanswer = 0;
- while ((unsigned)curanswer < header.ancount)
- {
- q = 0;
- while (q == 0 && i < length)
- {
- if (header.payload[i] > 63)
- {
- i += 2;
- q = 1;
- }
- else
- {
- if (header.payload[i] == 0)
- {
- i++;
- q = 1;
- }
- else i += header.payload[i] + 1; /* skip length and label */
- }
- }
- if (static_cast<int>(length - i) < 10)
- return std::make_pair((unsigned char*)NULL,"Incorrectly sized DNS reply");
-
- /* XXX: We actually initialise 'rr' here including its ttl field */
- DNS::FillResourceRecord(&rr,&header.payload[i]);
-
- i += 10;
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"Resolver: rr.type is %d and this.type is %d rr.class %d this.class %d", rr.type, this->type, rr.rr_class, this->rr_class);
- if (rr.type != this->type)
- {
- curanswer++;
- i += rr.rdlength;
- continue;
- }
- if (rr.rr_class != this->rr_class)
- {
- curanswer++;
- i += rr.rdlength;
- continue;
- }
- break;
- }
- if ((unsigned int)curanswer == header.ancount)
- return std::make_pair((unsigned char*)NULL,"No A, AAAA or PTR type answers (" + ConvToStr(header.ancount) + " answers)");
-
- if (i + rr.rdlength > (unsigned int)length)
- return std::make_pair((unsigned char*)NULL,"Resource record larger than stated");
-
- if (rr.rdlength > 1023)
- return std::make_pair((unsigned char*)NULL,"Resource record too large");
-
- this->ttl = rr.ttl;
-
- switch (rr.type)
- {
- /*
- * CNAME and PTR are compressed. We need to decompress them.
- */
- case DNS_QUERY_CNAME:
- case DNS_QUERY_PTR:
- {
- unsigned short lowest_pos = length;
- o = 0;
- q = 0;
- while (q == 0 && i < length && o + 256 < 1023)
- {
- /* DN label found (byte over 63) */
- if (header.payload[i] > 63)
- {
- memcpy(&ptr,&header.payload[i],2);
-
- i = ntohs(ptr);
-
- /* check that highest two bits are set. if not, we've been had */
- if ((i & DN_COMP_BITMASK) != DN_COMP_BITMASK)
- return std::make_pair((unsigned char *) NULL, "DN label decompression header is bogus");
-
- /* mask away the two highest bits. */
- i &= ~DN_COMP_BITMASK;
-
- /* and decrease length by 12 bytes. */
- i -= 12;
-
- if (i >= lowest_pos)
- return std::make_pair((unsigned char *) NULL, "Invalid decompression pointer");
- lowest_pos = i;
- }
- else
- {
- if (header.payload[i] == 0)
- {
- q = 1;
- }
- else
- {
- res[o] = 0;
- if (o != 0)
- res[o++] = '.';
-
- if (o + header.payload[i] > sizeof(DNSHeader))
- return std::make_pair((unsigned char *) NULL, "DN label decompression is impossible -- malformed/hostile packet?");
-
- memcpy(&res[o], &header.payload[i + 1], header.payload[i]);
- o += header.payload[i];
- i += header.payload[i] + 1;
- }
- }
- }
- res[o] = 0;
- }
- break;
- case DNS_QUERY_AAAA:
- if (rr.rdlength != sizeof(struct in6_addr))
- return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 16 bytes for an ipv6 entry -- malformed/hostile packet?");
-
- memcpy(res,&header.payload[i],rr.rdlength);
- res[rr.rdlength] = 0;
- break;
- case DNS_QUERY_A:
- if (rr.rdlength != sizeof(struct in_addr))
- return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 4 bytes for an ipv4 entry -- malformed/hostile packet?");
-
- memcpy(res,&header.payload[i],rr.rdlength);
- res[rr.rdlength] = 0;
- break;
- default:
- return std::make_pair((unsigned char *) NULL, "don't know how to handle undefined type (" + ConvToStr(rr.type) + ") -- rejecting");
- break;
- }
- return std::make_pair(res,"No error");
-}
-
-/** Close the master socket */
-DNS::~DNS()
-{
- ServerInstance->SE->Shutdown(this, 2);
- ServerInstance->SE->Close(this);
- ServerInstance->Timers->DelTimer(this->PruneTimer);
- if (cache)
- delete cache;
-}
-
-CachedQuery* DNS::GetCache(const std::string &source)
-{
- dnscache::iterator x = cache->find(source.c_str());
- if (x != cache->end())
- return &(x->second);
- else
- return NULL;
-}
-
-void DNS::DelCache(const std::string &source)
-{
- cache->erase(source.c_str());
-}
-
-void Resolver::TriggerCachedResult()
-{
- if (CQ)
- OnLookupComplete(CQ->data, time_left, true);
-}
-
-/** High level abstraction of dns used by application at large */
-Resolver::Resolver(const std::string &source, QueryType qt, bool &cached, Module* creator) : Creator(creator), input(source), querytype(qt)
-{
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"Resolver::Resolver");
- cached = false;
-
- CQ = ServerInstance->Res->GetCache(source);
- if (CQ)
- {
- time_left = CQ->CalcTTLRemaining();
- if (!time_left)
- {
- ServerInstance->Res->DelCache(source);
- }
- else
- {
- cached = true;
- return;
- }
- }
-
- switch (querytype)
- {
- case DNS_QUERY_A:
- this->myid = ServerInstance->Res->GetIP(source.c_str());
- break;
-
- case DNS_QUERY_PTR4:
- querytype = DNS_QUERY_PTR;
- this->myid = ServerInstance->Res->GetNameForce(source.c_str(), PROTOCOL_IPV4);
- break;
-
- case DNS_QUERY_PTR6:
- querytype = DNS_QUERY_PTR;
- this->myid = ServerInstance->Res->GetNameForce(source.c_str(), PROTOCOL_IPV6);
- break;
-
- case DNS_QUERY_AAAA:
- this->myid = ServerInstance->Res->GetIP6(source.c_str());
- break;
-
- case DNS_QUERY_CNAME:
- this->myid = ServerInstance->Res->GetCName(source.c_str());
- break;
-
- default:
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS request with unknown query type %d", querytype);
- this->myid = -1;
- break;
- }
- if (this->myid == -1)
- {
- throw ModuleException("Resolver: Couldn't get an id to make a request");
- }
- else
- {
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"DNS request id %d", this->myid);
- }
-}
-
-/** Called when an error occurs */
-void Resolver::OnError(ResolverError, const std::string&)
-{
- /* Nothing in here */
-}
-
-/** Destroy a resolver */
-Resolver::~Resolver()
-{
- /* Nothing here (yet) either */
-}
-
-/** Get the request id associated with this class */
-int Resolver::GetId()
-{
- return this->myid;
-}
-
-Module* Resolver::GetCreator()
-{
- return this->Creator;
-}
-
-/** Process a socket read event */
-void DNS::HandleEvent(EventType, int)
-{
- /* Fetch the id and result of the next available packet */
- DNSResult res(0,"",0,"");
- res.id = 0;
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"Handle DNS event");
-
- res = this->GetResult();
-
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"Result id %d", res.id);
-
- /* Is there a usable request id? */
- if (res.id != -1)
- {
- /* Its an error reply */
- if (res.id & ERROR_MASK)
- {
- /* Mask off the error bit */
- res.id -= ERROR_MASK;
- /* Marshall the error to the correct class */
- if (Classes[res.id])
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsBad++;
- Classes[res.id]->OnError(RESOLVER_NXDOMAIN, res.result);
- delete Classes[res.id];
- Classes[res.id] = NULL;
- }
- return;
- }
- else
- {
- /* It is a non-error result, marshall the result to the correct class */
- if (Classes[res.id])
- {
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDnsGood++;
-
- if (!this->GetCache(res.original.c_str()))
- this->cache->insert(std::make_pair(res.original.c_str(), CachedQuery(res.result, res.ttl)));
-
- Classes[res.id]->OnLookupComplete(res.result, res.ttl, false);
- delete Classes[res.id];
- Classes[res.id] = NULL;
- }
- }
-
- if (ServerInstance && ServerInstance->stats)
- ServerInstance->stats->statsDns++;
- }
-}
-
-/** Add a derived Resolver to the working set */
-bool DNS::AddResolverClass(Resolver* r)
-{
- ServerInstance->Logs->Log("RESOLVER",DEBUG,"AddResolverClass 0x%08lx", (unsigned long)r);
- /* Check the pointers validity and the id's validity */
- if ((r) && (r->GetId() > -1))
- {
- /* Check the slot isnt already occupied -
- * This should NEVER happen unless we have
- * a severely broken DNS server somewhere
- */
- if (!Classes[r->GetId()])
- {
- /* Set up the pointer to the class */
- Classes[r->GetId()] = r;
- return true;
- }
- }
-
- /* Pointer or id not valid, or duplicate id.
- * Free the item and return
- */
- delete r;
- return false;
-}
-
-void DNS::CleanResolvers(Module* module)
-{
- for (int i = 0; i < MAX_REQUEST_ID; i++)
- {
- if (Classes[i])
- {
- if (Classes[i]->GetCreator() == module)
- {
- Classes[i]->OnError(RESOLVER_FORCEUNLOAD, "Parent module is unloading");
- delete Classes[i];
- Classes[i] = NULL;
- }
- }
- }
-}
#include "socketengine.h"
#include "filelogger.h"
-FileLogStream::FileLogStream(int loglevel, FileWriter *fw)
- : LogStream(loglevel), f(fw)
+FileLogStream::FileLogStream(LogLevel loglevel, FileWriter *fw) : LogStream(loglevel), f(fw)
{
ServerInstance->Logs->AddLoggerRef(f);
}
ServerInstance->Logs->DelLoggerRef(f);
}
-void FileLogStream::OnLog(int loglevel, const std::string &type, const std::string &text)
+void FileLogStream::OnLog(LogLevel loglevel, const std::string &type, const std::string &text)
{
- static char TIMESTR[26];
+ static std::string TIMESTR;
static time_t LAST = 0;
if (loglevel < this->loglvl)
time_t local = ServerInstance->Time();
struct tm *timeinfo = localtime(&local);
- strlcpy(TIMESTR,asctime(timeinfo),26);
- TIMESTR[24] = ':';
+ TIMESTR.assign(asctime(timeinfo), 24);
+ TIMESTR += ": ";
LAST = ServerInstance->Time();
}
- std::string out = std::string(TIMESTR) + " " + text.c_str() + "\n";
+ std::string out = TIMESTR;
+ out += text;
+ out += '\n';
this->f->WriteLogLine(out);
}
#include "inspircd.h"
#include "hashcomp.h"
-#include "hash_map.h"
/******************************************************
*
* scene spend a lot of time debating (arguing) about
* the best way to write hash functions to hash irc
* nicknames, channels etc.
- * We are lucky as C++ developers as hash_map does
+ * We are lucky as C++ developers as unordered_map does
* a lot of this for us. It does intellegent memory
* requests, bucketing, search functions, insertion
* and deletion etc. All we have to do is write some
*
******************************************************/
-/** A mapping of uppercase to lowercase, including scandinavian
- * 'oddities' as specified by RFC1459, e.g. { -> [, and | -> \
- */
-unsigned const char rfc_case_insensitive_map[256] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 0-19 */
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, /* 20-39 */
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, /* 40-59 */
- 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, /* 60-79 */
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 94, 95, 96, 97, 98, 99, /* 80-99 */
- 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, /* 100-119 */
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, /* 120-139 */
- 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, /* 140-159 */
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, /* 160-179 */
- 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, /* 180-199 */
- 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, /* 200-219 */
- 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, /* 220-239 */
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 /* 240-255 */
-};
-/** Case insensitive map, ASCII rules.
- * That is;
- * [ != {, but A == a.
+/**
+ * A case insensitive mapping of characters from upper case to lower case for
+ * the ASCII character set.
*/
unsigned const char ascii_case_insensitive_map[256] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, /* 0-19 */
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, /* 20-39 */
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, /* 40-59 */
- 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, /* 60-79 */
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, /* 80-99 */
- 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, /* 100-119 */
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, /* 120-139 */
- 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, /* 140-159 */
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, /* 160-179 */
- 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, /* 180-199 */
- 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, /* 200-219 */
- 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, /* 220-239 */
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 /* 240-255 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // 0-9
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 10-19
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, // 20-29
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, // 30-39
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, // 40-49
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, // 50-59
+ 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, // 60-69
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 70-79
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, // 80-89
+ 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, // 90-99
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, // 100-109
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, // 110-119
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, // 120-129
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, // 130-139
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, // 140-149
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 150-159
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, // 160-169
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, // 170-179
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, // 180-189
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, // 190-199
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, // 200-209
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, // 210-219
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, // 220-229
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 230-249
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, // 240-249
+ 250, 251, 252, 253, 254, 255, // 250-255
};
-/** Case sensitive map.
- * Can technically also be used for ASCII case sensitive comparisons, as [ != {, etc.
+
+
+/**
+ * A case insensitive mapping of characters from upper case to lower case for
+ * the character set of RFC 1459. This is identical to ASCII with the small
+ * exception of {}| being considered to be the lower case equivalents of the
+ * characters []\ respectively.
*/
-unsigned const char rfc_case_sensitive_map[256] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
- 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
- 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
- 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
- 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
- 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
- 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
- 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+unsigned const char rfc_case_insensitive_map[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // 0-9
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 10-19
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, // 20-29
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, // 30-39
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, // 40-49
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, // 50-59
+ 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, // 60-69
+ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 70-79
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, // 80-89
+ 122, 123, 124, 125, 94, 95, 96, 97, 98, 99, // 90-99
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, // 100-109
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, // 110-119
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, // 120-129
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, // 130-139
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, // 140-149
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 150-159
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, // 160-169
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, // 170-179
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, // 180-189
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, // 190-199
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, // 200-209
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, // 210-219
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, // 220-229
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 230-239
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, // 240-249
+ 250, 251, 252, 253, 254, 255, // 250-255
};
-/* convert a string to lowercase. Note following special circumstances
- * taken from RFC 1459. Many "official" server branches still hold to this
- * rule so i will too;
- *
- * Because of IRC's scandanavian origin, the characters {}| are
- * considered to be the lower case equivalents of the characters []\,
- * respectively. This is a critical issue when determining the
- * equivalence of two nicknames.
+/**
+ * A case sensitive mapping of characters from upper case to lower case for the
+ * character set of RFC 1459. This is identical to ASCII.
*/
-void nspace::strlower(char *n)
-{
- if (n)
- {
- for (char* t = n; *t; t++)
- *t = national_case_insensitive_map[(unsigned char)*t];
- }
-}
-
-#ifdef HASHMAP_DEPRECATED
- size_t CoreExport nspace::insensitive::operator()(const std::string &s) const
-#else
- size_t nspace::hash<std::string>::operator()(const std::string &s) const
-#endif
-
-{
- /* XXX: NO DATA COPIES! :)
- * The hash function here is practically
- * a copy of the one in STL's hash_fun.h,
- * only with *x replaced with national_case_insensitive_map[*x].
- * This avoids a copy to use hash<const char*>
- */
- register size_t t = 0;
- for (std::string::const_iterator x = s.begin(); x != s.end(); ++x) /* ++x not x++, as its faster */
- t = 5 * t + national_case_insensitive_map[(unsigned char)*x];
- return t;
-}
-
+unsigned const char rfc_case_sensitive_map[256] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // 0-9
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // 10-19
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, // 20-29
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, // 30-39
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, // 40-49
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, // 50-59
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, // 60-69
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 70-79
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, // 80-89
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, // 90-99
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, // 100-109
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, // 110-119
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, // 120-129
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, // 130-139
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, // 140-149
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, // 150-159
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, // 160-169
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, // 170-179
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, // 180-189
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, // 190-199
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, // 200-209
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, // 210-219
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, // 220-229
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, // 230-239
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, // 240-249
+ 250, 251, 252, 253, 254, 255, // 250-255
+};
size_t CoreExport irc::hash::operator()(const irc::string &s) const
{
return (national_case_insensitive_map[*n1] == national_case_insensitive_map[*n2]);
}
+size_t irc::insensitive::operator()(const std::string &s) const
+{
+ /* XXX: NO DATA COPIES! :)
+ * The hash function here is practically
+ * a copy of the one in STL's hash_fun.h,
+ * only with *x replaced with national_case_insensitive_map[*x].
+ * This avoids a copy to use hash<const char*>
+ */
+ register size_t t = 0;
+ for (std::string::const_iterator x = s.begin(); x != s.end(); ++x) /* ++x not x++, as its faster */
+ t = 5 * t + national_case_insensitive_map[(unsigned char)*x];
+ return t;
+}
+
/******************************************************
*
* This is the implementation of our special irc::string
return (n >= 0) ? s1 : NULL;
}
-irc::tokenstream::tokenstream(const std::string &source) : tokens(source), last_pushed(false)
-{
- /* Record starting position and current position */
- last_starting_position = tokens.begin();
- n = tokens.begin();
-}
-
-irc::tokenstream::~tokenstream()
+irc::tokenstream::tokenstream(const std::string &source) : spacesepstream(source)
{
}
bool irc::tokenstream::GetToken(std::string &token)
{
- std::string::iterator lsp = last_starting_position;
-
- while (n != tokens.end())
- {
- /** Skip multi space, converting " " into " "
- */
- while ((n+1 != tokens.end()) && (*n == ' ') && (*(n+1) == ' '))
- n++;
-
- if ((last_pushed) && (*n == ':'))
- {
- /* If we find a token thats not the first and starts with :,
- * this is the last token on the line
- */
- std::string::iterator curr = ++n;
- n = tokens.end();
- token = std::string(curr, tokens.end());
- return true;
- }
+ bool first = !pos;
- last_pushed = false;
+ if (!spacesepstream::GetToken(token))
+ return false;
- if ((*n == ' ') || (n+1 == tokens.end()))
+ /* This is the last parameter */
+ if (token[0] == ':' && !first)
+ {
+ token = token.substr(1);
+ if (!StreamEnd())
{
- /* If we find a space, or end of string, this is the end of a token.
- */
- last_starting_position = n+1;
- last_pushed = *n == ' ';
-
- std::string strip(lsp, n+1 == tokens.end() ? n+1 : n++);
- while ((strip.length()) && (strip.find_last_of(' ') == strip.length() - 1))
- strip.erase(strip.end() - 1);
-
- token = strip;
- return !token.empty();
+ token += ' ';
+ token += GetRemaining();
}
-
- n++;
+ pos = tokens.length() + 1;
}
- token.clear();
- return false;
+
+ return true;
}
bool irc::tokenstream::GetToken(irc::string &token)
return returnval;
}
-irc::sepstream::sepstream(const std::string &source, char seperator) : tokens(source), sep(seperator)
+irc::sepstream::sepstream(const std::string& source, char separator, bool allowempty)
+ : tokens(source), sep(separator), pos(0), allow_empty(allowempty)
{
- last_starting_position = tokens.begin();
- n = tokens.begin();
}
bool irc::sepstream::GetToken(std::string &token)
{
- std::string::iterator lsp = last_starting_position;
+ if (this->StreamEnd())
+ {
+ token.clear();
+ return false;
+ }
- while (n != tokens.end())
+ if (!this->allow_empty)
{
- if ((*n == sep) || (n+1 == tokens.end()))
+ this->pos = this->tokens.find_first_not_of(this->sep, this->pos);
+ if (this->pos == std::string::npos)
{
- last_starting_position = n+1;
- token = std::string(lsp, n+1 == tokens.end() ? n+1 : n++);
-
- while ((token.length()) && (token.find_last_of(sep) == token.length() - 1))
- token.erase(token.end() - 1);
-
- if (token.empty())
- n++;
-
- return n == tokens.end() ? false : true;
+ this->pos = this->tokens.length() + 1;
+ token.clear();
+ return false;
}
-
- n++;
}
- token.clear();
- return false;
-}
-
-const std::string irc::sepstream::GetRemaining()
-{
- return std::string(n, tokens.end());
-}
+ size_t p = this->tokens.find(this->sep, this->pos);
+ if (p == std::string::npos)
+ p = this->tokens.length();
-bool irc::sepstream::StreamEnd()
-{
- return ((n + 1) == tokens.end());
-}
+ token = this->tokens.substr(this->pos, p - this->pos);
+ this->pos = p + 1;
-irc::sepstream::~sepstream()
-{
+ return true;
}
-std::string irc::hex(const unsigned char *raw, size_t rawsz)
+const std::string irc::sepstream::GetRemaining()
{
- if (!rawsz)
- return "";
-
- /* EWW! This used to be using sprintf, which is WAY inefficient. -Special */
-
- const char *hex = "0123456789abcdef";
- static char hexbuf[MAXBUF];
-
- size_t i, j;
- for (i = 0, j = 0; j < rawsz; ++j)
- {
- hexbuf[i++] = hex[raw[j] / 16];
- hexbuf[i++] = hex[raw[j] % 16];
- }
- hexbuf[i] = 0;
-
- return hexbuf;
+ return !this->StreamEnd() ? this->tokens.substr(this->pos) : "";
}
-CoreExport const char* irc::Spacify(const char* n)
+bool irc::sepstream::StreamEnd()
{
- static char x[MAXBUF];
- strlcpy(x,n,MAXBUF);
- for (char* y = x; *y; y++)
- if (*y == '_')
- *y = ' ';
- return x;
+ return this->pos > this->tokens.length();
}
-
irc::modestacker::modestacker(bool add) : adding(add)
{
sequence.clear();
return n;
}
-irc::stringjoiner::stringjoiner(const std::string &seperator, const std::vector<std::string> &sequence, int begin, int end)
+irc::stringjoiner::stringjoiner(const std::string& separator, const std::vector<std::string>& sequence, unsigned int begin, unsigned int end)
{
if (end < begin)
return; // nothing to do here
- for (int v = begin; v < end; v++)
- joined.append(sequence[v]).append(seperator);
+ for (unsigned int v = begin; v < end; v++)
+ joined.append(sequence[v]).append(separator);
joined.append(sequence[end]);
}
-irc::stringjoiner::stringjoiner(const std::string &seperator, const std::deque<std::string> &sequence, int begin, int end)
-{
- if (end < begin)
- return; // nothing to do here
-
- for (int v = begin; v < end; v++)
- joined.append(sequence[v]).append(seperator);
- joined.append(sequence[end]);
-}
-
-irc::stringjoiner::stringjoiner(const std::string &seperator, const char* const* sequence, int begin, int end)
-{
- if (end < begin)
- return; // nothing to do here
-
- for (int v = begin; v < end; v++)
- joined.append(sequence[v]).append(seperator);
- joined.append(sequence[end]);
-}
-
-std::string& irc::stringjoiner::GetJoined()
-{
- return joined;
-}
-
irc::portparser::portparser(const std::string &source, bool allow_overlapped)
: sep(source), in_range(0), range_begin(0), range_end(0), overlapped(allow_overlapped)
{
return atoi(x.c_str());
}
}
-
-/*const std::basic_string& SearchAndReplace(std::string& text, const std::string& pattern, const std::string& replace)
-{
- std::string replacement;
- if ((!pattern.empty()) && (!text.empty()))
- {
- for (std::string::size_type n = 0; n != text.length(); ++n)
- {
- if (text.length() >= pattern.length() && text.substr(n, pattern.length()) == pattern)
- {
- replacement.append(replace);
- n = n + pattern.length() - 1;
- }
- else
- {
- replacement += text[n];
- }
- }
- }
- text = replacement;
- return text;
-}*/
return iter->second;
}
-User* InspIRCd::FindNick(const char* nick)
-{
- if (isdigit(*nick))
- return FindUUID(nick);
-
- user_hash::iterator iter = this->Users->clientlist->find(nick);
-
- if (iter == this->Users->clientlist->end())
- return NULL;
-
- return iter->second;
-}
-
User* InspIRCd::FindNickOnly(const std::string &nick)
{
user_hash::iterator iter = this->Users->clientlist->find(nick);
return iter->second;
}
-User* InspIRCd::FindNickOnly(const char* nick)
-{
- user_hash::iterator iter = this->Users->clientlist->find(nick);
-
- if (iter == this->Users->clientlist->end())
- return NULL;
-
- return iter->second;
-}
-
User *InspIRCd::FindUUID(const std::string &uid)
{
user_hash::iterator finduuid = this->Users->uuidlist->find(uid);
return finduuid->second;
}
-
-User *InspIRCd::FindUUID(const char *uid)
-{
- return FindUUID(std::string(uid));
-}
-
/* find a channel record by channel name and return a pointer to it */
-Channel* InspIRCd::FindChan(const char* chan)
-{
- chan_hash::iterator iter = chanlist->find(chan);
-
- if (iter == chanlist->end())
- /* Couldn't find it */
- return NULL;
-
- return iter->second;
-}
Channel* InspIRCd::FindChan(const std::string &chan)
{
User* u = *i;
if (u->registered == REG_ALL)
{
- u->WriteServ("NOTICE %s :%s",u->nick.c_str(),s.c_str());
- }
+ u->WriteNotice(s);
+ }
else
{
/* Unregistered connections receive ERROR, not a NOTICE */
}
}
-/* return channel count */
-long InspIRCd::ChannelCount()
-{
- return chanlist->size();
-}
-
bool InspIRCd::IsValidMask(const std::string &mask)
{
const char* dest = mask.c_str();
}
/* true for valid channel name, false else */
-bool IsChannelHandler::Call(const char *chname, size_t max)
+bool IsChannelHandler::Call(const std::string& chname)
{
- const char *c = chname + 1;
+ if (chname.empty() || chname.length() > ServerInstance->Config->Limits.ChanMax)
+ return false;
- /* check for no name - don't check for !*chname, as if it is empty, it won't be '#'! */
- if (!chname || *chname != '#')
- {
+ if (chname[0] != '#')
return false;
- }
- while (*c)
+ for (std::string::const_iterator i = chname.begin()+1; i != chname.end(); ++i)
{
- switch (*c)
+ switch (*i)
{
case ' ':
case ',':
case 7:
return false;
}
-
- c++;
- }
-
- size_t len = c - chname;
- /* too long a name - note funky pointer arithmetic here. */
- if (len > max)
- {
- return false;
}
return true;
}
/* true for valid nickname, false else */
-bool IsNickHandler::Call(const char* n, size_t max)
+bool IsNickHandler::Call(const std::string& n)
{
- if (!n || !*n)
+ if (n.empty() || n.length() > ServerInstance->Config->Limits.NickMax)
return false;
- unsigned int p = 0;
- for (const char* i = n; *i; i++, p++)
+ for (std::string::const_iterator i = n.begin(); i != n.end(); ++i)
{
if ((*i >= 'A') && (*i <= '}'))
{
continue;
}
- if ((((*i >= '0') && (*i <= '9')) || (*i == '-')) && (i > n))
+ if ((((*i >= '0') && (*i <= '9')) || (*i == '-')) && (i != n.begin()))
{
/* "0"-"9", "-" can occur anywhere BUT the first char of a nickname */
continue;
return false;
}
- /* too long? or not */
- return (p <= max);
+ return true;
}
/* return true for good ident, false else */
-bool IsIdentHandler::Call(const char* n)
+bool IsIdentHandler::Call(const std::string& n)
{
- if (!n || !*n)
+ if (n.empty())
return false;
- for (const char* i = n; *i; i++)
+ for (std::string::const_iterator i = n.begin(); i != n.end(); ++i)
{
if ((*i >= 'A') && (*i <= '}'))
{
return true;
}
-bool IsSIDHandler::Call(const std::string &str)
+bool InspIRCd::IsSID(const std::string &str)
{
/* Returns true if the string given is exactly 3 characters long,
* starts with a digit, and the other two characters are A-Z or digits
((str[2] >= 'A' && str[2] <= 'Z') || isdigit(str[2])));
}
-/* open the proper logfile */
-bool InspIRCd::OpenLog(char**, int)
-{
- if (!Config->cmdline.writelog) return true; // Skip opening default log if -nolog
-
- if (Config->cmdline.startup_log.empty())
- Config->cmdline.startup_log = LOG_PATH "/startup.log";
- FILE* startup = fopen(Config->cmdline.startup_log.c_str(), "a+");
-
- if (!startup)
- {
- return false;
- }
-
- FileWriter* fw = new FileWriter(startup);
- FileLogStream *f = new FileLogStream((Config->cmdline.forcedebug ? DEBUG : DEFAULT), fw);
-
- this->Logs->AddLogType("*", f, true);
-
- return true;
-}
-
void InspIRCd::CheckRoot()
{
#ifndef _WIN32
if (geteuid() == 0)
{
std::cout << "ERROR: You are running an irc server as root! DO NOT DO THIS!" << std::endl << std::endl;
- this->Logs->Log("STARTUP",DEFAULT,"Can't start as root");
+ this->Logs->Log("STARTUP", LOG_DEFAULT, "Can't start as root");
Exit(EXIT_STATUS_ROOT);
}
#endif
void InspIRCd::SendWhoisLine(User* user, User* dest, int numeric, const char* format, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
- va_start (argsPtr, format);
- vsnprintf(textbuffer, MAXBUF, format, argsPtr);
- va_end(argsPtr);
-
- this->SendWhoisLine(user, dest, numeric, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, format, format)
+ this->SendWhoisLine(user, dest, numeric, textbuffer);
}
/** Refactored by Brain, Jun 2009. Much faster with some clever O(1) array
* lookups and pointer maths.
*/
-long InspIRCd::Duration(const std::string &str)
+unsigned long InspIRCd::Duration(const std::string &str)
{
unsigned char multiplier = 0;
long total = 0;
return total + subtotal;
}
+const char* InspIRCd::Format(va_list &vaList, const char* formatString)
+{
+ static std::vector<char> formatBuffer(1024);
+
+ while (true)
+ {
+ va_list dst;
+ va_copy(dst, vaList);
+
+ int vsnret = vsnprintf(&formatBuffer[0], formatBuffer.size(), formatString, dst);
+ if (vsnret > 0 && static_cast<unsigned>(vsnret) < formatBuffer.size())
+ {
+ return &formatBuffer[0];
+ }
+
+ formatBuffer.resize(formatBuffer.size() * 2);
+ }
+
+ throw CoreException();
+}
+
+const char* InspIRCd::Format(const char* formatString, ...)
+{
+ const char* ret;
+ VAFORMAT(ret, formatString, formatString);
+ return ret;
+}
+
bool InspIRCd::ULine(const std::string& sserver)
{
if (sserver.empty())
return std::string(ctime(&curtime),24);
}
-// You should only pass a single character to this.
-void InspIRCd::AddExtBanChar(char c)
-{
- std::string &tok = Config->data005;
- std::string::size_type ebpos = tok.find(" EXTBAN=,");
-
- if (ebpos == std::string::npos)
- {
- tok.append(" EXTBAN=,");
- tok.push_back(c);
- }
- else
- {
- ebpos += 9;
- while (isalpha(tok[ebpos]) && tok[ebpos] < c)
- ebpos++;
- tok.insert(ebpos, 1, c);
- }
-}
-
std::string InspIRCd::GenRandomStr(int length, bool printable)
{
char* buf = new char[length];
/* $Core */
#include "inspircd.h"
-#include "inspircd_version.h"
#include <signal.h>
#ifndef _WIN32
#include "testsuite.h"
InspIRCd* ServerInstance = NULL;
-int* mysig = NULL;
/** Seperate from the other casemap tables so that code *can* still exclusively rely on RFC casemapping
* if it must.
/* Must be deleted before modes as it decrements modelines */
if (FakeClient)
FakeClient->cull();
- if (Res)
- Res->cull();
DeleteZero(this->FakeClient);
DeleteZero(this->Users);
DeleteZero(this->Modes);
DeleteZero(this->BanCache);
DeleteZero(this->SNO);
DeleteZero(this->Config);
- DeleteZero(this->Res);
DeleteZero(this->chanlist);
DeleteZero(this->PI);
DeleteZero(this->Threads);
}
}
-void InspIRCd::ResetMaxBans()
-{
- for (chan_hash::const_iterator i = chanlist->begin(); i != chanlist->end(); i++)
- i->second->ResetMaxBans();
-}
-
-/** Because hash_map doesn't free its buckets when we delete items, we occasionally
- * recreate the hash to free them up.
- * We do this by copying the entries from the old hash to a new hash, causing all
- * empty buckets to be weeded out of the hash.
- * Since this is quite expensive, it's not done very often.
- */
-void InspIRCd::RehashUsersAndChans()
-{
- user_hash* old_users = Users->clientlist;
- Users->clientlist = new user_hash;
- for (user_hash::const_iterator n = old_users->begin(); n != old_users->end(); n++)
- Users->clientlist->insert(*n);
- delete old_users;
-
- user_hash* old_uuid = Users->uuidlist;
- Users->uuidlist = new user_hash;
- for (user_hash::const_iterator n = old_uuid->begin(); n != old_uuid->end(); n++)
- Users->uuidlist->insert(*n);
- delete old_uuid;
-
- chan_hash* old_chans = chanlist;
- chanlist = new chan_hash;
- for (chan_hash::const_iterator n = old_chans->begin(); n != old_chans->end(); n++)
- chanlist->insert(*n);
- delete old_chans;
-
- // Reset the already_sent IDs so we don't wrap it around and drop a message
- LocalUser::already_sent_id = 0;
- for (LocalUserList::const_iterator i = Users->local_users.begin(); i != Users->local_users.end(); i++)
- {
- (**i).already_sent = 0;
- (**i).RemoveExpiredInvites();
- }
-}
-
void InspIRCd::SetSignals()
{
#ifndef _WIN32
rlimit rl;
if (getrlimit(RLIMIT_CORE, &rl) == -1)
{
- this->Logs->Log("STARTUP",DEFAULT,"Failed to getrlimit()!");
+ this->Logs->Log("STARTUP", LOG_DEFAULT, "Failed to getrlimit()!");
return false;
}
rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_CORE, &rl) == -1)
- this->Logs->Log("STARTUP",DEFAULT,"setrlimit() failed, cannot increase coredump size.");
+ this->Logs->Log("STARTUP", LOG_DEFAULT, "setrlimit() failed, cannot increase coredump size.");
return true;
#endif
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());
+ this->Logs->Log("STARTUP", LOG_DEFAULT, "Failed to write PID-file '%s', exiting.",fname.c_str());
Exit(EXIT_STATUS_PID);
}
#endif
* THIS MUST MATCH THE ORDER OF DECLARATION OF THE FUNCTORS, e.g. the methods
* themselves within the class.
*/
- NICKForced("NICKForced", NULL),
OperQuit("OperQuit", NULL),
GenRandom(&HandleGenRandom),
IsChannel(&HandleIsChannel),
- IsSID(&HandleIsSID),
Rehash(&HandleRehash),
IsNick(&HandleIsNick),
IsIdent(&HandleIsIdent),
- FloodQuitUser(&HandleFloodQuitUser),
OnCheckExemption(&HandleOnCheckExemption)
{
ServerInstance = this;
- Extensions.Register(&NICKForced);
Extensions.Register(&OperQuit);
FailedPortList pl;
this->Parser = 0;
this->XLines = 0;
this->Modes = 0;
- this->Res = 0;
this->ConfigThread = NULL;
this->FakeClient = NULL;
/* Default implementation does nothing */
this->PI = new ProtocolInterface;
- this->s_signal = 0;
-
// Create base manager classes early, so nothing breaks
this->Users = new UserManager;
this->SNO = new SnomaskManager;
this->BanCache = new BanCacheManager;
this->Modules = new ModuleManager();
+ dynamic_reference_base::reset_all();
this->stats = new serverstats();
this->Timers = new TimerManager;
this->Parser = new CommandParser;
struct option longopts[] =
{
{ "nofork", no_argument, &do_nofork, 1 },
- { "logfile", required_argument, NULL, 'f' },
{ "config", required_argument, NULL, 'c' },
{ "debug", no_argument, &do_debug, 1 },
{ "nolog", no_argument, &do_nolog, 1 },
};
int index;
- while ((c = getopt_long(argc, argv, ":c:f:", longopts, &index)) != -1)
+ while ((c = getopt_long(argc, argv, ":c:", longopts, &index)) != -1)
{
switch (c)
{
- case 'f':
- /* Log filename was set */
- Config->cmdline.startup_log = optarg;
- break;
case 'c':
/* Config filename was set */
ConfigFileName = optarg;
default:
/* Fall through to handle other weird values too */
std::cout << "Unknown parameter '" << argv[optind-1] << "'" << std::endl;
- std::cout << "Usage: " << argv[0] << " [--nofork] [--nolog] [--debug] [--logfile <filename>] " << std::endl <<
- std::string(static_cast<int>(8+strlen(argv[0])), ' ') << "[--runasroot] [--version] [--config <config>] [--testsuite]" << std::endl;
+ std::cout << "Usage: " << argv[0] << " [--nofork] [--nolog] [--debug] [--config <config>]" << std::endl <<
+ std::string(static_cast<int>(8+strlen(argv[0])), ' ') << "[--runasroot] [--version] [--testsuite]" << std::endl;
Exit(EXIT_STATUS_ARGV);
break;
}
if (do_debug)
{
FileWriter* fw = new FileWriter(stdout);
- FileLogStream* fls = new FileLogStream(RAWIO, fw);
+ FileLogStream* fls = new FileLogStream(LOG_RAWIO, fw);
Logs->AddLogTypes("*", fls, true);
}
- else if (!this->OpenLog(argv, argc))
- {
- std::cout << "ERROR: Could not open initial logfile " << Config->cmdline.startup_log << ": " << strerror(errno) << std::endl << std::endl;
- Exit(EXIT_STATUS_LOG);
- }
if (!ServerConfig::FileExists(ConfigFileName.c_str()))
{
#endif
{
std::cout << "ERROR: Cannot open config file: " << ConfigFileName << std::endl << "Exiting..." << std::endl;
- this->Logs->Log("STARTUP",DEFAULT,"Unable to open config file %s", ConfigFileName.c_str());
+ this->Logs->Log("STARTUP", LOG_DEFAULT, "Unable to open config file %s", ConfigFileName.c_str());
Exit(EXIT_STATUS_CONFIG);
}
}
std::cout << con_green << "(C) InspIRCd Development Team." << con_reset << std::endl << std::endl;
std::cout << "Developers:" << std::endl;
std::cout << con_green << "\tBrain, FrostyCoolSlug, w00t, Om, Special, peavey" << std::endl;
- std::cout << "\taquanight, psychon, dz, danieldg, jackmcbarn" << std::endl;\r
+ std::cout << "\taquanight, psychon, dz, danieldg, jackmcbarn" << std::endl;
std::cout << "\tAttila" << con_reset << std::endl << std::endl;
std::cout << "Others:\t\t\t" << con_green << "See /INFO Output" << con_reset << std::endl;
this->CheckRoot();
else
{
- std::cout << "* WARNING * WARNING * WARNING * WARNING * WARNING *" << std::endl\r
- << "YOU ARE RUNNING INSPIRCD AS ROOT. THIS IS UNSUPPORTED" << std::endl\r
- << "AND IF YOU ARE HACKED, CRACKED, SPINDLED OR MUTILATED" << std::endl\r
- << "OR ANYTHING ELSE UNEXPECTED HAPPENS TO YOU OR YOUR" << std::endl\r
- << "SERVER, THEN IT IS YOUR OWN FAULT. IF YOU DID NOT MEAN" << std::endl\r
- << "TO START INSPIRCD AS ROOT, HIT CTRL+C NOW AND RESTART" << std::endl\r
- << "THE PROGRAM AS A NORMAL USER. YOU HAVE BEEN WARNED!" << std::endl << std::endl\r
- << "InspIRCd starting in 20 seconds, ctrl+c to abort..." << std::endl;\r
+ std::cout << "* WARNING * WARNING * WARNING * WARNING * WARNING *" << std::endl
+ << "YOU ARE RUNNING INSPIRCD AS ROOT. THIS IS UNSUPPORTED" << std::endl
+ << "AND IF YOU ARE HACKED, CRACKED, SPINDLED OR MUTILATED" << std::endl
+ << "OR ANYTHING ELSE UNEXPECTED HAPPENS TO YOU OR YOUR" << std::endl
+ << "SERVER, THEN IT IS YOUR OWN FAULT. IF YOU DID NOT MEAN" << std::endl
+ << "TO START INSPIRCD AS ROOT, HIT CTRL+C NOW AND RESTART" << std::endl
+ << "THE PROGRAM AS A NORMAL USER. YOU HAVE BEEN WARNED!" << std::endl << std::endl
+ << "InspIRCd starting in 20 seconds, ctrl+c to abort..." << std::endl;
sleep(20);
}
#endif
if (!this->DaemonSeed())
{
std::cout << "ERROR: could not go into daemon mode. Shutting down." << std::endl;
- Logs->Log("STARTUP", DEFAULT, "ERROR: could not go into daemon mode. Shutting down.");
+ Logs->Log("STARTUP", LOG_DEFAULT, "ERROR: could not go into daemon mode. Shutting down.");
Exit(EXIT_STATUS_FORK);
}
}
this->Config->Read();
this->Config->Apply(NULL, "");
Logs->OpenFileLogs();
+ ModeParser::InitBuiltinModes();
- this->Res = new DNS();
-
- /*
- * Initialise SID/UID.
- * For an explanation as to exactly how this works, and why it works this way, see GetUID().
- * -- w00t
- */
+ // If we don't have a SID, generate one based on the server name and the server description
if (Config->sid.empty())
- {
- // Generate one
- unsigned int sid = 0;
- char sidstr[4];
-
- for (const char* x = Config->ServerName.c_str(); *x; ++x)
- sid = 5 * sid + *x;
- for (const char* y = Config->ServerDesc.c_str(); *y; ++y)
- sid = 5 * sid + *y;
- sprintf(sidstr, "%03d", sid % 1000);
+ Config->sid = UIDGenerator::GenerateSID(Config->ServerName, Config->ServerDesc);
- Config->sid = sidstr;
- }
+ // Initialize the UID generator with our sid
+ this->UIDGen.init(Config->sid);
/* set up fake client again this time with the correct uid */
this->FakeClient = new FakeUser(Config->sid, Config->ServerName);
this->Modules->LoadAll();
/* Just in case no modules were loaded - fix for bug #101 */
- this->BuildISupport();
+ this->ISupport.Build();
Config->ApplyDisabledCommands(Config->DisabledCommands);
if (!pl.empty())
if (kill(getppid(), SIGTERM) == -1)
{
std::cout << "Error killing parent process: " << strerror(errno) << std::endl;
- Logs->Log("STARTUP", DEFAULT, "Error killing parent process: %s",strerror(errno));
+ Logs->Log("STARTUP", LOG_DEFAULT, "Error killing parent process: %s",strerror(errno));
}
}
fclose(stdout);
if (dup2(fd, STDIN_FILENO) < 0)
- Logs->Log("STARTUP", DEFAULT, "Failed to dup /dev/null to stdin.");
+ Logs->Log("STARTUP", LOG_DEFAULT, "Failed to dup /dev/null to stdin.");
if (dup2(fd, STDOUT_FILENO) < 0)
- Logs->Log("STARTUP", DEFAULT, "Failed to dup /dev/null to stdout.");
+ Logs->Log("STARTUP", LOG_DEFAULT, "Failed to dup /dev/null to stdout.");
if (dup2(fd, STDERR_FILENO) < 0)
- Logs->Log("STARTUP", DEFAULT, "Failed to dup /dev/null to stderr.");
+ Logs->Log("STARTUP", LOG_DEFAULT, "Failed to dup /dev/null to stderr.");
close(fd);
}
else
{
- Logs->Log("STARTUP", DEFAULT,"Keeping pseudo-tty open as we are running in the foreground.");
+ Logs->Log("STARTUP", LOG_DEFAULT, "Keeping pseudo-tty open as we are running in the foreground.");
}
#else
/* Set win32 service as running, if we are running as a service */
QueryPerformanceFrequency(&stats->QPFrequency);
#endif
- Logs->Log("STARTUP", DEFAULT, "Startup complete as '%s'[%s], %d max open sockets", Config->ServerName.c_str(),Config->GetSID().c_str(), SE->GetMaxFds());
+ Logs->Log("STARTUP", LOG_DEFAULT, "Startup complete as '%s'[%s], %d max open sockets", Config->ServerName.c_str(),Config->GetSID().c_str(), SE->GetMaxFds());
#ifndef _WIN32
std::string SetUser = Config->ConfValue("security")->getString("runasuser");
if (ret == -1)
{
- this->Logs->Log("SETGROUPS", DEFAULT, "setgroups() failed (wtf?): %s", strerror(errno));
+ this->Logs->Log("SETGROUPS", LOG_DEFAULT, "setgroups() failed (wtf?): %s", strerror(errno));
this->QuickExit(0);
}
if (!g)
{
- this->Logs->Log("SETGUID", DEFAULT, "getgrnam() failed (bad user?): %s", strerror(errno));
+ this->Logs->Log("SETGUID", LOG_DEFAULT, "getgrnam() failed (bad user?): %s", strerror(errno));
this->QuickExit(0);
}
if (ret == -1)
{
- this->Logs->Log("SETGUID", DEFAULT, "setgid() failed (bad user?): %s", strerror(errno));
+ this->Logs->Log("SETGUID", LOG_DEFAULT, "setgid() failed (bad user?): %s", strerror(errno));
this->QuickExit(0);
}
}
if (!u)
{
- this->Logs->Log("SETGUID", DEFAULT, "getpwnam() failed (bad user?): %s", strerror(errno));
+ this->Logs->Log("SETGUID", LOG_DEFAULT, "getpwnam() failed (bad user?): %s", strerror(errno));
this->QuickExit(0);
}
if (ret == -1)
{
- this->Logs->Log("SETGUID", DEFAULT, "setuid() failed (bad user?): %s", strerror(errno));
+ this->Logs->Log("SETGUID", LOG_DEFAULT, "setuid() failed (bad user?): %s", strerror(errno));
this->QuickExit(0);
}
}
if (this->ConfigThread && this->ConfigThread->IsDone())
{
/* Rehash has completed */
- this->Logs->Log("CONFIG",DEBUG,"Detected ConfigThread exiting, tidying up...");
+ this->Logs->Log("CONFIG", LOG_DEBUG, "Detected ConfigThread exiting, tidying up...");
this->ConfigThread->Finish();
{
SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is jumping FORWARDS! Clock skipped %lu secs.", (unsigned long)TIME.tv_sec - OLDTIME);
}
-\r
+
OLDTIME = TIME.tv_sec;
if ((TIME.tv_sec % 3600) == 0)
{
- this->RehashUsersAndChans();
+ Users->GarbageCollect();
FOREACH_MOD(I_OnGarbageCollect, OnGarbageCollect());
}
GlobalCulls.Apply();
AtomicActions.Run();
- if (this->s_signal)
+ if (s_signal)
{
this->SignalHandler(s_signal);
- this->s_signal = 0;
+ s_signal = 0;
}
}
/**********************************************************************************/
-/**
- * An ircd in five lines! bwahahaha. ahahahahaha. ahahah *cough*.
- */
-
/* this returns true when all modules are satisfied that the user should be allowed onto the irc server
* (until this returns true, a user will block in the waiting state, waiting to connect up to the
* registration timeout maximum seconds)
return (res == MOD_RES_PASSTHRU);
}
+sig_atomic_t InspIRCd::s_signal = 0;
+
void InspIRCd::SetSignal(int signal)
{
- *mysig = signal;
+ s_signal = signal;
}
/* On posix systems, the flow of the program starts right here, with
ENTRYPOINT
{
new InspIRCd(argc, argv);
- mysig = &ServerInstance->s_signal;
ServerInstance->Run();
delete ServerInstance;
return 0;
irc::sockets::sockaddrs addr, bind;
if (!irc::sockets::aptosa(ipaddr, aport, addr))
{
- ServerInstance->Logs->Log("SOCKET", DEBUG, "BUG: Hostname passed to BufferedSocket, rather than an IP address!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "BUG: Hostname passed to BufferedSocket, rather than an IP address!");
return I_ERR_CONNECT;
}
ServerInstance->SE->NonBlocking(fd);
- if (ServerInstance->SE->Connect(this, &dest.sa, sa_size(dest)) == -1)
+ if (ServerInstance->SE->Connect(this, &dest.sa, dest.sa_size()) == -1)
{
if (errno != EINPROGRESS)
return I_ERR_CONNECT;
this->Timeout = new SocketTimeout(this->GetFd(), this, timeout, ServerInstance->Time());
ServerInstance->Timers->AddTimer(this->Timeout);
- ServerInstance->Logs->Log("SOCKET", DEBUG,"BufferedSocket::DoConnect success");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "BufferedSocket::DoConnect success");
return I_ERR_NONE;
}
}
catch (CoreException& modexcept)
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT,"%s threw an exception: %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "%s threw an exception: %s",
modexcept.GetSource(), modexcept.GetReason());
}
IOHook = NULL;
}
catch (CoreException& modexcept)
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "%s threw an exception: %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "%s threw an exception: %s",
modexcept.GetSource(), modexcept.GetReason());
return;
}
return;
if (!error.empty() || fd < 0 || fd == INT_MAX)
{
- ServerInstance->Logs->Log("SOCKET", DEBUG, "DoWrite on errored or closed socket");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DoWrite on errored or closed socket");
return;
}
}
catch (CoreException& modexcept)
{
- ServerInstance->Logs->Log("SOCKET", DEBUG,"%s threw an exception: %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "%s threw an exception: %s",
modexcept.GetSource(), modexcept.GetReason());
}
}
{
if (fd < 0)
{
- ServerInstance->Logs->Log("SOCKET", DEBUG, "Attempt to write data to dead socket: %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to write data to dead socket: %s",
data.c_str());
return;
}
ServerInstance->SE->ChangeEventMask(this, FD_ADD_TRIAL_WRITE);
}
-void SocketTimeout::Tick(time_t)
+bool SocketTimeout::Tick(time_t)
{
- ServerInstance->Logs->Log("SOCKET", DEBUG,"SocketTimeout::Tick");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "SocketTimeout::Tick");
if (ServerInstance->SE->GetRef(this->sfd) != this->sock)
- return;
+ return false;
if (this->sock->state == I_CONNECTING)
{
}
this->sock->Timeout = NULL;
+ return false;
}
void BufferedSocket::OnConnected() { }
this->Close();
if (Timeout)
{
- ServerInstance->Timers->DelTimer(Timeout);
- Timeout = NULL;
+ // The timer is removed from the TimerManager in Timer::~Timer()
+ delete Timeout;
}
}
}
catch (CoreException& ex)
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "Caught exception in socket processing on FD %d - '%s'",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Caught exception in socket processing on FD %d - '%s'",
fd, ex.GetReason());
SetError(ex.GetReason());
}
if (!error.empty())
{
- ServerInstance->Logs->Log("SOCKET", DEBUG, "Error on FD %d - '%s'", fd, error.c_str());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Error on FD %d - '%s'", fd, error.c_str());
OnError(errcode);
}
}
#include "inspircd.h"
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef HAS_STRLCPY
-CoreExport size_t strlcat(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz, dlen;
-
- while (n-- != 0 && *d != '\0')
- d++;
-
- dlen = d - dst;
- n = siz - dlen;
-
- if (n == 0)
- return(dlen + strlen(s));
-
- while (*s != '\0')
- {
- if (n != 1)
- {
- *d++ = *s;
- n--;
- }
-
- s++;
- }
-
- *d = '\0';
- return(dlen + (s - src)); /* count does not include NUL */
-}
-
-CoreExport size_t strlcpy(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0)
- {
- do
- {
- if ((*d++ = *s++) == 0)
- break;
- } while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0)
- {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++);
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
-#endif
-
-CoreExport int charlcat(char* x,char y,int z)
-{
- char* x__n = x;
- int v = 0;
-
- while(*x__n++)
- v++;
-
- if (v < z - 1)
- {
- *--x__n = y;
- *++x__n = 0;
- }
-
- return v;
-}
-
-CoreExport bool charremove(char* mp, char remove)
-{
- char* mptr = mp;
- bool shift_down = false;
-
- while (*mptr)
- {
- if (*mptr == remove)
- shift_down = true;
-
- if (shift_down)
- *mptr = *(mptr+1);
-
- mptr++;
- }
-
- return shift_down;
-}
-
static const char hextable[] = "0123456789abcdef";
-std::string BinToHex(const std::string& data)
+std::string BinToHex(const void* raw, size_t l)
{
- int l = data.length();
+ const char* data = static_cast<const char*>(raw);
std::string rv;
rv.reserve(l * 2);
- for(int i=0; i < l; i++)
+ for (size_t i = 0; i < l; i++)
{
unsigned char c = data[i];
- rv.append(1, hextable[c >> 4]);
- rv.append(1, hextable[c & 0xF]);
+ rv.push_back(hextable[c >> 4]);
+ rv.push_back(hextable[c & 0xF]);
}
return rv;
}
#include "socket.h"
#include "socketengine.h"
+#ifdef USE_TCP_DEFER_ACCEPT
+#include <netinet/tcp.h>
+#endif
+
ListenSocket::ListenSocket(ConfigTag* tag, const irc::sockets::sockaddrs& bind_to)
: bind_tag(tag)
{
if (rv >= 0)
rv = ServerInstance->SE->Listen(this->fd, ServerInstance->Config->MaxConn);
+ int timeout = tag->getInt("defer", 0);
+ if (timeout && !rv)
+ {
+#ifdef USE_TCP_DEFER_ACCEPT
+ setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, sizeof(timeout));
+#elif defined USE_SO_ACCEPTFILTER
+ struct accept_filter_arg afa;
+ memset(&afa, 0, sizeof(afa));
+ strcpy(afa.af_name, "dataready");
+ setsockopt(fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa));
+#endif
+ }
+
if (rv < 0)
{
int errstore = errno;
if (this->GetFd() > -1)
{
ServerInstance->SE->DelFd(this);
- ServerInstance->Logs->Log("SOCKET", DEBUG,"Shut down listener on fd %d", this->fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Shut down listener on fd %d", this->fd);
ServerInstance->SE->Shutdown(this, 2);
if (ServerInstance->SE->Close(this) != 0)
- ServerInstance->Logs->Log("SOCKET", DEBUG,"Failed to cancel listener: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Failed to cancel listener: %s", strerror(errno));
this->fd = -1;
}
}
socklen_t length = sizeof(client);
int incomingSockfd = ServerInstance->SE->Accept(this, &client.sa, &length);
- ServerInstance->Logs->Log("SOCKET",DEBUG,"HandleEvent for Listensocket %s nfd=%d", bind_desc.c_str(), incomingSockfd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "HandleEvent for Listensocket %s nfd=%d", bind_desc.c_str(), incomingSockfd);
if (incomingSockfd < 0)
{
ServerInstance->stats->statsRefused++;
socklen_t sz = sizeof(server);
if (getsockname(incomingSockfd, &server.sa, &sz))
{
- ServerInstance->Logs->Log("SOCKET", DEBUG, "Can't get peername: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Can't get peername: %s", strerror(errno));
irc::sockets::aptosa(bind_addr, bind_port, server);
}
*/
if (incomingSockfd >= ServerInstance->SE->GetMaxFds())
{
- ServerInstance->Logs->Log("SOCKET", DEBUG, "Server is full");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Server is full");
ServerInstance->SE->Shutdown(incomingSockfd, 2);
ServerInstance->SE->Close(incomingSockfd);
ServerInstance->stats->statsRefused++;
else
{
ServerInstance->stats->statsRefused++;
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"Refusing connection on %s - %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Refusing connection on %s - %s",
bind_desc.c_str(), res == MOD_RES_DENY ? "Connection refused by module" : "Module for this port not found");
ServerInstance->SE->Close(incomingSockfd);
}
switch (e)
{
case EVENT_ERROR:
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"ListenSocket::HandleEvent() received a socket engine error event! well shit! '%s'", strerror(err));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ListenSocket::HandleEvent() received a socket engine error event! well shit! '%s'", strerror(err));
break;
case EVENT_WRITE:
- ServerInstance->Logs->Log("SOCKET",DEBUG,"*** BUG *** ListenSocket::HandleEvent() got a WRITE event!!!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "*** BUG *** ListenSocket::HandleEvent() got a WRITE event!!!");
break;
case EVENT_READ:
this->AcceptInternal();
--- /dev/null
+/*
+ * 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
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "inspircd.h"
+#include "listmode.h"
+
+ListModeBase::ListModeBase(Module* Creator, const std::string& Name, char modechar, const std::string &eolstr, unsigned int lnum, unsigned int eolnum, bool autotidy, const std::string &ctag)
+ : ModeHandler(Creator, Name, modechar, PARAM_ALWAYS, MODETYPE_CHANNEL),
+ listnumeric(lnum), endoflistnumeric(eolnum), endofliststring(eolstr), tidy(autotidy),
+ configtag(ctag), extItem("listbase_mode_" + name + "_list", Creator)
+{
+ list = true;
+}
+
+void ListModeBase::DisplayList(User* user, Channel* channel)
+{
+ ChanData* cd = extItem.get(channel);
+ if (cd)
+ {
+ for (ModeList::reverse_iterator it = cd->list.rbegin(); it != cd->list.rend(); ++it)
+ {
+ user->WriteNumeric(listnumeric, "%s %s %s %s %lu", user->nick.c_str(), channel->name.c_str(), it->mask.c_str(), (!it->setter.empty() ? it->setter.c_str() : ServerInstance->Config->ServerName.c_str()), (unsigned long) it->time);
+ }
+ }
+ user->WriteNumeric(endoflistnumeric, "%s %s :%s", user->nick.c_str(), channel->name.c_str(), endofliststring.c_str());
+}
+
+void ListModeBase::DisplayEmptyList(User* user, Channel* channel)
+{
+ user->WriteNumeric(endoflistnumeric, "%s %s :%s", user->nick.c_str(), channel->name.c_str(), endofliststring.c_str());
+}
+
+void ListModeBase::RemoveMode(Channel* channel, irc::modestacker& stack)
+{
+ ChanData* cd = extItem.get(channel);
+ if (cd)
+ {
+ for (ModeList::iterator it = cd->list.begin(); it != cd->list.end(); it++)
+ {
+ stack.Push(this->GetModeChar(), it->mask);
+ }
+ }
+}
+
+void ListModeBase::DoRehash()
+{
+ ConfigTagList tags = ServerInstance->Config->ConfTags(configtag);
+
+ limitlist oldlimits = chanlimits;
+ chanlimits.clear();
+
+ for (ConfigIter i = tags.first; i != tags.second; i++)
+ {
+ // For each <banlist> tag
+ ConfigTag* c = i->second;
+ ListLimit limit(c->getString("chan"), c->getInt("limit"));
+
+ if (limit.mask.size() && limit.limit > 0)
+ chanlimits.push_back(limit);
+ }
+
+ if (chanlimits.empty())
+ chanlimits.push_back(ListLimit("*", 64));
+
+ // Most of the time our settings are unchanged, so we can avoid iterating the chanlist
+ if (oldlimits == chanlimits)
+ return;
+
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); ++i)
+ {
+ ChanData* cd = extItem.get(i->second);
+ if (cd)
+ cd->maxitems = -1;
+ }
+}
+
+void ListModeBase::DoImplements(Module* m)
+{
+ ServerInstance->Modules->AddService(extItem);
+ this->DoRehash();
+ Implementation eventlist[] = { I_OnSyncChannel, I_OnRehash };
+ ServerInstance->Modules->Attach(eventlist, m, sizeof(eventlist)/sizeof(Implementation));
+}
+
+unsigned int ListModeBase::FindLimit(const std::string& channame)
+{
+ for (limitlist::iterator it = chanlimits.begin(); it != chanlimits.end(); ++it)
+ {
+ if (InspIRCd::Match(channame, it->mask))
+ {
+ // We have a pattern matching the channel
+ return it->limit;
+ }
+ }
+ return 64;
+}
+
+unsigned int ListModeBase::GetLimitInternal(const std::string& channame, ChanData* cd)
+{
+ if (cd->maxitems < 0)
+ cd->maxitems = FindLimit(channame);
+ return cd->maxitems;
+}
+
+unsigned int ListModeBase::GetLimit(Channel* channel)
+{
+ ChanData* cd = extItem.get(channel);
+ if (!cd) // just find the limit
+ return FindLimit(channel->name);
+
+ return GetLimitInternal(channel->name, cd);
+}
+
+ModeAction ListModeBase::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding)
+{
+ // Try and grab the list
+ ChanData* cd = extItem.get(channel);
+
+ if (adding)
+ {
+ if (tidy)
+ ModeParser::CleanMask(parameter);
+
+ if (parameter.length() > 250)
+ return MODEACTION_DENY;
+
+ // If there was no list
+ if (!cd)
+ {
+ // Make one
+ cd = new ChanData;
+ extItem.set(channel, cd);
+ }
+
+ // Check if the item already exists in the list
+ for (ModeList::iterator it = cd->list.begin(); it != cd->list.end(); it++)
+ {
+ if (parameter == it->mask)
+ {
+ /* Give a subclass a chance to error about this */
+ TellAlreadyOnList(source, channel, parameter);
+
+ // it does, deny the change
+ return MODEACTION_DENY;
+ }
+ }
+
+ if ((IS_LOCAL(source)) && (cd->list.size() >= GetLimitInternal(channel->name, cd)))
+ {
+ /* List is full, give subclass a chance to send a custom message */
+ TellListTooLong(source, channel, parameter);
+ parameter.clear();
+ return MODEACTION_DENY;
+ }
+
+ /* Ok, it *could* be allowed, now give someone subclassing us
+ * a chance to validate the parameter.
+ * The param is passed by reference, so they can both modify it
+ * and tell us if we allow it or not.
+ *
+ * eg, the subclass could:
+ * 1) allow
+ * 2) 'fix' parameter and then allow
+ * 3) deny
+ */
+ if (ValidateParam(source, channel, parameter))
+ {
+ // And now add the mask onto the list...
+ cd->list.push_back(ListItem(parameter, source->nick, ServerInstance->Time()));
+ return MODEACTION_ALLOW;
+ }
+ else
+ {
+ /* If they deny it they have the job of giving an error message */
+ return MODEACTION_DENY;
+ }
+ }
+ else
+ {
+ // We're taking the mode off
+ if (cd)
+ {
+ for (ModeList::iterator it = cd->list.begin(); it != cd->list.end(); ++it)
+ {
+ if (parameter == it->mask)
+ {
+ cd->list.erase(it);
+ return MODEACTION_ALLOW;
+ }
+ }
+ }
+
+ /* Tried to remove something that wasn't set */
+ TellNotSet(source, channel, parameter);
+ parameter.clear();
+ return MODEACTION_DENY;
+ }
+}
+
+void ListModeBase::DoSyncChannel(Channel* chan, Module* proto, void* opaque)
+{
+ ChanData* cd = extItem.get(chan);
+ if (!cd)
+ return;
+
+ irc::modestacker modestack(true);
+ std::vector<std::string> stackresult;
+ std::vector<TranslateType> types;
+ types.push_back(TR_TEXT);
+
+ for (ModeList::iterator it = cd->list.begin(); it != cd->list.end(); it++)
+ modestack.Push(mode, it->mask);
+
+ while (modestack.GetStackedLine(stackresult))
+ {
+ types.assign(stackresult.size(), this->GetTranslateType());
+ proto->ProtoSendMode(opaque, TYPE_CHANNEL, chan, stackresult, types);
+ stackresult.clear();
+ }
+}
+
+bool ListModeBase::ValidateParam(User*, Channel*, std::string&)
+{
+ return true;
+}
+
+void ListModeBase::TellListTooLong(User* source, Channel* channel, std::string& parameter)
+{
+ source->WriteNumeric(478, "%s %s %s :Channel ban list is full", source->nick.c_str(), channel->name.c_str(), parameter.c_str());
+}
+
+void ListModeBase::TellAlreadyOnList(User*, Channel*, std::string&)
+{
+}
+
+void ListModeBase::TellNotSet(User*, Channel*, std::string&)
+{
+}
#include "inspircd.h"
-
#include "filelogger.h"
/*
*
*/
+const char LogStream::LogHeader[] =
+ "Log started for " VERSION " (" REVISION ", " MODULE_INIT_STR ")"
+ " - compiled on " SYSTEM;
+
LogManager::LogManager()
{
Logging = false;
}
std::string type = tag->getString("type");
std::string level = tag->getString("level");
- int loglevel = DEFAULT;
+ LogLevel loglevel = LOG_DEFAULT;
if (level == "rawio")
{
- loglevel = RAWIO;
+ loglevel = LOG_RAWIO;
ServerInstance->Config->RawLog = true;
}
else if (level == "debug")
{
- loglevel = DEBUG;
+ loglevel = LOG_DEBUG;
}
else if (level == "verbose")
{
- loglevel = VERBOSE;
+ loglevel = LOG_VERBOSE;
}
else if (level == "default")
{
- loglevel = DEFAULT;
+ loglevel = LOG_DEFAULT;
}
else if (level == "sparse")
{
- loglevel = SPARSE;
+ loglevel = LOG_SPARSE;
}
else if (level == "none")
{
- loglevel = NONE;
+ loglevel = LOG_NONE;
}
FileWriter* fw;
std::string target = tag->getString("target");
fw = fwi->second;
}
FileLogStream* fls = new FileLogStream(loglevel, fw);
- fls->OnLog(SPARSE, "HEADER", InspIRCd::LogHeader);
+ fls->OnLog(LOG_SPARSE, "HEADER", LogStream::LogHeader);
AddLogTypes(type, fls, true);
}
}
{
if (ServerInstance->Config && ServerInstance->Config->cmdline.forcedebug)
return;
- std::map<std::string, std::vector<LogStream*> >().swap(LogStreams); /* Clear it */
- std::map<LogStream*, std::vector<std::string> >().swap(GlobalLogStreams); /* Clear it */
+
+ LogStreams.clear();
+ GlobalLogStreams.clear();
+
for (std::map<LogStream*, int>::iterator i = AllLogStreams.begin(); i != AllLogStreams.end(); ++i)
{
delete i->first;
}
- std::map<LogStream*, int>().swap(AllLogStreams); /* And clear it */
+
+ AllLogStreams.clear();
}
void LogManager::AddLogTypes(const std::string &types, LogStream* l, bool autoclose)
bool LogManager::AddLogType(const std::string &type, LogStream *l, bool autoclose)
{
- std::map<std::string, std::vector<LogStream *> >::iterator i = LogStreams.find(type);
-
- if (i != LogStreams.end())
- {
- i->second.push_back(l);
- }
- else
- {
- std::vector<LogStream *> v;
- v.push_back(l);
- LogStreams[type] = v;
- }
+ LogStreams[type].push_back(l);
if (type == "*")
- {
GlobalLogStreams.insert(std::make_pair(l, std::vector<std::string>()));
- }
if (autoclose)
- {
- std::map<LogStream*, int>::iterator ai = AllLogStreams.find(l);
- if (ai == AllLogStreams.end())
- {
- AllLogStreams.insert(std::make_pair(l, 1));
- }
- else
- {
- ++ai->second;
- }
- }
+ AllLogStreams[l]++;
return true;
}
std::vector<LogStream*>::iterator it;
while ((it = std::find(i->second.begin(), i->second.end(), l)) != i->second.end())
{
- if (it == i->second.end())
- continue;
i->second.erase(it);
}
}
- std::map<LogStream *, std::vector<std::string> >::iterator gi = GlobalLogStreams.find(l);
- if (gi != GlobalLogStreams.end())
- {
- GlobalLogStreams.erase(gi);
- }
+
+ GlobalLogStreams.erase(l);
+
std::map<LogStream*, int>::iterator ai = AllLogStreams.begin();
if (ai == AllLogStreams.end())
{
return; /* Done. */
}
+
delete ai->first;
AllLogStreams.erase(ai);
}
std::map<std::string, std::vector<LogStream *> >::iterator i = LogStreams.find(type);
if (type == "*")
{
- std::map<LogStream *, std::vector<std::string> >::iterator gi = GlobalLogStreams.find(l);
- if (gi != GlobalLogStreams.end()) GlobalLogStreams.erase(gi);
+ GlobalLogStreams.erase(l);
}
if (i != LogStreams.end())
return true;
}
-void LogManager::Log(const std::string &type, int loglevel, const char *fmt, ...)
+void LogManager::Log(const std::string &type, LogLevel loglevel, const char *fmt, ...)
{
if (Logging)
- {
return;
- }
-
- va_list a;
- static char buf[65536];
-
- va_start(a, fmt);
- vsnprintf(buf, 65536, fmt, a);
- va_end(a);
- this->Log(type, loglevel, std::string(buf));
+ std::string buf;
+ VAFORMAT(buf, fmt, fmt);
+ this->Log(type, loglevel, buf);
}
-void LogManager::Log(const std::string &type, int loglevel, const std::string &msg)
+void LogManager::Log(const std::string &type, LogLevel loglevel, const std::string &msg)
{
if (Logging)
{
// XXX: For now, just return. Don't throw an exception. It'd be nice to find out if this is happening, but I'm terrified of breaking so close to final release. -- w00t
// throw CoreException("FileWriter::WriteLogLine called with a closed logfile");
- fprintf(log,"%s",line.c_str());
- if (writeops++ % 20)
+ fputs(line.c_str(), log);
+ if (++writeops % 20 == 0)
{
fflush(log);
}
#include "inspircd.h"
-
-/* +s (secret) */
-/* +p (private) */
-/* +m (moderated) */
-/* +t (only (half) ops can change topic) */
-/* +n (no external messages) */
-/* +i (invite only) */
-/* +w (see wallops) */
-/* +i (invisible) */
-#include "modes/simplemodes.h"
-/* +b (bans) */
-#include "modes/cmode_b.h"
-/* +k (keyed channel) */
-#include "modes/cmode_k.h"
-/* +l (channel user limit) */
-#include "modes/cmode_l.h"
-/* +o (channel op) */
-#include "modes/cmode_o.h"
-/* +v (channel voice) */
-#include "modes/cmode_v.h"
-/* +o (operator) */
-#include "modes/umode_o.h"
-/* +s (server notice masks) */
-#include "modes/umode_s.h"
+#include "builtinmodes.h"
ModeHandler::ModeHandler(Module* Creator, const std::string& Name, char modeletter, ParamSpec Params, ModeType type)
: ServiceProvider(Creator, Name, SERVICE_MODE), m_paramtype(TR_TEXT),
{
}
-bool ModeHandler::IsListMode()
-{
- return list;
-}
-
unsigned int ModeHandler::GetPrefixRank()
{
return 0;
return true;
}
-ModeWatcher::ModeWatcher(Module* Creator, char modeletter, ModeType type)
- : mode(modeletter), m_type(type), creator(Creator)
+ModeWatcher::ModeWatcher(Module* Creator, const std::string& modename, ModeType type)
+ : mode(modename), m_type(type), creator(Creator)
{
}
{
}
-char ModeWatcher::GetModeChar()
-{
- return mode;
-}
-
ModeType ModeWatcher::GetModeType()
{
return m_type;
}
-bool ModeWatcher::BeforeMode(User*, User*, Channel*, std::string&, bool, ModeType)
+bool ModeWatcher::BeforeMode(User*, User*, Channel*, std::string&, bool)
{
return true;
}
-void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool, ModeType)
+void ModeWatcher::AfterMode(User*, User*, Channel*, const std::string&, bool)
{
}
-User* ModeParser::SanityChecks(User *user, const char *dest, Channel *chan, int)
-{
- User *d;
- if ((!user) || (!dest) || (!chan) || (!*dest))
- {
- return NULL;
- }
- d = ServerInstance->FindNick(dest);
- if (!d)
- {
- user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), dest);
- return NULL;
- }
- return d;
-}
-
void ModeParser::DisplayCurrentModes(User *user, User* targetuser, Channel* targetchannel, const char* text)
{
if (targetchannel)
{
/* Display user's current mode string */
user->WriteNumeric(RPL_UMODEIS, "%s :+%s",targetuser->nick.c_str(),targetuser->FormatModes());
- if (IS_OPER(targetuser))
+ if ((targetuser->IsOper()))
user->WriteNumeric(RPL_SNOMASKIS, "%s +%s :Server notice mask", targetuser->nick.c_str(), targetuser->FormatNoticeMasks());
return;
}
std::string ¶meter, bool SkipACL)
{
ModeType type = chan ? MODETYPE_CHANNEL : MODETYPE_USER;
- unsigned char mask = chan ? MASK_CHANNEL : MASK_USER;
ModeHandler *mh = FindMode(modechar, type);
int pcnt = mh->GetNumParams(adding);
}
}
- unsigned char handler_id = (modechar - 'A') | mask;
-
- for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
+ // Ask mode watchers whether this mode change is OK
+ std::pair<ModeWatchIter, ModeWatchIter> itpair = modewatchermap.equal_range(mh->name);
+ for (ModeWatchIter i = itpair.first; i != itpair.second; ++i)
{
- if ((*watchers)->BeforeMode(user, targetuser, chan, parameter, adding, type) == false)
- return MODEACTION_DENY;
- /* A module whacked the parameter completely, and there was one. abort. */
- if (pcnt && parameter.empty())
- return MODEACTION_DENY;
+ ModeWatcher* mw = i->second;
+ if (mw->GetModeType() == type)
+ {
+ if (!mw->BeforeMode(user, targetuser, chan, parameter, adding))
+ return MODEACTION_DENY;
+
+ // A module whacked the parameter completely, and there was one. Abort.
+ if (pcnt && parameter.empty())
+ return MODEACTION_DENY;
+ }
}
- if (IS_LOCAL(user) && !IS_OPER(user))
+ if (IS_LOCAL(user) && !user->IsOper())
{
char* disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes;
if (disabled[modechar - 'A'])
if (adding && IS_LOCAL(user) && mh->NeedsOper() && !user->HasModePermission(modechar, type))
{
/* It's an oper only mode, and they don't have access to it. */
- if (IS_OPER(user))
+ if (user->IsOper())
{
user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c",
- user->nick.c_str(), user->oper->NameStr(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
+ user->nick.c_str(), user->oper->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
}
else
{
if (ma != MODEACTION_ALLOW)
return ma;
- for (ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
- (*watchers)->AfterMode(user, targetuser, chan, parameter, adding, type);
+ itpair = modewatchermap.equal_range(mh->name);
+ for (ModeWatchIter i = itpair.first; i != itpair.second; ++i)
+ {
+ ModeWatcher* mw = i->second;
+ if (mw->GetModeType() == type)
+ mw->AfterMode(user, targetuser, chan, parameter, adding);
+ }
return MODEACTION_ALLOW;
}
display = false;
}
- unsigned char handler_id = (mletter - 'A') | MASK_CHANNEL;
-
- for(ModeWatchIter watchers = modewatchers[handler_id].begin(); watchers != modewatchers[handler_id].end(); watchers++)
+ // Ask mode watchers whether it's OK to show the list
+ std::pair<ModeWatchIter, ModeWatchIter> itpair = modewatchermap.equal_range(mh->name);
+ for (ModeWatchIter i = itpair.first; i != itpair.second; ++i)
{
- std::string dummyparam;
+ ModeWatcher* mw = i->second;
+ if (mw->GetModeType() == MODETYPE_CHANNEL)
+ {
+ std::string dummyparam;
- if (!((*watchers)->BeforeMode(user, NULL, chan, dummyparam, true, MODETYPE_CHANNEL)))
- display = false;
+ if (!mw->BeforeMode(user, NULL, chan, dummyparam, true))
+ {
+ // A mode watcher doesn't want us to show the list
+ display = false;
+ break;
+ }
+ }
}
+
if (display)
mh->DisplayList(user, chan);
else
}
}
-const std::string& ModeParser::GetLastParse()
-{
- return LastParse;
-}
-
void ModeParser::CleanMask(std::string &mask)
{
std::string::size_type pos_of_pling = mask.find_first_of('!');
return false;
modehandlers[pos] = mh;
+ RecreateModeListFor004Numeric();
return true;
}
// The channel may not be in the hash after RemoveMode(), see m_permchannels
Channel* chan = i->second;
++i;
- mh->RemoveMode(chan);
+
+ irc::modestacker stack(false);
+ mh->RemoveMode(chan, stack);
+
+ std::vector<std::string> stackresult;
+ stackresult.push_back(chan->name);
+ while (stack.GetStackedLine(stackresult))
+ {
+ ServerInstance->SendMode(stackresult, ServerInstance->FakeClient);
+ stackresult.erase(stackresult.begin() + 1, stackresult.end());
+ }
}
break;
}
modehandlers[pos] = NULL;
+ RecreateModeListFor004Numeric();
return true;
}
return modehandlers[pos];
}
-std::string ModeParser::UserModeList()
+std::string ModeParser::CreateModeList(ModeType mt, bool needparam)
{
- char modestr[256];
- int pointer = 0;
+ std::string modestr;
+ unsigned char mask = ((mt == MODETYPE_CHANNEL) ? MASK_CHANNEL : MASK_USER);
for (unsigned char mode = 'A'; mode <= 'z'; mode++)
{
- unsigned char pos = (mode-65) | MASK_USER;
+ unsigned char pos = (mode-65) | mask;
- if (modehandlers[pos])
- modestr[pointer++] = mode;
+ if ((modehandlers[pos]) && ((!needparam) || (modehandlers[pos]->GetNumParams(true))))
+ modestr.push_back(mode);
}
- modestr[pointer++] = 0;
- return modestr;
-}
-std::string ModeParser::ChannelModeList()
-{
- char modestr[256];
- int pointer = 0;
-
- for (unsigned char mode = 'A'; mode <= 'z'; mode++)
- {
- unsigned char pos = (mode-65) | MASK_CHANNEL;
-
- if (modehandlers[pos])
- modestr[pointer++] = mode;
- }
- modestr[pointer++] = 0;
return modestr;
}
-std::string ModeParser::ParaModeList()
+void ModeParser::RecreateModeListFor004Numeric()
{
- char modestr[256];
- int pointer = 0;
-
- for (unsigned char mode = 'A'; mode <= 'z'; mode++)
- {
- unsigned char pos = (mode-65) | MASK_CHANNEL;
-
- if ((modehandlers[pos]) && (modehandlers[pos]->GetNumParams(true)))
- modestr[pointer++] = mode;
- }
- modestr[pointer++] = 0;
- return modestr;
+ Cached004ModeList = CreateModeList(MODETYPE_USER) + " " + CreateModeList(MODETYPE_CHANNEL) + " " + CreateModeList(MODETYPE_CHANNEL, true);
}
ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
return lettersAndModes ? "(" + mprefixes + ")" + mletters : mletters;
}
-bool ModeParser::AddModeWatcher(ModeWatcher* mw)
+void ModeParser::AddModeWatcher(ModeWatcher* mw)
{
- unsigned char mask = 0;
- unsigned char pos = 0;
-
- if (!mw)
- return false;
-
- if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
- return false;
-
- mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
- pos = (mw->GetModeChar()-65) | mask;
-
- modewatchers[pos].push_back(mw);
-
- return true;
+ modewatchermap.insert(std::make_pair(mw->GetModeName(), mw));
}
bool ModeParser::DelModeWatcher(ModeWatcher* mw)
{
- unsigned char mask = 0;
- unsigned char pos = 0;
-
- if (!mw)
- return false;
-
- if ((mw->GetModeChar() < 'A') || (mw->GetModeChar() > 'z'))
- return false;
-
- mw->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
- pos = (mw->GetModeChar()-65) | mask;
-
- ModeWatchIter a = find(modewatchers[pos].begin(),modewatchers[pos].end(),mw);
-
- if (a == modewatchers[pos].end())
+ std::pair<ModeWatchIter, ModeWatchIter> itpair = modewatchermap.equal_range(mw->GetModeName());
+ for (ModeWatchIter i = itpair.first; i != itpair.second; ++i)
{
- return false;
+ if (i->second == mw)
+ {
+ modewatchermap.erase(i);
+ return true;
+ }
}
- modewatchers[pos].erase(a);
-
- return true;
+ return false;
}
-/** This default implementation can remove simple user modes
- */
-void ModeHandler::RemoveMode(User* user, irc::modestacker* stack)
+void ModeHandler::RemoveMode(User* user)
{
+ // Remove the mode if it's set on the user
if (user->IsModeSet(this->GetModeChar()))
{
- if (stack)
- {
- stack->Push(this->GetModeChar());
- }
- else
- {
- std::vector<std::string> parameters;
- parameters.push_back(user->nick);
- parameters.push_back("-");
- parameters[1].push_back(this->GetModeChar());
- ServerInstance->Modes->Process(parameters, ServerInstance->FakeClient);
- }
+ std::vector<std::string> parameters;
+ parameters.push_back(user->nick);
+ parameters.push_back("-");
+ parameters[1].push_back(this->GetModeChar());
+ ServerInstance->Modes->Process(parameters, ServerInstance->FakeClient);
}
}
-/** This default implementation can remove simple channel modes
- * (no parameters)
- */
-void ModeHandler::RemoveMode(Channel* channel, irc::modestacker* stack)
+void ModeHandler::RemoveMode(Channel* channel, irc::modestacker& stack)
{
- if (channel->IsModeSet(this->GetModeChar()))
+ if (this->GetPrefixRank())
{
- if (stack)
- {
- stack->Push(this->GetModeChar());
- }
+ RemovePrefixMode(channel, stack);
+ }
+ else if (channel->IsModeSet(this->GetModeChar()))
+ {
+ if (this->GetNumParams(false))
+ // Removing this mode requires a parameter
+ stack.Push(this->GetModeChar(), channel->GetModeParameter(this->GetModeChar()));
else
- {
- std::vector<std::string> parameters;
- parameters.push_back(channel->name);
- parameters.push_back("-");
- parameters[1].push_back(this->GetModeChar());
- ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
- }
+ stack.Push(this->GetModeChar());
+ }
+}
+
+void ModeHandler::RemovePrefixMode(Channel* chan, irc::modestacker& stack)
+{
+ const UserMembList* userlist = chan->GetUsers();
+ for (UserMembCIter i = userlist->begin(); i != userlist->end(); ++i)
+ {
+ if (i->second->hasMode(this->GetModeChar()))
+ stack.Push(this->GetModeChar(), i->first->nick);
}
}
ModeUserOperator uo;
ModeUserServerNoticeMask us;
- void init(ModeParser* modes)
- {
- modes->AddMode(&s);
- modes->AddMode(&p);
- modes->AddMode(&m);
- modes->AddMode(&t);
- modes->AddMode(&n);
- modes->AddMode(&i);
- modes->AddMode(&k);
- modes->AddMode(&l);
- modes->AddMode(&b);
- modes->AddMode(&o);
- modes->AddMode(&v);
- modes->AddMode(&uw);
- modes->AddMode(&ui);
- modes->AddMode(&uo);
- modes->AddMode(&us);
+ void init()
+ {
+ ServiceProvider* modes[] = { &s, &p, &m, &t, &n, &i, &k, &l, &b, &o, &v,
+ &uw, &ui, &uo, &us };
+ ServerInstance->Modules->AddServices(modes, sizeof(modes)/sizeof(ServiceProvider*));
}
};
static builtin_modes static_modes;
+void ModeParser::InitBuiltinModes()
+{
+ static_modes.init();
+ static_modes.b.DoRehash();
+}
+
ModeParser::ModeParser()
{
/* Clear mode handler list */
seq = 0;
memset(&sent, 0, sizeof(sent));
-
- static_modes.init(this);
}
ModeParser::~ModeParser()
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
- * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
- *
- * This file is part of InspIRCd. InspIRCd is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "inspircd.h"
-#include <string>
-#include <vector>
-#include "inspircd_config.h"
-#include "configreader.h"
-#include "hash_map.h"
-#include "mode.h"
-#include "channels.h"
-#include "users.h"
-#include "modules.h"
-#include "inspstring.h"
-#include "hashcomp.h"
-#include "modes/cmode_b.h"
-
-ModeChannelBan::ModeChannelBan() : ModeHandler(NULL, "ban", 'b', PARAM_ALWAYS, MODETYPE_CHANNEL)
-{
- list = true;
-}
-
-ModeAction ModeChannelBan::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding)
-{
- int status = channel->GetPrefixValue(source);
- /* Call the correct method depending on wether we're adding or removing the mode */
- if (adding)
- {
- this->AddBan(source, parameter, channel, status);
- }
- else
- {
- this->DelBan(source, parameter, channel, status);
- }
- /* If the method above 'ate' the parameter by reducing it to an empty string, then
- * it won't matter wether we return ALLOW or DENY here, as an empty string overrides
- * the return value and is always MODEACTION_DENY if the mode is supposed to have
- * a parameter.
- */
- return MODEACTION_ALLOW;
-}
-
-void ModeChannelBan::RemoveMode(Channel* channel, irc::modestacker* stack)
-{
- BanList copy;
-
- for (BanList::iterator i = channel->bans.begin(); i != channel->bans.end(); i++)
- {
- copy.push_back(*i);
- }
-
- for (BanList::iterator i = copy.begin(); i != copy.end(); i++)
- {
- if (stack)
- {
- stack->Push(this->GetModeChar(), i->data);
- }
- else
- {
- std::vector<std::string> parameters; parameters.push_back(channel->name); parameters.push_back("-b"); parameters.push_back(i->data);
- ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
- }
- }
-}
-
-void ModeChannelBan::RemoveMode(User*, irc::modestacker* stack)
-{
-}
-
-void ModeChannelBan::DisplayList(User* user, Channel* channel)
-{
- /* Display the channel banlist */
- for (BanList::reverse_iterator i = channel->bans.rbegin(); i != channel->bans.rend(); ++i)
- {
- user->WriteServ("367 %s %s %s %s %lu",user->nick.c_str(), channel->name.c_str(), i->data.c_str(), i->set_by.c_str(), (unsigned long)i->set_time);
- }
- user->WriteServ("368 %s %s :End of channel ban list",user->nick.c_str(), channel->name.c_str());
- return;
-}
-
-void ModeChannelBan::DisplayEmptyList(User* user, Channel* channel)
-{
- user->WriteServ("368 %s %s :End of channel ban list",user->nick.c_str(), channel->name.c_str());
-}
-
-std::string& ModeChannelBan::AddBan(User *user, std::string &dest, Channel *chan, int)
-{
- if ((!user) || (!chan))
- {
- ServerInstance->Logs->Log("MODE",DEFAULT,"*** BUG *** AddBan was given an invalid parameter");
- dest.clear();
- return dest;
- }
-
- /* Attempt to tidy the mask */
- ModeParser::CleanMask(dest);
- /* If the mask was invalid, we exit */
- if (dest.empty() || dest.length() > 250)
- return dest;
-
- long maxbans = chan->GetMaxBans();
- if (IS_LOCAL(user) && ((unsigned)chan->bans.size() >= (unsigned)maxbans))
- {
- user->WriteServ("478 %s %s :Channel ban list for %s is full (maximum entries for this channel is %ld)",user->nick.c_str(), chan->name.c_str(), chan->name.c_str(), maxbans);
- dest.clear();
- return dest;
- }
-
- ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnAddBan, MOD_RESULT, (user,chan,dest));
- if (MOD_RESULT == MOD_RES_DENY)
- {
- dest.clear();
- return dest;
- }
-
- for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
- {
- if (i->data == dest)
- {
- /* dont allow a user to set the same ban twice */
- dest.clear();
- return dest;
- }
- }
-
- b.set_time = ServerInstance->Time();
- b.data.assign(dest, 0, MAXBUF);
- b.set_by.assign(user->nick, 0, 64);
- chan->bans.push_back(b);
- return dest;
-}
-
-std::string& ModeChannelBan::DelBan(User *user, std::string& dest, Channel *chan, int)
-{
- if ((!user) || (!chan))
- {
- ServerInstance->Logs->Log("MODE",DEFAULT,"*** BUG *** TakeBan was given an invalid parameter");
- dest.clear();
- return dest;
- }
-
- for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
- {
- if (!strcasecmp(i->data.c_str(), dest.c_str()))
- {
- ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnDelBan, MOD_RESULT, (user, chan, dest));
- if (MOD_RESULT == MOD_RES_DENY)
- {
- dest.clear();
- return dest;
- }
- chan->bans.erase(i);
- return dest;
- }
- }
- dest.clear();
- return dest;
-}
-
#include "mode.h"
#include "channels.h"
#include "users.h"
-#include "modes/cmode_k.h"
+#include "builtinmodes.h"
ModeChannelKey::ModeChannelKey() : ModeHandler(NULL, "key", 'k', PARAM_ALWAYS, MODETYPE_CHANNEL)
{
}
-void ModeChannelKey::RemoveMode(Channel* channel, irc::modestacker* stack)
-{
- /** +k needs a parameter when being removed,
- * so we have a special-case RemoveMode here for it
- */
-
- if (channel->IsModeSet('k'))
- {
- if (stack)
- {
- stack->Push('k', channel->GetModeParameter('k'));
- }
- else
- {
- std::vector<std::string> parameters;
- parameters.push_back(channel->name);
- parameters.push_back("-k");
- parameters.push_back(channel->GetModeParameter('k'));
- ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
- }
- }
-}
-
-void ModeChannelKey::RemoveMode(User*, irc::modestacker* stack)
-{
-}
-
ModeAction ModeChannelKey::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding)
{
bool exists = channel->IsModeSet('k');
#include "mode.h"
#include "channels.h"
#include "users.h"
-#include "modes/cmode_l.h"
+#include "builtinmodes.h"
ModeChannelLimit::ModeChannelLimit() : ParamChannelModeHandler(NULL, "limit", 'l')
{
#include "channels.h"
#include "users.h"
#include "modules.h"
-#include "modes/cmode_o.h"
+#include "builtinmodes.h"
ModeChannelOp::ModeChannelOp() : ModeHandler(NULL, "op", 'o', PARAM_ALWAYS, MODETYPE_CHANNEL)
{
return OP_VALUE;
}
-void ModeChannelOp::RemoveMode(Channel* channel, irc::modestacker* stack)
-{
- const UserMembList* clist = channel->GetUsers();
-
- for (UserMembCIter i = clist->begin(); i != clist->end(); i++)
- {
- if (stack)
- stack->Push(this->GetModeChar(), i->first->nick);
- else
- {
- std::vector<std::string> parameters;
- parameters.push_back(channel->name);
- parameters.push_back("-o");
- parameters.push_back(i->first->nick);
- ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
- }
- }
-}
-
-void ModeChannelOp::RemoveMode(User*, irc::modestacker* stack)
-{
-}
-
ModeAction ModeChannelOp::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding)
{
return MODEACTION_ALLOW;
#include "channels.h"
#include "users.h"
#include "modules.h"
-#include "modes/cmode_v.h"
+#include "builtinmodes.h"
ModeChannelVoice::ModeChannelVoice() : ModeHandler(NULL, "voice", 'v', PARAM_ALWAYS, MODETYPE_CHANNEL)
{
return VOICE_VALUE;
}
-void ModeChannelVoice::RemoveMode(Channel* channel, irc::modestacker* stack)
-{
- const UserMembList* clist = channel->GetUsers();
-
- for (UserMembCIter i = clist->begin(); i != clist->end(); i++)
- {
- if (stack)
- stack->Push(this->GetModeChar(), i->first->nick);
- else
- {
- std::vector<std::string> parameters;
- parameters.push_back(channel->name);
- parameters.push_back("-v");
- parameters.push_back(i->first->nick);
- ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
- }
- }
-}
-
-void ModeChannelVoice::RemoveMode(User*, irc::modestacker* stack)
-{
-}
-
ModeAction ModeChannelVoice::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding)
{
return MODEACTION_ALLOW;
#include "mode.h"
#include "channels.h"
#include "users.h"
-#include "modes/umode_o.h"
+#include "builtinmodes.h"
ModeUserOperator::ModeUserOperator() : ModeHandler(NULL, "oper", 'o', PARAM_NONE, MODETYPE_USER)
{
ModeAction ModeUserOperator::OnModeChange(User* source, User* dest, Channel*, std::string&, bool adding)
{
/* Only opers can execute this class at all */
- if (!ServerInstance->ULine(source->server) && !IS_OPER(source))
+ if (!ServerInstance->ULine(source->server) && !source->IsOper())
return MODEACTION_DENY;
/* Not even opers can GIVE the +o mode, only take it away */
#include "mode.h"
#include "channels.h"
#include "users.h"
-#include "modes/umode_s.h"
+#include "builtinmodes.h"
ModeUserServerNoticeMask::ModeUserServerNoticeMask() : ModeHandler(NULL, "snomask", 's', PARAM_SETONLY, MODETYPE_USER)
{
void ModeUserServerNoticeMask::OnParameterMissing(User* user, User* dest, Channel* channel)
{
- user->WriteServ("NOTICE %s :*** The user mode +s requires a parameter (server notice mask). Please provide a parameter, e.g. '+s +*'.",
- user->nick.c_str());
+ user->WriteNotice("*** The user mode +s requires a parameter (server notice mask). Please provide a parameter, e.g. '+s +*'.");
}
-
#include "socket.h"
#include "socketengine.h"
#include "command_parse.h"
-#include "dns.h"
#include "exitcodes.h"
#include <iostream>
if (filename.find('/') != std::string::npos)
return false;
- char modfile[MAXBUF];
- snprintf(modfile,MAXBUF,"%s/%s",ServerInstance->Config->ModPath.c_str(),filename.c_str());
+ const std::string moduleFile = ServerInstance->Config->ModPath + "/" + filename;
- if (!ServerConfig::FileExists(modfile))
+ if (!ServerConfig::FileExists(moduleFile.c_str()))
{
LastModuleError = "Module file could not be found: " + filename;
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
return false;
}
if (Modules.find(filename) != Modules.end())
{
LastModuleError = "Module " + filename + " is already loaded, cannot load a module twice!";
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
return false;
}
Module* newmod = NULL;
- DLLManager* newhandle = new DLLManager(modfile);
+ DLLManager* newhandle = new DLLManager(moduleFile.c_str());
try
{
std::string version = newhandle->GetVersion();
if (defer)
{
- ServerInstance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s (Module version %s)",
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "New module introduced: %s (Module version %s)",
filename.c_str(), version.c_str());
}
else
newmod->init();
Version v = newmod->GetVersion();
- ServerInstance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s (Module version %s)%s",
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "New module introduced: %s (Module version %s)%s",
filename.c_str(), version.c_str(), (!(v.Flags & VF_VENDOR) ? " [3rd Party]" : " [Vendor]"));
}
}
else
{
LastModuleError = "Unable to load " + filename + ": " + newhandle->LastError();
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
delete newhandle;
return false;
}
else
delete newhandle;
LastModuleError = "Unable to load " + filename + ": " + modexcept.GetReason();
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
return false;
}
if (prioritizationState == PRIO_STATE_LAST)
break;
if (tries == 19)
- ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected while loading " + filename);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Hook priority dependency loop detected while loading " + filename);
}
- ServerInstance->BuildISupport();
+ ServerInstance->ISupport.Build();
return true;
}
if (!Load(entry->d_name, true))
{
- ServerInstance->Logs->Log("MODULE", DEFAULT, this->LastError());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, this->LastError());
std::cout << std::endl << "[" << con_red << "*" << con_reset << "] " << this->LastError() << std::endl << std::endl;
ServerInstance->Exit(EXIT_STATUS_MODULE);
}
if (!this->Load(name, true))
{
- ServerInstance->Logs->Log("MODULE", DEFAULT, this->LastError());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, this->LastError());
std::cout << std::endl << "[" << con_red << "*" << con_reset << "] " << this->LastError() << std::endl << std::endl;
ServerInstance->Exit(EXIT_STATUS_MODULE);
}
Module* mod = i->second;
try
{
- ServerInstance->Logs->Log("MODULE", DEBUG, "Initializing %s", i->first.c_str());
+ ServerInstance->Logs->Log("MODULE", LOG_DEBUG, "Initializing %s", i->first.c_str());
mod->init();
}
catch (CoreException& modexcept)
{
LastModuleError = "Unable to initialize " + mod->ModuleSourceFile + ": " + modexcept.GetReason();
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
std::cout << std::endl << "[" << con_red << "*" << con_reset << "] " << LastModuleError << std::endl << std::endl;
ServerInstance->Exit(EXIT_STATUS_MODULE);
}
break;
if (tries == 19)
{
- ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected");
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Hook priority dependency loop detected");
ServerInstance->Exit(EXIT_STATUS_MODULE);
}
}
Modules[name] = mod;
if (defer)
{
- ServerInstance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s", name.c_str());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "New module introduced: %s", name.c_str());
return true;
}
else
{
if (mod)
DoSafeUnload(mod);
- ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + name + ": " + modexcept.GetReason());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Unable to load " + name + ": " + modexcept.GetReason());
return false;
}
FOREACH_MOD(I_OnLoadModule,OnLoadModule(mod));
if (prioritizationState == PRIO_STATE_LAST)
break;
if (tries == 19)
- ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected while loading " + name);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Hook priority dependency loop detected while loading " + name);
}
- ServerInstance->BuildISupport();
+ ServerInstance->ISupport.Build();
return true;
}
if (!this->Load(name, true))
{
- ServerInstance->Logs->Log("MODULE", DEFAULT, this->LastError());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, this->LastError());
std::cout << std::endl << "[" << con_red << "*" << con_reset << "] " << this->LastError() << std::endl << std::endl;
ServerInstance->Exit(EXIT_STATUS_MODULE);
}
for(std::map<std::string, Module*>::iterator i = Modules.begin(); i != Modules.end(); i++)
{
Module* mod = i->second;
- try
+ try
{
mod->init();
}
catch (CoreException& modexcept)
{
LastModuleError = "Unable to initialize " + mod->ModuleSourceFile + ": " + modexcept.GetReason();
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
std::cout << std::endl << "[" << con_red << "*" << con_reset << "] " << LastModuleError << std::endl << std::endl;
ServerInstance->Exit(EXIT_STATUS_MODULE);
}
break;
if (tries == 19)
{
- ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected");
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Hook priority dependency loop detected");
ServerInstance->Exit(EXIT_STATUS_MODULE);
}
}
*/
+#include <fstream>
#include "inspircd.h"
#include "xline.h"
#include "socket.h"
#include "socketengine.h"
#include "command_parse.h"
-#include "dns.h"
#include "exitcodes.h"
#ifndef _WIN32
#endif
static std::vector<dynamic_reference_base*>* dynrefs = NULL;
+static bool dynref_init_complete = false;
void dynamic_reference_base::reset_all()
{
+ dynref_init_complete = true;
if (!dynrefs)
return;
for(unsigned int i = 0; i < dynrefs->size(); i++)
- (*dynrefs)[i]->ClearCache();
+ (*dynrefs)[i]->resolve();
}
// Version is a simple class for holding a modules version number
void Module::OnPreRehash(User*, const std::string&) { }
void Module::OnModuleRehash(User*, const std::string&) { }
void Module::OnRehash(User*) { }
-ModResult Module::OnUserPreJoin(User*, Channel*, const char*, std::string&, const std::string&) { return MOD_RES_PASSTHRU; }
+ModResult Module::OnUserPreJoin(LocalUser*, Channel*, const std::string&, std::string&, const std::string&) { return MOD_RES_PASSTHRU; }
void Module::OnMode(User*, void*, int, const std::vector<std::string>&, const std::vector<TranslateType>&) { }
void Module::OnOper(User*, const std::string&) { }
void Module::OnPostOper(User*, const std::string&, const std::string &) { }
void Module::OnInfo(User*) { }
void Module::OnWhois(User*, User*) { }
ModResult Module::OnUserPreInvite(User*, User*, Channel*, time_t) { return MOD_RES_PASSTHRU; }
-ModResult Module::OnUserPreMessage(User*, void*, int, std::string&, char, CUList&) { return MOD_RES_PASSTHRU; }
-ModResult Module::OnUserPreNotice(User*, void*, int, std::string&, char, CUList&) { return MOD_RES_PASSTHRU; }
+ModResult Module::OnUserPreMessage(User*, void*, int, std::string&, char, CUList&, MessageType) { return MOD_RES_PASSTHRU; }
ModResult Module::OnUserPreNick(User*, const std::string&) { return MOD_RES_PASSTHRU; }
void Module::OnUserPostNick(User*, const std::string&) { }
ModResult Module::OnPreMode(User*, User*, Channel*, const std::vector<std::string>&) { return MOD_RES_PASSTHRU; }
-void Module::On005Numeric(std::string&) { }
+void Module::On005Numeric(std::map<std::string, std::string>&) { }
ModResult Module::OnKill(User*, User*, const std::string&) { return MOD_RES_PASSTHRU; }
void Module::OnLoadModule(Module*) { }
void Module::OnUnloadModule(Module*) { }
ModResult Module::OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype) { return MOD_RES_PASSTHRU; }
void Module::OnGlobalOper(User*) { }
void Module::OnPostConnect(User*) { }
-ModResult Module::OnAddBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; }
-ModResult Module::OnDelBan(User*, Channel*, const std::string &) { return MOD_RES_PASSTHRU; }
void Module::OnStreamSocketAccept(StreamSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { }
int Module::OnStreamSocketWrite(StreamSocket*, std::string&) { return -1; }
void Module::OnStreamSocketClose(StreamSocket*) { }
void Module::OnStreamSocketConnect(StreamSocket*) { }
int Module::OnStreamSocketRead(StreamSocket*, std::string&) { return -1; }
-void Module::OnUserMessage(User*, void*, int, const std::string&, char, const CUList&) { }
-void Module::OnUserNotice(User*, void*, int, const std::string&, char, const CUList&) { }
+void Module::OnUserMessage(User*, void*, int, const std::string&, char, const CUList&, MessageType) { }
void Module::OnRemoteKill(User*, User*, const std::string&, const std::string&) { }
void Module::OnUserInvite(User*, User*, Channel*, time_t) { }
void Module::OnPostTopicChange(User*, Channel*, const std::string&) { }
void Module::ProtoSendMode(void*, TargetTypeFlags, void*, const std::vector<std::string>&, const std::vector<TranslateType>&) { }
void Module::OnDecodeMetaData(Extensible*, const std::string&, const std::string&) { }
void Module::ProtoSendMetaData(void*, Extensible*, const std::string&, const std::string&) { }
-void Module::OnWallops(User*, const std::string&) { }
void Module::OnChangeHost(User*, const std::string&) { }
void Module::OnChangeName(User*, const std::string&) { }
void Module::OnChangeIdent(User*, const std::string&) { }
if ((modfind == Modules.end()) || (modfind->second != mod) || (mod->dying))
{
LastModuleError = "Module " + mod->ModuleSourceFile + " is not loaded, cannot unload it!";
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
return false;
}
if (mod->GetVersion().Flags & VF_STATIC)
{
LastModuleError = "Module " + mod->ModuleSourceFile + " not unloadable (marked static)";
- ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, LastModuleError);
return false;
}
void ModuleManager::DoSafeUnload(Module* mod)
{
+ // First, notify all modules that a module is about to be unloaded, so in case
+ // they pass execution to the soon to be unloaded module, it will happen now,
+ // i.e. before we unregister the services of the module being unloaded
+ FOREACH_MOD(I_OnUnloadModule,OnUnloadModule(mod));
+
std::map<std::string, Module*>::iterator modfind = Modules.find(mod->ModuleSourceFile);
std::vector<reference<ExtensionItem> > items;
ModeHandler* mh;
mh = ServerInstance->Modes->FindMode(m, MODETYPE_USER);
if (mh && mh->creator == mod)
- ServerInstance->Modes->DelMode(mh);
+ this->DelService(*mh);
mh = ServerInstance->Modes->FindMode(m, MODETYPE_CHANNEL);
if (mh && mh->creator == mod)
- ServerInstance->Modes->DelMode(mh);
+ this->DelService(*mh);
}
for(std::multimap<std::string, ServiceProvider*>::iterator i = DataProviders.begin(); i != DataProviders.end(); )
{
dynamic_reference_base::reset_all();
- /* Tidy up any dangling resolvers */
- ServerInstance->Res->CleanResolvers(mod);
-
- FOREACH_MOD(I_OnUnloadModule,OnUnloadModule(mod));
-
DetachAll(mod);
Modules.erase(modfind);
ServerInstance->GlobalCulls.AddItem(mod);
- ServerInstance->Logs->Log("MODULE", DEFAULT,"Module %s unloaded",mod->ModuleSourceFile.c_str());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Module %s unloaded",mod->ModuleSourceFile.c_str());
this->ModCount--;
- ServerInstance->BuildISupport();
+ ServerInstance->ISupport.Build();
}
void ModuleManager::UnloadAll()
return LastModuleError;
}
-CmdResult InspIRCd::CallCommandHandler(const std::string &commandname, const std::vector<std::string>& parameters, User* user)
-{
- return this->Parser->CallHandler(commandname, parameters, user);
-}
-
-bool InspIRCd::IsValidModuleCommand(const std::string &commandname, int pcnt, User* user)
-{
- return this->Parser->IsValidCommand(commandname, pcnt, user);
-}
-
void ModuleManager::AddService(ServiceProvider& item)
{
switch (item.service)
case SERVICE_MODE:
if (!ServerInstance->Modes->AddMode(static_cast<ModeHandler*>(&item)))
throw ModuleException("Mode "+std::string(item.name)+" already exists.");
+ DataProviders.insert(std::make_pair("mode/" + item.name, &item));
+ dynamic_reference_base::reset_all();
return;
case SERVICE_METADATA:
if (!ServerInstance->Extensions.Register(static_cast<ExtensionItem*>(&item)))
case SERVICE_DATA:
case SERVICE_IOHOOK:
{
+ if (item.name.substr(0, 5) == "mode/")
+ throw ModuleException("The \"mode/\" service name prefix is reserved.");
+
DataProviders.insert(std::make_pair(item.name, &item));
std::string::size_type slash = item.name.find('/');
if (slash != std::string::npos)
DataProviders.insert(std::make_pair(item.name.substr(0, slash), &item));
DataProviders.insert(std::make_pair(item.name.substr(slash + 1), &item));
}
+ dynamic_reference_base::reset_all();
return;
}
default:
case SERVICE_MODE:
if (!ServerInstance->Modes->DelMode(static_cast<ModeHandler*>(&item)))
throw ModuleException("Mode "+std::string(item.name)+" does not exist.");
- return;
+ // Fall through
case SERVICE_DATA:
case SERVICE_IOHOOK:
{
if (!dynrefs)
dynrefs = new std::vector<dynamic_reference_base*>;
dynrefs->push_back(this);
+ if (dynref_init_complete)
+ resolve();
}
dynamic_reference_base::~dynamic_reference_base()
void dynamic_reference_base::SetProvider(const std::string& newname)
{
name = newname;
- ClearCache();
-}
-
-void dynamic_reference_base::lookup()
-{
- if (!*this)
- throw ModuleException("Dynamic reference to '" + name + "' failed to resolve");
-}
-
-dynamic_reference_base::operator bool()
-{
- if (!value)
- {
- std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.find(name);
- if (i != ServerInstance->Modules->DataProviders.end())
- value = static_cast<DataProvider*>(i->second);
- }
- return (value != NULL);
+ resolve();
}
-void InspIRCd::SendMode(const std::vector<std::string>& parameters, User *user)
+void dynamic_reference_base::resolve()
{
- this->Modes->Process(parameters, user);
+ std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.find(name);
+ if (i != ServerInstance->Modules->DataProviders.end())
+ value = static_cast<DataProvider*>(i->second);
+ else
+ value = NULL;
}
-
void InspIRCd::SendGlobalMode(const std::vector<std::string>& parameters, User *user)
{
Modes->Process(parameters, user);
this->PI->SendMode(parameters[0], Modes->GetLastParseParams(), Modes->GetLastParseTranslate());
}
-bool InspIRCd::AddResolver(Resolver* r, bool cached)
-{
- if (!cached)
- return this->Res->AddResolverClass(r);
- else
- {
- r->TriggerCachedResult();
- delete r;
- return true;
- }
-}
-
Module* ModuleManager::Find(const std::string &name)
{
std::map<std::string, Module*>::iterator modfind = Modules.find(name);
return retval;
}
-ConfigReader::ConfigReader()
+FileReader::FileReader(const std::string& filename)
{
- this->error = 0;
- ServerInstance->Logs->Log("MODULE", DEBUG, "ConfigReader is deprecated in 2.0; "
- "use ServerInstance->Config->ConfValue(\"key\") or ->ConfTags(\"key\") instead");
+ Load(filename);
}
-
-ConfigReader::~ConfigReader()
+void FileReader::Load(const std::string& filename)
{
-}
-
-static ConfigTag* SlowGetTag(const std::string &tag, int index)
-{
- ConfigTagList tags = ServerInstance->Config->ConfTags(tag);
- while (tags.first != tags.second)
+ // If the file is stored in the file cache then we used that version instead.
+ ConfigFileCache::iterator it = ServerInstance->Config->Files.find(filename);
+ if (it != ServerInstance->Config->Files.end())
{
- if (!index)
- return tags.first->second;
- tags.first++;
- index--;
+ this->lines = it->second;
}
- return NULL;
-}
-
-std::string ConfigReader::ReadValue(const std::string &tag, const std::string &name, const std::string &default_value, int index, bool allow_linefeeds)
-{
- std::string result = default_value;
- if (!SlowGetTag(tag, index)->readString(name, result, allow_linefeeds))
- {
- this->error = CONF_VALUE_NOT_FOUND;
- }
- return result;
-}
-
-std::string ConfigReader::ReadValue(const std::string &tag, const std::string &name, int index, bool allow_linefeeds)
-{
- return ReadValue(tag, name, "", index, allow_linefeeds);
-}
-
-bool ConfigReader::ReadFlag(const std::string &tag, const std::string &name, const std::string &default_value, int index)
-{
- bool def = (default_value == "yes");
- return SlowGetTag(tag, index)->getBool(name, def);
-}
-
-bool ConfigReader::ReadFlag(const std::string &tag, const std::string &name, int index)
-{
- return ReadFlag(tag, name, "", index);
-}
-
-
-int ConfigReader::ReadInteger(const std::string &tag, const std::string &name, const std::string &default_value, int index, bool need_positive)
-{
- int v = atoi(default_value.c_str());
- int result = SlowGetTag(tag, index)->getInt(name, v);
-
- if ((need_positive) && (result < 0))
+ else
{
- this->error = CONF_INT_NEGATIVE;
- return 0;
- }
+ lines.clear();
- return result;
-}
-
-int ConfigReader::ReadInteger(const std::string &tag, const std::string &name, int index, bool need_positive)
-{
- return ReadInteger(tag, name, "", index, need_positive);
-}
-
-long ConfigReader::GetError()
-{
- long olderr = this->error;
- this->error = 0;
- return olderr;
-}
+ std::ifstream stream(filename.c_str());
+ if (!stream.is_open())
+ throw CoreException(filename + " does not exist or is not readable!");
-int ConfigReader::Enumerate(const std::string &tag)
-{
- ServerInstance->Logs->Log("MODULE", DEBUG, "Module is using ConfigReader::Enumerate on %s; this is slow!",
- tag.c_str());
- int i=0;
- while (SlowGetTag(tag, i)) i++;
- return i;
-}
-
-FileReader::FileReader(const std::string &filename)
-{
- LoadFile(filename);
-}
-
-FileReader::FileReader()
-{
-}
+ std::string line;
+ while (std::getline(stream, line))
+ {
+ lines.push_back(line);
+ totalSize += line.size() + 2;
+ }
-std::string FileReader::Contents()
-{
- std::string x;
- for (file_cache::iterator a = this->fc.begin(); a != this->fc.end(); a++)
- {
- x.append(*a);
- x.append("\r\n");
+ stream.close();
}
- return x;
}
-unsigned long FileReader::ContentSize()
+std::string FileReader::GetString()
{
- return this->contentsize;
-}
-
-void FileReader::CalcSize()
-{
- unsigned long n = 0;
- for (file_cache::iterator a = this->fc.begin(); a != this->fc.end(); a++)
- n += (a->length() + 2);
- this->contentsize = n;
-}
-
-void FileReader::LoadFile(const std::string &filename)
-{
- std::map<std::string, file_cache>::iterator file = ServerInstance->Config->Files.find(filename);
- if (file != ServerInstance->Config->Files.end())
+ std::string buffer;
+ for (file_cache::iterator it = this->lines.begin(); it != this->lines.end(); ++it)
{
- this->fc = file->second;
+ buffer.append(*it);
+ buffer.append("\r\n");
}
- else
- {
- fc.clear();
- FILE* f = fopen(filename.c_str(), "r");
- if (!f)
- return;
- char linebuf[MAXBUF*10];
- while (fgets(linebuf, sizeof(linebuf), f))
- {
- int len = strlen(linebuf);
- if (len)
- fc.push_back(std::string(linebuf, len - 1));
- }
- fclose(f);
- }
- CalcSize();
-}
-
-
-FileReader::~FileReader()
-{
-}
-
-bool FileReader::Exists()
-{
- return (!(fc.size() == 0));
-}
-
-std::string FileReader::GetLine(int x)
-{
- if ((x<0) || ((unsigned)x>=fc.size()))
- return "";
- return fc[x];
-}
-
-int FileReader::FileSize()
-{
- return fc.size();
+ return buffer;
}
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
- *
- * 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/>.
- */
-
-
-#ifndef ACCOUNT_H
-#define ACCOUNT_H
-
-#include <map>
-#include <string>
-
-class AccountEvent : public Event
-{
- public:
- User* const user;
- const std::string account;
- AccountEvent(Module* me, User* u, const std::string& name)
- : Event(me, "account_login"), user(u), account(name)
- {
- }
-};
-
-typedef StringExtItem AccountExtItem;
-
-inline AccountExtItem* GetAccountExtItem()
-{
- return static_cast<AccountExtItem*>(ServerInstance->Extensions.GetItem("accountname"));
-}
-
-#endif
std::string* SetExt(LocalUser* user)
{
- const char* c = GeoIP_country_code_by_addr(gi, user->GetIPString());
+ const char* c = GeoIP_country_code_by_addr(gi, user->GetIPString().c_str());
if (!c)
c = "UNK";
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
gi = GeoIP_new(GEOIP_STANDARD);
if (gi == NULL)
GeoIP_delete(gi);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides a way to assign users to connect classes by country using GeoIP lookup", VF_VENDOR);
}
- ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass)
+ ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) CXX11_OVERRIDE
{
std::string* cc = ext.get(user);
if (!cc)
return MOD_RES_DENY;
}
- ModResult OnStats(char symbol, User* user, string_list &out)
+ ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
{
if (symbol != 'G')
return MOD_RES_PASSTHRU;
};
MODULE_INIT(ModuleGeoIP)
-
conn = NULL;
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(ldapAuthed);
ServerInstance->Modules->AddService(ldapVhost);
ldap_unbind_ext(conn, NULL, NULL);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("ldapauth");
whitelistedcidrs.clear();
return result;
}
- virtual void OnUserConnect(LocalUser *user)
+ void OnUserConnect(LocalUser *user) CXX11_OVERRIDE
{
std::string* cc = ldapVhost.get(user);
if (cc)
}
}
- ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
if ((!allowpattern.empty()) && (InspIRCd::Match(user->nick,allowpattern)))
{
attr_value.bv_val = const_cast<char*>(val.c_str());
attr_value.bv_len = val.length();
- ServerInstance->Logs->Log("m_ldapauth", DEBUG, "LDAP compare: %s=%s", attr.c_str(), val.c_str());
+ ServerInstance->Logs->Log("m_ldapauth", LOG_DEBUG, "LDAP compare: %s=%s", attr.c_str(), val.c_str());
authed = (ldap_compare_ext_s(conn, DN, attr.c_str(), &attr_value, NULL, NULL) == LDAP_COMPARE_TRUE);
return true;
}
- ModResult OnCheckReady(LocalUser* user)
+ ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
return ldapAuthed.get(user) ? MOD_RES_PASSTHRU : MOD_RES_DENY;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allow/Deny connections based upon answer from LDAP server", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleLDAPAuth)
/* $ModDesc: Adds the ability to authenticate opers via LDAP */
/* $LinkerFlags: -lldap */
-// Duplicated code, also found in cmd_oper and m_sqloper
-static bool OneOfMatches(const char* host, const char* ip, const std::string& hostlist)
-{
- std::stringstream hl(hostlist);
- std::string xhost;
- while (hl >> xhost)
- {
- if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
- {
- return true;
- }
- }
- return false;
-}
-
struct RAIILDAPString
{
char *str;
std::string acceptedhosts = tag->getString("host");
std::string hostname = user->ident + "@" + user->host;
- if (!OneOfMatches(hostname.c_str(), user->GetIPString(), acceptedhosts))
+ if (!InspIRCd::MatchMask(acceptedhosts, hostname, user->GetIPString()))
return false;
if (!LookupOper(opername, inputpass))
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnRehash, I_OnPreCommand };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- virtual ~ModuleLDAPAuth()
+ ~ModuleLDAPAuth()
{
if (conn)
ldap_unbind_ext(conn, NULL, NULL);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("ldapoper");
return true;
}
- ModResult OnPreCommand(std::string& command, std::vector<std::string>& parameters, LocalUser* user, bool validated, const std::string& original_line)
+ ModResult OnPreCommand(std::string& command, std::vector<std::string>& parameters, LocalUser* user, bool validated, const std::string& original_line) CXX11_OVERRIDE
{
if (validated && command == "OPER" && parameters.size() >= 2)
{
}
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Adds the ability to authenticate opers via LDAP", VF_VENDOR);
}
public:
QueryThread(ModuleMsSQL* mod) : Parent(mod) { }
~QueryThread() { }
- virtual void Run();
- virtual void OnNotify();
+ void Run();
+ void OnNotify();
};
class MsSQLResult : public SQLresult
{
}
- ~MsSQLResult()
- {
- }
-
void AddRow(int colsnum, char **dat, char **colname)
{
colnames.clear();
rows++;
}
- virtual int Rows()
+ int Rows()
{
return rows;
}
- virtual int Cols()
+ int Cols()
{
return cols;
}
- virtual std::string ColName(int column)
+ std::string ColName(int column)
{
if (column < (int)colnames.size())
{
return "";
}
- virtual int ColNum(const std::string &column)
+ int ColNum(const std::string &column)
{
for (unsigned int i = 0; i < colnames.size(); i++)
{
return 0;
}
- virtual SQLfield GetValue(int row, int column)
+ SQLfield GetValue(int row, int column)
{
if ((row >= 0) && (row < rows) && (column >= 0) && (column < Cols()))
{
return SQLfield("",true);
}
- virtual SQLfieldList& GetRow()
+ SQLfieldList& GetRow()
{
if (currentrow < rows)
return fieldlists[currentrow];
return emptyfieldlist;
}
- virtual SQLfieldMap& GetRowMap()
+ SQLfieldMap& GetRowMap()
{
/* In an effort to reduce overhead we don't actually allocate the map
* until the first time it's needed...so...
return *fieldmap;
}
- virtual SQLfieldList* GetRowPtr()
+ SQLfieldList* GetRowPtr()
{
fieldlist = new SQLfieldList();
return fieldlist;
}
- virtual SQLfieldMap* GetRowMapPtr()
+ SQLfieldMap* GetRowMapPtr()
{
fieldmap = new SQLfieldMap();
return fieldmap;
}
- virtual void Free(SQLfieldMap* fm)
+ void Free(SQLfieldMap* fm)
{
delete fm;
}
- virtual void Free(SQLfieldList* fl)
+ void Free(SQLfieldList* fl)
{
delete fl;
}
if (tds_process_simple_query(sock) != TDS_SUCCEED)
{
LoggingMutex->Lock();
- ServerInstance->Logs->Log("m_mssql",DEFAULT, "WARNING: Could not select database " + host.name + " for DB with id: " + host.id);
+ ServerInstance->Logs->Log("m_mssql", LOG_DEFAULT, "WARNING: Could not select database " + host.name + " for DB with id: " + host.id);
LoggingMutex->Unlock();
CloseDB();
}
else
{
LoggingMutex->Lock();
- ServerInstance->Logs->Log("m_mssql",DEFAULT, "WARNING: Could not select database " + host.name + " for DB with id: " + host.id);
+ ServerInstance->Logs->Log("m_mssql", LOG_DEFAULT, "WARNING: Could not select database " + host.name + " for DB with id: " + host.id);
LoggingMutex->Unlock();
CloseDB();
}
else
{
LoggingMutex->Lock();
- ServerInstance->Logs->Log("m_mssql",DEFAULT, "WARNING: Could not connect to DB with id: " + host.id);
+ ServerInstance->Logs->Log("m_mssql", LOG_DEFAULT, "WARNING: Could not connect to DB with id: " + host.id);
LoggingMutex->Unlock();
CloseDB();
}
char* msquery = strdup(req->query.q.data());
LoggingMutex->Lock();
- ServerInstance->Logs->Log("m_mssql",DEBUG,"doing Query: %s",msquery);
+ ServerInstance->Logs->Log("m_mssql", LOG_DEBUG, "doing Query: %s",msquery);
LoggingMutex->Unlock();
if (tds_submit_query(sock, msquery) != TDS_SUCCEED)
{
int tds_res;
while (tds_process_tokens(sock, &tds_res, NULL, TDS_TOKEN_RESULTS) == TDS_SUCCEED)
{
- //ServerInstance->Logs->Log("m_mssql",DEBUG,"<******> result type: %d", tds_res);
- //ServerInstance->Logs->Log("m_mssql",DEBUG,"AFFECTED ROWS: %d", sock->rows_affected);
+ //ServerInstance->Logs->Log("m_mssql", LOG_DEBUG, "<******> result type: %d", tds_res);
+ //ServerInstance->Logs->Log("m_mssql", LOG_DEBUG, "AFFECTED ROWS: %d", sock->rows_affected);
switch (tds_res)
{
case TDS_ROWFMT_RESULT:
{
SQLConn* sc = (SQLConn*)pContext->parent;
LoggingMutex->Lock();
- ServerInstance->Logs->Log("m_mssql", DEBUG, "Message for DB with id: %s -> %s", sc->host.id.c_str(), pMessage->message);
+ ServerInstance->Logs->Log("m_mssql", LOG_DEBUG, "Message for DB with id: %s -> %s", sc->host.id.c_str(), pMessage->message);
LoggingMutex->Unlock();
return 0;
}
{
SQLConn* sc = (SQLConn*)pContext->parent;
LoggingMutex->Lock();
- ServerInstance->Logs->Log("m_mssql", DEFAULT, "Error for DB with id: %s -> %s", sc->host.id.c_str(), pMessage->message);
+ ServerInstance->Logs->Log("m_mssql", LOG_DEFAULT, "Error for DB with id: %s -> %s", sc->host.id.c_str(), pMessage->message);
LoggingMutex->Unlock();
return 0;
}
queryDispatcher = new QueryThread(this);
}
- void init()
+ void init() CXX11_OVERRIDE
{
ReadConf();
ServerInstance->Modules->AddService(sqlserv);
}
- virtual ~ModuleMsSQL()
+ ~ModuleMsSQL()
{
queryDispatcher->join();
delete queryDispatcher;
if (HasHost(hi))
{
LoggingMutex->Lock();
- ServerInstance->Logs->Log("m_mssql",DEFAULT, "WARNING: A MsSQL connection with id: %s already exists. Aborting database open attempt.", hi.id.c_str());
+ ServerInstance->Logs->Log("m_mssql", LOG_DEFAULT, "WARNING: A MsSQL connection with id: %s already exists. Aborting database open attempt.", hi.id.c_str());
LoggingMutex->Unlock();
return;
}
connections.clear();
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
queryDispatcher->LockQueue();
ReadConf();
queryDispatcher->UnlockQueueWakeup();
}
- void OnRequest(Request& request)
+ void OnRequest(Request& request) CXX11_OVERRIDE
{
if(strcmp(SQLREQID, request.id) == 0)
{
return ++currid;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("MsSQL provider", VF_VENDOR);
}
#include "inspircd.h"
#include <mysql.h>
-#include "sql.h"
+#include "modules/sql.h"
#ifdef _WIN32
# pragma comment(lib, "mysqlclient.lib")
ConnMap connections; // main thread only
ModuleSQL();
- void init();
+ void init() CXX11_OVERRIDE;
~ModuleSQL();
- void OnRehash(User* user);
- void OnUnloadModule(Module* mod);
- Version GetVersion();
+ void OnRehash(User* user) CXX11_OVERRIDE;
+ void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
+ Version GetVersion() CXX11_OVERRIDE;
};
class DispatcherThread : public SocketThread
public:
DispatcherThread(ModuleSQL* CreatorModule) : Parent(CreatorModule) { }
~DispatcherThread() { }
- virtual void Run();
- virtual void OnNotify();
+ void Run();
+ void OnNotify();
};
#if !defined(MYSQL_VERSION_ID) || MYSQL_VERSION_ID<32224
}
- ~MySQLresult()
- {
- }
-
- virtual int Rows()
+ int Rows()
{
return rows;
}
- virtual void GetCols(std::vector<std::string>& result)
+ void GetCols(std::vector<std::string>& result)
{
result.assign(colnames.begin(), colnames.end());
}
- virtual SQLEntry GetValue(int row, int column)
+ SQLEntry GetValue(int row, int column)
{
if ((row >= 0) && (row < rows) && (column >= 0) && (column < (int)fieldlists[row].size()))
{
return SQLEntry();
}
- virtual bool GetRow(SQLEntries& result)
+ bool GetRow(SQLEntries& result)
{
if (currentrow < rows)
{
#include <cstdlib>
#include <sstream>
#include <libpq-fe.h>
-#include "sql.h"
+#include "modules/sql.h"
/* $ModDesc: PostgreSQL Service Provider module for all other m_sql* modules, uses v2 of the SQL API */
/* $CompileFlags: -Iexec("pg_config --includedir") eval("my $s = `pg_config --version`;$s =~ /^.*?(\d+)\.(\d+)\.(\d+).*?$/;my $v = hex(sprintf("0x%02x%02x%02x", $1, $2, $3));print "-DPGSQL_HAS_ESCAPECONN" if(($v >= 0x080104) || ($v >= 0x07030F && $v < 0x070400) || ($v >= 0x07040D && $v < 0x080000) || ($v >= 0x080008 && $v < 0x080100));") */
ReconnectTimer(ModulePgSQL* m) : Timer(5, ServerInstance->Time(), false), mod(m)
{
}
- virtual void Tick(time_t TIME);
+ bool Tick(time_t TIME);
};
struct QueueItem
PQclear(res);
}
- virtual int Rows()
+ int Rows()
{
return rows;
}
- virtual void GetCols(std::vector<std::string>& result)
+ void GetCols(std::vector<std::string>& result)
{
result.resize(PQnfields(res));
for(unsigned int i=0; i < result.size(); i++)
}
}
- virtual SQLEntry GetValue(int row, int column)
+ SQLEntry GetValue(int row, int column)
{
char* v = PQgetvalue(res, row, column);
if (!v || PQgetisnull(res, row, column))
return SQLEntry(std::string(v, PQgetlength(res, row, column)));
}
- virtual bool GetRow(SQLEntries& result)
+ bool GetRow(SQLEntries& result)
{
if (currentrow >= PQntuples(res))
return false;
{
if (!DoConnect())
{
- ServerInstance->Logs->Log("m_pgsql",DEFAULT, "WARNING: Could not connect to database " + tag->getString("id"));
+ ServerInstance->Logs->Log("m_pgsql", LOG_DEFAULT, "WARNING: Could not connect to database " + tag->getString("id"));
DelayReconnect();
}
}
}
}
- virtual void HandleEvent(EventType et, int errornum)
+ void HandleEvent(EventType et, int errornum)
{
switch (et)
{
if (!ServerInstance->SE->AddFd(this, FD_WANT_NO_WRITE | FD_WANT_NO_READ))
{
- ServerInstance->Logs->Log("m_pgsql",DEBUG, "BUG: Couldn't add pgsql socket to socket engine");
+ ServerInstance->Logs->Log("m_pgsql", LOG_DEBUG, "BUG: Couldn't add pgsql socket to socket engine");
return false;
}
int error;
size_t escapedsize = PQescapeStringConn(sql, &buffer[0], parm.data(), parm.length(), &error);
if (error)
- ServerInstance->Logs->Log("m_pgsql", DEBUG, "BUG: Apparently PQescapeStringConn() failed");
+ ServerInstance->Logs->Log("m_pgsql", LOG_DEBUG, "BUG: Apparently PQescapeStringConn() failed");
#else
size_t escapedsize = PQescapeString(&buffer[0], parm.data(), parm.length());
#endif
int error;
size_t escapedsize = PQescapeStringConn(sql, &buffer[0], parm.data(), parm.length(), &error);
if (error)
- ServerInstance->Logs->Log("m_pgsql", DEBUG, "BUG: Apparently PQescapeStringConn() failed");
+ ServerInstance->Logs->Log("m_pgsql", LOG_DEBUG, "BUG: Apparently PQescapeStringConn() failed");
#else
size_t escapedsize = PQescapeString(&buffer[0], parm.data(), parm.length());
#endif
ReconnectTimer* retimer;
ModulePgSQL()
+ : retimer(NULL)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ReadConf();
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModulePgSQL()
+ ~ModulePgSQL()
{
- if (retimer)
- ServerInstance->Timers->DelTimer(retimer);
+ delete retimer;
ClearAllConnections();
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadConf();
}
connections.clear();
}
- void OnUnloadModule(Module* mod)
+ void OnUnloadModule(Module* mod) CXX11_OVERRIDE
{
SQLerror err(SQL_BAD_DBID);
for(ConnMap::iterator i = connections.begin(); i != connections.end(); i++)
}
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("PostgreSQL Service Provider module for all other m_sql* modules, uses v2 of the SQL API", VF_VENDOR);
}
};
-void ReconnectTimer::Tick(time_t time)
+bool ReconnectTimer::Tick(time_t time)
{
mod->retimer = NULL;
mod->ReadConf();
+ return false;
}
void SQLConn::DelayReconnect()
#include "inspircd.h"
#include <pcre.h>
-#include "m_regex.h"
+#include "modules/regex.h"
/* $ModDesc: Regex Provider Module for PCRE */
-/* $ModDep: m_regex.h */
+/* $ModDep: modules/regex.h */
/* $CompileFlags: exec("pcre-config --cflags") */
/* $LinkerFlags: exec("pcre-config --libs") rpath("pcre-config --libs") -lpcre */
class PCREException : public ModuleException
{
-public:
+ public:
PCREException(const std::string& rx, const std::string& error, int erroffset)
: ModuleException("Error in regex " + rx + " at offset " + ConvToStr(erroffset) + ": " + error)
{
class PCRERegex : public Regex
{
-private:
pcre* regex;
-public:
+ public:
PCRERegex(const std::string& rx) : Regex(rx)
{
const char* error;
regex = pcre_compile(rx.c_str(), 0, &error, &erroffset, NULL);
if (!regex)
{
- ServerInstance->Logs->Log("REGEX", DEBUG, "pcre_compile failed: /%s/ [%d] %s", rx.c_str(), erroffset, error);
+ ServerInstance->Logs->Log("REGEX", LOG_DEBUG, "pcre_compile failed: /%s/ [%d] %s", rx.c_str(), erroffset, error);
throw PCREException(rx, error, erroffset);
}
}
- virtual ~PCRERegex()
+ ~PCRERegex()
{
pcre_free(regex);
}
- virtual bool Matches(const std::string& text)
+ bool Matches(const std::string& text)
{
if (pcre_exec(regex, NULL, text.c_str(), text.length(), 0, 0, NULL, 0) > -1)
{
class ModuleRegexPCRE : public Module
{
-public:
+ public:
PCREFactory ref;
- ModuleRegexPCRE() : ref(this) {
+ ModuleRegexPCRE() : ref(this)
+ {
ServerInstance->Modules->AddService(ref);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Regex Provider Module for PCRE", VF_VENDOR);
}
#include "inspircd.h"
-#include "m_regex.h"
+#include "modules/regex.h"
#include <sys/types.h>
#include <regex.h>
/* $ModDesc: Regex Provider Module for POSIX Regular Expressions */
-/* $ModDep: m_regex.h */
+/* $ModDep: modules/regex.h */
class POSIXRegexException : public ModuleException
{
-public:
+ public:
POSIXRegexException(const std::string& rx, const std::string& error)
: ModuleException("Error in regex " + rx + ": " + error)
{
class POSIXRegex : public Regex
{
-private:
regex_t regbuf;
-public:
+ public:
POSIXRegex(const std::string& rx, bool extended) : Regex(rx)
{
int flags = (extended ? REG_EXTENDED : 0) | REG_NOSUB;
}
}
- virtual ~POSIXRegex()
+ ~POSIXRegex()
{
regfree(®buf);
}
- virtual bool Matches(const std::string& text)
+ bool Matches(const std::string& text)
{
if (regexec(®buf, text.c_str(), 0, NULL, 0) == 0)
{
class ModuleRegexPOSIX : public Module
{
PosixFactory ref;
-public:
- ModuleRegexPOSIX() : ref(this) {
+
+ public:
+ ModuleRegexPOSIX() : ref(this)
+ {
ServerInstance->Modules->AddService(ref);
Implementation eventlist[] = { I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Regex Provider Module for POSIX Regular Expressions", VF_VENDOR);
}
- void OnRehash(User* u)
+ void OnRehash(User* u) CXX11_OVERRIDE
{
ref.extended = ServerInstance->Config->ConfValue("posix")->getBool("extended");
}
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
+
#include "inspircd.h"
-#include "m_regex.h"
+#include "modules/regex.h"
#include <regex>
/* $ModDesc: Regex Provider Module for std::regex Regular Expressions */
* Specify the Regular Expression engine to use here. Valid settings are
* bre, ere, awk, grep, egrep, ecmascript (default if not specified)*/
/* $CompileFlags: -std=c++11 */
-/* $ModDep: m_regex.h */
+/* $ModDep: modules/regex.h */
class StdRegexException : public ModuleException
{
-public:
+ public:
StdRegexException(const std::string& rx, const std::string& error)
: ModuleException(std::string("Error in regex ") + rx + ": " + error)
{
class StdRegex : public Regex
{
-private:
std::regex regexcl;
-public:
+
+ public:
StdRegex(const std::string& rx, std::regex::flag_type fltype) : Regex(rx)
{
try{
throw StdRegexException(rx, rxerr.what());
}
}
-
- virtual bool Matches(const std::string& text)
+
+ bool Matches(const std::string& text)
{
return std::regex_search(text, regexcl);
}
{
public:
StdRegexFactory ref;
- ModuleRegexStd() : ref(this) {
+ ModuleRegexStd() : ref(this)
+ {
ServerInstance->Modules->AddService(ref);
Implementation eventlist[] = { I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Regex Provider Module for std::regex", VF_VENDOR);
}
-
- void OnRehash(User* u)
+
+ void OnRehash(User* u) CXX11_OVERRIDE
{
ConfigTag* Conf = ServerInstance->Config->ConfValue("stdregex");
std::string regextype = Conf->getString("type", "ecmascript");
-
+
if(regextype == "bre")
ref.regextype = std::regex::basic;
else if(regextype == "ere")
#include "inspircd.h"
-#include "m_regex.h"
+#include "modules/regex.h"
#include <sys/types.h>
#include <tre/regex.h>
/* $ModDesc: Regex Provider Module for TRE Regular Expressions */
/* $CompileFlags: pkgconfincludes("tre","tre/regex.h","") */
/* $LinkerFlags: pkgconflibs("tre","/libtre.so","-ltre") rpath("pkg-config --libs tre") */
-/* $ModDep: m_regex.h */
+/* $ModDep: modules/regex.h */
class TRERegexException : public ModuleException
{
-public:
+ public:
TRERegexException(const std::string& rx, const std::string& error)
: ModuleException("Error in regex " + rx + ": " + error)
{
class TRERegex : public Regex
{
-private:
regex_t regbuf;
public:
}
}
- virtual ~TRERegex()
+ ~TRERegex()
{
regfree(®buf);
}
- virtual bool Matches(const std::string& text)
+ bool Matches(const std::string& text)
{
if (regexec(®buf, text.c_str(), 0, NULL, 0) == 0)
{
}
};
-class TREFactory : public RegexFactory {
+class TREFactory : public RegexFactory
+{
public:
TREFactory(Module* m) : RegexFactory(m, "regex/tre") {}
Regex* Create(const std::string& expr)
class ModuleRegexTRE : public Module
{
TREFactory trf;
-public:
- ModuleRegexTRE() : trf(this) {
- ServerInstance->Modules->AddService(trf);
- }
- Version GetVersion()
+ public:
+ ModuleRegexTRE() : trf(this)
{
- return Version("Regex Provider Module for TRE Regular Expressions", VF_VENDOR);
+ ServerInstance->Modules->AddService(trf);
}
- ~ModuleRegexTRE()
+ Version GetVersion() CXX11_OVERRIDE
{
+ return Version("Regex Provider Module for TRE Regular Expressions", VF_VENDOR);
}
};
#include "inspircd.h"
#include <sqlite3.h>
-#include "sql.h"
+#include "modules/sql.h"
#ifdef _WIN32
# pragma comment(lib, "sqlite3.lib")
{
}
- ~SQLite3Result()
- {
- }
-
- virtual int Rows()
+ int Rows()
{
return rows;
}
- virtual bool GetRow(SQLEntries& result)
+ bool GetRow(SQLEntries& result)
{
if (currentrow < rows)
{
}
}
- virtual void GetCols(std::vector<std::string>& result)
+ void GetCols(std::vector<std::string>& result)
{
result.assign(columns.begin(), columns.end());
}
class SQLConn : public SQLProvider
{
- private:
sqlite3* conn;
reference<ConfigTag> config;
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"));
+ ServerInstance->Logs->Log("m_sqlite3", LOG_DEFAULT, "WARNING: Could not open DB with id: " + tag->getString("id"));
conn = NULL;
}
}
sqlite3_finalize(stmt);
}
- virtual void submit(SQLQuery* query, const std::string& q)
+ void submit(SQLQuery* query, const std::string& q)
{
Query(query, q);
delete query;
}
- virtual void submit(SQLQuery* query, const std::string& q, const ParamL& p)
+ void submit(SQLQuery* query, const std::string& q, const ParamL& p)
{
std::string res;
unsigned int param = 0;
submit(query, res);
}
- virtual void submit(SQLQuery* query, const std::string& q, const ParamM& p)
+ void submit(SQLQuery* query, const std::string& q, const ParamM& p)
{
std::string res;
for(std::string::size_type i = 0; i < q.length(); i++)
class ModuleSQLite3 : public Module
{
- private:
ConnMap conns;
public:
- ModuleSQLite3()
- {
- }
-
- void init()
+ void init() CXX11_OVERRIDE
{
ReadConf();
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleSQLite3()
+ ~ModuleSQLite3()
{
ClearConns();
}
}
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadConf();
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("sqlite3 provider", VF_VENDOR);
}
#include <gcrypt.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
-#include "ssl.h"
-#include "m_cap.h"
+#include "modules/ssl.h"
+#include "modules/cap.h"
#ifdef _WIN32
# pragma comment(lib, "libgnutls.lib")
}
public:
-
ModuleSSLGnuTLS()
: starttls(this), capHandler(this, "tls"), iohook(this, "ssl/gnutls", SERVICE_IOHOOK)
{
dh_alloc = false;
}
- void init()
+ void init() CXX11_OVERRIDE
{
// Needs the flag as it ignores a plain /rehash
OnModuleRehash(NULL,"ssl");
ServerInstance->Modules->AddService(starttls);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
sslports.clear();
continue;
const std::string& portid = port->bind_desc;
- ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, "m_ssl_gnutls.so: Enabling SSL for port %s", portid.c_str());
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: Enabling SSL for port %s", portid.c_str());
if (port->bind_tag->getString("type", "clients") == "clients" && port->bind_addr != "127.0.0.1")
{
}
}
- void OnModuleRehash(User* user, const std::string ¶m)
+ void OnModuleRehash(User* user, const std::string ¶m) CXX11_OVERRIDE
{
if(param != "ssl")
return;
ret = gnutls_certificate_allocate_credentials(&x509_cred);
cred_alloc = (ret >= 0);
if (!cred_alloc)
- ServerInstance->Logs->Log("m_ssl_gnutls",DEBUG, "m_ssl_gnutls.so: Failed to allocate certificate credentials: %s", gnutls_strerror(ret));
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEBUG, "m_ssl_gnutls.so: Failed to allocate certificate credentials: %s", gnutls_strerror(ret));
if((ret =gnutls_certificate_set_x509_trust_file(x509_cred, cafile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
- ServerInstance->Logs->Log("m_ssl_gnutls",DEBUG, "m_ssl_gnutls.so: Failed to set X.509 trust file '%s': %s", cafile.c_str(), gnutls_strerror(ret));
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEBUG, "m_ssl_gnutls.so: Failed to set X.509 trust file '%s': %s", cafile.c_str(), gnutls_strerror(ret));
if((ret = gnutls_certificate_set_x509_crl_file (x509_cred, crlfile.c_str(), GNUTLS_X509_FMT_PEM)) < 0)
- ServerInstance->Logs->Log("m_ssl_gnutls",DEBUG, "m_ssl_gnutls.so: Failed to set X.509 CRL file '%s': %s", crlfile.c_str(), gnutls_strerror(ret));
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEBUG, "m_ssl_gnutls.so: Failed to set X.509 CRL file '%s': %s", crlfile.c_str(), gnutls_strerror(ret));
FileReader reader;
- reader.LoadFile(certfile);
- std::string cert_string = reader.Contents();
+ reader.Load(certfile);
+ std::string cert_string = reader.GetString();
gnutls_datum_t cert_datum = { (unsigned char*)cert_string.data(), static_cast<unsigned int>(cert_string.length()) };
- reader.LoadFile(keyfile);
- std::string key_string = reader.Contents();
+ reader.Load(keyfile);
+ std::string key_string = reader.GetString();
gnutls_datum_t key_datum = { (unsigned char*)key_string.data(), static_cast<unsigned int>(key_string.length()) };
// If this fails, no SSL port will work. At all. So, do the smart thing - throw a ModuleException
if ((ret = gnutls_priority_init(&priority, priocstr, &prioerror)) < 0)
{
// gnutls did not understand the user supplied string, log and fall back to the default priorities
- ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to set priorities to \"%s\": %s Syntax error at position %u, falling back to default (NORMAL)", priorities.c_str(), gnutls_strerror(ret), (unsigned int) (prioerror - priocstr));
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: Failed to set priorities to \"%s\": %s Syntax error at position %u, falling back to default (NORMAL)", priorities.c_str(), gnutls_strerror(ret), (unsigned int) (prioerror - priocstr));
gnutls_priority_init(&priority, "NORMAL", NULL);
}
#else
if (priorities != "NORMAL")
- ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: You've set <gnutls:priority> to a value other than the default, but this is only supported with GnuTLS v2.1.7 or newer. Your GnuTLS version is older than that so the option will have no effect.");
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: You've set <gnutls:priority> to a value other than the default, but this is only supported with GnuTLS v2.1.7 or newer. Your GnuTLS version is older than that so the option will have no effect.");
#endif
#if(GNUTLS_VERSION_MAJOR < 2 || ( GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 12 ) )
dh_alloc = (ret >= 0);
if (!dh_alloc)
{
- ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters: %s", gnutls_strerror(ret));
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: Failed to initialise DH parameters: %s", gnutls_strerror(ret));
return;
}
if (!dhfile.empty())
{
// Try to load DH params from file
- reader.LoadFile(dhfile);
- std::string dhstring = reader.Contents();
+ reader.Load(dhfile);
+ std::string dhstring = reader.GetString();
gnutls_datum_t dh_datum = { (unsigned char*)dhstring.data(), static_cast<unsigned int>(dhstring.length()) };
if ((ret = gnutls_dh_params_import_pkcs3(dh_params, &dh_datum, GNUTLS_X509_FMT_PEM)) < 0)
{
// File unreadable or GnuTLS was unhappy with the contents, generate the DH primes now
- ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, "m_ssl_gnutls.so: Generating DH parameters because I failed to load them from file '%s': %s", dhfile.c_str(), gnutls_strerror(ret));
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: Generating DH parameters because I failed to load them from file '%s': %s", dhfile.c_str(), gnutls_strerror(ret));
GenerateDHParams();
}
}
int ret;
if((ret = gnutls_dh_params_generate2(dh_params, dh_bits)) < 0)
- ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to generate DH parameters (%d bits): %s", dh_bits, gnutls_strerror(ret));
+ ServerInstance->Logs->Log("m_ssl_gnutls", LOG_DEFAULT, "m_ssl_gnutls.so: Failed to generate DH parameters (%d bits): %s", dh_bits, gnutls_strerror(ret));
}
~ModuleSSLGnuTLS()
ServerInstance->GenRandom = &ServerInstance->HandleGenRandom;
}
- void OnCleanup(int target_type, void* item)
+ void OnCleanup(int target_type, void* item) CXX11_OVERRIDE
{
if(target_type == TYPE_USER)
{
}
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides SSL support for clients", VF_VENDOR);
}
-
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
if (!sslports.empty())
- output.append(" SSL=" + sslports);
+ tokens["SSL"] = sslports;
if (starttls.enabled)
- output.append(" STARTTLS");
+ tokens["STARTTLS"];
}
- void OnHookIO(StreamSocket* user, ListenSocket* lsb)
+ void OnHookIO(StreamSocket* user, ListenSocket* lsb) CXX11_OVERRIDE
{
if (!user->GetIOHook() && lsb->bind_tag->getString("ssl") == "gnutls")
{
}
}
- void OnRequest(Request& request)
+ void OnRequest(Request& request) CXX11_OVERRIDE
{
if (strcmp("GET_SSL_CERT", request.id) == 0)
{
Handshake(session, user);
}
- void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
+ void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE
{
issl_session* session = &sessions[user->GetFd()];
InitSession(user, true);
}
- void OnStreamSocketConnect(StreamSocket* user)
+ void OnStreamSocketConnect(StreamSocket* user) CXX11_OVERRIDE
{
InitSession(user, false);
}
- void OnStreamSocketClose(StreamSocket* user)
+ void OnStreamSocketClose(StreamSocket* user) CXX11_OVERRIDE
{
CloseSession(&sessions[user->GetFd()]);
}
- int OnStreamSocketRead(StreamSocket* user, std::string& recvq)
+ int OnStreamSocketRead(StreamSocket* user, std::string& recvq) CXX11_OVERRIDE
{
issl_session* session = &sessions[user->GetFd()];
return 0;
}
- int OnStreamSocketWrite(StreamSocket* user, std::string& sendq)
+ int OnStreamSocketWrite(StreamSocket* user, std::string& sendq) CXX11_OVERRIDE
{
issl_session* session = &sessions[user->GetFd()];
}
}
- void OnUserConnect(LocalUser* user)
+ void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
{
if (user->eh.GetIOHook() == this)
{
ssl_cert* cert = sessions[user->eh.GetFd()].cert;
if (cert->fingerprint.empty())
- user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), cipher.c_str());
+ user->WriteNotice("*** You are connected using SSL cipher '" + cipher + "'");
else
- user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\""
- " and your SSL fingerprint is %s", user->nick.c_str(), cipher.c_str(), cert->fingerprint.c_str());
+ user->WriteNotice("*** You are connected using SSL cipher '" + cipher +
+ "' and your SSL fingerprint is " + cert->fingerprint);
}
}
}
}
else
{
- certinfo->fingerprint = irc::hex(digest, digest_size);
+ certinfo->fingerprint = BinToHex(digest, digest_size);
}
/* Beware here we do not check for errors.
gnutls_x509_crt_deinit(cert);
}
- void OnEvent(Event& ev)
+ void OnEvent(Event& ev) CXX11_OVERRIDE
{
if (starttls.enabled)
capHandler.HandleEvent(ev);
# define __AVAILABILITYMACROS__
# define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
#endif
-
+
#include "inspircd.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
-#include "ssl.h"
+#include "modules/ssl.h"
#ifdef _WIN32
# pragma comment(lib, "libcrypto.lib")
SSL_CTX_set_verify(clictx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, OnVerify);
}
- void init()
+ void init() CXX11_OVERRIDE
{
// Needs the flag as it ignores a plain /rehash
OnModuleRehash(NULL,"ssl");
ServerInstance->Modules->AddService(iohook);
}
- void OnHookIO(StreamSocket* user, ListenSocket* lsb)
+ void OnHookIO(StreamSocket* user, ListenSocket* lsb) CXX11_OVERRIDE
{
if (!user->GetIOHook() && lsb->bind_tag->getString("ssl") == "openssl")
{
}
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
sslports.clear();
continue;
const std::string& portid = port->bind_desc;
- ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Enabling SSL for port %s", portid.c_str());
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "m_ssl_openssl.so: Enabling SSL for port %s", portid.c_str());
if (port->bind_tag->getString("type", "clients") == "clients" && port->bind_addr != "127.0.0.1")
{
}
}
- void OnModuleRehash(User* user, const std::string ¶m)
+ void OnModuleRehash(User* user, const std::string ¶m) CXX11_OVERRIDE
{
if (param != "ssl")
return;
{
if ((!SSL_CTX_set_cipher_list(ctx, ciphers.c_str())) || (!SSL_CTX_set_cipher_list(clictx, ciphers.c_str())))
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't set cipher list to %s.", ciphers.c_str());
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "m_ssl_openssl.so: Can't set cipher list to %s.", ciphers.c_str());
ERR_print_errors_cb(error_callback, this);
}
}
*/
if ((!SSL_CTX_use_certificate_chain_file(ctx, certfile.c_str())) || (!SSL_CTX_use_certificate_chain_file(clictx, certfile.c_str())))
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read certificate file %s. %s", certfile.c_str(), strerror(errno));
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "m_ssl_openssl.so: Can't read certificate file %s. %s", certfile.c_str(), strerror(errno));
ERR_print_errors_cb(error_callback, this);
}
if (((!SSL_CTX_use_PrivateKey_file(ctx, keyfile.c_str(), SSL_FILETYPE_PEM))) || (!SSL_CTX_use_PrivateKey_file(clictx, keyfile.c_str(), SSL_FILETYPE_PEM)))
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read key file %s. %s", keyfile.c_str(), strerror(errno));
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "m_ssl_openssl.so: Can't read key file %s. %s", keyfile.c_str(), strerror(errno));
ERR_print_errors_cb(error_callback, this);
}
/* Load the CAs we trust*/
if (((!SSL_CTX_load_verify_locations(ctx, cafile.c_str(), 0))) || (!SSL_CTX_load_verify_locations(clictx, cafile.c_str(), 0)))
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't read CA list from %s. This is only a problem if you want to verify client certificates, otherwise it's safe to ignore this message. Error: %s", cafile.c_str(), strerror(errno));
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "m_ssl_openssl.so: Can't read CA list from %s. This is only a problem if you want to verify client certificates, otherwise it's safe to ignore this message. Error: %s", cafile.c_str(), strerror(errno));
ERR_print_errors_cb(error_callback, this);
}
if (dhpfile == NULL)
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so Couldn't open DH file %s: %s", dhfile.c_str(), strerror(errno));
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "m_ssl_openssl.so Couldn't open DH file %s: %s", dhfile.c_str(), strerror(errno));
throw ModuleException("Couldn't open DH file " + dhfile + ": " + strerror(errno));
}
else
ret = PEM_read_DHparams(dhpfile, NULL, NULL, NULL);
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());
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "m_ssl_openssl.so: Couldn't set DH parameters %s. SSL errors follow:", dhfile.c_str());
ERR_print_errors_cb(error_callback, this);
}
}
fclose(dhpfile);
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
if (!sslports.empty())
- output.append(" SSL=" + sslports);
+ tokens["SSL"] = sslports;
}
~ModuleSSLOpenSSL()
delete[] sessions;
}
- void OnUserConnect(LocalUser* user)
+ void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
{
if (user->eh.GetIOHook() == this)
{
if (sessions[user->eh.GetFd()].sess)
{
if (!sessions[user->eh.GetFd()].cert->fingerprint.empty())
- user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\""
- " and your SSL fingerprint is %s", user->nick.c_str(), SSL_get_cipher(sessions[user->eh.GetFd()].sess), sessions[user->eh.GetFd()].cert->fingerprint.c_str());
+ user->WriteNotice("*** You are connected using SSL cipher '" + std::string(SSL_get_cipher(sessions[user->eh.GetFd()].sess)) +
+ "' and your SSL fingerprint is " + sessions[user->eh.GetFd()].cert->fingerprint);
else
- user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), SSL_get_cipher(sessions[user->eh.GetFd()].sess));
+ user->WriteNotice("*** You are connected using SSL cipher '" + std::string(SSL_get_cipher(sessions[user->eh.GetFd()].sess)) + "'");
}
}
}
- void OnCleanup(int target_type, void* item)
+ void OnCleanup(int target_type, void* item) CXX11_OVERRIDE
{
if (target_type == TYPE_USER)
{
}
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides SSL support for clients", VF_VENDOR);
}
- void OnRequest(Request& request)
+ void OnRequest(Request& request) CXX11_OVERRIDE
{
if (strcmp("GET_SSL_CERT", request.id) == 0)
{
}
}
- void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
+ void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE
{
int fd = user->GetFd();
if (SSL_set_fd(session->sess, fd) == 0)
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEBUG,"BUG: Can't set fd with SSL_set_fd: %d", fd);
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEBUG, "BUG: Can't set fd with SSL_set_fd: %d", fd);
return;
}
Handshake(user, session);
}
- void OnStreamSocketConnect(StreamSocket* user)
+ void OnStreamSocketConnect(StreamSocket* user) CXX11_OVERRIDE
{
int fd = user->GetFd();
/* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */
if (SSL_set_fd(session->sess, fd) == 0)
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEBUG,"BUG: Can't set fd with SSL_set_fd: %d", fd);
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEBUG, "BUG: Can't set fd with SSL_set_fd: %d", fd);
return;
}
Handshake(user, session);
}
- void OnStreamSocketClose(StreamSocket* user)
+ void OnStreamSocketClose(StreamSocket* user) CXX11_OVERRIDE
{
int fd = user->GetFd();
/* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */
CloseSession(&sessions[fd]);
}
- int OnStreamSocketRead(StreamSocket* user, std::string& recvq)
+ int OnStreamSocketRead(StreamSocket* user, std::string& recvq) CXX11_OVERRIDE
{
int fd = user->GetFd();
/* Are there any possibilities of an out of range fd? Hope not, but lets be paranoid */
return 0;
}
- int OnStreamSocketWrite(StreamSocket* user, std::string& buffer)
+ int OnStreamSocketWrite(StreamSocket* user, std::string& buffer) CXX11_OVERRIDE
{
int fd = user->GetFd();
}
else
{
- certinfo->fingerprint = irc::hex(md, n);
+ certinfo->fingerprint = BinToHex(md, n);
}
if ((ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(cert), ServerInstance->Time()) == -1) || (ASN1_UTCTIME_cmp_time_t(X509_get_notBefore(cert), ServerInstance->Time()) == 0))
static int error_callback(const char *str, size_t len, void *u)
{
- ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "SSL error: " + std::string(str, len - 1));
+ ServerInstance->Logs->Log("m_ssl_openssl", LOG_DEFAULT, "SSL error: " + std::string(str, len - 1));
//
// XXX: Remove this line, it causes valgrind warnings...
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 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
- * 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/>.
- */
-
-
-#ifndef HASH_H
-#define HASH_H
-
-#include "modules.h"
-
-class HashProvider : public DataProvider
-{
- public:
- const unsigned int out_size;
- const unsigned int block_size;
- HashProvider(Module* mod, const std::string& Name, int osiz, int bsiz)
- : DataProvider(mod, Name), out_size(osiz), block_size(bsiz) {}
- virtual std::string sum(const std::string& data) = 0;
- inline std::string hexsum(const std::string& data)
- {
- return BinToHex(sum(data));
- }
-
- inline std::string b64sum(const std::string& data)
- {
- return BinToBase64(sum(data), NULL, 0);
- }
-
- /** Allows the IVs for the hash to be specified. As the choice of initial IV is
- * important for the security of a hash, this should not be used except to
- * maintain backwards compatability. This also allows you to change the hex
- * sequence from its default of "0123456789abcdef", which does not improve the
- * strength of the output, but helps confuse those attempting to implement it.
- *
- * Example:
- * \code
- * unsigned int iv[] = { 0xFFFFFFFF, 0x00000000, 0xAAAAAAAA, 0xCCCCCCCC };
- * std::string result = Hash.sumIV(iv, "fedcba9876543210", "data");
- * \endcode
- */
- virtual std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata) = 0;
-
- /** HMAC algorithm, RFC 2104 */
- std::string hmac(const std::string& key, const std::string& msg)
- {
- std::string hmac1, hmac2;
- std::string kbuf = key.length() > block_size ? sum(key) : key;
- kbuf.resize(block_size);
-
- for (size_t n = 0; n < block_size; n++)
- {
- hmac1.push_back(static_cast<char>(kbuf[n] ^ 0x5C));
- hmac2.push_back(static_cast<char>(kbuf[n] ^ 0x36));
- }
- hmac2.append(msg);
- hmac1.append(sum(hmac2));
- return sum(hmac1);
- }
-};
-
-#endif
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
- * Copyright (C) 2007 John Brooks <john.brooks@dereferenced.net>
- * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
- * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
- *
- * 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 "base.h"
-
-#ifndef HTTPD_H
-#define HTTPD_H
-
-#include <string>
-#include <sstream>
-#include <map>
-
-/** A modifyable list of HTTP header fields
- */
-class HTTPHeaders
-{
- protected:
- std::map<std::string,std::string> headers;
- public:
-
- /** Set the value of a header
- * Sets the value of the named header. If the header is already present, it will be replaced
- */
- void SetHeader(const std::string &name, const std::string &data)
- {
- headers[name] = data;
- }
-
- /** Set the value of a header, only if it doesn't exist already
- * Sets the value of the named header. If the header is already present, it will NOT be updated
- */
- void CreateHeader(const std::string &name, const std::string &data)
- {
- if (!IsSet(name))
- SetHeader(name, data);
- }
-
- /** Remove the named header
- */
- void RemoveHeader(const std::string &name)
- {
- headers.erase(name);
- }
-
- /** Remove all headers
- */
- void Clear()
- {
- headers.clear();
- }
-
- /** Get the value of a header
- * @return The value of the header, or an empty string
- */
- std::string GetHeader(const std::string &name)
- {
- std::map<std::string,std::string>::iterator it = headers.find(name);
- if (it == headers.end())
- return std::string();
-
- return it->second;
- }
-
- /** Check if the given header is specified
- * @return true if the header is specified
- */
- bool IsSet(const std::string &name)
- {
- std::map<std::string,std::string>::iterator it = headers.find(name);
- return (it != headers.end());
- }
-
- /** Get all headers, formatted by the HTTP protocol
- * @return Returns all headers, formatted according to the HTTP protocol. There is no request terminator at the end
- */
- std::string GetFormattedHeaders()
- {
- std::string re;
-
- for (std::map<std::string,std::string>::iterator i = headers.begin(); i != headers.end(); i++)
- re += i->first + ": " + i->second + "\r\n";
-
- return re;
- }
-};
-
-class HttpServerSocket;
-
-/** This class represents a HTTP request.
- */
-class HTTPRequest : public Event
-{
- protected:
- std::string type;
- std::string document;
- std::string ipaddr;
- std::string postdata;
-
- public:
-
- HTTPHeaders *headers;
- int errorcode;
-
- /** A socket pointer, which you must return in your HTTPDocument class
- * if you reply to this request.
- */
- HttpServerSocket* sock;
-
- /** Initialize HTTPRequest.
- * This constructor is called by m_httpd.so to initialize the class.
- * @param request_type The request type, e.g. GET, POST, HEAD
- * @param uri The URI, e.g. /page
- * @param hdr The headers sent with the request
- * @param opaque An opaque pointer used internally by m_httpd, which you must pass back to the module in your reply.
- * @param ip The IP address making the web request.
- * @param pdata The post data (content after headers) received with the request, up to Content-Length in size
- */
- HTTPRequest(Module* me, const std::string &eventid, const std::string &request_type, const std::string &uri,
- HTTPHeaders* hdr, HttpServerSocket* socket, const std::string &ip, const std::string &pdata)
- : Event(me, eventid), type(request_type), document(uri), ipaddr(ip), postdata(pdata), headers(hdr), sock(socket)
- {
- }
-
- /** Get the post data (request content).
- * All post data will be returned, including carriage returns and linefeeds.
- * @return The postdata
- */
- std::string& GetPostData()
- {
- return postdata;
- }
-
- /** Get the request type.
- * Any request type can be intercepted, even ones which are invalid in the HTTP/1.1 spec.
- * @return The request type, e.g. GET, POST, HEAD
- */
- std::string& GetType()
- {
- return type;
- }
-
- /** Get URI.
- * The URI string (URL minus hostname and scheme) will be provided by this function.
- * @return The URI being requested
- */
- std::string& GetURI()
- {
- return document;
- }
-
- /** Get IP address of requester.
- * The requesting system's ip address will be returned.
- * @return The IP address as a string
- */
- std::string& GetIP()
- {
- return ipaddr;
- }
-};
-
-/** You must return a HTTPDocument to the httpd module by using the Request class.
- * When you initialize this class you may initialize it with all components required to
- * form a valid HTTP response, including document data, headers, and a response code.
- */
-class HTTPDocumentResponse : public Request
-{
- public:
- std::stringstream* document;
- int responsecode;
- HTTPHeaders headers;
- HTTPRequest& src;
-
- /** Initialize a HTTPRequest ready for sending to m_httpd.so.
- * @param opaque The socket pointer you obtained from the HTTPRequest at an earlier time
- * @param doc A stringstream containing the document body
- * @param response A valid HTTP/1.0 or HTTP/1.1 response code. The response text will be determined for you
- * based upon the response code.
- * @param extra Any extra headers to include with the defaults, seperated by carriage return and linefeed.
- */
- HTTPDocumentResponse(Module* me, HTTPRequest& req, std::stringstream* doc, int response)
- : Request(me, req.source, "HTTP-DOC"), document(doc), responsecode(response), src(req)
- {
- }
-};
-
-#endif
-
class ModuleAbbreviation : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->Attach(I_OnPreCommand, this);
}
ServerInstance->Modules->SetPriority(this, I_OnPreCommand, PRIORITY_FIRST);
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the ability to abbreviate commands a-la BBC BASIC keywords.",VF_VENDOR);
}
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
/* Command is already validated, has a length of 0, or last character is not a . */
if (validated || command.empty() || *command.rbegin() != '.')
class ModuleAlias : public Module
{
- private:
-
char fprefix;
/* We cant use a map, there may be multiple aliases with the same name.
* We can, however, use a fancy invention: the multimap. Maps a key to one or more values.
* -- w00t
- */
+ */
std::multimap<irc::string, Alias> Aliases;
/* whether or not +B users are allowed to use fantasy commands */
bool AllowBots;
- virtual void ReadAliases()
+ void ReadAliases()
{
ConfigTag* fantasy = ServerInstance->Config->ConfValue("fantasy");
AllowBots = fantasy->getBool("allowbots", false);
}
public:
-
- void init()
+ void init() CXX11_OVERRIDE
{
ReadAliases();
Implementation eventlist[] = { I_OnPreCommand, I_OnRehash, I_OnUserMessage };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleAlias()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides aliases of commands.", VF_VENDOR);
}
return word;
}
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
std::multimap<irc::string, Alias>::iterator i, upperbound;
return MOD_RES_PASSTHRU;
}
- virtual void OnUserMessage(User *user, void *dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
+ void OnUserMessage(User *user, void *dest, int target_type, const std::string &text, char status, const CUList &exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
- if (target_type != TYPE_CHANNEL)
+ if ((target_type != TYPE_CHANNEL) || (msgtype != MSG_PRIVMSG))
{
return;
}
}
}
- if ((a->OperOnly) && (!IS_OPER(user)))
+ if ((a->OperOnly) && (!user->IsOper()))
return 0;
if (!a->RequiredNick.empty())
std::string command, token;
ss.GetToken(command);
- while (ss.GetToken(token) && (pars.size() <= MAXPARAMETERS))
+ while (ss.GetToken(token))
{
pars.push_back(token);
}
ServerInstance->Parser->CallHandler(command, pars, user);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadAliases();
}
- virtual void Prioritize()
+ void Prioritize()
{
// Prioritise after spanningtree so that channel aliases show the alias before the effects.
Module* linkmod = ServerInstance->Modules->Find("m_spanningtree.so");
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(ni);
Implementation eventlist[] = { I_OnUserPreInvite, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('A');
+ tokens["EXTBAN"].push_back('A');
}
- virtual ModResult OnUserPreInvite(User* user,User* dest,Channel* channel, time_t timeout)
+ ModResult OnUserPreInvite(User* user,User* dest,Channel* channel, time_t timeout) CXX11_OVERRIDE
{
if (IS_LOCAL(user))
{
return MOD_RES_PASSTHRU;
}
- virtual ~ModuleAllowInvite()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for channel mode +A, allowing /invite freely on a channel and extban A to deny specific users it",VF_VENDOR);
}
}
};
-
class Modulealltime : public Module
{
CommandAlltime mycommand;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(mycommand);
}
- virtual ~Modulealltime()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Display timestamps from all servers connected to the network", VF_OPTCOMMON | VF_VENDOR);
}
class ModuleAuditorium : public Module
{
- private:
AuditoriumMode aum;
bool OpsVisible;
bool OpsCanSee;
bool OperCanSee;
+
public:
ModuleAuditorium() : aum(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(aum);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleAuditorium()
- {
- }
-
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("auditorium");
OpsVisible = tag->getBool("opvisible");
OperCanSee = tag->getBool("opercansee", true);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows for auditorium channels (+u) where nobody can see others joining and parting or the nick list", VF_VENDOR);
}
return false;
}
- void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick)
+ void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick) CXX11_OVERRIDE
{
// Some module already hid this from being displayed, don't bother
if (nick.empty())
}
}
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts)
+ void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) CXX11_OVERRIDE
{
BuildExcept(memb, excepts);
}
- void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts)
+ void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) CXX11_OVERRIDE
{
BuildExcept(memb, excepts);
}
- void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts)
+ void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) CXX11_OVERRIDE
{
BuildExcept(memb, excepts);
}
- void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception)
+ void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception) CXX11_OVERRIDE
{
UCListIter i = include.begin();
while (i != include.end())
}
}
- void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line)
+ void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line) CXX11_OVERRIDE
{
Channel* channel = ServerInstance->FindChan(params[0]);
if (!channel)
#include "inspircd.h"
-#include "u_listmode.h"
+#include "listmode.h"
/* $ModDesc: Provides support for the +w channel mode, autoop list */
{
AutoOpList mh;
-public:
+ public:
ModuleAutoOp() : mh(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(mh);
mh.DoImplements(this);
ServerInstance->Modules->Attach(list, this, sizeof(list)/sizeof(Implementation));
}
- void OnPostJoin(Membership *memb)
+ void OnPostJoin(Membership *memb) CXX11_OVERRIDE
{
if (!IS_LOCAL(memb->user))
return;
- modelist* list = mh.extItem.get(memb->chan);
+ ListModeBase::ModeList* list = mh.GetList(memb->chan);
if (list)
{
std::string modeline("+");
std::vector<std::string> modechange;
modechange.push_back(memb->chan->name);
- for (modelist::iterator it = list->begin(); it != list->end(); it++)
+ for (ListModeBase::ModeList::iterator it = list->begin(); it != list->end(); it++)
{
std::string::size_type colon = it->mask.find(':');
if (colon == std::string::npos)
}
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque)
+ void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
{
mh.DoSyncChannel(chan, proto, opaque);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
mh.DoRehash();
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the +w channel mode", VF_VENDOR);
}
#include "inspircd.h"
-#include "u_listmode.h"
+#include "listmode.h"
/* $ModDesc: Provides support for the +e channel mode */
-/* $ModDep: ../../include/u_listmode.h */
/* Written by Om<om@inspircd.org>, April 2005. */
/* Rewritten to use the listmode utility by Om, December 2005 */
{
BanException be;
-public:
+ public:
ModuleBanException() : be(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(be);
ServerInstance->Modules->Attach(list, this, sizeof(list)/sizeof(Implementation));
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" EXCEPTS=e");
+ tokens["EXCEPTS"] = "e";
}
- ModResult OnExtBanCheck(User *user, Channel *chan, char type)
+ ModResult OnExtBanCheck(User *user, Channel *chan, char type) CXX11_OVERRIDE
{
if (chan != NULL)
{
- modelist *list = be.extItem.get(chan);
+ ListModeBase::ModeList *list = be.GetList(chan);
if (!list)
return MOD_RES_PASSTHRU;
- for (modelist::iterator it = list->begin(); it != list->end(); it++)
+ for (ListModeBase::ModeList::iterator it = list->begin(); it != list->end(); it++)
{
if (it->mask[0] != type || it->mask[1] != ':')
continue;
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckChannelBan(User* user, Channel* chan)
+ ModResult OnCheckChannelBan(User* user, Channel* chan) CXX11_OVERRIDE
{
if (chan)
{
- modelist *list = be.extItem.get(chan);
+ ListModeBase::ModeList *list = be.GetList(chan);
if (!list)
{
return MOD_RES_PASSTHRU;
}
- for (modelist::iterator it = list->begin(); it != list->end(); it++)
+ for (ListModeBase::ModeList::iterator it = list->begin(); it != list->end(); it++)
{
if (chan->CheckBan(user, it->mask))
{
return MOD_RES_PASSTHRU;
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque)
+ void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
{
be.DoSyncChannel(chan, proto, opaque);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
be.DoRehash();
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the +e channel mode", VF_VENDOR);
}
#include "inspircd.h"
-#include "u_listmode.h"
+#include "listmode.h"
/* $ModDesc: Allows an extended ban (+b) syntax redirecting banned users to another channel */
};
typedef std::vector<BanRedirectEntry> BanRedirectList;
-typedef std::deque<std::string> StringDeque;
class BanRedirect : public ModeWatcher
{
+ ModeReference ban;
public:
SimpleExtItem<BanRedirectList> extItem;
- BanRedirect(Module* parent) : ModeWatcher(parent, 'b', MODETYPE_CHANNEL),
- extItem("banredirect", parent)
+ BanRedirect(Module* parent)
+ : ModeWatcher(parent, "ban", MODETYPE_CHANNEL)
+ , ban(parent, "ban")
+ , extItem("banredirect", parent)
{
}
- bool BeforeMode(User* source, User* dest, Channel* channel, std::string ¶m, bool adding, ModeType type)
+ bool BeforeMode(User* source, User* dest, Channel* channel, std::string ¶m, bool adding)
{
/* nick!ident@host -> nick!ident@host
* nick!ident@host#chan -> nick!ident@host#chan
* nick#chan -> nick!*@*#chan
*/
- if(channel && (type == MODETYPE_CHANNEL) && param.length())
+ if ((channel) && !param.empty())
{
BanRedirectList* redirects;
std::string mask[4];
enum { NICK, IDENT, HOST, CHAN } current = NICK;
std::string::iterator start_pos = param.begin();
- long maxbans = channel->GetMaxBans();
if (param.length() >= 2 && param[1] == ':')
return true;
- if(adding && (channel->bans.size() > static_cast<unsigned>(maxbans)))
+ ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
+ unsigned int maxbans = banlm->GetLimit(channel);
+ ListModeBase::ModeList* list = banlm->GetList(channel);
+ if ((list) && (adding) && (maxbans <= list->size()))
{
- source->WriteNumeric(478, "%s %s :Channel ban list for %s is full (maximum entries for this channel is %ld)", source->nick.c_str(), channel->name.c_str(), channel->name.c_str(), maxbans);
+ source->WriteNumeric(478, "%s %s :Channel ban list for %s is full (maximum entries for this channel is %u)", source->nick.c_str(), channel->name.c_str(), channel->name.c_str(), maxbans);
return false;
}
{
if (adding && IS_LOCAL(source))
{
- if (!ServerInstance->IsChannel(mask[CHAN].c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (!ServerInstance->IsChannel(mask[CHAN]))
{
source->WriteNumeric(403, "%s %s :Invalid channel name in redirection (%s)", source->nick.c_str(), channel->name.c_str(), mask[CHAN].c_str());
return false;
}
- void init()
+ void init() CXX11_OVERRIDE
{
- if(!ServerInstance->Modes->AddModeWatcher(&re))
- throw ModuleException("Could not add mode watcher");
-
+ ServerInstance->Modes->AddModeWatcher(&re);
ServerInstance->Modules->AddService(re.extItem);
Implementation list[] = { I_OnUserPreJoin };
ServerInstance->Modules->Attach(list, this, sizeof(list)/sizeof(Implementation));
}
- virtual void OnCleanup(int target_type, void* item)
+ void OnCleanup(int target_type, void* item) CXX11_OVERRIDE
{
if(target_type == TYPE_CHANNEL)
{
if(redirects)
{
irc::modestacker modestack(false);
- StringDeque stackresult;
+ std::vector<std::string> stackresult;
std::vector<std::string> mode_junk;
mode_junk.push_back(chan->name);
}
}
- virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
if (chan)
{
user->WriteNumeric(474, "%s %s :Cannot join channel (You are banned)", user->nick.c_str(), chan->name.c_str());
user->WriteNumeric(470, "%s %s %s :You are banned from this channel, so you are automatically transfered to the redirected channel.", user->nick.c_str(), chan->name.c_str(), redir->targetchan.c_str());
nofollow = true;
- Channel::JoinUser(user, redir->targetchan.c_str(), false, "", false, ServerInstance->Time());
+ Channel::JoinUser(user, redir->targetchan);
nofollow = false;
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
}
- virtual ~ModuleBanRedirect()
+ ~ModuleBanRedirect()
{
/* XXX is this the best place to do this? */
if (!ServerInstance->Modes->DelModeWatcher(&re))
- ServerInstance->Logs->Log("m_banredirect.so", DEBUG, "Failed to delete modewatcher!");
+ ServerInstance->Logs->Log("m_banredirect.so", LOG_DEBUG, "Failed to delete modewatcher!");
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows an extended ban (+b) syntax redirecting banned users to another channel", VF_COMMON|VF_VENDOR);
}
*/
class BlockedMessage
{
-public:
+ public:
std::string message;
irc::string target;
time_t sent;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
this->OnRehash(NULL);
ServerInstance->Modules->AddService(blockamsg);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleBlockAmsg()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Attempt to block /amsg, at least some of the irritating mIRC scripts.",VF_VENDOR);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("blockamsg");
ForgetDelay = tag->getInt("delay", -1);
action = IBLOCK_KILLOPERS;
}
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
// Don't do anything with unregistered users
if (user->registered != REG_ALL)
}
};
-
MODULE_INIT(ModuleBlockAmsg)
int percent;
unsigned int minlen;
char capsmap[256];
-public:
+public:
ModuleBlockCAPS() : bc(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->AddService(bc);
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_On005Numeric };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_OnRehash, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('B');
+ tokens["EXTBAN"].push_back('B');
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadConf();
}
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (target_type == TYPE_CHANNEL)
{
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
- }
-
void ReadConf()
{
ConfigTag* tag = ServerInstance->Config->ConfValue("blockcaps");
capsmap[(unsigned char)*n] = 1;
if (percent < 1 || percent > 100)
{
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "<blockcaps:percent> out of range, setting to default of 100.");
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "<blockcaps:percent> out of range, setting to default of 100.");
percent = 100;
}
if (minlen < 1 || minlen > MAXBUF-1)
{
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "<blockcaps:minlen> out of range, setting to default of 1.");
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "<blockcaps:minlen> out of range, setting to default of 1.");
minlen = 1;
}
}
- virtual ~ModuleBlockCAPS()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support to block all-CAPS channel messages and notices", VF_VENDOR);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(bc);
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_On005Numeric };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('c');
+ tokens["EXTBAN"].push_back('c');
}
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if ((target_type == TYPE_CHANNEL) && (IS_LOCAL(user)))
{
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
- }
-
- virtual ~ModuleBlockColor()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +c to block color",VF_VENDOR);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(bm);
Implementation eventlist[] = { I_OnWhois };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleBotMode()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides user mode +B to mark the user as a bot",VF_VENDOR);
}
- virtual void OnWhois(User* src, User* dst)
+ void OnWhois(User* src, User* dst) CXX11_OVERRIDE
{
if (dst->IsModeSet('B'))
{
ServerInstance->SendWhoisLine(src, dst, 335, src->nick+" "+dst->nick+" :is a bot on "+ServerInstance->Config->Network);
}
}
-
};
-
MODULE_INIT(ModuleBotMode)
if (!targ)
{
- ServerInstance->Logs->Log("m_callerid", DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (1)");
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (1)");
continue; // shouldn't happen, but oh well.
}
if (it2 != targ->wholistsme.end())
targ->wholistsme.erase(it2);
else
- ServerInstance->Logs->Log("m_callerid", DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (2)");
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (2)");
}
delete dat;
}
TRANSLATE2(TR_CUSTOM, TR_END);
}
- virtual void EncodeParameter(std::string& parameter, int index)
+ void EncodeParameter(std::string& parameter, int index)
{
if (index != 0)
return;
callerid_data *targ = extInfo.get(whotoadd, true);
targ->wholistsme.push_back(dat);
- user->WriteServ("NOTICE %s :%s is now on your accept list", user->nick.c_str(), whotoadd->nick.c_str());
+ user->WriteNotice(whotoadd->nick + " is now on your accept list");
return true;
}
if (!dat2)
{
// How the fuck is this possible.
- ServerInstance->Logs->Log("m_callerid", DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (3)");
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (3)");
return false;
}
// Found me!
dat2->wholistsme.erase(it);
else
- ServerInstance->Logs->Log("m_callerid", DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (4)");
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (4)");
- user->WriteServ("NOTICE %s :%s is no longer on your accept list", user->nick.c_str(), whotoremove->nick.c_str());
+ user->WriteNotice(whotoremove->nick + " is no longer on your accept list");
return true;
}
};
class ModuleCallerID : public Module
{
-private:
CommandAccept cmd;
User_g myumode;
if (it2 != dat->accepting.end())
dat->accepting.erase(it2);
else
- ServerInstance->Logs->Log("m_callerid", DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (5)");
+ ServerInstance->Logs->Log("m_callerid", LOG_DEFAULT, "ERROR: Inconsistency detected in callerid state, please report (5)");
}
userdata->wholistsme.clear();
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->AddService(cmd.extInfo);
- Implementation eventlist[] = { I_OnRehash, I_OnUserPostNick, I_OnUserQuit, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage };
+ Implementation eventlist[] = { I_OnRehash, I_OnUserPostNick, I_OnUserQuit, I_On005Numeric, I_OnUserPreMessage };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleCallerID()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implementation of callerid, usermode +g, /accept", VF_COMMON | VF_VENDOR);
}
- virtual void On005Numeric(std::string& output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output += " CALLERID=g";
+ tokens["CALLERID"] = "g";
}
ModResult PreText(User* user, User* dest, std::string& text)
if (!dest->IsModeSet('g') || (user == dest))
return MOD_RES_PASSTHRU;
- if (operoverride && IS_OPER(user))
+ if (operoverride && user->IsOper())
return MOD_RES_PASSTHRU;
callerid_data* dat = cmd.extInfo.get(dest, true);
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList &exempt_list)
- {
- if (IS_LOCAL(user) && target_type == TYPE_USER)
- return PreText(user, (User*)dest, text);
-
- return MOD_RES_PASSTHRU;
- }
-
- virtual ModResult OnUserPreNotice(User* user, void* dest, int target_type, std::string& text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (IS_LOCAL(user) && target_type == TYPE_USER)
return PreText(user, (User*)dest, text);
return MOD_RES_PASSTHRU;
}
- void OnUserPostNick(User* user, const std::string& oldnick)
+ void OnUserPostNick(User* user, const std::string& oldnick) CXX11_OVERRIDE
{
if (!tracknick)
RemoveFromAllAccepts(user);
}
- void OnUserQuit(User* user, const std::string& message, const std::string& oper_message)
+ void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) CXX11_OVERRIDE
{
RemoveFromAllAccepts(user);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("callerid");
cmd.maxaccepts = tag->getInt("maxaccepts", 16);
};
MODULE_INIT(ModuleCallerID)
-
-
#include "inspircd.h"
-#include "m_cap.h"
+#include "modules/cap.h"
/* $ModDesc: Provides the CAP negotiation mechanism seen in ratbox-derived ircds */
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->AddService(cmd.reghold);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ModResult OnCheckReady(LocalUser* user)
+ ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
/* Users in CAP state get held until CAP END */
if (cmd.reghold.get(user))
return MOD_RES_PASSTHRU;
}
- ~ModuleCAP()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Client CAP extension support", VF_VENDOR);
}
};
MODULE_INIT(ModuleCAP)
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
- *
- * 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/>.
- */
-
-
-#ifndef M_CAP_H
-#define M_CAP_H
-
-class CapEvent : public Event
-{
- public:
- enum CapEventType
- {
- CAPEVENT_REQ,
- CAPEVENT_LS,
- CAPEVENT_LIST,
- CAPEVENT_CLEAR
- };
-
- CapEventType type;
- std::vector<std::string> wanted;
- std::vector<std::string> ack;
- User* user;
- CapEvent(Module* sender, User* u, CapEventType capevtype) : Event(sender, "cap_request"), type(capevtype), user(u) {}
-};
-
-class GenericCap
-{
- public:
- LocalIntExt ext;
- const std::string cap;
- GenericCap(Module* parent, const std::string &Cap) : ext("cap_" + Cap, parent), cap(Cap)
- {
- ServerInstance->Modules->AddService(ext);
- }
-
- void HandleEvent(Event& ev)
- {
- if (ev.id != "cap_request")
- return;
-
- CapEvent *data = static_cast<CapEvent*>(&ev);
- if (data->type == CapEvent::CAPEVENT_REQ)
- {
- for (std::vector<std::string>::iterator it = data->wanted.begin(); it != data->wanted.end(); ++it)
- {
- if (it->empty())
- continue;
- bool enablecap = ((*it)[0] != '-');
- if (((enablecap) && (*it == cap)) || (*it == "-" + cap))
- {
- // 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);
- break;
- }
- }
- }
- else if (data->type == CapEvent::CAPEVENT_LS)
- {
- data->wanted.push_back(cap);
- }
- else if (data->type == CapEvent::CAPEVENT_LIST)
- {
- if (ext.get(data->user))
- data->wanted.push_back(cap);
- }
- else if (data->type == CapEvent::CAPEVENT_CLEAR)
- {
- data->ack.push_back("-" + cap);
- ext.set(data->user, 0);
- }
- }
-};
-
-#endif
*/
class CBan : public XLine
{
-public:
+private:
+ std::string displaytext;
irc::string matchtext;
+public:
CBan(time_t s_time, long d, const std::string& src, const std::string& re, const std::string& ch)
: XLine(s_time, d, src, re, "CBAN")
{
+ this->displaytext = ch;
this->matchtext = ch.c_str();
}
- ~CBan()
- {
- }
-
// XXX I shouldn't have to define this
bool Matches(User *u)
{
return false;
}
- void DisplayExpiry()
+ const std::string& Displayable()
{
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired CBan %s (set by %s %ld seconds ago)",
- this->matchtext.c_str(), this->source.c_str(), (long int)(ServerInstance->Time() - this->set_time));
- }
-
- const char* Displayable()
- {
- return matchtext.c_str();
+ return displaytext;
}
};
}
else
{
- user->WriteServ("NOTICE %s :*** CBan %s not found in list, try /stats C.",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNotice("*** CBan " + parameters[0] + " not found in list, try /stats C.");
return CMD_FAILURE;
}
}
else
{
// Adding - XXX todo make this respect <insane> tag perhaps..
- long duration = ServerInstance->Duration(parameters[1]);
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
const char *reason = (parameters.size() > 2) ? parameters[2].c_str() : "No reason supplied";
CBan* r = new CBan(ServerInstance->Time(), duration, user->nick.c_str(), reason, parameters[0].c_str());
else
{
delete r;
- user->WriteServ("NOTICE %s :*** CBan for %s already exists", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** CBan for " + parameters[0] + " already exists");
return CMD_FAILURE;
}
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->XLines->RegisterFactory(&f);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleCBan()
+ ~ModuleCBan()
{
ServerInstance->XLines->DelAll("CBAN");
ServerInstance->XLines->UnregisterFactory(&f);
}
- virtual ModResult OnStats(char symbol, User* user, string_list &out)
+ ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
{
if (symbol != 'C')
return MOD_RES_PASSTHRU;
return MOD_RES_DENY;
}
- virtual ModResult OnUserPreJoin(User *user, Channel *chan, const char *cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
XLine *rl = ServerInstance->XLines->MatchesLine("CBAN", cname);
if (rl)
{
// Channel is banned.
- user->WriteServ( "384 %s %s :Cannot join channel, CBANed (%s)", user->nick.c_str(), cname, rl->reason.c_str());
+ user->WriteServ( "384 %s %s :Cannot join channel, CBANed (%s)", user->nick.c_str(), cname.c_str(), rl->reason.c_str());
ServerInstance->SNO->WriteGlobalSno('a', "%s tried to join %s which is CBANed (%s)",
- user->nick.c_str(), cname, rl->reason.c_str());
+ user->nick.c_str(), cname.c_str(), rl->reason.c_str());
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Gives /cban, aka C:lines. Think Q:lines, for channels.", VF_COMMON | VF_VENDOR);
}
};
MODULE_INIT(ModuleCBan)
-
public:
ModuleCensor() : cu(this), cc(this) { }
- void init()
+ void init() CXX11_OVERRIDE
{
/* Read the configuration file on startup.
*/
OnRehash(NULL);
ServerInstance->Modules->AddService(cu);
ServerInstance->Modules->AddService(cc);
- Implementation eventlist[] = { I_OnRehash, I_OnUserPreMessage, I_OnUserPreNotice };
+ Implementation eventlist[] = { I_OnRehash, I_OnUserPreMessage };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
-
- virtual ~ModuleCensor()
- {
- }
-
// format of a config entry is <badword text="shit" replace="poo">
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
- }
-
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
/*
* reload our config file on rehash - we must destroy and re-allocate the classes
}
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides user and channel +G mode",VF_VENDOR);
}
#include "inspircd.h"
#include "xline.h"
+#include "modules/dns.h"
/* $ModDesc: Change user's hosts connecting from known CGI:IRC hosts */
/** Resolver for CGI:IRC hostnames encoded in ident/GECOS
*/
-class CGIResolver : public Resolver
+class CGIResolver : public DNS::Request
{
std::string typ;
std::string theiruid;
LocalIntExt& waiting;
bool notify;
public:
- CGIResolver(Module* me, bool NotifyOpers, const std::string &source, LocalUser* u,
- const std::string &type, bool &cached, LocalIntExt& ext)
- : Resolver(source, DNS_QUERY_PTR4, cached, me), typ(type), theiruid(u->uuid),
+ CGIResolver(DNS::Manager *mgr, Module* me, bool NotifyOpers, const std::string &source, LocalUser* u,
+ const std::string &ttype, LocalIntExt& ext)
+ : DNS::Request(mgr, me, source, DNS::QUERY_PTR), typ(ttype), theiruid(u->uuid),
waiting(ext), notify(NotifyOpers)
{
}
- virtual void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
+ void OnLookupComplete(const DNS::Query *r) CXX11_OVERRIDE
{
/* Check the user still exists */
User* them = ServerInstance->FindUUID(theiruid);
if ((them) && (!them->quitting))
{
- if (notify)
- ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", them->nick.c_str(), them->host.c_str(), result.c_str(), typ.c_str());
+ LocalUser* lu = IS_LOCAL(them);
+ if (!lu)
+ return;
- if (result.length() > 64)
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+ if (ans_record.rdata.empty() || ans_record.rdata.length() > 64)
return;
- them->host = result;
- them->dhost = result;
+
+ if (notify)
+ ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", them->nick.c_str(), them->host.c_str(), ans_record.rdata.c_str(), typ.c_str());
+
+ them->host = them->dhost = ans_record.rdata;
them->InvalidateCache();
- them->CheckLines(true);
+ lu->CheckLines(true);
}
}
- virtual void OnError(ResolverError e, const std::string &errormessage)
+ void OnError(const DNS::Query *r) CXX11_OVERRIDE
{
if (!notify)
return;
}
}
- virtual ~CGIResolver()
+ ~CGIResolver()
{
User* them = ServerInstance->FindUUID(theiruid);
if (!them)
{
CommandWebirc cmd;
LocalIntExt waiting;
+ dynamic_reference<DNS::Manager> DNS;
static void RecheckClass(LocalUser* user)
{
user->host = user->dhost = user->GetIPString();
user->InvalidateCache();
RecheckClass(user);
+
// Don't create the resolver if the core couldn't put the user in a connect class or when dns is disabled
- if (user->quitting || ServerInstance->Config->NoUserDns)
+ if (user->quitting || !DNS || user->MyClass->nouserdns)
return;
+ CGIResolver* r = new CGIResolver(*this->DNS, this, cmd.notify, newip, user, (was_pass ? "PASS" : "IDENT"), waiting);
try
{
- bool cached;
- CGIResolver* r = new CGIResolver(this, cmd.notify, newip, user, (was_pass ? "PASS" : "IDENT"), cached, waiting);
- ServerInstance->AddResolver(r, cached);
waiting.set(user, waiting.get(user) + 1);
+ this->DNS->Process(r);
}
- catch (...)
+ catch (DNS::Exception &ex)
{
+ int count = waiting.get(user);
+ if (count)
+ waiting.set(user, count - 1);
+ delete r;
if (cmd.notify)
- ServerInstance->SNO->WriteToSnoMask('a', "Connecting user %s detected as using CGI:IRC (%s), but I could not resolve their hostname!", user->nick.c_str(), user->host.c_str());
+ ServerInstance->SNO->WriteToSnoMask('a', "Connecting user %s detected as using CGI:IRC (%s), but I could not resolve their hostname; %s", user->nick.c_str(), user->host.c_str(), ex.GetReason());
}
}
public:
- ModuleCgiIRC() : cmd(this), waiting("cgiirc-delay", this)
+ ModuleCgiIRC()
+ : cmd(this)
+ , waiting("cgiirc-delay", this)
+ , DNS(this, "DNS")
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServiceProvider* providerlist[] = { &cmd, &cmd.realhost, &cmd.realip, &cmd.webirc_hostname, &cmd.webirc_ip, &waiting };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
cmd.Hosts.clear();
{
if (type == "webirc" && password.empty())
{
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "m_cgiirc: Missing password in config: %s", hostmask.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "m_cgiirc: Missing password in config: %s", hostmask.c_str());
}
else
{
else
{
cgitype = PASS;
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "m_cgiirc.so: Invalid <cgihost:type> value in config: %s, setting it to \"pass\"", type.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "m_cgiirc.so: Invalid <cgihost:type> value in config: %s, setting it to \"pass\"", type.c_str());
}
cmd.Hosts.push_back(CGIhost(hostmask, cgitype, password));
}
else
{
- ServerInstance->Logs->Log("CONFIG",DEFAULT, "m_cgiirc.so: Invalid <cgihost:mask> value in config: %s", hostmask.c_str());
+ ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "m_cgiirc.so: Invalid <cgihost:mask> value in config: %s", hostmask.c_str());
continue;
}
}
}
- ModResult OnCheckReady(LocalUser *user)
+ ModResult OnCheckReady(LocalUser *user) CXX11_OVERRIDE
{
if (waiting.get(user))
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
- ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
for(CGIHostlist::iterator iter = cmd.Hosts.begin(); iter != cmd.Hosts.end(); iter++)
{
return true;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Change user's hosts connecting from known CGI:IRC hosts",VF_VENDOR);
}
class ModuleChanCreate : public Module
{
- private:
public:
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->SNO->EnableSnomask('j', "CHANCREATE");
Implementation eventlist[] = { I_OnUserJoin };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides snomasks 'j' and 'J', to which notices about newly created channels are sent",VF_VENDOR);
}
-
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& except)
+ void OnUserJoin(Membership* memb, bool sync, bool created, CUList& except) CXX11_OVERRIDE
{
if ((created) && (IS_LOCAL(memb->user)))
{
#define _SCL_SECURE_NO_DEPRECATE
#include "inspircd.h"
-#include "u_listmode.h"
+#include "listmode.h"
/** Handles channel mode +g
*/
public:
ChanFilter(Module* Creator) : ListModeBase(Creator, "filter", 'g', "End of channel spamfilter list", 941, 940, false, "chanfilter") { }
- virtual bool ValidateParam(User* user, Channel* chan, std::string &word)
+ bool ValidateParam(User* user, Channel* chan, std::string &word)
{
if ((word.length() > 35) || (word.empty()))
{
return true;
}
- virtual bool TellListTooLong(User* user, Channel* chan, std::string &word)
+ void TellListTooLong(User* user, Channel* chan, std::string &word)
{
user->WriteNumeric(939, "%s %s %s :Channel spamfilter list is full", user->nick.c_str(), chan->name.c_str(), word.c_str());
- return true;
}
- virtual void TellAlreadyOnList(User* user, Channel* chan, std::string &word)
+ void TellAlreadyOnList(User* user, Channel* chan, std::string &word)
{
user->WriteNumeric(937, "%s %s :The word %s is already on the spamfilter list",user->nick.c_str(), chan->name.c_str(), word.c_str());
}
- virtual void TellNotSet(User* user, Channel* chan, std::string &word)
+ void TellNotSet(User* user, Channel* chan, std::string &word)
{
user->WriteNumeric(938, "%s %s :No such spamfilter word is set",user->nick.c_str(), chan->name.c_str());
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cf);
cf.DoImplements(this);
- Implementation eventlist[] = { I_OnRehash, I_OnUserPreMessage, I_OnUserPreNotice, I_OnSyncChannel };
+ Implementation eventlist[] = { I_OnRehash, I_OnUserPreMessage, I_OnSyncChannel };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
hidemask = ServerInstance->Config->ConfValue("chanfilter")->getBool("hidemask");
cf.DoRehash();
}
- virtual ModResult ProcessMessages(User* user,Channel* chan,std::string &text)
+ ModResult ProcessMessages(User* user,Channel* chan,std::string &text)
{
ModResult res = ServerInstance->OnCheckExemption(user,chan,"filter");
if (!IS_LOCAL(user) || res == MOD_RES_ALLOW)
return MOD_RES_PASSTHRU;
- modelist* list = cf.extItem.get(chan);
+ ListModeBase::ModeList* list = cf.GetList(chan);
if (list)
{
- for (modelist::iterator i = list->begin(); i != list->end(); i++)
+ for (ListModeBase::ModeList::iterator i = list->begin(); i != list->end(); i++)
{
if (InspIRCd::Match(text, i->mask))
{
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (target_type == TYPE_CHANNEL)
{
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
- }
-
- virtual void OnSyncChannel(Channel* chan, Module* proto, void* opaque)
+ void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
{
cf.DoSyncChannel(chan, proto, opaque);
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel-specific censor lists (like mode +G but varies from channel to channel)", VF_VENDOR);
}
-
- virtual ~ModuleChanFilter()
- {
- }
};
MODULE_INIT(ModuleChanFilter)
return MODEACTION_DENY;
unsigned int len = ConvToInt(parameter.substr(0, colon));
- int time = ServerInstance->Duration(duration);
+ int time = InspIRCd::Duration(duration);
if (len == 0 || time < 0)
return MODEACTION_DENY;
if (len > maxlines && IS_LOCAL(source))
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(m);
ServerInstance->Modules->AddService(m.ext);
OnRehash(NULL);
}
- void OnRehash(User*)
+ void OnRehash(User*) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("chanhistory");
m.maxlines = tag->getInt("maxlines", 50);
sendnotice = tag->getBool("notice", true);
}
- void OnUserMessage(User* user,void* dest,int target_type, const std::string &text, char status, const CUList&)
+ void OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList&, MessageType msgtype) CXX11_OVERRIDE
{
- if (target_type == TYPE_CHANNEL && status == 0)
+ if ((target_type == TYPE_CHANNEL) && (status == 0) && (msgtype == MSG_PRIVMSG))
{
Channel* c = (Channel*)dest;
HistoryList* list = m.ext.get(c);
if (list)
{
- char buf[MAXBUF];
- snprintf(buf, MAXBUF, ":%s PRIVMSG %s :%s",
- user->GetFullHost().c_str(), c->name.c_str(), text.c_str());
- list->lines.push_back(HistoryItem(buf));
+ const std::string line = ":" + user->GetFullHost() + " PRIVMSG " + c->name + " :" + text;
+ list->lines.push_back(HistoryItem(line));
if (list->lines.size() > list->maxlen)
list->lines.pop_front();
}
}
}
- void OnPostJoin(Membership* memb)
+ void OnPostJoin(Membership* memb) CXX11_OVERRIDE
{
if (IS_REMOTE(memb->user))
return;
if (sendnotice)
{
- memb->user->WriteServ("NOTICE %s :Replaying up to %d lines of pre-join history spanning up to %d seconds",
- memb->chan->name.c_str(), list->maxlen, list->maxtime);
+ memb->user->WriteNotice("Replaying up to " + ConvToStr(list->maxlen) + " lines of pre-join history spanning up to " + ConvToStr(list->maxtime) + " seconds");
}
for(std::deque<HistoryItem>::iterator i = list->lines.begin(); i != list->lines.end(); ++i)
}
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel history replayed on join", VF_VENDOR);
}
class ModuleChanLog : public Module
{
- private:
/*
* Multimap so people can redirect a snomask to multiple channels.
*/
ChanLogTargets logstreams;
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnRehash, I_OnSendSnotice };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- virtual ~ModuleChanLog()
- {
- }
-
- virtual void OnRehash(User *user)
+ void OnRehash(User *user) CXX11_OVERRIDE
{
std::string snomasks;
std::string channel;
if (channel.empty() || snomasks.empty())
{
- ServerInstance->Logs->Log("m_chanlog", DEFAULT, "Malformed chanlog tag, ignoring");
+ ServerInstance->Logs->Log("m_chanlog", LOG_DEFAULT, "Malformed chanlog tag, ignoring");
continue;
}
for (std::string::const_iterator it = snomasks.begin(); it != snomasks.end(); it++)
{
logstreams.insert(std::make_pair(*it, channel));
- ServerInstance->Logs->Log("m_chanlog", DEFAULT, "Logging %c to %s", *it, channel.c_str());
+ ServerInstance->Logs->Log("m_chanlog", LOG_DEFAULT, "Logging %c to %s", *it, channel.c_str());
}
}
}
- virtual ModResult OnSendSnotice(char &sno, std::string &desc, const std::string &msg)
+ ModResult OnSendSnotice(char &sno, std::string &desc, const std::string &msg) CXX11_OVERRIDE
{
std::pair<ChanLogTargets::const_iterator, ChanLogTargets::const_iterator> itpair = logstreams.equal_range(sno);
if (itpair.first == itpair.second)
return MOD_RES_PASSTHRU;
- char buf[MAXBUF];
- snprintf(buf, MAXBUF, "\2%s\2: %s", desc.c_str(), msg.c_str());
+ const std::string snotice = "\2" + desc + "\2: " + msg;
for (ChanLogTargets::const_iterator it = itpair.first; it != itpair.second; ++it)
{
Channel *c = ServerInstance->FindChan(it->second);
if (c)
{
- c->WriteChannelWithServ(ServerInstance->Config->ServerName, "PRIVMSG %s :%s", c->name.c_str(), buf);
- ServerInstance->PI->SendChannelPrivmsg(c, 0, buf);
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "PRIVMSG %s :%s", c->name.c_str(), snotice.c_str());
+ ServerInstance->PI->SendChannelPrivmsg(c, 0, snotice);
}
}
return MOD_RES_PASSTHRU;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Logs snomask output to channel(s).", VF_VENDOR);
}
};
-
MODULE_INIT(ModuleChanLog)
-
-
-
-
-
-
-
-
-
-/*
- * This is for the "old" chanlog module which intercepted messages going to the logfile..
- * I don't consider it all that useful, and it's quite dangerous if setup incorrectly, so
- * this is defined out but left intact in case someone wants to develop it further someday.
- *
- * -- w00t (aug 23rd, 2008)
- */
-#define OLD_CHANLOG 0
-
-#if OLD_CHANLOG
-class ChannelLogStream : public LogStream
-{
- private:
- std::string channel;
-
- public:
- ChannelLogStream(int loglevel, const std::string &chan) : LogStream(loglevel), channel(chan)
- {
- }
-
- virtual void OnLog(int loglevel, const std::string &type, const std::string &msg)
- {
- Channel *c = ServerInstance->FindChan(channel);
- static bool Logging = false;
-
- if (loglevel < this->loglvl)
- return;
-
- if (Logging)
- return;
-
- if (c)
- {
- Logging = true; // this avoids (rare chance) loops with logging server IO on networks
- char buf[MAXBUF];
- snprintf(buf, MAXBUF, "\2%s\2: %s", type.c_str(), msg.c_str());
-
- c->WriteChannelWithServ(ServerInstance->Config->ServerName, "PRIVMSG %s :%s", c->name.c_str(), buf);
- ServerInstance->PI->SendChannelPrivmsg(c, 0, buf);
- Logging = false;
- }
- }
-};
-#endif
-
static std::bitset<256> allowedmap;
-class NewIsChannelHandler : public HandlerBase2<bool, const char*, size_t>
+class NewIsChannelHandler : public HandlerBase1<bool, const std::string&>
{
public:
NewIsChannelHandler() { }
- virtual ~NewIsChannelHandler() { }
- virtual bool Call(const char*, size_t);
+ ~NewIsChannelHandler() { }
+ bool Call(const std::string&);
};
-bool NewIsChannelHandler::Call(const char* c, size_t max)
+bool NewIsChannelHandler::Call(const std::string& channame)
{
- /* check for no name - don't check for !*chname, as if it is empty, it won't be '#'! */
- if (!c || *c++ != '#')
+ if (channame.empty() || channame.length() > ServerInstance->Config->Limits.ChanMax || channame[0] != '#')
+ return false;
+
+ for (std::string::const_iterator c = channame.begin(); c != channame.end(); ++c)
+ {
+ unsigned int i = *c & 0xFF;
+ if (!allowedmap[i])
return false;
+ }
- while (*c && --max)
- {
- unsigned int i = *c++ & 0xFF;
- if (!allowedmap[i])
- return false;
- }
- // a name of exactly max length will have max = 1 here; the null does not trigger --max
- return max;
+ return true;
}
class ModuleChannelNames : public Module
{
- private:
NewIsChannelHandler myhandler;
- caller2<bool, const char*, size_t> rememberer;
+ caller1<bool, const std::string&> rememberer;
bool badchan;
public:
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->IsChannel = &myhandler;
Implementation eventlist[] = { I_OnRehash, I_OnUserKick };
std::vector<Channel*> chanvec;
for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); ++i)
{
- if (!ServerInstance->IsChannel(i->second->name.c_str(), MAXBUF))
+ if (!ServerInstance->IsChannel(i->second->name))
chanvec.push_back(i->second);
}
std::vector<Channel*>::reverse_iterator c2 = chanvec.rbegin();
badchan = false;
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("channames");
std::string denyToken = tag->getString("denyrange");
ValidateChans();
}
- virtual void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& except_list)
+ void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& except_list) CXX11_OVERRIDE
{
if (badchan)
{
}
}
- virtual ~ModuleChannelNames()
+ ~ModuleChannelNames()
{
ServerInstance->IsChannel = rememberer;
ValidateChans();
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements config tags which allow changing characters allowed in channel names", VF_VENDOR);
}
class ModuleBadChannelExtban : public Module
{
- private:
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleBadChannelExtban()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Extban 'j' - channel status/join ban", VF_OPTCOMMON|VF_VENDOR);
}
- ModResult OnCheckBan(User *user, Channel *c, const std::string& mask)
+ ModResult OnCheckBan(User *user, Channel *c, const std::string& mask) CXX11_OVERRIDE
{
if ((mask.length() > 2) && (mask[0] == 'j') && (mask[1] == ':'))
{
return MOD_RES_PASSTHRU;
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('j');
+ tokens["EXTBAN"].push_back('j');
}
};
-
MODULE_INIT(ModuleBadChannelExtban)
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2006-2009 Robin Burchell <robin+git@viroteck.net>
- * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
- * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
- * Copyright (C) 2004-2008 Craig Edwards <craigedwards@brainbox.cc>
- * Copyright (C) 2007 John Brooks <john.brooks@dereferenced.net>
- * Copyright (C) 2007 Dennis Friis <peavey@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
- * License as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "inspircd.h"
-
-/* $ModDesc: Provides channel modes +a and +q */
-
-#define PROTECT_VALUE 40000
-#define FOUNDER_VALUE 50000
-
-struct ChanProtectSettings
-{
- bool DeprivSelf;
- bool DeprivOthers;
- bool FirstInGetsFounder;
- bool booting;
- ChanProtectSettings() : booting(true) {}
-};
-
-static ChanProtectSettings settings;
-
-/** Handles basic operation of +qa channel modes
- */
-class FounderProtectBase
-{
- private:
- const std::string type;
- const char mode;
- const int list;
- const int end;
- public:
- FounderProtectBase(char Mode, const std::string &mtype, int l, int e) :
- type(mtype), mode(Mode), list(l), end(e)
- {
- }
-
- void RemoveMode(Channel* channel, irc::modestacker* stack)
- {
- const UserMembList* cl = channel->GetUsers();
- std::vector<std::string> mode_junk;
- mode_junk.push_back(channel->name);
- irc::modestacker modestack(false);
- std::deque<std::string> stackresult;
-
- for (UserMembCIter i = cl->begin(); i != cl->end(); i++)
- {
- if (i->second->hasMode(mode))
- {
- if (stack)
- stack->Push(mode, i->first->nick);
- else
- modestack.Push(mode, i->first->nick);
- }
- }
-
- if (stack)
- return;
-
- 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 DisplayList(User* user, Channel* channel)
- {
- const UserMembList* cl = channel->GetUsers();
- for (UserMembCIter i = cl->begin(); i != cl->end(); ++i)
- {
- if (i->second->hasMode(mode))
- {
- user->WriteServ("%d %s %s %s", list, user->nick.c_str(), channel->name.c_str(), i->first->nick.c_str());
- }
- }
- user->WriteServ("%d %s %s :End of channel %s list", end, user->nick.c_str(), channel->name.c_str(), type.c_str());
- }
-
- bool CanRemoveOthers(User* u1, Channel* c)
- {
- Membership* m1 = c->GetUser(u1);
- return (settings.DeprivOthers && m1 && m1->hasMode(mode));
- }
-};
-
-/** Abstraction of FounderProtectBase for channel mode +q
- */
-class ChanFounder : public ModeHandler, public FounderProtectBase
-{
- public:
- ChanFounder(Module* Creator)
- : ModeHandler(Creator, "founder", 'q', PARAM_ALWAYS, MODETYPE_CHANNEL),
- FounderProtectBase('q', "founder", 386, 387)
- {
- ModeHandler::list = true;
- levelrequired = FOUNDER_VALUE;
- m_paramtype = TR_NICK;
- }
-
- void setPrefix(int pfx)
- {
- prefix = pfx;
- }
-
- unsigned int GetPrefixRank()
- {
- return FOUNDER_VALUE;
- }
-
- void RemoveMode(Channel* channel, irc::modestacker* stack)
- {
- FounderProtectBase::RemoveMode(channel, stack);
- }
-
- void RemoveMode(User* user, irc::modestacker* stack)
- {
- }
-
- ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding)
- {
- User* theuser = ServerInstance->FindNick(parameter);
- // remove own privs?
- if (source == theuser && !adding && settings.DeprivSelf)
- return MOD_RES_ALLOW;
-
- if (!adding && FounderProtectBase::CanRemoveOthers(source, channel))
- {
- return MOD_RES_PASSTHRU;
- }
- else
- {
- source->WriteNumeric(468, "%s %s :Only servers may set channel mode +q", source->nick.c_str(), channel->name.c_str());
- return MOD_RES_DENY;
- }
- }
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding)
- {
- return MODEACTION_ALLOW;
- }
-
- void DisplayList(User* user, Channel* channel)
- {
- FounderProtectBase::DisplayList(user,channel);
- }
-};
-
-/** Abstraction of FounderProtectBase for channel mode +a
- */
-class ChanProtect : public ModeHandler, public FounderProtectBase
-{
- public:
- ChanProtect(Module* Creator)
- : ModeHandler(Creator, "admin", 'a', PARAM_ALWAYS, MODETYPE_CHANNEL),
- FounderProtectBase('a',"protected user", 388, 389)
- {
- ModeHandler::list = true;
- levelrequired = PROTECT_VALUE;
- m_paramtype = TR_NICK;
- }
-
- void setPrefix(int pfx)
- {
- prefix = pfx;
- }
-
-
- unsigned int GetPrefixRank()
- {
- return PROTECT_VALUE;
- }
-
- void RemoveMode(Channel* channel, irc::modestacker* stack)
- {
- FounderProtectBase::RemoveMode(channel, stack);
- }
-
- void RemoveMode(User* user, irc::modestacker* stack)
- {
- }
-
- ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding)
- {
- User* theuser = ServerInstance->FindNick(parameter);
- // source has +q
- if (channel->GetPrefixValue(source) > PROTECT_VALUE)
- return MOD_RES_ALLOW;
-
- // removing own privs?
- if (source == theuser && !adding && settings.DeprivSelf)
- return MOD_RES_ALLOW;
-
- if (!adding && FounderProtectBase::CanRemoveOthers(source, channel))
- {
- return MOD_RES_PASSTHRU;
- }
- else
- {
- source->WriteNumeric(482, "%s %s :You are not a channel founder", source->nick.c_str(), channel->name.c_str());
- return MOD_RES_DENY;
- }
- }
-
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding)
- {
- return MODEACTION_ALLOW;
- }
-
- void DisplayList(User* user, Channel* channel)
- {
- FounderProtectBase::DisplayList(user, channel);
- }
-
-};
-
-class ModuleChanProtect : public Module
-{
- ChanProtect cp;
- ChanFounder cf;
- public:
- ModuleChanProtect() : cp(this), cf(this)
- {
- }
-
- void init()
- {
- /* Load config stuff */
- LoadSettings();
- settings.booting = false;
-
- ServerInstance->Modules->AddService(cf);
- ServerInstance->Modules->AddService(cp);
-
- Implementation eventlist[] = { I_OnUserPreJoin };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- }
-
- void LoadSettings()
- {
- ConfigTag* tag = ServerInstance->Config->ConfValue("chanprotect");
-
- settings.FirstInGetsFounder = tag->getBool("noservices");
-
- std::string qpre = tag->getString("qprefix");
- char QPrefix = qpre.empty() ? 0 : qpre[0];
-
- std::string apre = tag->getString("aprefix");
- char APrefix = apre.empty() ? 0 : apre[0];
-
- if ((APrefix && QPrefix) && APrefix == QPrefix)
- throw ModuleException("What the smeg, why are both your +q and +a prefixes the same character?");
-
- if (settings.booting)
- {
- if (APrefix && ServerInstance->Modes->FindPrefix(APrefix) && ServerInstance->Modes->FindPrefix(APrefix) != &cp)
- throw ModuleException("Looks like the +a prefix you picked for m_chanprotect is already in use. Pick another.");
-
- if (QPrefix && ServerInstance->Modes->FindPrefix(QPrefix) && ServerInstance->Modes->FindPrefix(QPrefix) != &cf)
- throw ModuleException("Looks like the +q prefix you picked for m_chanprotect is already in use. Pick another.");
-
- cp.setPrefix(APrefix);
- cf.setPrefix(QPrefix);
- }
- settings.DeprivSelf = tag->getBool("deprotectself", true);
- settings.DeprivOthers = tag->getBool("deprotectothers", true);
- }
-
- ModResult OnUserPreJoin(User *user, Channel *chan, const char *cname, std::string &privs, const std::string &keygiven)
- {
- // if the user is the first user into the channel, mark them as the founder, but only if
- // the config option for it is set
-
- if (settings.FirstInGetsFounder && !chan)
- privs += 'q';
-
- return MOD_RES_PASSTHRU;
- }
-
- Version GetVersion()
- {
- return Version("Founder and Protect modes (+qa)", VF_VENDOR);
- }
-};
-
-MODULE_INIT(ModuleChanProtect)
/* $ModDesc: Provides the /CHECK command to retrieve information on a user, channel, hostname or IP address */
#include "inspircd.h"
+#include "listmode.h"
/** Handle /CHECK
*/
class CommandCheck : public Command
{
+ ModeReference ban;
public:
- CommandCheck(Module* parent) : Command(parent,"CHECK", 1)
+ CommandCheck(Module* parent)
+ : Command(parent,"CHECK", 1)
+ , ban(parent, "ban")
{
flags_needed = 'o'; syntax = "<nickname>|<ip>|<hostmask>|<channel> <server>";
}
user->SendText(checkstr + " signon " + timestring(targuser->signon));
user->SendText(checkstr + " nickts " + timestring(targuser->age));
if (loctarg)
- user->SendText(checkstr + " lastmsg " + timestring(targuser->idle_lastmsg));
+ user->SendText(checkstr + " lastmsg " + timestring(loctarg->idle_lastmsg));
- if (IS_AWAY(targuser))
+ if (targuser->IsAway())
{
/* user is away */
user->SendText(checkstr + " awaytime " + timestring(targuser->awaytime));
user->SendText(checkstr + " awaymsg " + targuser->awaymsg);
}
- if (IS_OPER(targuser))
+ if (targuser->IsOper())
{
OperInfo* oper = targuser->oper;
/* user is an oper of type ____ */
- user->SendText(checkstr + " opertype " + oper->NameStr());
+ user->SendText(checkstr + " opertype " + oper->name);
if (loctarg)
{
std::string umodes;
user->SendText(checkstr + " member " + tmpbuf);
}
- irc::modestacker modestack(true);
- for(BanList::iterator b = targchan->bans.begin(); b != targchan->bans.end(); ++b)
- {
- modestack.Push('b', b->data);
- }
- std::vector<std::string> stackresult;
- std::vector<TranslateType> dummy;
- while (modestack.GetStackedLine(stackresult))
- {
- creator->ProtoSendMode(user, TYPE_CHANNEL, targchan, stackresult, dummy);
- stackresult.clear();
- }
+ // We know that the mode handler for bans is in the core and is derived from ListModeBase
+ ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
+ banlm->DoSyncChannel(targchan, creator, user);
+
+ // Show other listmodes as well
FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(targchan,creator,user));
dumpExt(user, checkstr, targchan);
}
}
};
-
class ModuleCheck : public Module
{
- private:
CommandCheck mycommand;
public:
ModuleCheck() : mycommand(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(mycommand);
}
- ~ModuleCheck()
- {
- }
-
void ProtoSendMode(void* uv, TargetTypeFlags, void*, const std::vector<std::string>& result, const std::vector<TranslateType>&)
{
User* user = (User*)uv;
user->SendText(checkstr);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("CHECK command, view user, channel, IP address or hostname information", VF_VENDOR|VF_OPTCOMMON);
}
*/
class CommandChghost : public Command
{
- private:
char* hostmap;
public:
CommandChghost(Module* Creator, char* hmap) : Command(Creator,"CHGHOST", 2), hostmap(hmap)
if (parameters[1].length() > 63)
{
- user->WriteServ("NOTICE %s :*** CHGHOST: Host too long", user->nick.c_str());
+ user->WriteNotice("*** CHGHOST: Host too long");
return CMD_FAILURE;
}
{
if (!hostmap[(unsigned char)*x])
{
- user->WriteServ("NOTICE "+user->nick+" :*** CHGHOST: Invalid characters in hostname");
+ user->WriteNotice("*** CHGHOST: Invalid characters in hostname");
return CMD_FAILURE;
}
}
{
CommandChghost cmd;
char hostmap[256];
+
public:
ModuleChgHost() : cmd(this, hostmap)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
std::string hmap = ServerInstance->Config->ConfValue("hostname")->getString("charmap", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_/0123456789");
hostmap[(unsigned char)*n] = 1;
}
- ~ModuleChgHost()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the CHGHOST command", VF_OPTCOMMON | VF_VENDOR);
}
-
};
MODULE_INIT(ModuleChgHost)
if (parameters[1].length() > ServerInstance->Config->Limits.IdentMax)
{
- user->WriteServ("NOTICE %s :*** CHGIDENT: Ident is too long", user->nick.c_str());
+ user->WriteNotice("*** CHGIDENT: Ident is too long");
return CMD_FAILURE;
}
if (!ServerInstance->IsIdent(parameters[1].c_str()))
{
- user->WriteServ("NOTICE %s :*** CHGIDENT: Invalid characters in ident", user->nick.c_str());
+ user->WriteNotice("*** CHGIDENT: Invalid characters in ident");
return CMD_FAILURE;
}
}
};
-
class ModuleChgIdent : public Module
{
CommandChgident cmd;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleChgIdent()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the CHGIDENT command", VF_OPTCOMMON | VF_VENDOR);
}
};
MODULE_INIT(ModuleChgIdent)
-
if (parameters[1].empty())
{
- user->WriteServ("NOTICE %s :*** CHGNAME: GECOS must be specified", user->nick.c_str());
+ user->WriteNotice("*** CHGNAME: GECOS must be specified");
return CMD_FAILURE;
}
if (parameters[1].length() > ServerInstance->Config->Limits.MaxGecos)
{
- user->WriteServ("NOTICE %s :*** CHGNAME: GECOS too long", user->nick.c_str());
+ user->WriteNotice("*** CHGNAME: GECOS too long");
return CMD_FAILURE;
}
}
};
-
class ModuleChgName : public Module
{
CommandChgname cmd;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleChgName()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the CHGNAME command", VF_OPTCOMMON | VF_VENDOR);
}
#include "inspircd.h"
-#include "hash.h"
+#include "modules/hash.h"
/* $ModDesc: Provides masking of user hostnames */
enum CloakMode
{
- /** 1.2-compatible host-based cloak */
- MODE_COMPAT_HOST,
- /** 1.2-compatible IP-only cloak */
- MODE_COMPAT_IPONLY,
/** 2.0 cloak of "half" of the hostname plus the full IP hash */
MODE_HALF_CLOAK,
/** 2.0 cloak of IP hash, split at 2 common CIDR range points */
{
public:
LocalStringExt ext;
-
std::string debounce_uid;
time_t debounce_ts;
int debounce_count;
return MODEACTION_ALLOW;
}
}
-
};
class CommandCloak : public Command
std::string prefix;
std::string suffix;
std::string key;
- unsigned int compatkey[4];
const char* xtab[4];
dynamic_reference<HashProvider> Hash;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
return rv;
}
- std::string CompatCloak4(const char* ip)
- {
- irc::sepstream seps(ip, '.');
- std::string octet[4];
- int i[4];
-
- for (int j = 0; j < 4; j++)
- {
- seps.GetToken(octet[j]);
- i[j] = atoi(octet[j].c_str());
- }
-
- octet[3] = octet[0] + "." + octet[1] + "." + octet[2] + "." + octet[3];
- octet[2] = octet[0] + "." + octet[1] + "." + octet[2];
- octet[1] = octet[0] + "." + octet[1];
-
- /* Reset the Hash module and send it our IV */
-
- std::string rv;
-
- /* Send the Hash module a different hex table for each octet group's Hash sum */
- for (int k = 0; k < 4; k++)
- {
- rv.append(Hash->sumIV(compatkey, xtab[(compatkey[k]+i[k]) % 4], octet[k]).substr(0,6));
- if (k < 3)
- rv.append(".");
- }
- /* Stick them all together */
- return rv;
- }
-
- std::string CompatCloak6(const char* ip)
- {
- std::vector<std::string> hashies;
- std::string item;
- int rounds = 0;
-
- /* Reset the Hash module and send it our IV */
-
- for (const char* input = ip; *input; input++)
- {
- item += *input;
- if (item.length() > 7)
- {
- hashies.push_back(Hash->sumIV(compatkey, xtab[(compatkey[0]+rounds) % 4], item).substr(0,8));
- item.clear();
- }
- rounds++;
- }
- if (!item.empty())
- {
- hashies.push_back(Hash->sumIV(compatkey, xtab[(compatkey[0]+rounds) % 4], item).substr(0,8));
- }
- /* Stick them all together */
- return irc::stringjoiner(":", hashies, 0, hashies.size() - 1).GetJoined();
- }
-
std::string SegmentIP(const irc::sockets::sockaddrs& ip, bool full)
{
std::string bindata;
return rv;
}
- ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask)
+ ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask) CXX11_OVERRIDE
{
LocalUser* lu = IS_LOCAL(user);
if (!lu)
/* Check if they have a cloaked host, but are not using it */
if (cloak && *cloak != user->dhost)
{
- char cmask[MAXBUF];
- snprintf(cmask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), cloak->c_str());
- if (InspIRCd::Match(cmask,mask))
+ const std::string cloakMask = user->nick + "!" + user->ident + "@" + *cloak;
+ if (InspIRCd::Match(cloakMask, mask))
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
// this unsets umode +x on every host change. If we are actually doing a +x
// mode change, we will call SetMode back to true AFTER the host change is done.
- void OnChangeHost(User* u, const std::string& host)
+ void OnChangeHost(User* u, const std::string& host) CXX11_OVERRIDE
{
if(u->IsModeSet('x'))
{
}
}
- ~ModuleCloaking()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
std::string testcloak = "broken";
if (Hash)
{
switch (mode)
{
- case MODE_COMPAT_HOST:
- testcloak = prefix + "-" + Hash->sumIV(compatkey, xtab[0], "*").substr(0,10);
- break;
- case MODE_COMPAT_IPONLY:
- testcloak = Hash->sumIV(compatkey, xtab[0], "*").substr(0,10);
- break;
case MODE_HALF_CLOAK:
testcloak = prefix + SegmentCloak("*", 3, 8) + suffix;
break;
return Version("Provides masking of user hostnames", VF_COMMON|VF_VENDOR, testcloak);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("cloak");
prefix = tag->getString("prefix");
suffix = tag->getString("suffix", ".IP");
std::string modestr = tag->getString("mode");
- if (modestr == "compat-host")
- mode = MODE_COMPAT_HOST;
- else if (modestr == "compat-ip")
- mode = MODE_COMPAT_IPONLY;
- else if (modestr == "half")
+ if (modestr == "half")
mode = MODE_HALF_CLOAK;
else if (modestr == "full")
mode = MODE_OPAQUE;
else
- throw ModuleException("Bad value for <cloak:mode>; must be one of compat-host, compat-ip, half, full");
+ throw ModuleException("Bad value for <cloak:mode>; must be half or full");
- if (mode == MODE_COMPAT_HOST || mode == MODE_COMPAT_IPONLY)
- {
- bool lowercase = tag->getBool("lowercase");
-
- /* These are *not* using the need_positive parameter of ReadInteger -
- * that will limit the valid values to only the positive values in a
- * signed int. Instead, accept any value that fits into an int and
- * cast it to an unsigned int. That will, a bit oddly, give us the full
- * spectrum of an unsigned integer. - Special
- *
- * We must limit the keys or else we get different results on
- * amd64/x86 boxes. - psychon */
- const unsigned int limit = 0x80000000;
- compatkey[0] = (unsigned int) tag->getInt("key1");
- compatkey[1] = (unsigned int) tag->getInt("key2");
- compatkey[2] = (unsigned int) tag->getInt("key3");
- compatkey[3] = (unsigned int) tag->getInt("key4");
-
- if (!lowercase)
- {
- xtab[0] = "F92E45D871BCA630";
- xtab[1] = "A1B9D80C72E653F4";
- xtab[2] = "1ABC078934DEF562";
- xtab[3] = "ABCDEF5678901234";
- }
- else
- {
- xtab[0] = "f92e45d871bca630";
- xtab[1] = "a1b9d80c72e653f4";
- xtab[2] = "1abc078934def562";
- xtab[3] = "abcdef5678901234";
- }
-
- if (prefix.empty())
- prefix = ServerInstance->Config->Network;
-
- if (!compatkey[0] || !compatkey[1] || !compatkey[2] || !compatkey[3] ||
- compatkey[0] >= limit || compatkey[1] >= limit || compatkey[2] >= limit || compatkey[3] >= limit)
- {
- std::string detail;
- if (!compatkey[0] || compatkey[0] >= limit)
- detail = "<cloak:key1> is not valid, it may be set to a too high/low value, or it may not exist.";
- else if (!compatkey[1] || compatkey[1] >= limit)
- detail = "<cloak:key2> is not valid, it may be set to a too high/low value, or it may not exist.";
- else if (!compatkey[2] || compatkey[2] >= limit)
- detail = "<cloak:key3> is not valid, it may be set to a too high/low value, or it may not exist.";
- else if (!compatkey[3] || compatkey[3] >= limit)
- detail = "<cloak:key4> is not valid, it may be set to a too high/low value, or it may not exist.";
-
- throw ModuleException("You have not defined cloak keys for m_cloaking!!! THIS IS INSECURE AND SHOULD BE CHECKED! - " + detail);
- }
- }
- else
- {
- key = tag->getString("key");
- if (key.empty() || key == "secret")
- throw ModuleException("You have not defined cloak keys for m_cloaking. Define <cloak:key> as a network-wide secret.");
- }
+ key = tag->getString("key");
+ if (key.empty() || key == "secret")
+ throw ModuleException("You have not defined cloak keys for m_cloaking. Define <cloak:key> as a network-wide secret.");
}
std::string GenCloak(const irc::sockets::sockaddrs& ip, const std::string& ipstr, const std::string& host)
switch (mode)
{
- case MODE_COMPAT_HOST:
- {
- if (ipstr != host)
- {
- std::string tail = LastTwoDomainParts(host);
-
- // xtab is not used here due to a bug in 1.2 cloaking
- chost = prefix + "-" + Hash->sumIV(compatkey, "0123456789abcdef", host).substr(0,8) + tail;
-
- /* Fix by brain - if the cloaked host is > the max length of a host (64 bytes
- * according to the DNS RFC) then they get cloaked as an IP.
- */
- if (chost.length() <= 64)
- break;
- }
- // fall through to IP cloak
- }
- case MODE_COMPAT_IPONLY:
- if (ip.sa.sa_family == AF_INET6)
- chost = CompatCloak6(ipstr.c_str());
- else
- chost = CompatCloak4(ipstr.c_str());
- break;
case MODE_HALF_CLOAK:
{
if (ipstr != host)
return chost;
}
- void OnUserConnect(LocalUser* dest)
+ void OnUserConnect(LocalUser* dest) CXX11_OVERRIDE
{
std::string* cloak = cu.ext.get(dest);
if (cloak)
else
cloak = mod->GenCloak(sa, "", parameters[0]);
- user->WriteServ("NOTICE %s :*** Cloak for %s is %s", user->nick.c_str(), parameters[0].c_str(), cloak.c_str());
+ user->WriteNotice("*** Cloak for " + parameters[0] + " is " + cloak);
return CMD_SUCCESS;
}
}
};
-
class ModuleClones : public Module
{
- private:
CommandClones cmd;
public:
ModuleClones() : cmd(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleClones()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the /CLONES command to retrieve information on clones.", VF_VENDOR);
}
-
-
};
MODULE_INIT(ModuleClones)
int total = 0;
for (std::map<std::string,int>::iterator ci = closed.begin(); ci != closed.end(); ci++)
{
- src->WriteServ("NOTICE %s :*** Closed %d unknown connection%s from [%s]",src->nick.c_str(),(*ci).second,((*ci).second>1)?"s":"",(*ci).first.c_str());
- total += (*ci).second;
+ src->WriteNotice("*** Closed " + ConvToStr(ci->second) + " unknown " + (ci->second == 1 ? "connection" : "connections") +
+ " from [" + ci->first + "]");
+ total += ci->second;
}
if (total)
- src->WriteServ("NOTICE %s :*** %i unknown connection%s closed",src->nick.c_str(),total,(total>1)?"s":"");
+ src->WriteNotice("*** " + ConvToStr(total) + " unknown " + (total == 1 ? "connection" : "connections") + " closed");
else
- src->WriteServ("NOTICE %s :*** No unknown connections found",src->nick.c_str());
+ src->WriteNotice("*** No unknown connections found");
return CMD_SUCCESS;
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleClose()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides /CLOSE functionality", VF_VENDOR);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(pm);
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
+ ServerInstance->Modules->Attach(I_OnUserPreMessage, this);
}
- virtual ~ModulePrivacyMode()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Adds user mode +c, which if set, users must be on a common channel with you to private message you", VF_VENDOR);
}
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (target_type == TYPE_USER)
{
User* t = (User*)dest;
- if (!IS_OPER(user) && (t->IsModeSet('c')) && (!ServerInstance->ULine(user->server)) && !user->SharesChannelWith(t))
+ if (!user->IsOper() && (t->IsModeSet('c')) && (!ServerInstance->ULine(user->server)) && !user->SharesChannelWith(t))
{
user->WriteNumeric(ERR_CANTSENDTOUSER, "%s %s :You are not permitted to send private messages to this user (+c set)", user->nick.c_str(), t->nick.c_str());
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
}
-
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreMessage(user, dest, target_type, text, status, exempt_list);
- }
};
-
MODULE_INIT(ModulePrivacyMode)
class ModuleConnJoin : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnPostConnect };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
ServerInstance->Modules->SetPriority(this, I_OnPostConnect, PRIORITY_LAST);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Forces users to join the specified channel(s) on connect", VF_VENDOR);
}
- void OnPostConnect(User* user)
+ void OnPostConnect(User* user) CXX11_OVERRIDE
{
- if (!IS_LOCAL(user))
+ LocalUser* localuser = IS_LOCAL(user);
+ if (!localuser)
return;
std::string chanlist = ServerInstance->Config->ConfValue("autojoin")->getString("channel");
- chanlist = user->GetClass()->config->getString("autojoin", chanlist);
+ chanlist = localuser->GetClass()->config->getString("autojoin", chanlist);
irc::commasepstream chans(chanlist);
std::string chan;
while (chans.GetToken(chan))
{
- if (ServerInstance->IsChannel(chan.c_str(), ServerInstance->Config->Limits.ChanMax))
- Channel::JoinUser(user, chan.c_str(), false, "", false, ServerInstance->Time());
+ if (ServerInstance->IsChannel(chan))
+ Channel::JoinUser(localuser, chan);
}
}
};
-
MODULE_INIT(ModuleConnJoin)
class ModuleModesOnConnect : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->Attach(I_OnUserConnect, this);
}
ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_FIRST);
}
- virtual ~ModuleModesOnConnect()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Sets (and unsets) modes on users when they connect", VF_VENDOR);
}
- virtual void OnUserConnect(LocalUser* user)
+ void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
{
// Backup and zero out the disabled usermodes, so that we can override them here.
char save[64];
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(ext);
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("waitpong");
sendsnotice = tag->getBool("sendsnotice", true);
killonbadreply = tag->getBool("killonbadreply", true);
}
- ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
std::string pingrpl = ServerInstance->GenRandomStr(10);
user->Write("PING :%s", pingrpl.c_str());
if(sendsnotice)
- user->WriteServ("NOTICE %s :*** If you are having problems connecting due to ping timeouts, please type /quote PONG %s or /raw PONG %s now.", user->nick.c_str(), pingrpl.c_str(), pingrpl.c_str());
+ user->WriteNotice("*** If you are having problems connecting due to ping timeouts, please type /quote PONG " + pingrpl + " or /raw PONG " + pingrpl + " now.");
ext.set(user, pingrpl);
return MOD_RES_PASSTHRU;
}
- ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser* user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser* user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
if (command == "PONG")
{
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckReady(LocalUser* user)
+ ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
return ext.get(user) ? MOD_RES_DENY : MOD_RES_PASSTHRU;
}
- ~ModuleWaitPong()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Require pong prior to registration", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleWaitPong)
class ModuleConnectBan : public Module
{
- private:
clonemap connects;
unsigned int threshold;
unsigned int banduration;
unsigned int ipv4_cidr;
unsigned int ipv6_cidr;
+
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnSetUserIP, I_OnGarbageCollect, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- virtual ~ModuleConnectBan()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Throttles the connections of IP ranges who try to connect flood.", VF_VENDOR);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("connectban");
if (threshold == 0)
threshold = 10;
- banduration = ServerInstance->Duration(tag->getString("duration", "10m"));
+ banduration = InspIRCd::Duration(tag->getString("duration", "10m"));
if (banduration == 0)
banduration = 10*60;
}
- virtual void OnSetUserIP(LocalUser* u)
+ void OnSetUserIP(LocalUser* u) CXX11_OVERRIDE
{
if (u->exempt)
return;
}
}
- virtual void OnGarbageCollect()
+ void OnGarbageCollect()
{
- ServerInstance->Logs->Log("m_connectban",DEBUG, "Clearing map.");
+ ServerInstance->Logs->Log("m_connectban", LOG_DEBUG, "Clearing map.");
connects.clear();
}
};
class ModuleConnFlood : public Module
{
-private:
int seconds, timeout, boot_wait;
unsigned int conns;
unsigned int maxconns;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
InitConf();
Implementation eventlist[] = { I_OnRehash, I_OnUserRegister };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Connection throttle", VF_VENDOR);
}
first = ServerInstance->Time();
}
- virtual ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
if (user->exempt)
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
InitConf();
}
return MOD_RES_PASSTHRU;
}
- void RemoveMode(Channel* channel, irc::modestacker* stack)
- {
- const UserMembList* cl = channel->GetUsers();
- std::vector<std::string> mode_junk;
- mode_junk.push_back(channel->name);
- irc::modestacker modestack(false);
- std::deque<std::string> stackresult;
-
- for (UserMembCIter i = cl->begin(); i != cl->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;
-
- 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)
- {
- }
-
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding)
{
return MODEACTION_ALLOW;
{
std::vector<CustomPrefixMode*> modes;
public:
- ModuleCustomPrefix()
- {
- }
-
- void init()
+ void init() CXX11_OVERRIDE
{
ConfigTagList tags = ServerInstance->Config->ConfTags("customprefix");
while (tags.first != tags.second)
delete *i;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides custom prefix channel modes", VF_VENDOR);
}
syntax = "<user> <password>";
}
- bool OneOfMatches(const char* host, const char* ip, const char* hostlist)
- {
- std::stringstream hl(hostlist);
- std::string xhost;
- while (hl >> xhost)
- {
- if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
- {
- return true;
- }
- }
- return false;
- }
-
CmdResult Handle(const std::vector<std::string> ¶meters, User* user)
{
- char TheHost[MAXBUF];
- char TheIP[MAXBUF];
-
- snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(), user->host.c_str());
- snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(), user->GetIPString());
+ const std::string userHost = user->ident + "@" + user->host;
+ const std::string userIP = user->ident + "@" + user->GetIPString();
ConfigTagList tags = ServerInstance->Config->ConfTags("title");
for (ConfigIter i = tags.first; i != tags.second; ++i)
std::string title = i->second->getString("title");
std::string vhost = i->second->getString("vhost");
- if (Name == parameters[0] && !ServerInstance->PassCompare(user, pass, parameters[1], hash) && OneOfMatches(TheHost,TheIP,host.c_str()) && !title.empty())
+ if (Name == parameters[0] && !ServerInstance->PassCompare(user, pass, parameters[1], hash) &&
+ InspIRCd::MatchMask(host, userHost, userIP) && !title.empty())
{
ctitle.set(user, title);
if (!vhost.empty())
user->ChangeDisplayedHost(vhost.c_str());
- user->WriteServ("NOTICE %s :Custom title set to '%s'",user->nick.c_str(), title.c_str());
+ user->WriteNotice("Custom title set to '" + title + "'");
return CMD_SUCCESS;
}
}
- user->WriteServ("NOTICE %s :Invalid title credentials",user->nick.c_str());
+ user->WriteNotice("Invalid title credentials");
return CMD_SUCCESS;
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->AddService(cmd.ctitle);
}
// :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games.
- ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text)
+ ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text) CXX11_OVERRIDE
{
/* We use this and not OnWhois because this triggers for remote, too */
if (numeric == 312)
return MOD_RES_PASSTHRU;
}
- ~ModuleCustomTitle()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Custom Title for users", VF_OPTCOMMON | VF_VENDOR);
}
/** Handle /CYCLE
*/
-class CommandCycle : public Command
+class CommandCycle : public SplitCommand
{
public:
- CommandCycle(Module* Creator) : Command(Creator,"CYCLE", 1)
+ CommandCycle(Module* Creator)
+ : SplitCommand(Creator, "CYCLE", 1)
{
Penalty = 3; syntax = "<channel> :[reason]";
TRANSLATE3(TR_TEXT, TR_TEXT, TR_END);
}
- CmdResult Handle (const std::vector<std::string> ¶meters, User *user)
+ CmdResult HandleLocal(const std::vector<std::string> ¶meters, LocalUser* user)
{
Channel* channel = ServerInstance->FindChan(parameters[0]);
std::string reason = ConvToStr("Cycling");
if (channel->GetPrefixValue(user) < VOICE_VALUE && channel->IsBanned(user))
{
/* banned, boned. drop the message. */
- user->WriteServ("NOTICE "+user->nick+" :*** You may not cycle, as you are banned on channel " + channel->name);
+ user->WriteNotice("*** You may not cycle, as you are banned on channel " + channel->name);
return CMD_FAILURE;
}
channel->PartUser(user, reason);
-
- Channel::JoinUser(user, parameters[0].c_str(), true, "", false, ServerInstance->Time());
+ Channel::JoinUser(user, parameters[0], true);
}
return CMD_SUCCESS;
class ModuleCycle : public Module
{
CommandCycle cmd;
+
public:
ModuleCycle()
: cmd(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleCycle()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides command CYCLE, acts as a server-side HOP command to part and rejoin a channel.", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleCycle)
std::string mask = target->nick+"!"+target->ident+"@"+target->dhost;
std::string default_length = ServerInstance->Config->ConfValue("dccallow")->getString("length");
- long length;
+ unsigned long length;
if (parameters.size() < 2)
{
- length = ServerInstance->Duration(default_length);
+ length = InspIRCd::Duration(default_length);
}
else if (!atoi(parameters[1].c_str()))
{
}
else
{
- length = ServerInstance->Duration(parameters[1]);
+ length = InspIRCd::Duration(parameters[1]);
}
if (!ServerInstance->IsValidMask(mask))
class ModuleDCCAllow : public Module
{
CommandDccallow cmd;
- public:
+ public:
ModuleDCCAllow()
: cmd(this)
{
ext = NULL;
}
- void init()
+ void init() CXX11_OVERRIDE
{
ext = new SimpleExtItem<dccallowlist>("dccallow", this);
ServerInstance->Modules->AddService(*ext);
ServerInstance->Modules->AddService(cmd);
ReadFileConf();
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserQuit, I_OnUserPostNick, I_OnRehash };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserQuit, I_OnUserPostNick, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadFileConf();
}
- virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
+ void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message) CXX11_OVERRIDE
{
dccallowlist* udl = ext->get(user);
RemoveNick(user);
}
- virtual void OnUserPostNick(User* user, const std::string &oldnick)
+ void OnUserPostNick(User* user, const std::string &oldnick) CXX11_OVERRIDE
{
RemoveNick(user);
}
- virtual ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreNotice(user, dest, target_type, text, status, exempt_list);
- }
-
- virtual ModResult OnUserPreNotice(User* user, void* dest, int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return MOD_RES_PASSTHRU;
if ((!found) && (defaultaction == "allow"))
return MOD_RES_PASSTHRU;
- user->WriteServ("NOTICE %s :The user %s is not accepting DCC SENDs from you. Your file %s was not sent.", user->nick.c_str(), u->nick.c_str(), filename.c_str());
- u->WriteServ("NOTICE %s :%s (%s@%s) attempted to send you a file named %s, which was blocked.", u->nick.c_str(), user->nick.c_str(), user->ident.c_str(), user->dhost.c_str(), filename.c_str());
- u->WriteServ("NOTICE %s :If you trust %s and were expecting this, you can type /DCCALLOW HELP for information on the DCCALLOW system.", u->nick.c_str(), user->nick.c_str());
+ user->WriteNotice("The user " + u->nick + " is not accepting DCC SENDs from you. Your file " + filename + " was not sent.");
+ u->WriteNotice(user->nick + " (" + user->ident + "@" + user->dhost + ") attempted to send you a file named " + filename + ", which was blocked.");
+ u->WriteNotice("If you trust " + user->nick + " and were expecting this, you can type /DCCALLOW HELP for information on the DCCALLOW system.");
return MOD_RES_DENY;
}
else if ((type == "CHAT") && (blockchat))
{
- user->WriteServ("NOTICE %s :The user %s is not accepting DCC CHAT requests from you.", user->nick.c_str(), u->nick.c_str());
- u->WriteServ("NOTICE %s :%s (%s@%s) attempted to initiate a DCC CHAT session, which was blocked.", u->nick.c_str(), user->nick.c_str(), user->ident.c_str(), user->dhost.c_str());
- u->WriteServ("NOTICE %s :If you trust %s and were expecting this, you can type /DCCALLOW HELP for information on the DCCALLOW system.", u->nick.c_str(), user->nick.c_str());
+ user->WriteNotice("The user " + u->nick + " is not accepting DCC CHAT requests from you.");
+ u->WriteNotice(user->nick + " (" + user->ident + "@" + user->dhost + ") attempted to initiate a DCC CHAT session, which was blocked.");
+ u->WriteNotice("If you trust " + user->nick + " and were expecting this, you can type /DCCALLOW HELP for information on the DCCALLOW system.");
return MOD_RES_DENY;
}
}
if (i->nickname == user->nick)
{
- u->WriteServ("NOTICE %s :%s left the network or changed their nickname and has been removed from your DCCALLOW list", u->nick.c_str(), i->nickname.c_str());
+ u->WriteNotice(i->nickname + " left the network or changed their nickname and has been removed from your DCCALLOW list");
u->WriteNumeric(995, "%s %s :Removed %s from your DCCALLOW list", u->nick.c_str(), u->nick.c_str(), i->nickname.c_str());
dl->erase(i);
break;
}
}
- virtual ~ModuleDCCAllow()
+ ~ModuleDCCAllow()
{
delete ext;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the /DCCALLOW command", VF_COMMON | VF_VENDOR);
}
{
if (!dest->IsModeSet('d'))
{
- dest->WriteServ("NOTICE %s :*** You have enabled usermode +d, deaf mode. This mode means you WILL NOT receive any messages from any channels you are in. If you did NOT mean to do this, use /mode %s -d.", dest->nick.c_str(), dest->nick.c_str());
+ dest->WriteNotice("*** You have enabled usermode +d, deaf mode. This mode means you WILL NOT receive any messages from any channels you are in. If you did NOT mean to do this, use /mode " + dest->nick + " -d.");
dest->SetMode('d',true);
return MODEACTION_ALLOW;
}
class ModuleDeaf : public Module
{
User_d m1;
-
std::string deaf_bypasschars;
std::string deaf_bypasschars_uline;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(m1);
OnRehash(NULL);
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("deaf");
deaf_bypasschars = tag->getString("bypasschars");
deaf_bypasschars_uline = tag->getString("bypasscharsuline");
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (target_type == TYPE_CHANNEL)
{
Channel* chan = (Channel*)dest;
if (chan)
- this->BuildDeafList(MSG_NOTICE, chan, user, status, text, exempt_list);
+ this->BuildDeafList(msgtype, chan, user, status, text, exempt_list);
}
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- if (target_type == TYPE_CHANNEL)
- {
- Channel* chan = (Channel*)dest;
- if (chan)
- this->BuildDeafList(MSG_PRIVMSG, chan, user, status, text, exempt_list);
- }
-
- return MOD_RES_PASSTHRU;
- }
-
- virtual void BuildDeafList(MessageType message_type, Channel* chan, User* sender, char status, const std::string &text, CUList &exempt_list)
+ void BuildDeafList(MessageType message_type, Channel* chan, User* sender, char status, const std::string &text, CUList &exempt_list)
{
const UserMembList *ulist = chan->GetUsers();
bool is_a_uline;
}
}
- virtual ~ModuleDeaf()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides usermode +d to block channel messages and channel notices", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleDeaf)
class DelayJoinMode : public ModeHandler
{
- private:
CUList empty;
public:
DelayJoinMode(Module* Parent) : ModeHandler(Parent, "delayjoin", 'D', PARAM_NONE, MODETYPE_CHANNEL)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(djm);
ServerInstance->Modules->AddService(unjoined);
Implementation eventlist[] = { I_OnUserJoin, I_OnUserPart, I_OnUserKick, I_OnBuildNeighborList, I_OnNamesListItem, I_OnText, I_OnRawMode };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleDelayJoin();
- Version GetVersion();
- void OnNamesListItem(User* issuer, Membership*, std::string &prefixes, std::string &nick);
- void OnUserJoin(Membership*, bool, bool, CUList&);
+ Version GetVersion() CXX11_OVERRIDE;
+ void OnNamesListItem(User* issuer, Membership*, std::string &prefixes, std::string &nick) CXX11_OVERRIDE;
+ void OnUserJoin(Membership*, bool, bool, CUList&) CXX11_OVERRIDE;
void CleanUser(User* user);
- void OnUserPart(Membership*, std::string &partmessage, CUList&);
- void OnUserKick(User* source, Membership*, const std::string &reason, CUList&);
- void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception);
- void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list);
- ModResult OnRawMode(User* user, Channel* channel, const char mode, const std::string ¶m, bool adding, int pcnt);
+ void OnUserPart(Membership*, std::string &partmessage, CUList&) CXX11_OVERRIDE;
+ void OnUserKick(User* source, Membership*, const std::string &reason, CUList&) CXX11_OVERRIDE;
+ void OnBuildNeighborList(User* source, UserChanList &include, std::map<User*,bool> &exception) CXX11_OVERRIDE;
+ void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list) CXX11_OVERRIDE;
+ ModResult OnRawMode(User* user, Channel* channel, const char mode, const std::string ¶m, bool adding, int pcnt) CXX11_OVERRIDE;
};
ModeAction DelayJoinMode::OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding)
return MODEACTION_ALLOW;
}
-ModuleDelayJoin::~ModuleDelayJoin()
-{
-}
-
Version ModuleDelayJoin::GetVersion()
{
return Version("Allows for delay-join channels (+D) where users don't appear to join until they speak", VF_VENDOR);
class ModuleDelayMsg : public Module
{
- private:
DelayMsgMode djm;
public:
ModuleDelayMsg() : djm(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(djm);
ServerInstance->Modules->AddService(djm.jointime);
Implementation eventlist[] = { I_OnUserJoin, I_OnUserPreMessage};
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- Version GetVersion();
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList&);
- ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string &text, char status, CUList &exempt_list);
+ Version GetVersion() CXX11_OVERRIDE;
+ void OnUserJoin(Membership* memb, bool sync, bool created, CUList&) CXX11_OVERRIDE;
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE;
};
ModeAction DelayMsgMode::OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding)
}
}
-ModResult ModuleDelayMsg::OnUserPreMessage(User* user, void* dest, int target_type, std::string &text, char status, CUList &exempt_list)
+ModResult ModuleDelayMsg::OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype)
{
/* Server origin */
if ((!user) || (!IS_LOCAL(user)))
return MOD_RES_PASSTHRU;
- if (target_type != TYPE_CHANNEL)
+ if ((target_type != TYPE_CHANNEL) || (msgtype != MSG_PRIVMSG))
return MOD_RES_PASSTHRU;
Channel* channel = (Channel*) dest;
}
MODULE_INIT(ModuleDelayMsg)
-
class ModuleDenyChannels : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnUserPreJoin, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
/* check for redirect validity and loops/chains */
ConfigTagList tags = ServerInstance->Config->ConfTags("badchan");
if (!redirect.empty())
{
- if (!ServerInstance->IsChannel(redirect.c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (!ServerInstance->IsChannel(redirect))
{
if (user)
- user->WriteServ("NOTICE %s :Invalid badchan redirect '%s'", user->nick.c_str(), redirect.c_str());
+ user->WriteNotice("Invalid badchan redirect '" + redirect + "'");
throw ModuleException("Invalid badchan redirect, not a channel");
}
{
/* <badchan:redirect> is a badchan */
if (user)
- user->WriteServ("NOTICE %s :Badchan %s redirects to badchan %s", user->nick.c_str(), name.c_str(), redirect.c_str());
+ user->WriteNotice("Badchan " + name + " redirects to badchan " + redirect);
throw ModuleException("Badchan redirect loop");
}
}
}
}
- virtual ~ModuleDenyChannels()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements config tags which allow blocking of joins to channels", VF_VENDOR);
}
- virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
ConfigTagList tags = ServerInstance->Config->ConfTags("badchan");
for (ConfigIter j = tags.first; j != tags.second; ++j)
{
if (InspIRCd::Match(cname, j->second->getString("name")))
{
- if (IS_OPER(user) && j->second->getBool("allowopers"))
+ if (user->IsOper() && j->second->getBool("allowopers"))
{
return MOD_RES_PASSTHRU;
}
}
}
- if (ServerInstance->IsChannel(redirect.c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (ServerInstance->IsChannel(redirect))
{
/* simple way to avoid potential loops: don't redirect to +L channels */
Channel *newchan = ServerInstance->FindChan(redirect);
if ((!newchan) || (!(newchan->IsModeSet('L'))))
{
- user->WriteNumeric(926, "%s %s :Channel %s is forbidden, redirecting to %s: %s",user->nick.c_str(),cname,cname,redirect.c_str(), reason.c_str());
- Channel::JoinUser(user,redirect.c_str(),false,"",false,ServerInstance->Time());
+ user->WriteNumeric(926, "%s %s :Channel %s is forbidden, redirecting to %s: %s",user->nick.c_str(),cname.c_str(),cname.c_str(),redirect.c_str(), reason.c_str());
+ Channel::JoinUser(user, redirect);
return MOD_RES_DENY;
}
}
- user->WriteNumeric(926, "%s %s :Channel %s is forbidden: %s",user->nick.c_str(),cname,cname,reason.c_str());
+ user->WriteNumeric(926, "%s %s :Channel %s is forbidden: %s",user->nick.c_str(),cname.c_str(),cname.c_str(),reason.c_str());
return MOD_RES_DENY;
}
}
CmdResult Handle (const std::vector<std::string> ¶meters, User *user)
{
- Channel* c = ServerInstance->FindChan(parameters[0]);
- if (c && c->HasUser(user))
- {
- std::vector<std::string> modes;
- modes.push_back(parameters[0]);
- modes.push_back("-v");
- modes.push_back(user->nick);
+ std::vector<std::string> modes;
+ modes.push_back(parameters[0]);
+ modes.push_back("-v");
+ modes.push_back(user->nick);
- ServerInstance->SendGlobalMode(modes, ServerInstance->FakeClient);
- return CMD_SUCCESS;
- }
-
- return CMD_FAILURE;
+ ServerInstance->SendGlobalMode(modes, ServerInstance->FakeClient);
+ return CMD_SUCCESS;
}
};
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleDeVoice()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides voiced users with the ability to devoice themselves.", VF_VENDOR);
}
#include "inspircd.h"
#include "xline.h"
+#include "modules/dns.h"
/* $ModDesc: Provides handling of DNS blacklists */
unsigned char records[256];
unsigned long stats_hits, stats_misses;
DNSBLConfEntry(): type(A_BITMASK),duration(86400),bitmask(0),stats_hits(0), stats_misses(0) {}
- ~DNSBLConfEntry() { }
};
/** Resolver for CGI:IRC hostnames encoded in ident/GECOS
*/
-class DNSBLResolver : public Resolver
+class DNSBLResolver : public DNS::Request
{
std::string theiruid;
LocalStringExt& nameExt;
public:
- DNSBLResolver(Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, DNSBLConfEntry *conf, bool &cached)
- : Resolver(hostname, DNS_QUERY_A, cached, me), theiruid(u->uuid), nameExt(match), countExt(ctr), ConfEntry(conf)
+ DNSBLResolver(DNS::Manager *mgr, Module *me, LocalStringExt& match, LocalIntExt& ctr, const std::string &hostname, LocalUser* u, DNSBLConfEntry *conf)
+ : DNS::Request(mgr, me, hostname, DNS::QUERY_A, true), theiruid(u->uuid), nameExt(match), countExt(ctr), ConfEntry(conf)
{
}
/* Note: This may be called multiple times for multiple A record results */
- virtual void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
+ void OnLookupComplete(const DNS::Query *r) CXX11_OVERRIDE
{
/* Check the user still exists */
LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid);
- if (them)
+ if (!them)
+ return;
+
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+
+ int i = countExt.get(them);
+ if (i)
+ countExt.set(them, i - 1);
+
+ // Now we calculate the bitmask: 256*(256*(256*a+b)+c)+d
+
+ unsigned int bitmask = 0, record = 0;
+ bool match = false;
+ in_addr resultip;
+
+ inet_aton(ans_record.rdata.c_str(), &resultip);
+
+ switch (ConfEntry->type)
+ {
+ case DNSBLConfEntry::A_BITMASK:
+ bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */
+ bitmask &= ConfEntry->bitmask;
+ match = (bitmask != 0);
+ break;
+ case DNSBLConfEntry::A_RECORD:
+ record = resultip.s_addr >> 24; /* Last octet */
+ match = (ConfEntry->records[record] == 1);
+ break;
+ }
+
+ if (match)
{
- 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())
+ std::string reason = ConfEntry->reason;
+ std::string::size_type x = reason.find("%ip%");
+ while (x != std::string::npos)
{
- unsigned int bitmask = 0, record = 0;
- bool match = false;
- in_addr resultip;
+ reason.erase(x, 4);
+ reason.insert(x, them->GetIPString());
+ x = reason.find("%ip%");
+ }
- inet_aton(result.c_str(), &resultip);
+ ConfEntry->stats_hits++;
- switch (ConfEntry->type)
+ switch (ConfEntry->banaction)
+ {
+ case DNSBLConfEntry::I_KILL:
{
- case DNSBLConfEntry::A_BITMASK:
- bitmask = resultip.s_addr >> 24; /* Last octet (network byte order) */
- bitmask &= ConfEntry->bitmask;
- match = (bitmask != 0);
- break;
- case DNSBLConfEntry::A_RECORD:
- record = resultip.s_addr >> 24; /* Last octet */
- match = (ConfEntry->records[record] == 1);
+ ServerInstance->Users->QuitUser(them, "Killed (" + reason + ")");
break;
}
-
- if (match)
+ case DNSBLConfEntry::I_MARK:
{
- std::string reason = ConfEntry->reason;
- std::string::size_type x = reason.find("%ip%");
- while (x != std::string::npos)
+ if (!ConfEntry->ident.empty())
{
- reason.erase(x, 4);
- reason.insert(x, them->GetIPString());
- x = reason.find("%ip%");
+ them->WriteServ("304 " + them->nick + " :Your ident has been set to " + ConfEntry->ident + " because you matched " + reason);
+ them->ChangeIdent(ConfEntry->ident.c_str());
}
- ConfEntry->stats_hits++;
-
- switch (ConfEntry->banaction)
+ if (!ConfEntry->host.empty())
{
- case DNSBLConfEntry::I_KILL:
- {
- ServerInstance->Users->QuitUser(them, "Killed (" + reason + ")");
- break;
- }
- case DNSBLConfEntry::I_MARK:
- {
- if (!ConfEntry->ident.empty())
- {
- them->WriteServ("304 " + them->nick + " :Your ident has been set to " + ConfEntry->ident + " because you matched " + reason);
- them->ChangeIdent(ConfEntry->ident.c_str());
- }
-
- if (!ConfEntry->host.empty())
- {
- them->WriteServ("304 " + them->nick + " :Your host has been set to " + ConfEntry->host + " because you matched " + reason);
- them->ChangeDisplayedHost(ConfEntry->host.c_str());
- }
-
- nameExt.set(them, ConfEntry->name);
- break;
- }
- case DNSBLConfEntry::I_KLINE:
- {
- KLine* kl = new KLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
- "*", them->GetIPString());
- if (ServerInstance->XLines->AddLine(kl,NULL))
- {
- std::string timestr = ServerInstance->TimeString(kl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s",
- them->GetIPString(), timestr.c_str(), reason.c_str());
- ServerInstance->XLines->ApplyLines();
- }
- else
- delete kl;
- break;
- }
- case DNSBLConfEntry::I_GLINE:
- {
- GLine* gl = new GLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
- "*", them->GetIPString());
- if (ServerInstance->XLines->AddLine(gl,NULL))
- {
- std::string timestr = ServerInstance->TimeString(gl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s",
- them->GetIPString(), timestr.c_str(), reason.c_str());
- ServerInstance->XLines->ApplyLines();
- }
- else
- delete gl;
- break;
- }
- case DNSBLConfEntry::I_ZLINE:
- {
- ZLine* zl = new ZLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
- them->GetIPString());
- if (ServerInstance->XLines->AddLine(zl,NULL))
- {
- std::string timestr = ServerInstance->TimeString(zl->expiry);
- ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on *@%s to expire on %s: %s",
- them->GetIPString(), timestr.c_str(), reason.c_str());
- ServerInstance->XLines->ApplyLines();
- }
- else
- delete zl;
- break;
- }
- case DNSBLConfEntry::I_UNKNOWN:
- {
- break;
- }
- break;
+ them->WriteServ("304 " + them->nick + " :Your host has been set to " + ConfEntry->host + " because you matched " + reason);
+ them->ChangeDisplayedHost(ConfEntry->host.c_str());
}
- ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s%s detected as being on a DNS blacklist (%s) with result %d", them->nick.empty() ? "<unknown>" : "", them->GetFullRealHost().c_str(), ConfEntry->domain.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record);
+ nameExt.set(them, ConfEntry->name);
+ break;
+ }
+ case DNSBLConfEntry::I_KLINE:
+ {
+ KLine* kl = new KLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
+ "*", them->GetIPString());
+ if (ServerInstance->XLines->AddLine(kl,NULL))
+ {
+ std::string timestr = ServerInstance->TimeString(kl->expiry);
+ ServerInstance->SNO->WriteGlobalSno('x',"K:line added due to DNSBL match on *@%s to expire on %s: %s",
+ them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ delete kl;
+ break;
+ }
+ case DNSBLConfEntry::I_GLINE:
+ {
+ GLine* gl = new GLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
+ "*", them->GetIPString());
+ if (ServerInstance->XLines->AddLine(gl,NULL))
+ {
+ std::string timestr = ServerInstance->TimeString(gl->expiry);
+ ServerInstance->SNO->WriteGlobalSno('x',"G:line added due to DNSBL match on *@%s to expire on %s: %s",
+ them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ delete gl;
+ break;
+ }
+ case DNSBLConfEntry::I_ZLINE:
+ {
+ ZLine* zl = new ZLine(ServerInstance->Time(), ConfEntry->duration, ServerInstance->Config->ServerName.c_str(), reason.c_str(),
+ them->GetIPString());
+ if (ServerInstance->XLines->AddLine(zl,NULL))
+ {
+ std::string timestr = ServerInstance->TimeString(zl->expiry);
+ ServerInstance->SNO->WriteGlobalSno('x',"Z:line added due to DNSBL match on *@%s to expire on %s: %s",
+ them->GetIPString().c_str(), timestr.c_str(), reason.c_str());
+ ServerInstance->XLines->ApplyLines();
+ }
+ else
+ delete zl;
+ break;
}
- else
- ConfEntry->stats_misses++;
+ case DNSBLConfEntry::I_UNKNOWN:
+ default:
+ break;
}
- else
- ConfEntry->stats_misses++;
+
+ ServerInstance->SNO->WriteGlobalSno('a', "Connecting user %s%s detected as being on a DNS blacklist (%s) with result %d", them->nick.empty() ? "<unknown>" : "", them->GetFullRealHost().c_str(), ConfEntry->domain.c_str(), (ConfEntry->type==DNSBLConfEntry::A_BITMASK) ? bitmask : record);
}
+ else
+ ConfEntry->stats_misses++;
}
- virtual void OnError(ResolverError e, const std::string &errormessage)
+ void OnError(const DNS::Query *q) CXX11_OVERRIDE
{
LocalUser* them = (LocalUser*)ServerInstance->FindUUID(theiruid);
- if (them)
- {
- int i = countExt.get(them);
- if (i)
- countExt.set(them, i - 1);
- }
- }
+ if (!them)
+ return;
- virtual ~DNSBLResolver()
- {
+ int i = countExt.get(them);
+ if (i)
+ countExt.set(them, i - 1);
+
+ if (q->error == DNS::ERROR_NO_RECORDS || q->error == DNS::ERROR_DOMAIN_NOT_FOUND)
+ ConfEntry->stats_misses++;
}
};
class ModuleDNSBL : public Module
{
std::vector<DNSBLConfEntry *> DNSBLConfEntries;
+ dynamic_reference<DNS::Manager> DNS;
LocalStringExt nameExt;
LocalIntExt countExt;
return DNSBLConfEntry::I_UNKNOWN;
}
public:
- ModuleDNSBL() : nameExt("dnsbl_match", this), countExt("dnsbl_pending", this) { }
+ ModuleDNSBL() : DNS(this, "DNS"), nameExt("dnsbl_match", this), countExt("dnsbl_pending", this) { }
- void init()
+ void init() CXX11_OVERRIDE
{
ReadConf();
ServerInstance->Modules->AddService(nameExt);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleDNSBL()
+ ~ModuleDNSBL()
{
ClearEntries();
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides handling of DNS blacklists", VF_VENDOR);
}
}
e->banaction = str2banaction(tag->getString("action"));
- e->duration = ServerInstance->Duration(tag->getString("duration", "60"));
+ e->duration = InspIRCd::Duration(tag->getString("duration", "60"));
/* Use portparser for record replies */
}
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadConf();
}
- void OnSetUserIP(LocalUser* user)
+ void OnSetUserIP(LocalUser* user) CXX11_OVERRIDE
{
- if ((user->exempt) || (user->client_sa.sa.sa_family != AF_INET))
+ if ((user->exempt) || (user->client_sa.sa.sa_family != AF_INET) || !DNS)
return;
if (user->MyClass)
return;
}
else
- ServerInstance->Logs->Log("m_dnsbl", DEBUG, "User has no connect class in OnSetUserIP");
+ ServerInstance->Logs->Log("m_dnsbl", LOG_DEBUG, "User has no connect class in OnSetUserIP");
unsigned char a, b, c, d;
- char reversedipbuf[128];
- std::string reversedip;
-
d = (unsigned char) (user->client_sa.in4.sin_addr.s_addr >> 24) & 0xFF;
c = (unsigned char) (user->client_sa.in4.sin_addr.s_addr >> 16) & 0xFF;
b = (unsigned char) (user->client_sa.in4.sin_addr.s_addr >> 8) & 0xFF;
a = (unsigned char) user->client_sa.in4.sin_addr.s_addr & 0xFF;
- snprintf(reversedipbuf, 128, "%d.%d.%d.%d", d, c, b, a);
- reversedip = std::string(reversedipbuf);
+ const std::string reversedip = ConvToStr(d) + "." + ConvToStr(c) + "." + ConvToStr(b) + "." + ConvToStr(a);
countExt.set(user, DNSBLConfEntries.size());
// For each DNSBL, we will run through this lookup
- unsigned int i = 0;
- while (i < DNSBLConfEntries.size())
+ for (unsigned i = 0; i < DNSBLConfEntries.size(); ++i)
{
// Fill hostname with a dnsbl style host (d.c.b.a.domain.tld)
std::string hostname = reversedip + "." + DNSBLConfEntries[i]->domain;
/* now we'd need to fire off lookups for `hostname'. */
- bool cached;
- DNSBLResolver *r = new DNSBLResolver(this, nameExt, countExt, hostname, user, DNSBLConfEntries[i], cached);
- ServerInstance->AddResolver(r, cached);
+ DNSBLResolver *r = new DNSBLResolver(*this->DNS, this, nameExt, countExt, hostname, user, DNSBLConfEntries[i]);
+ try
+ {
+ this->DNS->Process(r);
+ }
+ catch (DNS::Exception &ex)
+ {
+ delete r;
+ ServerInstance->Logs->Log("m_dnsbl", LOG_DEBUG, std::string(ex.GetReason()));
+ }
+
if (user->quitting)
break;
- i++;
}
}
- ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass)
+ ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) CXX11_OVERRIDE
{
std::string dnsbl;
if (!myclass->config->readString("dnsbl", dnsbl))
return MOD_RES_PASSTHRU;
return MOD_RES_DENY;
}
-
- ModResult OnCheckReady(LocalUser *user)
+
+ ModResult OnCheckReady(LocalUser *user) CXX11_OVERRIDE
{
if (countExt.get(user))
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
- ModResult OnStats(char symbol, User* user, string_list &results)
+ ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE
{
if (symbol != 'd')
return MOD_RES_PASSTHRU;
#include "inspircd.h"
-#include "u_listmode.h"
+#include "listmode.h"
/* $ModDesc: Provides the ability to allow channel operators to be exempt from certain modes. */
return true;
}
- bool TellListTooLong(User* user, Channel* chan, std::string &word)
+ void TellListTooLong(User* user, Channel* chan, std::string &word)
{
user->WriteNumeric(959, "%s %s %s :Channel exemptchanops list is full", user->nick.c_str(), chan->name.c_str(), word.c_str());
- return true;
}
void TellAlreadyOnList(User* user, Channel* chan, std::string &word)
public:
ExemptChanOps ec;
ExemptHandler(Module* me) : ec(me) {}
-
+
ModeHandler* FindMode(const std::string& mid)
{
if (mid.length() == 1)
unsigned int mypfx = chan->GetPrefixValue(user);
std::string minmode;
- modelist* list = ec.extItem.get(chan);
+ ListModeBase::ModeList* list = ec.GetList(chan);
if (list)
{
- for (modelist::iterator i = list->begin(); i != list->end(); ++i)
+ for (ListModeBase::ModeList::iterator i = list->begin(); i != list->end(); ++i)
{
std::string::size_type pos = (*i).mask.find(':');
if (pos == std::string::npos)
ExemptHandler eh;
public:
-
ModuleExemptChanOps() : eh(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(eh.ec);
Implementation eventlist[] = { I_OnRehash, I_OnSyncChannel };
ServerInstance->OnCheckExemption = &ServerInstance->HandleOnCheckExemption;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the ability to allow channel operators to be exempt from certain modes.",VF_VENDOR);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
eh.ec.DoRehash();
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque)
+ void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
{
eh.ec.DoSyncChannel(chan, proto, opaque);
}
#include "inspircd.h"
#include "xline.h"
-#include "m_regex.h"
+#include "modules/regex.h"
/* $ModDesc: Text (spam) filtering */
std::set<std::string> exemptfromfilter; // List of channel names excluded from filtering.
ModuleFilter();
- void init();
+ void init() CXX11_OVERRIDE;
CullResult cull();
- ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list);
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE;
FilterResult* FilterMatch(User* user, const std::string &text, int flags);
bool DeleteFilter(const std::string &freeform);
std::pair<bool, std::string> AddFilter(const std::string &freeform, FilterAction type, const std::string &reason, long duration, const std::string &flags);
- ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list);
- void OnRehash(User* user);
- Version GetVersion();
+ void OnRehash(User* user) CXX11_OVERRIDE;
+ Version GetVersion() CXX11_OVERRIDE;
std::string EncodeFilter(FilterResult* filter);
FilterResult DecodeFilter(const std::string &data);
- void OnSyncNetwork(Module* proto, void* opaque);
- void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata);
- ModResult OnStats(char symbol, User* user, string_list &results);
- ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line);
- void OnUnloadModule(Module* mod);
+ void OnSyncNetwork(Module* proto, void* opaque) CXX11_OVERRIDE;
+ void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) CXX11_OVERRIDE;
+ ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE;
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE;
+ void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
bool AppliesToMe(User* user, FilterResult* filter, int flags);
void ReadFilters();
static bool StringToFilterAction(const std::string& str, FilterAction& fa);
Module *me = creator;
if (static_cast<ModuleFilter *>(me)->DeleteFilter(parameters[0]))
{
- user->WriteServ("NOTICE %s :*** Removed filter '%s'", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** Removed filter '" + parameters[0] + "'");
ServerInstance->SNO->WriteToSnoMask(IS_LOCAL(user) ? 'a' : 'A', "FILTER: "+user->nick+" removed filter '"+parameters[0]+"'");
return CMD_SUCCESS;
}
else
{
- user->WriteServ("NOTICE %s :*** Filter '%s' not found in list, try /stats s.", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** Filter '" + parameters[0] + "' not found in list, try /stats s.");
return CMD_FAILURE;
}
}
if (!ModuleFilter::StringToFilterAction(parameters[1], type))
{
- user->WriteServ("NOTICE %s :*** Invalid filter type '%s'. Supported types are 'gline', 'none', 'block', 'silent' and 'kill'.", user->nick.c_str(), parameters[1].c_str());
+ user->WriteNotice("*** Invalid filter type '" + parameters[1] + "'. Supported types are 'gline', 'none', 'block', 'silent' and 'kill'.");
return CMD_FAILURE;
}
{
if (parameters.size() >= 5)
{
- duration = ServerInstance->Duration(parameters[3]);
+ duration = InspIRCd::Duration(parameters[3]);
reasonindex = 4;
}
else
{
- user->WriteServ("NOTICE %s :*** Not enough parameters: When setting a gline type filter, a gline duration must be specified as the third parameter.", user->nick.c_str());
+ user->WriteNotice("*** Not enough parameters: When setting a gline type filter, a gline duration must be specified as the third parameter.");
return CMD_FAILURE;
}
}
std::pair<bool, std::string> result = static_cast<ModuleFilter *>(me)->AddFilter(freeform, type, parameters[reasonindex], duration, flags);
if (result.first)
{
- user->WriteServ("NOTICE %s :*** Added filter '%s', type '%s'%s%s, flags '%s', reason: '%s'", user->nick.c_str(), freeform.c_str(),
- parameters[1].c_str(), (duration ? ", duration " : ""), (duration ? parameters[3].c_str() : ""),
- flags.c_str(), parameters[reasonindex].c_str());
+ user->WriteNotice("*** Added filter '" + freeform + "', type '" + parameters[1] + "'" +
+ (duration ? ", duration " + parameters[3] : "") + ", flags '" + flags + "', reason: '" +
+ parameters[reasonindex] + "'");
ServerInstance->SNO->WriteToSnoMask(IS_LOCAL(user) ? 'a' : 'A', "FILTER: "+user->nick+" added filter '"+freeform+"', type '"+parameters[1]+"', "+(duration ? "duration "+parameters[3]+", " : "")+"flags '"+flags+"', reason: "+parameters[reasonindex]);
}
else
{
- user->WriteServ("NOTICE %s :*** Filter '%s' could not be added: %s", user->nick.c_str(), freeform.c_str(), result.second.c_str());
+ user->WriteNotice("*** Filter '" + freeform + "' could not be added: " + result.second);
return CMD_FAILURE;
}
}
else
{
- user->WriteServ("NOTICE %s :*** Not enough parameters.", user->nick.c_str());
+ user->WriteNotice("*** Not enough parameters.");
return CMD_FAILURE;
}
bool ModuleFilter::AppliesToMe(User* user, FilterResult* filter, int iflags)
{
- if ((filter->flag_no_opers) && IS_OPER(user))
+ if ((filter->flag_no_opers) && user->IsOper())
return false;
if ((iflags & FLAG_PRIVMSG) && (!filter->flag_privmsg))
return false;
void ModuleFilter::init()
{
ServerInstance->Modules->AddService(filtcommand);
- Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_OnUnloadModule };
+ Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnRehash, I_OnUnloadModule };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
filters.clear();
}
-ModResult ModuleFilter::OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
-{
- if (!IS_LOCAL(user))
- return MOD_RES_PASSTHRU;
-
- flags = FLAG_PRIVMSG;
- return OnUserPreNotice(user,dest,target_type,text,status,exempt_list);
-}
-
-ModResult ModuleFilter::OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ModResult ModuleFilter::OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype)
{
/* Leave ulines alone */
if ((ServerInstance->ULine(user->server)) || (!IS_LOCAL(user)))
return MOD_RES_PASSTHRU;
- if (!flags)
- flags = FLAG_NOTICE;
+ flags = (msgtype == MSG_PRIVMSG) ? FLAG_PRIVMSG : FLAG_NOTICE;
FilterResult* f = this->FilterMatch(user, text, flags);
if (f)
if (target_type == TYPE_CHANNEL)
user->WriteNumeric(404, "%s %s :Message to channel blocked and opers notified (%s)",user->nick.c_str(), target.c_str(), f->reason.c_str());
else
- user->WriteServ("NOTICE "+user->nick+" :Your message to "+target+" was blocked and opers notified: "+f->reason);
+ user->WriteNotice("Your message to "+target+" was blocked and opers notified: "+f->reason);
}
else if (f->action == FA_SILENT)
{
if (target_type == TYPE_CHANNEL)
user->WriteNumeric(404, "%s %s :Message to channel blocked (%s)",user->nick.c_str(), target.c_str(), f->reason.c_str());
else
- user->WriteServ("NOTICE "+user->nick+" :Your message to "+target+" was blocked: "+f->reason);
+ user->WriteNotice("Your message to "+target+" was blocked: "+f->reason);
}
else if (f->action == FA_KILL)
{
delete gl;
}
- ServerInstance->Logs->Log("FILTER",DEFAULT,"FILTER: "+ user->nick + " had their message filtered, target was " + target + ": " + f->reason + " Action: " + ModuleFilter::FilterActionToString(f->action));
+ ServerInstance->Logs->Log("FILTER", LOG_DEFAULT, "FILTER: "+ user->nick + " had their message filtered, target was " + target + ": " + f->reason + " Action: " + ModuleFilter::FilterActionToString(f->action));
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
/* Are they parting, if so, kill is applicable */
if ((parting) && (f->action == FA_KILL))
{
- user->WriteServ("NOTICE %s :*** Your PART message was filtered: %s", user->nick.c_str(), f->reason.c_str());
+ user->WriteNotice("*** Your PART message was filtered: " + f->reason);
ServerInstance->Users->QuitUser(user, "Filtered: " + f->reason);
}
if (f->action == FA_GLINE)
}
catch (ModuleException& e)
{
- ServerInstance->Logs->Log("m_filter", DEBUG, "Error when unserializing filter: " + std::string(e.GetReason()));
+ ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "Error when unserializing filter: " + std::string(e.GetReason()));
}
}
}
InspIRCd::StripColor(stripped_text);
}
- //ServerInstance->Logs->Log("m_filter", DEBUG, "Match '%s' against '%s'", text.c_str(), index->freeform.c_str());
+ //ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "Match '%s' against '%s'", text.c_str(), index->freeform.c_str());
if (index->regex->Matches(filter->flag_strip_color ? stripped_text : text))
{
- //ServerInstance->Logs->Log("m_filter", DEBUG, "MATCH");
+ //ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "MATCH");
return &*index;
}
- //ServerInstance->Logs->Log("m_filter", DEBUG, "NO MATCH");
+ //ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "NO MATCH");
}
return NULL;
}
}
catch (ModuleException &e)
{
- ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", freeform.c_str(), e.GetReason());
+ ServerInstance->Logs->Log("m_filter", LOG_DEFAULT, "Error in regular expression '%s': %s", freeform.c_str(), e.GetReason());
return std::make_pair(false, e.GetReason());
}
return std::make_pair(true, "");
std::string reason = i->second->getString("reason");
std::string action = i->second->getString("action");
std::string flgs = i->second->getString("flags");
- long gline_time = ServerInstance->Duration(i->second->getString("duration"));
+ unsigned long gline_time = InspIRCd::Duration(i->second->getString("duration"));
if (flgs.empty())
flgs = "*";
try
{
filters.push_back(ImplFilter(this, reason, fa, gline_time, pattern, flgs));
- ServerInstance->Logs->Log("m_filter", DEFAULT, "Regular expression %s loaded.", pattern.c_str());
+ ServerInstance->Logs->Log("m_filter", LOG_DEFAULT, "Regular expression %s loaded.", pattern.c_str());
}
catch (ModuleException &e)
{
- ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", pattern.c_str(), e.GetReason());
+ ServerInstance->Logs->Log("m_filter", LOG_DEFAULT, "Error in regular expression '%s': %s", pattern.c_str(), e.GetReason());
}
}
}
class ModuleGecosBan : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleGecosBan()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Extban 'r' - realname (gecos) ban", VF_OPTCOMMON|VF_VENDOR);
}
- ModResult OnCheckBan(User *user, Channel *c, const std::string& mask)
+ ModResult OnCheckBan(User *user, Channel *c, const std::string& mask) CXX11_OVERRIDE
{
if ((mask.length() > 2) && (mask[0] == 'r') && (mask[1] == ':'))
{
return MOD_RES_PASSTHRU;
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('r');
+ tokens["EXTBAN"].push_back('r');
}
};
CmdResult Handle (const std::vector<std::string> ¶meters, User *user)
{
+ if (!ServerInstance->Config->ConfValue("security")->getBool("allowcoreunload") &&
+ InspIRCd::Match(parameters[0], "cmd_*.so", ascii_case_insensitive_map))
+ {
+ user->WriteNumeric(972, "%s %s :You cannot unload core commands!", user->nick.c_str(), parameters[0].c_str());
+ return CMD_FAILURE;
+ }
+
std::string servername = parameters.size() > 1 ? parameters[1] : "*";
if (InspIRCd::Match(ServerInstance->Config->ServerName.c_str(), servername))
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd1);
ServerInstance->Modules->AddService(cmd2);
ServerInstance->Modules->AddService(cmd3);
}
- ~ModuleGlobalLoad()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows global loading of a module.", VF_COMMON | VF_VENDOR);
}
};
MODULE_INIT(ModuleGlobalLoad)
-
public:
ModuleGlobops() : cmd(this) {}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->SNO->EnableSnomask('g',"GLOBOPS");
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for GLOBOPS and snomask +g", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleGlobops)
+++ /dev/null
-/*
- * 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
- * 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/>.
- */
-
-
-/* $ModDesc: Channel half-operator mode provider */
-
-#include "inspircd.h"
-
-class ModeChannelHalfOp : public ModeHandler
-{
- public:
- ModeChannelHalfOp(Module* parent);
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding);
- unsigned int GetPrefixRank();
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
-
- ModResult AccessCheck(User* src, Channel*, std::string& value, bool adding)
- {
- if (!adding && src->nick == value)
- return MOD_RES_ALLOW;
- return MOD_RES_PASSTHRU;
- }
-};
-
-ModeChannelHalfOp::ModeChannelHalfOp(Module* parent) : ModeHandler(parent, "halfop", 'h', PARAM_ALWAYS, MODETYPE_CHANNEL)
-{
- list = true;
- prefix = '%';
- levelrequired = OP_VALUE;
- m_paramtype = TR_NICK;
-}
-
-unsigned int ModeChannelHalfOp::GetPrefixRank()
-{
- return HALFOP_VALUE;
-}
-
-void ModeChannelHalfOp::RemoveMode(Channel* channel, irc::modestacker* stack)
-{
- const UserMembList* clist = channel->GetUsers();
-
- for (UserMembCIter i = clist->begin(); i != clist->end(); i++)
- {
- if (stack)
- {
- stack->Push(this->GetModeChar(), i->first->nick);
- }
- else
- {
- std::vector<std::string> parameters;
- parameters.push_back(channel->name);
- parameters.push_back("-h");
- parameters.push_back(i->first->nick);
- ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
- }
- }
-
-}
-
-void ModeChannelHalfOp::RemoveMode(User*, irc::modestacker* stack)
-{
-}
-
-ModeAction ModeChannelHalfOp::OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding)
-{
- return MODEACTION_ALLOW;
-}
-
-class ModuleHalfop : public Module
-{
- ModeChannelHalfOp mh;
- public:
- ModuleHalfop() : mh(this)
- {
- }
-
- void init()
- {
- ServerInstance->Modules->AddService(mh);
- }
-
- Version GetVersion()
- {
- return Version("Channel half-operator mode provider", VF_VENDOR);
- }
-};
-
-MODULE_INIT(ModuleHalfop)
class ModuleHelpop : public Module
{
- private:
std::string h_file;
CommandHelpop cmd;
Helpop ho;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ReadConfig();
ServerInstance->Modules->AddService(ho);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadConfig();
}
- void OnWhois(User* src, User* dst)
+ void OnWhois(User* src, User* dst) CXX11_OVERRIDE
{
if (dst->IsModeSet('h'))
{
}
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the /HELPOP command for useful information", VF_VENDOR);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(hm);
Implementation eventlist[] = { I_OnWhoisLine, I_OnRehash };
OnRehash(NULL);
}
- virtual ~ModuleHideChans()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for hiding channels with user mode +I", VF_VENDOR);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
AffectsOpers = ServerInstance->Config->ConfValue("hidechans")->getBool("affectsopers");
}
- ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text)
+ ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text) CXX11_OVERRIDE
{
/* always show to self */
if (user == dest)
}
};
-
MODULE_INIT(ModuleHideChans)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(hm);
Implementation eventlist[] = { I_OnWhoisLine, I_OnSendWhoLine };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
-
- virtual ~ModuleHideOper()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for hiding oper status with user mode +H", VF_VENDOR);
}
- ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text)
+ ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text) CXX11_OVERRIDE
{
/* Dont display numeric 313 (RPL_WHOISOPER) if they have +H set and the
* person doing the WHOIS is not an oper
return MOD_RES_PASSTHRU;
}
- void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line)
+ void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line) CXX11_OVERRIDE
{
if (user->IsModeSet('H') && !source->HasPrivPermission("users/auspex"))
{
}
};
-
MODULE_INIT(ModuleHideOper)
class ModuleHostChange : public Module
{
- private:
hostchanges_t hostchanges;
std::string MySuffix;
std::string MyPrefix;
std::string MySeparator;
public:
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
Implementation eventlist[] = { I_OnRehash, I_OnUserConnect };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* host = ServerInstance->Config->ConfValue("host");
MySuffix = host->getString("suffix");
}
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
// returns the version number of the module to be
// listed in /MODULES
return Version("Provides masking of user hostnames in a different way to m_cloaking", VF_VENDOR);
}
- virtual void OnUserConnect(LocalUser* user)
+ void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
{
for (hostchanges_t::iterator i = hostchanges.begin(); i != hostchanges.end(); i++)
{
}
if (!newhost.empty())
{
- user->WriteServ("NOTICE "+user->nick+" :Setting your virtual host: " + newhost);
+ user->WriteNotice("Setting your virtual host: " + newhost);
if (!user->ChangeDisplayedHost(newhost.c_str()))
- user->WriteServ("NOTICE "+user->nick+" :Could not set your virtual host: " + newhost);
+ user->WriteNotice("Could not set your virtual host: " + newhost);
return;
}
}
#include "inspircd.h"
-#include "httpd.h"
+#include "modules/httpd.h"
/* $ModDesc: Provides HTTP serving facilities to modules */
-/* $ModDep: httpd.h */
+/* $ModDep: modules/httpd.h */
class ModuleHttpServer;
std::string http_version;
public:
-
HttpServerSocket(int newfd, const std::string& IP, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
: BufferedSocket(newfd), ip(IP), postsize(0)
{
GetIOHook()->OnStreamSocketAccept(this, client, server);
}
- virtual void OnError(BufferedSocketError)
+ void OnError(BufferedSocketError) CXX11_OVERRIDE
{
ServerInstance->GlobalCulls.AddItem(this);
}
if (reqbuffer.length() >= 8192)
{
- ServerInstance->Logs->Log("m_httpd",DEBUG, "m_httpd dropped connection due to an oversized request buffer");
+ ServerInstance->Logs->Log("m_httpd", LOG_DEBUG, "m_httpd dropped connection due to an oversized request buffer");
reqbuffer.clear();
SetError("Buffer");
}
class ModuleHttpServer : public Module
{
std::vector<HttpServerSocket *> httpsocks;
- public:
- void init()
+ public:
+ void init() CXX11_OVERRIDE
{
HttpModule = this;
ServerInstance->Modules->Attach(I_OnAcceptConnection, this);
}
- void OnRequest(Request& request)
+ void OnRequest(Request& request) CXX11_OVERRIDE
{
if (strcmp(request.id, "HTTP-DOC") != 0)
return;
resp.src.sock->Page(resp.document, resp.responsecode, &resp.headers);
}
- ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
+ ModResult OnAcceptConnection(int nfd, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE
{
if (from->bind_tag->getString("type") != "httpd")
return MOD_RES_PASSTHRU;
return MOD_RES_ALLOW;
}
-
- virtual ~ModuleHttpServer()
+ ~ModuleHttpServer()
{
for (size_t i = 0; i < httpsocks.size(); i++)
{
}
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides HTTP serving facilities to modules", VF_VENDOR);
}
#include "inspircd.h"
-#include "httpd.h"
+#include "modules/httpd.h"
#include "protocol.h"
/* $ModDesc: Provides access control lists (passwording of resources, ip restrictions etc) to m_httpd.so dependent modules */
const std::string &set_whitelist, const std::string &set_blacklist)
: path(set_path), username(set_username), password(set_password), whitelist(set_whitelist),
blacklist(set_blacklist) { }
-
- ~HTTPACL() { }
};
class ModuleHTTPAccessList : public Module
{
-
std::string stylesheet;
std::vector<HTTPACL> acl_list;
public:
-
void OnRehash(User* user)
{
acl_list.clear();
}
}
- ServerInstance->Logs->Log("m_httpd_acl", DEBUG, "Read ACL: path=%s pass=%s whitelist=%s blacklist=%s", path.c_str(),
+ ServerInstance->Logs->Log("m_httpd_acl", LOG_DEBUG, "Read ACL: path=%s pass=%s whitelist=%s blacklist=%s", path.c_str(),
password.c_str(), whitelist.c_str(), blacklist.c_str());
acl_list.push_back(HTTPACL(path, username, password, whitelist, blacklist));
}
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
Implementation eventlist[] = { I_OnEvent, I_OnRehash };
void BlockAccess(HTTPRequest* http, int returnval, const std::string &extraheaderkey = "", const std::string &extraheaderval="")
{
- ServerInstance->Logs->Log("m_httpd_acl", DEBUG, "BlockAccess (%d)", returnval);
+ ServerInstance->Logs->Log("m_httpd_acl", LOG_DEBUG, "BlockAccess (%d)", returnval);
std::stringstream data("Access to this resource is denied by an access control list. Please contact your IRC administrator.");
HTTPDocumentResponse response(this, *http, &data, returnval);
response.Send();
}
- void OnEvent(Event& event)
+ void OnEvent(Event& event) CXX11_OVERRIDE
{
if (event.id == "httpd_acl")
{
- ServerInstance->Logs->Log("m_http_stats", DEBUG,"Handling httpd acl event");
+ ServerInstance->Logs->Log("m_http_stats", LOG_DEBUG, "Handling httpd acl event");
HTTPRequest* http = (HTTPRequest*)&event;
for (std::vector<HTTPACL>::const_iterator this_acl = acl_list.begin(); this_acl != acl_list.end(); ++this_acl)
{
if (InspIRCd::Match(http->GetIP(), entry, ascii_case_insensitive_map))
{
- ServerInstance->Logs->Log("m_httpd_acl", DEBUG, "Denying access to blacklisted resource %s (matched by pattern %s) from ip %s (matched by entry %s)",
+ ServerInstance->Logs->Log("m_httpd_acl", LOG_DEBUG, "Denying access to blacklisted resource %s (matched by pattern %s) from ip %s (matched by entry %s)",
http->GetURI().c_str(), this_acl->path.c_str(), http->GetIP().c_str(), entry.c_str());
BlockAccess(http, 403);
return;
if (!allow_access)
{
- ServerInstance->Logs->Log("m_httpd_acl", DEBUG, "Denying access to whitelisted resource %s (matched by pattern %s) from ip %s (Not in whitelist)",
+ ServerInstance->Logs->Log("m_httpd_acl", LOG_DEBUG, "Denying access to whitelisted resource %s (matched by pattern %s) from ip %s (Not in whitelist)",
http->GetURI().c_str(), this_acl->path.c_str(), http->GetIP().c_str());
BlockAccess(http, 403);
return;
if (!this_acl->password.empty() && !this_acl->username.empty())
{
/* Password auth, first look to see if we have a basic authentication header */
- ServerInstance->Logs->Log("m_httpd_acl", DEBUG, "Checking HTTP auth password for resource %s (matched by pattern %s) from ip %s, against username %s",
+ ServerInstance->Logs->Log("m_httpd_acl", LOG_DEBUG, "Checking HTTP auth password for resource %s (matched by pattern %s) from ip %s, against username %s",
http->GetURI().c_str(), this_acl->path.c_str(), http->GetIP().c_str(), this_acl->username.c_str());
if (http->headers->IsSet("Authorization"))
sep.GetToken(base64);
std::string userpass = Base64ToBin(base64);
- ServerInstance->Logs->Log("m_httpd_acl", DEBUG, "HTTP authorization: %s (%s)", userpass.c_str(), base64.c_str());
+ ServerInstance->Logs->Log("m_httpd_acl", LOG_DEBUG, "HTTP authorization: %s (%s)", userpass.c_str(), base64.c_str());
irc::sepstream userpasspair(userpass, ':');
if (userpasspair.GetToken(user))
/* Access granted if username and password are correct */
if (user == this_acl->username && pass == this_acl->password)
{
- ServerInstance->Logs->Log("m_httpd_acl", DEBUG, "HTTP authorization: password and username match");
+ ServerInstance->Logs->Log("m_httpd_acl", LOG_DEBUG, "HTTP authorization: password and username match");
return;
}
else
}
}
- virtual ~ModuleHTTPAccessList()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides access control lists (passwording of resources, ip restrictions etc) to m_httpd.so dependent modules", VF_VENDOR);
}
#include "inspircd.h"
-#include "httpd.h"
+#include "modules/httpd.h"
#include "protocol.h"
/* $ModDesc: Allows for the server configuration to be viewed over HTTP via m_httpd.so */
class ModuleHttpConfig : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnEvent };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
return ret;
}
- void OnEvent(Event& event)
+ void OnEvent(Event& event) CXX11_OVERRIDE
{
std::stringstream data("");
if (event.id == "httpd_url")
{
- ServerInstance->Logs->Log("m_http_stats", DEBUG,"Handling httpd event");
+ ServerInstance->Logs->Log("m_http_stats", LOG_DEBUG, "Handling httpd event");
HTTPRequest* http = (HTTPRequest*)&event;
if ((http->GetURI() == "/config") || (http->GetURI() == "/config/"))
}
}
- virtual ~ModuleHttpConfig()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows for the server configuration to be viewed over HTTP via m_httpd.so", VF_VENDOR);
}
#include "inspircd.h"
-#include "httpd.h"
+#include "modules/httpd.h"
#include "xline.h"
#include "protocol.h"
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnEvent };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
ret += it->second;
ret += ';';
}
- else if (*x == 0x9 || *x == 0xA || *x == 0xD ||
- (*x >= 0x20 && *x <= 0xD7FF) || (*x >= 0xE000 && *x <= 0x10FFFF))
+ else if (*x == 0x9 || *x == 0xA || *x == 0xD || *x >= 0x20)
{
// The XML specification defines the following characters as valid inside an XML document:
// Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
data << "</metadata>";
}
- void OnEvent(Event& event)
+ void OnEvent(Event& event) CXX11_OVERRIDE
{
std::stringstream data("");
if (event.id == "httpd_url")
{
- ServerInstance->Logs->Log("m_http_stats", DEBUG,"Handling httpd event");
+ ServerInstance->Logs->Log("m_http_stats", LOG_DEBUG, "Handling httpd event");
HTTPRequest* http = (HTTPRequest*)&event;
if ((http->GetURI() == "/stats") || (http->GetURI() == "/stats/"))
stime = gmtime(&server_uptime);
data << "<uptime><days>" << stime->tm_yday << "</days><hours>" << stime->tm_hour << "</hours><mins>" << stime->tm_min << "</mins><secs>" << stime->tm_sec << "</secs><boot_time_t>" << ServerInstance->startup_time << "</boot_time_t></uptime>";
- data << "<isupport>" << Sanitize(ServerInstance->Config->data005) << "</isupport></general><xlines>";
+ data << "<isupport>";
+ const std::vector<std::string>& isupport = ServerInstance->ISupport.GetLines();
+ for (std::vector<std::string>::const_iterator it = isupport.begin(); it != isupport.end(); it++)
+ {
+ data << Sanitize(*it) << std::endl;
+ }
+ data << "</isupport></general><xlines>";
std::vector<std::string> xltypes = ServerInstance->XLines->GetAllTypes();
for (std::vector<std::string>::iterator it = xltypes.begin(); it != xltypes.end(); ++it)
{
data << "<nickname>" << u->nick << "</nickname><uuid>" << u->uuid << "</uuid><realhost>"
<< u->host << "</realhost><displayhost>" << u->dhost << "</displayhost><gecos>"
<< Sanitize(u->fullname) << "</gecos><server>" << u->server << "</server>";
- if (IS_AWAY(u))
+ if (u->IsAway())
data << "<away>" << Sanitize(u->awaymsg) << "</away><awaytime>" << u->awaytime << "</awaytime>";
- if (IS_OPER(u))
- data << "<opertype>" << Sanitize(u->oper->NameStr()) << "</opertype>";
+ if (u->IsOper())
+ data << "<opertype>" << Sanitize(u->oper->name) << "</opertype>";
data << "<modes>" << u->FormatModes() << "</modes><ident>" << Sanitize(u->ident) << "</ident>";
LocalUser* lu = IS_LOCAL(u);
if (lu)
}
}
- virtual ~ModuleHttpStats()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides statistics over HTTP via m_httpd.so", VF_VENDOR);
}
}
}
- virtual void OnConnected()
+ void OnConnected()
{
- ServerInstance->Logs->Log("m_ident",DEBUG,"OnConnected()");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "OnConnected()");
ServerInstance->SE->ChangeEventMask(this, FD_WANT_POLL_READ | FD_WANT_NO_WRITE);
char req[32];
done = true;
}
- virtual void HandleEvent(EventType et, int errornum = 0)
+ void HandleEvent(EventType et, int errornum = 0)
{
switch (et)
{
break;
case EVENT_ERROR:
/* fd error event, ohshi- */
- ServerInstance->Logs->Log("m_ident",DEBUG,"EVENT_ERROR");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "EVENT_ERROR");
/* We *must* Close() here immediately or we get a
* huge storm of EVENT_ERROR events!
*/
*/
if (GetFd() > -1)
{
- ServerInstance->Logs->Log("m_ident",DEBUG,"Close ident socket %d", GetFd());
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "Close ident socket %d", GetFd());
ServerInstance->SE->DelFd(this);
ServerInstance->SE->Close(GetFd());
this->SetFd(-1);
if (recvresult < 3)
return;
- ServerInstance->Logs->Log("m_ident",DEBUG,"ReadResponse()");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "ReadResponse()");
/* Truncate at the first null character, but first make sure
* there is at least one null char (at the end of the buffer).
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(ext);
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleIdent()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for RFC1413 ident lookups", VF_VENDOR);
}
- virtual void OnRehash(User *user)
+ void OnRehash(User *user) CXX11_OVERRIDE
{
RequestTimeout = ServerInstance->Config->ConfValue("ident")->getInt("timeout", 5);
if (!RequestTimeout)
RequestTimeout = 5;
}
- void OnUserInit(LocalUser *user)
+ void OnUserInit(LocalUser *user) CXX11_OVERRIDE
{
ConfigTag* tag = user->MyClass->config;
if (!tag->getBool("useident", true))
return;
- user->WriteServ("NOTICE Auth :*** Looking up your ident...");
+ user->WriteNotice("*** Looking up your ident...");
try
{
}
catch (ModuleException &e)
{
- ServerInstance->Logs->Log("m_ident",DEBUG,"Ident exception: %s", e.GetReason());
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "Ident exception: %s", e.GetReason());
}
}
* creating a Timer object and especially better than creating a
* Timer per ident lookup!
*/
- virtual ModResult OnCheckReady(LocalUser *user)
+ ModResult OnCheckReady(LocalUser *user) CXX11_OVERRIDE
{
/* Does user have an ident socket attached at all? */
IdentRequestSocket *isock = ext.get(user);
if (!isock)
{
- ServerInstance->Logs->Log("m_ident",DEBUG, "No ident socket :(");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "No ident socket :(");
return MOD_RES_PASSTHRU;
}
- ServerInstance->Logs->Log("m_ident",DEBUG, "Has ident_socket");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "Has ident_socket");
time_t compare = isock->age;
compare += RequestTimeout;
if (ServerInstance->Time() >= compare)
{
/* Ident timeout */
- user->WriteServ("NOTICE Auth :*** Ident request timed out.");
- ServerInstance->Logs->Log("m_ident",DEBUG, "Timeout");
+ user->WriteNotice("*** Ident request timed out.");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "Timeout");
}
else if (!isock->HasResult())
{
// time still good, no result yet... hold the registration
- ServerInstance->Logs->Log("m_ident",DEBUG, "No result yet");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "No result yet");
return MOD_RES_DENY;
}
- ServerInstance->Logs->Log("m_ident",DEBUG, "Yay, result!");
+ ServerInstance->Logs->Log("m_ident", LOG_DEBUG, "Yay, result!");
/* wooo, got a result (it will be good, or bad) */
if (isock->result.empty())
{
user->ident.insert(0, 1, '~');
- user->WriteServ("NOTICE Auth :*** Could not find your ident, using %s instead.", user->ident.c_str());
+ user->WriteNotice("*** Could not find your ident, using " + user->ident + " instead.");
}
else
{
user->ident = isock->result;
- user->WriteServ("NOTICE Auth :*** Found your ident, '%s'", user->ident.c_str());
+ user->WriteNotice("*** Found your ident, '" + user->ident + "'");
}
user->InvalidateCache();
return MOD_RES_PASSTHRU;
}
- ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass)
+ ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) CXX11_OVERRIDE
{
if (myclass->config->getBool("requireident") && user->ident[0] == '~')
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
- virtual void OnCleanup(int target_type, void *item)
+ void OnCleanup(int target_type, void *item) CXX11_OVERRIDE
{
/* Module unloading, tidy up users */
if (target_type == TYPE_USER)
}
}
- virtual void OnUserDisconnect(LocalUser *user)
+ void OnUserDisconnect(LocalUser *user) CXX11_OVERRIDE
{
/* User disconnect (generic socket detatch event) */
IdentRequestSocket *isock = ext.get(user);
};
MODULE_INIT(ModuleIdent)
-
#include "inspircd.h"
-#include "u_listmode.h"
+#include "listmode.h"
/* $ModDesc: Provides support for the +I channel mode */
-/* $ModDep: ../../include/u_listmode.h */
/*
* Written by Om <om@inspircd.org>, April 2005.
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(ie);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" INVEX=I");
+ tokens["INVEX"] = "I";
}
- ModResult OnCheckInvite(User* user, Channel* chan)
+ ModResult OnCheckInvite(User* user, Channel* chan) CXX11_OVERRIDE
{
- modelist* list = ie.extItem.get(chan);
+ ListModeBase::ModeList* list = ie.GetList(chan);
if (list)
{
- for (modelist::iterator it = list->begin(); it != list->end(); it++)
+ for (ListModeBase::ModeList::iterator it = list->begin(); it != list->end(); it++)
{
if (chan->CheckBan(user, it->mask))
{
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckKey(User* user, Channel* chan, const std::string& key)
+ ModResult OnCheckKey(User* user, Channel* chan, const std::string& key) CXX11_OVERRIDE
{
if (invite_bypass_key)
return OnCheckInvite(user, chan);
return MOD_RES_PASSTHRU;
}
- void OnSyncChannel(Channel* chan, Module* proto, void* opaque)
+ void OnSyncChannel(Channel* chan, Module* proto, void* opaque) CXX11_OVERRIDE
{
ie.DoSyncChannel(chan, proto, opaque);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
invite_bypass_key = ServerInstance->Config->ConfValue("inviteexception")->getBool("bypasskey", true);
ie.DoRehash();
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the +I channel mode", VF_VENDOR);
}
/* $ModDesc: Provides support for extended-join, away-notify and account-notify CAP capabilities */
#include "inspircd.h"
-#include "account.h"
-#include "m_cap.h"
+#include "modules/account.h"
+#include "modules/cap.h"
class ModuleIRCv3 : public Module
{
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
Implementation eventlist[] = { I_OnUserJoin, I_OnPostJoin, I_OnSetAway, I_OnEvent, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* conf = ServerInstance->Config->ConfValue("ircv3");
accountnotify = conf->getBool("accoutnotify", true);
extendedjoin = conf->getBool("extendedjoin", true);
}
- void OnEvent(Event& ev)
+ void OnEvent(Event& ev) CXX11_OVERRIDE
{
if (awaynotify)
cap_awaynotify.HandleEvent(ev);
}
}
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts)
+ void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) CXX11_OVERRIDE
{
// Remember who is not going to see the JOIN because of other modules
- if ((awaynotify) && (IS_AWAY(memb->user)))
+ if ((awaynotify) && (memb->user->IsAway()))
last_excepts = excepts;
if (!extendedjoin)
}
}
- ModResult OnSetAway(User* user, const std::string &awaymsg)
+ ModResult OnSetAway(User* user, const std::string &awaymsg) CXX11_OVERRIDE
{
if (awaynotify)
{
return MOD_RES_PASSTHRU;
}
- void OnPostJoin(Membership *memb)
+ void OnPostJoin(Membership *memb) CXX11_OVERRIDE
{
- if ((!awaynotify) || (!IS_AWAY(memb->user)))
+ if ((!awaynotify) || (!memb->user->IsAway()))
return;
std::string line = ":" + memb->user->GetFullHost() + " AWAY :" + memb->user->awaymsg;
ServerInstance->Modules->SetPriority(this, I_OnUserJoin, PRIORITY_LAST);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for extended-join, away-notify and account-notify CAP capabilities", VF_VENDOR);
}
class joinfloodsettings
{
public:
- int secs;
- int joins;
+ unsigned int secs;
+ unsigned int joins;
time_t reset;
time_t unlocktime;
- int counter;
- bool locked;
+ unsigned int counter;
- joinfloodsettings(int b, int c) : secs(b), joins(c)
+ joinfloodsettings(unsigned int b, unsigned int c)
+ : secs(b), joins(c), unlocktime(0), counter(0)
{
reset = ServerInstance->Time() + secs;
- counter = 0;
- locked = false;
- };
+ }
void addjoin()
{
- counter++;
if (ServerInstance->Time() > reset)
{
- counter = 0;
+ counter = 1;
reset = ServerInstance->Time() + secs;
}
+ else
+ counter++;
}
bool shouldlock()
bool islocked()
{
- if (locked)
- {
- if (ServerInstance->Time() > unlocktime)
- {
- locked = false;
- return false;
- }
- else
- {
- return true;
- }
- }
- return false;
+ if (ServerInstance->Time() > unlocktime)
+ unlocktime = 0;
+
+ return (unlocktime != 0);
}
void lock()
{
- locked = true;
unlocktime = ServerInstance->Time() + 60;
}
+ bool operator==(const joinfloodsettings& other) const
+ {
+ return ((this->secs == other.secs) && (this->joins == other.joins));
+ }
};
/** Handles channel mode +j
{
if (adding)
{
- char ndata[MAXBUF];
- char* data = ndata;
- strlcpy(ndata,parameter.c_str(),MAXBUF);
- char* joins = data;
- char* secs = NULL;
- while (*data)
+ std::string::size_type colon = parameter.find(':');
+ if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
{
- if (*data == ':')
- {
- *data = 0;
- data++;
- secs = data;
- break;
- }
- else data++;
+ source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
+ return MODEACTION_DENY;
}
- if (secs)
- {
- /* Set up the flood parameters for this channel */
- int njoins = atoi(joins);
- int nsecs = atoi(secs);
- if ((njoins<1) || (nsecs<1))
- {
- source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
- parameter.clear();
- return MODEACTION_DENY;
- }
- else
- {
- joinfloodsettings* f = ext.get(channel);
- if (!f)
- {
- parameter = ConvToStr(njoins) + ":" +ConvToStr(nsecs);
- f = new joinfloodsettings(nsecs, njoins);
- ext.set(channel, f);
- channel->SetModeParam('j', parameter);
- return MODEACTION_ALLOW;
- }
- else
- {
- std::string cur_param = channel->GetModeParameter('j');
- parameter = ConvToStr(njoins) + ":" +ConvToStr(nsecs);
- if (cur_param == parameter)
- {
- // mode params match
- return MODEACTION_DENY;
- }
- else
- {
- // new mode param, replace old with new
- if ((nsecs > 0) && (njoins > 0))
- {
- f = new joinfloodsettings(nsecs, njoins);
- ext.set(channel, f);
- channel->SetModeParam('j', parameter);
- return MODEACTION_ALLOW;
- }
- else
- {
- return MODEACTION_DENY;
- }
- }
- }
- }
- }
- else
+ /* Set up the flood parameters for this channel */
+ unsigned int njoins = ConvToInt(parameter.substr(0, colon));
+ unsigned int nsecs = ConvToInt(parameter.substr(colon+1));
+ if ((njoins<1) || (nsecs<1))
{
source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
return MODEACTION_DENY;
}
+
+ joinfloodsettings jfs(nsecs, njoins);
+ joinfloodsettings* f = ext.get(channel);
+ if ((f) && (*f == jfs))
+ // mode params match
+ return MODEACTION_DENY;
+
+ ext.set(channel, jfs);
+ parameter = ConvToStr(njoins) + ":" + ConvToStr(nsecs);
+ channel->SetModeParam(this, parameter);
+ return MODEACTION_ALLOW;
}
else
{
+ if (!channel->IsModeSet(this))
+ return MODEACTION_DENY;
+
joinfloodsettings* f = ext.get(channel);
if (f)
{
ext.unset(channel);
- channel->SetModeParam('j', "");
+ channel->SetModeParam(this, "");
return MODEACTION_ALLOW;
}
}
class ModuleJoinFlood : public Module
{
-
JoinFlood jf;
public:
-
ModuleJoinFlood()
: jf(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(jf);
ServerInstance->Modules->AddService(jf.ext);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
if (chan)
{
return MOD_RES_PASSTHRU;
}
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts)
+ void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) CXX11_OVERRIDE
{
/* We arent interested in JOIN events caused by a network burst */
if (sync)
}
}
- ~ModuleJoinFlood()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +j (join flood protection)", VF_VENDOR);
}
if (!parameters.size())
{
if (port)
- user->WriteServ("NOTICE %s :*** Disabled jumpserver (previously set to '%s:%d')", user->nick.c_str(), redirect_to.c_str(), port);
+ user->WriteNotice("*** Disabled jumpserver (previously set to '" + redirect_to + ":" + ConvToStr(port) + "')");
else
- user->WriteServ("NOTICE %s :*** Jumpserver was not enabled.", user->nick.c_str());
+ user->WriteNotice("*** Jumpserver was not enabled.");
port = 0;
redirect_to.clear();
redirect_new_users = direction;
break;
default:
- user->WriteServ("NOTICE %s :*** Invalid JUMPSERVER flag: %c", user->nick.c_str(), *n);
+ user->WriteNotice("*** Invalid JUMPSERVER flag: " + ConvToStr(*n));
return CMD_FAILURE;
break;
}
if (!atoi(parameters[1].c_str()))
{
- user->WriteServ("NOTICE %s :*** Invalid port number", user->nick.c_str());
+ user->WriteNotice("*** Invalid port number");
return CMD_FAILURE;
}
for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); ++i)
{
User* t = *i;
- if (!IS_OPER(t))
+ if (!t->IsOper())
{
t->WriteNumeric(10, "%s %s %s :Please use this Server/Port instead", t->nick.c_str(), parameters[0].c_str(), parameters[1].c_str());
ServerInstance->Users->QuitUser(t, reason);
port = atoi(parameters[1].c_str());
}
- user->WriteServ("NOTICE %s :*** Set jumpserver to server '%s' port '%s', flags '+%s%s'%s%s%s: %s", user->nick.c_str(), parameters[0].c_str(), parameters[1].c_str(),
- redirect_all_immediately ? "a" : "",
- redirect_new_users ? "n" : "",
- n_done ? " (" : "",
- n_done ? n_done_s.c_str() : "",
- n_done ? " user(s) redirected)" : "",
- reason.c_str());
+ user->WriteNotice("*** Set jumpserver to server '" + parameters[0] + "' port '" + parameters[1] + "', flags '+" +
+ (redirect_all_immediately ? "a" : "") + (redirect_new_users ? "n'" : "'") +
+ (n_done ? " (" + n_done_s + "user(s) redirected): " : ": ") + reason);
}
return CMD_SUCCESS;
}
};
-
class ModuleJumpServer : public Module
{
CommandJumpserver js;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(js);
Implementation eventlist[] = { I_OnUserRegister, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleJumpServer()
- {
- }
-
- virtual ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
if (js.port && js.redirect_new_users)
{
return MOD_RES_PASSTHRU;
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
// Emergency way to unlock
if (!user) js.redirect_new_users = false;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the RPL_REDIR numeric and the /JUMPSERVER command.", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleJumpServer)
*/
class KickRejoin : public ModeHandler
{
+ static const unsigned int max = 60;
public:
- unsigned int max;
SimpleExtItem<delaylist> ext;
KickRejoin(Module* Creator)
: ModeHandler(Creator, "kicknorejoin", 'J', PARAM_SETONLY, MODETYPE_CHANNEL)
{
}
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding)
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE
{
if (adding)
{
KickRejoin kr;
public:
-
ModuleKickNoRejoin()
: kr(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(kr);
ServerInstance->Modules->AddService(kr.ext);
- Implementation eventlist[] = { I_OnUserPreJoin, I_OnUserKick, I_OnRehash };
+ Implementation eventlist[] = { I_OnUserPreJoin, I_OnUserKick };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- OnRehash(NULL);
- }
-
- void OnRehash(User* user)
- {
- kr.max = ServerInstance->Duration(ServerInstance->Config->ConfValue("kicknorejoin")->getString("maxtime"));
- if (!kr.max)
- kr.max = 30*60;
}
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
if (chan)
{
return MOD_RES_PASSTHRU;
}
- void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts)
+ void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) CXX11_OVERRIDE
{
if (memb->chan->IsModeSet(&kr) && (IS_LOCAL(memb->user)) && (source != memb->user))
{
}
}
- ~ModuleKickNoRejoin()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Channel mode to delay rejoin after kick", VF_VENDOR);
}
};
-
MODULE_INIT(ModuleKickNoRejoin)
if (sendnumeric)
c->WriteChannelWithServ(ServerInstance->Config->ServerName, "710 %s %s %s :is KNOCKing: %s", c->name.c_str(), c->name.c_str(), user->GetFullHost().c_str(), parameters[1].c_str());
- user->WriteServ("NOTICE %s :KNOCKing on %s", user->nick.c_str(), c->name.c_str());
+ user->WriteNotice("KNOCKing on " + c->name);
return CMD_SUCCESS;
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(kn);
ServerInstance->Modules->AddService(cmd);
OnRehash(NULL);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
std::string knocknotify = ServerInstance->Config->ConfValue("knock")->getString("notify");
irc::string notify(knocknotify.c_str());
}
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for /KNOCK and channel mode +K", VF_OPTCOMMON | VF_VENDOR);
}
/** Adds numerics
* 988 <nick> <servername> :Closed for new connections
* 989 <nick> <servername> :Open for new connections
-*/
-
+ */
class CommandLockserv : public Command
{
bool& locked;
-public:
+
+ public:
CommandLockserv(Module* Creator, bool& lock) : Command(Creator, "LOCKSERV", 0), locked(lock)
{
flags_needed = 'o';
{
if (locked)
{
- user->WriteServ("NOTICE %s :The server is already locked.", user->nick.c_str());
+ user->WriteNotice("The server is already locked.");
return CMD_FAILURE;
}
class CommandUnlockserv : public Command
{
-private:
bool& locked;
-public:
+ public:
CommandUnlockserv(Module* Creator, bool &lock) : Command(Creator, "UNLOCKSERV", 0), locked(lock)
{
flags_needed = 'o';
{
if (!locked)
{
- user->WriteServ("NOTICE %s :The server isn't locked.", user->nick.c_str());
+ user->WriteNotice("The server isn't locked.");
return CMD_FAILURE;
}
class ModuleLockserv : public Module
{
-private:
bool locked;
CommandLockserv lockcommand;
CommandUnlockserv unlockcommand;
-public:
+ public:
ModuleLockserv() : lockcommand(this, locked), unlockcommand(this, locked)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
locked = false;
ServerInstance->Modules->AddService(lockcommand);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleLockserv()
- {
- }
-
-
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
// Emergency way to unlock
if (!user) locked = false;
}
- virtual ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
if (locked)
{
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnCheckReady(LocalUser* user)
+ ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
return locked ? MOD_RES_DENY : MOD_RES_PASSTHRU;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows locking of the server to stop all incoming connections until unlocked again", VF_VENDOR);
}
{
std::string url;
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnPreCommand, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
url = ServerInstance->Config->ConfValue("security")->getString("maphide");
}
- ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
- if (validated && !IS_OPER(user) && !url.empty() && (command == "MAP" || command == "LINKS"))
+ if (validated && !user->IsOper() && !url.empty() && (command == "MAP" || command == "LINKS"))
{
- user->WriteServ("NOTICE %s :/%s has been disabled; visit %s", user->nick.c_str(), command.c_str(), url.c_str());
+ user->WriteNotice("/" + command + " has been disabled; visit " + url);
return MOD_RES_DENY;
}
else
return MOD_RES_PASSTHRU;
}
- virtual ~ModuleMapHide()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Hide /MAP and /LINKS in the same form as ircu (mostly useless)", VF_VENDOR);
}
};
MODULE_INIT(ModuleMapHide)
-
#ifdef HAS_STDINT
#include <stdint.h>
#endif
-#include "hash.h"
+#include "modules/hash.h"
/* The four core functions - F1 is optimized somewhat */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
return std::string(res, 16);
}
- std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata)
- {
- char res[33];
- GenHash(sdata.data(), res, HexMap, IV, sdata.length());
- return res;
- }
-
MD5Provider(Module* parent) : HashProvider(parent, "hash/md5", 16, 64) {}
};
ServerInstance->Modules->AddService(md5);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements MD5 hashing",VF_VENDOR);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(mf);
ServerInstance->Modules->AddService(mf.ext);
- Implementation eventlist[] = { I_OnUserPreNotice, I_OnUserPreMessage };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
+ ServerInstance->Modules->Attach(I_OnUserPreMessage, this);
}
ModResult ProcessMessages(User* user,Channel* dest, const std::string &text)
ServerInstance->SendGlobalMode(parameters, ServerInstance->FakeClient);
}
- char kickmessage[MAXBUF];
- snprintf(kickmessage, MAXBUF, "Channel flood triggered (limit is %u lines in %u secs)", f->lines, f->secs);
+ const std::string kickMessage = "Channel flood triggered (limit is " + ConvToStr(f->lines) +
+ " in " + ConvToStr(f->secs) + " secs)";
- dest->KickUser(ServerInstance->FakeClient, user, kickmessage);
+ dest->KickUser(ServerInstance->FakeClient, user, kickMessage);
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
}
- ModResult OnUserPreMessage(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list)
- {
- if (target_type == TYPE_CHANNEL)
- return ProcessMessages(user,(Channel*)dest,text);
-
- return MOD_RES_PASSTHRU;
- }
-
- ModResult OnUserPreNotice(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (target_type == TYPE_CHANNEL)
return ProcessMessages(user,(Channel*)dest,text);
{
// we want to be after all modules that might deny the message (e.g. m_muteban, m_noctcp, m_blockcolor, etc.)
ServerInstance->Modules->SetPriority(this, I_OnUserPreMessage, PRIORITY_LAST);
- ServerInstance->Modules->SetPriority(this, I_OnUserPreNotice, PRIORITY_LAST);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +f (message flood protection)", VF_VENDOR);
}
class ModuleMLock : public Module
{
-private:
StringExtItem mlock;
public:
ModuleMLock() : mlock("mlock", this) {};
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->Attach(I_OnPreMode, this);
ServerInstance->Modules->AddService(this->mlock);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements the ability to have server-side MLOCK enforcement.", VF_VENDOR);
}
ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
}
- ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters)
+ ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
{
if (!channel)
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
-
};
MODULE_INIT(ModuleMLock)
class ModuleQuietBan : public Module
{
- private:
public:
- void init()
+ void init() CXX11_OVERRIDE
{
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_On005Numeric };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleQuietBan()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements extban +b m: - mute bans",VF_OPTCOMMON|VF_VENDOR);
}
- virtual ModResult OnUserPreMessage(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (!IS_LOCAL(user) || target_type != TYPE_CHANNEL)
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreNotice(User *user, void *dest, int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreMessage(user, dest, target_type, text, status, exempt_list);
- }
-
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('m');
+ tokens["EXTBAN"].push_back('m');
}
};
-
MODULE_INIT(ModuleQuietBan)
-
if (mh->GetNumParams(true))
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());
- user->SendText(std::string(pfx), items);
+ const std::string line = ":" + ServerInstance->Config->ServerName + " 961 " + user->nick + " " + channel->name;
+ user->SendText(line, items);
user->WriteNumeric(960, "%s %s :End of mode list", user->nick.c_str(), channel->name.c_str());
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->AddService(dummyZ);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
}
ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
}
- ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters)
+ ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
{
if (!channel)
return MOD_RES_PASSTHRU;
#include "inspircd.h"
-#include "m_cap.h"
+#include "modules/cap.h"
/* $ModDesc: Provides the NAMESX (CAP multi-prefix) capability. */
class ModuleNamesX : public Module
{
- public:
GenericCap cap;
+ public:
ModuleNamesX() : cap(this, "multi-prefix")
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnPreCommand, I_OnNamesListItem, I_On005Numeric, I_OnEvent, I_OnSendWhoLine };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
-
- ~ModuleNamesX()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the NAMESX (CAP multi-prefix) capability.",VF_VENDOR);
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" NAMESX");
+ tokens["NAMESX"];
}
- ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
/* We don't actually create a proper command handler class for PROTOCTL,
* because other modules might want to have PROTOCTL hooks too.
return MOD_RES_PASSTHRU;
}
- void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick)
+ void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick) CXX11_OVERRIDE
{
if (!cap.ext.get(issuer))
return;
prefixes = memb->chan->GetAllPrefixChars(memb->user);
}
- void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line)
+ void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line) CXX11_OVERRIDE
{
if (!cap.ext.get(source))
return;
line.insert(pos, prefixes);
}
- void OnEvent(Event& ev)
+ void OnEvent(Event& ev) CXX11_OVERRIDE
{
cap.HandleEvent(ev);
}
/* $ModDesc: Provides an ability to have non-RFC1459 nicks & support for national CASEMAPPING */
-class lwbNickHandler : public HandlerBase2<bool, const char*, size_t>
+class lwbNickHandler : public HandlerBase1<bool, const std::string&>
{
public:
lwbNickHandler() { }
- virtual ~lwbNickHandler() { }
- virtual bool Call(const char*, size_t);
+ ~lwbNickHandler() { }
+ bool Call(const std::string&);
};
/*,m_reverse_additionalUp[256];*/
/* Conditions added */
-bool lwbNickHandler::Call(const char* n, size_t max)
+bool lwbNickHandler::Call(const std::string& nick)
{
- if (!n || !*n)
+ if (nick.empty())
return false;
+ const char* n = nick.c_str();
unsigned int p = 0;
for (const char* i = n; *i; i++, p++)
{
}
/* too long? or not -- pointer arithmetic rocks */
- return (p < max);
+ return (p < ServerInstance->Config->Limits.NickMax);
}
class ModuleNationalChars : public Module
{
- private:
lwbNickHandler myhandler;
std::string charset, casemapping;
unsigned char m_additional[256], m_additionalUp[256], m_lower[256], m_upper[256];
- caller2<bool, const char*, size_t> rememberer;
+ caller1<bool, const std::string&> rememberer;
bool forcequit;
const unsigned char * lowermap_rememberer;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
memcpy(m_lower, rfc_case_insensitive_map, 256);
national_case_insensitive_map = m_lower;
OnRehash(NULL);
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- std::string tmp(casemapping);
- tmp.insert(0, "CASEMAPPING=");
- SearchAndReplace(output, std::string("CASEMAPPING=rfc1459"), tmp);
+ tokens["CASEMAPPING"] = casemapping;
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("nationalchars");
charset = tag->getString("file");
{
/* Fix by Brain: Dont quit UID users */
User* n = *iter;
- if (!isdigit(n->nick[0]) && !ServerInstance->IsNick(n->nick.c_str(), ServerInstance->Config->Limits.NickMax))
+ if (!isdigit(n->nick[0]) && !ServerInstance->IsNick(n->nick))
ServerInstance->Users->QuitUser(n, message);
}
}
- virtual ~ModuleNationalChars()
+ ~ModuleNationalChars()
{
ServerInstance->IsNick = rememberer;
national_case_insensitive_map = lowermap_rememberer;
CheckForceQuit("National characters module unloaded");
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides an ability to have non-RFC1459 nicks & support for national CASEMAPPING", VF_VENDOR | VF_COMMON, charset);
}
std::ifstream ifs(filename.c_str());
if (ifs.fail())
{
- ServerInstance->Logs->Log("m_nationalchars",DEFAULT,"loadtables() called for missing file: %s", filename.c_str());
+ ServerInstance->Logs->Log("m_nationalchars", LOG_DEFAULT, "loadtables() called for missing file: %s", filename.c_str());
return;
}
{
if (loadtable(ifs, tables[n], 255) && (n < faillimit))
{
- ServerInstance->Logs->Log("m_nationalchars",DEFAULT,"loadtables() called for illegal file: %s (line %d)", filename.c_str(), n+1);
+ ServerInstance->Logs->Log("m_nationalchars", LOG_DEFAULT, "loadtables() called for illegal file: %s (line %d)", filename.c_str(), n+1);
return;
}
}
NickFlood nf;
public:
-
ModuleNickFlood()
: nf(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(nf);
ServerInstance->Modules->AddService(nf.ext);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ModResult OnUserPreNick(User* user, const std::string &newnick)
+ ModResult OnUserPreNick(User* user, const std::string &newnick) CXX11_OVERRIDE
{
- if (ServerInstance->NICKForced.get(user)) /* Allow forced nick changes */
- return MOD_RES_PASSTHRU;
-
for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++)
{
Channel *channel = *i;
/*
* XXX: HACK: We do the increment on the *POST* event here (instead of all together) because we have no way of knowing whether other modules would block a nickchange.
*/
- void OnUserPostNick(User* user, const std::string &oldnick)
+ void OnUserPostNick(User* user, const std::string &oldnick) CXX11_OVERRIDE
{
if (isdigit(user->nick[0])) /* allow switches to UID */
return;
}
}
- ~ModuleNickFlood()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Channel mode F - nick flood protection", VF_VENDOR);
}
if ((!target) || (target->registered != REG_ALL))
{
- user->WriteServ("NOTICE %s :*** No such nickname: '%s'", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** No such nickname: '" + parameters[0] + "'");
return CMD_FAILURE;
}
/* Do local sanity checks and bails */
if (IS_LOCAL(user))
{
- if (!ServerInstance->IsNick(parameters[1].c_str(), ServerInstance->Config->Limits.NickMax))
+ if (!ServerInstance->IsNick(parameters[1]))
{
- user->WriteServ("NOTICE %s :*** Invalid nickname '%s'", user->nick.c_str(), parameters[1].c_str());
+ user->WriteNotice("*** Invalid nickname '" + parameters[1] + "'");
return CMD_FAILURE;
}
locked.set(target, 1);
std::string oldnick = target->nick;
- if (target->ForceNickChange(parameters[1].c_str()))
+ if (target->ForceNickChange(parameters[1]))
ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used NICKLOCK to change and hold "+oldnick+" to "+parameters[1]);
else
{
if (!target)
{
- user->WriteServ("NOTICE %s :*** No such nickname: '%s'", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** No such nickname: '" + parameters[0] + "'");
return CMD_FAILURE;
}
}
};
-
class ModuleNickLock : public Module
{
LocalIntExt locked;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd1);
ServerInstance->Modules->AddService(cmd2);
ServerInstance->Modules->Attach(I_OnUserPreNick, this);
}
- ~ModuleNickLock()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the NICKLOCK command, allows an oper to change a users nick and lock them to it until they quit", VF_OPTCOMMON | VF_VENDOR);
}
- ModResult OnUserPreNick(User* user, const std::string &newnick)
+ ModResult OnUserPreNick(User* user, const std::string &newnick) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return MOD_RES_PASSTHRU;
- if (ServerInstance->NICKForced.get(user)) /* Allow forced nick changes */
- return MOD_RES_PASSTHRU;
-
if (locked.get(user))
{
user->WriteNumeric(447, "%s :You cannot change your nickname (your nick is locked)",user->nick.c_str());
class ModuleNoCTCP : public Module
{
-
NoCTCP nc;
public:
-
ModuleNoCTCP()
: nc(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(nc);
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_On005Numeric };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleNoCTCP()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +C to block CTCPs", VF_VENDOR);
}
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreNotice(user,dest,target_type,text,status,exempt_list);
- }
-
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if ((target_type == TYPE_CHANNEL) && (IS_LOCAL(user)))
{
return MOD_RES_PASSTHRU;
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('C');
+ tokens["EXTBAN"].push_back('C');
}
};
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(nk);
Implementation eventlist[] = { I_OnUserPreKick, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('Q');
+ tokens["EXTBAN"].push_back('Q');
}
- ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason)
+ ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason) CXX11_OVERRIDE
{
if (!memb->chan->GetExtBanStatus(source, 'Q').check(!memb->chan->IsModeSet('Q')))
{
return MOD_RES_PASSTHRU;
}
- ~ModuleNoKicks()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +Q to prevent kicks on the channel.", VF_VENDOR);
}
};
-
MODULE_INIT(ModuleNoKicks)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->AddService(nn);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleNoNickChange()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for channel mode +N & extban +b N: which prevents nick changes on channel", VF_VENDOR);
}
-
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('N');
+ tokens["EXTBAN"].push_back('N');
}
- virtual ModResult OnUserPreNick(User* user, const std::string &newnick)
+ ModResult OnUserPreNick(User* user, const std::string &newnick) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return MOD_RES_PASSTHRU;
- // Allow forced nick changes.
- if (ServerInstance->NICKForced.get(user))
- return MOD_RES_PASSTHRU;
-
for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++)
{
Channel* curr = *i;
if (res == MOD_RES_ALLOW)
continue;
- if (override && IS_OPER(user))
+ if (override && user->IsOper())
continue;
if (!curr->GetExtBanStatus(user, 'N').check(!curr->IsModeSet('N')))
return MOD_RES_PASSTHRU;
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
override = ServerInstance->Config->ConfValue("nonicks")->getBool("operoverride", false);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(nt);
- Implementation eventlist[] = { I_OnUserPreNotice, I_On005Numeric };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('T');
+ tokens["EXTBAN"].push_back('T');
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
ModResult res;
- if ((target_type == TYPE_CHANNEL) && (IS_LOCAL(user)))
+ if ((msgtype == MSG_NOTICE) && (target_type == TYPE_CHANNEL) && (IS_LOCAL(user)))
{
Channel* c = (Channel*)dest;
if (!c->GetExtBanStatus(user, 'T').check(!c->IsModeSet('T')))
return MOD_RES_PASSTHRU;
}
- virtual ~ModuleNoNotice()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +T to block notices to the channel", VF_VENDOR);
}
class ModulePartMsgBan : public Module
{
- private:
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnUserPart, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModulePartMsgBan()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements extban +b p: - part message bans", VF_OPTCOMMON|VF_VENDOR);
}
-
- virtual void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts)
+ void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) CXX11_OVERRIDE
{
if (!IS_LOCAL(memb->user))
return;
if (memb->chan->GetExtBanStatus(memb->user, 'p') == MOD_RES_DENY)
partmessage.clear();
-
- return;
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('p');
+ tokens["EXTBAN"].push_back('p');
}
};
-
MODULE_INIT(ModulePartMsgBan)
-
/** Handle /OJOIN
*/
-class CommandOjoin : public Command
+class CommandOjoin : public SplitCommand
{
public:
bool active;
- CommandOjoin(Module* parent) : Command(parent,"OJOIN", 1)
+ CommandOjoin(Module* parent) :
+ SplitCommand(parent, "OJOIN", 1)
{
flags_needed = 'o'; Penalty = 0; syntax = "<channel>";
active = false;
TRANSLATE3(TR_NICK, TR_TEXT, TR_END);
}
- CmdResult Handle (const std::vector<std::string>& parameters, User *user)
+ CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user)
{
// Make sure the channel name is allowable.
- if (!ServerInstance->IsChannel(parameters[0].c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (!ServerInstance->IsChannel(parameters[0]))
{
- user->WriteServ("NOTICE "+user->nick+" :*** Invalid characters in channel name or name too long");
+ user->WriteNotice("*** Invalid characters in channel name or name too long");
return CMD_FAILURE;
}
active = true;
- Channel* channel = Channel::JoinUser(user, parameters[0].c_str(), false, "", false);
+ // override is false because we want OnUserPreJoin to run
+ Channel* channel = Channel::JoinUser(user, parameters[0], false);
active = false;
if (channel)
m_paramtype = TR_NICK;
}
- void RemoveMode(Channel* channel, irc::modestacker* stack)
- {
- const UserMembList* cl = channel->GetUsers();
- std::vector<std::string> mode_junk;
- mode_junk.push_back(channel->name);
- irc::modestacker modestack(false);
- std::deque<std::string> stackresult;
-
- for (UserMembCIter i = cl->begin(); i != cl->end(); i++)
- {
- if (i->second->hasMode('Y'))
- {
- if (stack)
- stack->Push(this->GetModeChar(), i->first->nick);
- else
- modestack.Push(this->GetModeChar(), i->first->nick);
- }
- }
-
- if (stack)
- return;
-
- 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());
- }
- }
-
unsigned int GetPrefixRank()
{
return NETWORK_VALUE;
}
- void RemoveMode(User* user, irc::modestacker* stack)
- {
- }
-
ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding)
{
User* theuser = ServerInstance->FindNick(parameter);
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
/* Load config stuff */
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ModResult OnUserPreJoin(User *user, Channel *chan, const char *cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
if (mycommand.active)
{
return MOD_RES_PASSTHRU;
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* Conf = ServerInstance->Config->ConfValue("ojoin");
op = Conf->getBool("op", true);
}
- ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason)
+ ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason) CXX11_OVERRIDE
{
// Don't do anything if they're not +Y
if (!memb->hasMode('Y'))
ServerInstance->Modules->SetPriority(this, I_OnUserPreJoin, PRIORITY_FIRST);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Network Business Join", VF_VENDOR);
}
};
MODULE_INIT(ModuleOjoin)
-
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(oc);
Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric, I_OnUserPreJoin };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
- if (chan && chan->IsModeSet('O') && !IS_OPER(user))
+ if (chan && chan->IsModeSet('O') && !user->IsOper())
{
user->WriteNumeric(ERR_CANTJOINOPERSONLY, "%s %s :Only IRC operators may join %s (+O is set)",
user->nick.c_str(), chan->name.c_str(), chan->name.c_str());
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckBan(User *user, Channel *c, const std::string& mask)
+ ModResult OnCheckBan(User *user, Channel *c, const std::string& mask) CXX11_OVERRIDE
{
if ((mask.length() > 2) && (mask[0] == 'O') && (mask[1] == ':'))
{
- if (IS_OPER(user) && InspIRCd::Match(user->oper->name, mask.substr(2)))
+ if (user->IsOper() && InspIRCd::Match(user->oper->name, mask.substr(2)))
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('O');
+ tokens["EXTBAN"].push_back('O');
}
- ~ModuleOperChans()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for oper-only chans via the +O channel mode and 'O' extban", VF_VENDOR);
}
class ModuleOperjoin : public Module
{
- private:
std::string operChan;
std::vector<std::string> operChans;
bool override;
}
public:
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
Implementation eventlist[] = { I_OnPostOper, I_OnRehash };
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("operjoin");
tokenize(operChan,operChans);
}
- virtual ~ModuleOperjoin()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Forces opers to join the specified channel(s) on oper-up", VF_VENDOR);
}
- virtual void OnPostOper(User* user, const std::string &opertype, const std::string &opername)
+ void OnPostOper(User* user, const std::string &opertype, const std::string &opername) CXX11_OVERRIDE
{
- if (!IS_LOCAL(user))
+ LocalUser* localuser = IS_LOCAL(user);
+ if (!localuser)
return;
- for(std::vector<std::string>::iterator it = operChans.begin(); it != operChans.end(); it++)
- if (ServerInstance->IsChannel(it->c_str(), ServerInstance->Config->Limits.ChanMax))
- Channel::JoinUser(user, it->c_str(), override, "", false, ServerInstance->Time());
+ for (std::vector<std::string>::const_iterator i = operChans.begin(); i != operChans.end(); ++i)
+ if (ServerInstance->IsChannel(*i))
+ Channel::JoinUser(localuser, *i, override);
- std::string chanList = IS_OPER(user)->getConfig("autojoin");
+ std::string chanList = localuser->oper->getConfig("autojoin");
if (!chanList.empty())
{
std::vector<std::string> typechans;
tokenize(chanList, typechans);
for (std::vector<std::string>::const_iterator it = typechans.begin(); it != typechans.end(); ++it)
{
- if (ServerInstance->IsChannel(it->c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (ServerInstance->IsChannel(*it))
{
- Channel::JoinUser(user, it->c_str(), override, "", false, ServerInstance->Time());
+ Channel::JoinUser(localuser, *it, override);
}
}
}
class ModuleOperLevels : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->Attach(I_OnKill, this);
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Gives each oper type a 'level', cannot kill opers 'above' your level.", VF_VENDOR);
}
- virtual ModResult OnKill(User* source, User* dest, const std::string &reason)
+ ModResult OnKill(User* source, User* dest, const std::string &reason) CXX11_OVERRIDE
{
// oper killing an oper?
- if (IS_OPER(dest) && IS_OPER(source))
+ if (dest->IsOper() && source->IsOper())
{
std::string level = dest->oper->getConfig("level");
long dest_level = atol(level.c_str());
if (dest_level > source_level)
{
if (IS_LOCAL(source)) ServerInstance->SNO->WriteGlobalSno('a', "Oper %s (level %ld) attempted to /kill a higher oper: %s (level %ld): Reason: %s",source->nick.c_str(),source_level,dest->nick.c_str(),dest_level,reason.c_str());
- dest->WriteServ("NOTICE %s :*** Oper %s attempted to /kill you!",dest->nick.c_str(),source->nick.c_str());
+ dest->WriteNotice("*** Oper " + source->nick + " attempted to /kill you!");
source->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper %s is a higher level than you",source->nick.c_str(),dest->nick.c_str());
return MOD_RES_DENY;
}
};
MODULE_INIT(ModuleOperLevels)
-
bool tosnomask;
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnPreCommand, I_On005Numeric, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
- virtual ~ModuleOperLog()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("A module which logs all oper commands to the ircd log at default loglevel.", VF_VENDOR);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
tosnomask = ServerInstance->Config->ConfValue("operlog")->getBool("tosnomask", false);
}
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
/* If the command doesnt appear to be valid, we dont want to mess with it. */
if (!validated)
return MOD_RES_PASSTHRU;
- if ((IS_OPER(user)) && (IS_LOCAL(user)) && (user->HasPermission(command)))
+ if ((user->IsOper()) && (IS_LOCAL(user)) && (user->HasPermission(command)))
{
Command* thiscommand = ServerInstance->Parser->GetHandler(command);
if ((thiscommand) && (thiscommand->flags_needed == 'o'))
if (!parameters.empty())
line = irc::stringjoiner(" ", parameters, 0, parameters.size() - 1).GetJoined();
std::string msg = "[" + user->GetFullRealHost() + "] " + command + " " + line;
- ServerInstance->Logs->Log("m_operlog", DEFAULT, "OPERLOG: " + msg);
+ ServerInstance->Logs->Log("m_operlog", LOG_DEFAULT, "OPERLOG: " + msg);
if (tosnomask)
ServerInstance->SNO->WriteGlobalSno('r', msg);
}
return MOD_RES_PASSTHRU;
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" OPERLOG");
+ tokens["OPERLOG"];
}
};
-
MODULE_INIT(ModuleOperLog)
class ModuleModesOnOper : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->Attach(I_OnPostOper, this);
}
- virtual ~ModuleModesOnOper()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Sets (and unsets) modes on opers when they oper up", VF_VENDOR);
}
- virtual void OnPostOper(User* user, const std::string &opertype, const std::string &opername)
+ void OnPostOper(User* user, const std::string &opertype, const std::string &opername) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Shows a message to opers after oper-up, adds /opermotd", VF_VENDOR | VF_OPTCOMMON);
}
- virtual void OnOper(User* user, const std::string &opertype)
+ void OnOper(User* user, const std::string &opertype) CXX11_OVERRIDE
{
if (onoper && IS_LOCAL(user))
cmd.ShowOperMOTD(user);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
cmd.opermotd.clear();
ConfigTag* conf = ServerInstance->Config->ConfValue("opermotd");
onoper = conf->getBool("onoper", true);
- FileReader f(conf->getString("file", "opermotd"));
- for (int i=0, filesize = f.FileSize(); i < filesize; i++)
- cmd.opermotd.push_back(f.GetLine(i));
+ try
+ {
+ FileReader reader(conf->getString("file", "opermotd"));
+ cmd.opermotd = reader.GetVector();
+ }
+ catch (CoreException&)
+ {
+ // Nothing happens here as we do the error handling in ShowOperMOTD.
+ }
if (conf->getBool("processcolors"))
InspIRCd::ProcessColors(cmd.opermotd);
class HideOperWatcher : public ModeWatcher
{
ModuleOperPrefixMode* parentmod;
+
public:
- HideOperWatcher(ModuleOperPrefixMode* parent) : ModeWatcher((Module*) parent, 'H', MODETYPE_USER), parentmod(parent) {}
- void AfterMode(User* source, User* dest, Channel* channel, const std::string ¶meter, bool adding, ModeType type);
+ HideOperWatcher(ModuleOperPrefixMode* parent);
+ void AfterMode(User* source, User* dest, Channel* channel, const std::string ¶meter, bool adding);
};
class ModuleOperPrefixMode : public Module
{
- private:
OperPrefixMode opm;
- bool mw_added;
HideOperWatcher hideoperwatcher;
+
public:
ModuleOperPrefixMode()
- : opm(this), mw_added(false), hideoperwatcher(this)
+ : opm(this), hideoperwatcher(this)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(opm);
- Implementation eventlist[] = { I_OnUserPreJoin, I_OnPostOper, I_OnLoadModule, I_OnUnloadModule };
+ Implementation eventlist[] = { I_OnUserPreJoin, I_OnPostOper };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
/* To give clients a chance to learn about the new prefix we don't give +y to opers
* they need to rejoin them in order to get the oper prefix.
*/
- if (ServerInstance->Modules->Find("m_hideoper.so"))
- mw_added = ServerInstance->Modes->AddModeWatcher(&hideoperwatcher);
+ ServerInstance->Modes->AddModeWatcher(&hideoperwatcher);
}
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string& privs, const std::string& keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
- /* The user may have the +H umode on himself, but +H does not necessarily correspond
- * to the +H of m_hideoper.
- * However we only add the modewatcher when m_hideoper is loaded, so these
- * conditions (mw_added and the user being +H) together mean the user is a hidden oper.
- */
-
- if (IS_OPER(user) && (!mw_added || !user->IsModeSet('H')))
+ if ((user->IsOper()) && (user->IsModeSet('H')))
privs.push_back('y');
return MOD_RES_PASSTHRU;
}
}
}
- void OnPostOper(User* user, const std::string& opername, const std::string& opertype)
+ void OnPostOper(User* user, const std::string& opername, const std::string& opertype) CXX11_OVERRIDE
{
- if (IS_LOCAL(user) && (!mw_added || !user->IsModeSet('H')))
+ if (IS_LOCAL(user) && (!user->IsModeSet('H')))
SetOperPrefix(user, true);
}
- void OnLoadModule(Module* mod)
- {
- if ((!mw_added) && (mod->ModuleSourceFile == "m_hideoper.so"))
- mw_added = ServerInstance->Modes->AddModeWatcher(&hideoperwatcher);
- }
-
- void OnUnloadModule(Module* mod)
- {
- if ((mw_added) && (mod->ModuleSourceFile == "m_hideoper.so") && (ServerInstance->Modes->DelModeWatcher(&hideoperwatcher)))
- mw_added = false;
- }
~ModuleOperPrefixMode()
{
- if (mw_added)
- ServerInstance->Modes->DelModeWatcher(&hideoperwatcher);
+ ServerInstance->Modes->DelModeWatcher(&hideoperwatcher);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Gives opers cmode +y which provides a staff prefix.", VF_VENDOR);
}
}
};
-void HideOperWatcher::AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding, ModeType type)
+HideOperWatcher::HideOperWatcher(ModuleOperPrefixMode* parent)
+ : ModeWatcher(parent, "hideoper", MODETYPE_USER)
+ , parentmod(parent)
+{
+}
+
+void HideOperWatcher::AfterMode(User* source, User* dest, Channel* channel, const std::string& parameter, bool adding)
{
if (IS_LOCAL(dest))
parentmod->SetOperPrefix(dest, !adding);
public:
- void init()
+ void init() CXX11_OVERRIDE
{
// read our config options (main config file)
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
// re-read our config options on a rehash
ConfigTag* tag = ServerInstance->Config->ConfValue("override");
RequireKey = tag->getBool("requirekey");
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" OVERRIDE");
+ tokens["OVERRIDE"];
}
bool CanOverride(User* source, const char* token)
}
- ModResult OnPreTopicChange(User *source, Channel *channel, const std::string &topic)
+ ModResult OnPreTopicChange(User *source, Channel *channel, const std::string &topic) CXX11_OVERRIDE
{
- if (IS_LOCAL(source) && IS_OPER(source) && CanOverride(source, "TOPIC"))
+ if (IS_LOCAL(source) && source->IsOper() && CanOverride(source, "TOPIC"))
{
if (!channel->HasUser(source) || (channel->IsModeSet('t') && channel->GetPrefixValue(source) < HALFOP_VALUE))
{
return MOD_RES_PASSTHRU;
}
- ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason)
+ ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason) CXX11_OVERRIDE
{
- if (IS_OPER(source) && CanOverride(source,"KICK"))
+ if (source->IsOper() && CanOverride(source,"KICK"))
{
// If the kicker's status is less than the target's, or the kicker's status is less than or equal to voice
if ((memb->chan->GetPrefixValue(source) < memb->getRank()) || (memb->chan->GetPrefixValue(source) <= VOICE_VALUE))
return MOD_RES_PASSTHRU;
}
- ModResult OnPreMode(User* source,User* dest,Channel* channel, const std::vector<std::string>& parameters)
+ ModResult OnPreMode(User* source,User* dest,Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
{
if (!source || !channel)
return MOD_RES_PASSTHRU;
- if (!IS_OPER(source) || !IS_LOCAL(source))
+ if (!source->IsOper() || !IS_LOCAL(source))
return MOD_RES_PASSTHRU;
unsigned int mode = channel->GetPrefixValue(source);
return MOD_RES_PASSTHRU;
}
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
- if (IS_LOCAL(user) && IS_OPER(user))
+ if (user->IsOper())
{
if (chan)
{
if (chan->IsModeSet('i') && (CanOverride(user,"INVITE")))
{
- irc::string x(chan->name.c_str());
- if (!IS_LOCAL(user)->IsInvited(x))
+ if (!IS_LOCAL(user)->IsInvited(chan))
{
if (RequireKey && keygiven != "override")
{
// Can't join normally -- must use a special key to bypass restrictions
- user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
+ user->WriteNotice("*** You may not join normally. You must join with a key of 'override' to oper override.");
return MOD_RES_PASSTHRU;
}
if (NoisyOverride)
- chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass invite-only", cname, user->nick.c_str());
- ServerInstance->SNO->WriteGlobalSno('v', user->nick+" used oper override to bypass +i on "+std::string(cname));
+ chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass invite-only", cname.c_str(), user->nick.c_str());
+ ServerInstance->SNO->WriteGlobalSno('v', user->nick+" used oper override to bypass +i on " + cname);
}
return MOD_RES_ALLOW;
}
if (RequireKey && keygiven != "override")
{
// Can't join normally -- must use a special key to bypass restrictions
- user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
+ user->WriteNotice("*** You may not join normally. You must join with a key of 'override' to oper override.");
return MOD_RES_PASSTHRU;
}
if (NoisyOverride)
- chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass the channel key", cname, user->nick.c_str());
- ServerInstance->SNO->WriteGlobalSno('v', user->nick+" used oper override to bypass +k on "+std::string(cname));
+ chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass the channel key", cname.c_str(), user->nick.c_str());
+ ServerInstance->SNO->WriteGlobalSno('v', user->nick+" used oper override to bypass +k on " + cname);
return MOD_RES_ALLOW;
}
if (RequireKey && keygiven != "override")
{
// Can't join normally -- must use a special key to bypass restrictions
- user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
+ user->WriteNotice("*** You may not join normally. You must join with a key of 'override' to oper override.");
return MOD_RES_PASSTHRU;
}
if (NoisyOverride)
- chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass the channel limit", cname, user->nick.c_str());
- ServerInstance->SNO->WriteGlobalSno('v', user->nick+" used oper override to bypass +l on "+std::string(cname));
+ chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass the channel limit", cname.c_str(), user->nick.c_str());
+ ServerInstance->SNO->WriteGlobalSno('v', user->nick+" used oper override to bypass +l on " + cname);
return MOD_RES_ALLOW;
}
if (RequireKey && keygiven != "override")
{
// Can't join normally -- must use a special key to bypass restrictions
- user->WriteServ("NOTICE %s :*** You may not join normally. You must join with a key of 'override' to oper override.", user->nick.c_str());
+ user->WriteNotice("*** You may not join normally. You must join with a key of 'override' to oper override.");
return MOD_RES_PASSTHRU;
}
if (NoisyOverride)
- chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass channel ban", cname, user->nick.c_str());
- ServerInstance->SNO->WriteGlobalSno('v',"%s used oper override to bypass channel ban on %s", user->nick.c_str(), cname);
+ chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper override to bypass channel ban", cname.c_str(), user->nick.c_str());
+ ServerInstance->SNO->WriteGlobalSno('v',"%s used oper override to bypass channel ban on %s", user->nick.c_str(), cname.c_str());
return MOD_RES_ALLOW;
}
}
return MOD_RES_PASSTHRU;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for allowing opers to override certain things",VF_VENDOR);
}
class ModulePassForward : public Module
{
- private:
std::string nickrequired, forwardmsg, forwardcmd;
public:
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
Implementation eventlist[] = { I_OnPostConnect, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Sends server password to NickServ", VF_VENDOR);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("passforward");
nickrequired = tag->getString("nick", "NickServ");
}
}
- virtual void OnPostConnect(User* ruser)
+ void OnPostConnect(User* ruser) CXX11_OVERRIDE
{
LocalUser* user = IS_LOCAL(ruser);
if (!user || user->password.empty())
/* $ModDesc: Allows for hashed oper passwords */
#include "inspircd.h"
-#include "hash.h"
+#include "modules/hash.h"
/* Handle /MKPASSWD
*/
HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
if (!hp)
{
- user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str());
+ user->WriteNotice("Unknown hash type");
return;
}
std::string salt = ServerInstance->GenRandomStr(6, false);
std::string target = hp->hmac(salt, stuff);
std::string str = BinToBase64(salt) + "$" + BinToBase64(target, NULL, 0);
- user->WriteServ("NOTICE %s :%s hashed password for %s is %s",
- user->nick.c_str(), algo.c_str(), stuff.c_str(), str.c_str());
+ user->WriteNotice(algo + " hashed password for " + stuff + " is " + str);
return;
}
HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + algo);
{
/* Now attempt to generate a hash */
std::string hexsum = hp->hexsum(stuff);
- user->WriteServ("NOTICE %s :%s hashed password for %s is %s",
- user->nick.c_str(), algo.c_str(), stuff.c_str(), hexsum.c_str());
+ user->WriteNotice(algo + " hashed password for " + stuff + " is " + hexsum);
}
else
{
- user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str());
+ user->WriteNotice("Unknown hash type");
}
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
/* Read the config file first */
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ModResult OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype)
+ ModResult OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype) CXX11_OVERRIDE
{
if (hashtype.substr(0,5) == "hmac-")
{
return MOD_RES_PASSTHRU;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows for hashed oper passwords",VF_VENDOR);
}
f = fopen(tempname.c_str(), "w");
if (!f)
{
- ServerInstance->Logs->Log("m_permchannels",DEFAULT, "permchannels: Cannot create database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEFAULT, "permchannels: Cannot create database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot create new db: %s (%d)", strerror(errno), errno);
return false;
}
write_error |= fclose(f);
if (write_error)
{
- ServerInstance->Logs->Log("m_permchannels",DEFAULT, "permchannels: Cannot write to new database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEFAULT, "permchannels: Cannot write to new database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot write to new db: %s (%d)", strerror(errno), errno);
return false;
}
#ifdef _WIN32
if (remove(permchannelsconf.c_str()))
{
- ServerInstance->Logs->Log("m_permchannels",DEFAULT, "permchannels: Cannot remove old database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEFAULT, "permchannels: Cannot remove old database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot remove old database: %s (%d)", strerror(errno), errno);
return false;
}
// Use rename to move temporary to new db - this is guarenteed not to fuck up, even in case of a crash.
if (rename(tempname.c_str(), permchannelsconf.c_str()) < 0)
{
- ServerInstance->Logs->Log("m_permchannels",DEFAULT, "permchannels: Cannot move new to old database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEFAULT, "permchannels: Cannot move new to old database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot replace old with new db: %s (%d)", strerror(errno), errno);
return false;
}
if (channel->IsModeSet('P'))
{
channel->SetMode(this,false);
- if (channel->GetUserCounter() == 0)
- {
- channel->DelUser(ServerInstance->FakeClient);
- }
+ channel->CheckDestroy();
return MODEACTION_ALLOW;
}
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(p);
Implementation eventlist[] = { I_OnChannelPreDelete, I_OnPostTopicChange, I_OnRawMode, I_OnRehash, I_OnBackgroundTimer };
return Module::cull();
}
- virtual void OnRehash(User *user)
+ void OnRehash(User *user) CXX11_OVERRIDE
{
permchannelsconf = ServerInstance->Config->ConfValue("permchanneldb")->getString("filename");
}
if (channel.empty())
{
- ServerInstance->Logs->Log("m_permchannels", DEBUG, "Malformed permchannels tag with empty channel name.");
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEBUG, "Malformed permchannels tag with empty channel name.");
continue;
}
c = new Channel(channel, ServerInstance->Time());
if (!topic.empty())
{
- c->SetTopic(NULL, topic, true);
+ c->SetTopic(ServerInstance->FakeClient, topic, true);
/*
* Due to the way protocol works in 1.2, we need to hack the topic TS in such a way that this
*/
c->topicset = 42;
}
- ServerInstance->Logs->Log("m_permchannels", DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str());
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str());
if (modes.empty())
continue;
}
}
- virtual ModResult OnRawMode(User* user, Channel* chan, const char mode, const std::string ¶m, bool adding, int pcnt)
+ ModResult OnRawMode(User* user, Channel* chan, const char mode, const std::string ¶m, bool adding, int pcnt) CXX11_OVERRIDE
{
if (chan && (chan->IsModeSet('P') || mode == 'P'))
dirty = true;
return MOD_RES_PASSTHRU;
}
- virtual void OnPostTopicChange(User*, Channel *c, const std::string&)
+ void OnPostTopicChange(User*, Channel *c, const std::string&) CXX11_OVERRIDE
{
if (c->IsModeSet('P'))
dirty = true;
}
- void OnBackgroundTimer(time_t)
+ void OnBackgroundTimer(time_t) CXX11_OVERRIDE
{
if (dirty)
WriteDatabase();
}
catch (CoreException& e)
{
- ServerInstance->Logs->Log("m_permchannels", DEFAULT, "Error loading permchannels database: " + std::string(e.GetReason()));
+ ServerInstance->Logs->Log("m_permchannels", LOG_DEFAULT, "Error loading permchannels database: " + std::string(e.GetReason()));
}
}
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for channel mode +P to provide permanent channels",VF_VENDOR);
}
- virtual ModResult OnChannelPreDelete(Channel *c)
+ ModResult OnChannelPreDelete(Channel *c) CXX11_OVERRIDE
{
if (c->IsModeSet('P'))
return MOD_RES_DENY;
#include "inspircd.h"
-static FileReader *quotes = NULL;
-
-std::string prefix;
-std::string suffix;
-
-/** Handle /RANDQUOTE
- */
-class CommandRandquote : public Command
-{
- public:
- CommandRandquote(Module* Creator) : Command(Creator,"RANDQUOTE", 0)
- {
- }
-
- CmdResult Handle (const std::vector<std::string>& parameters, User *user)
- {
- int fsize = quotes->FileSize();
- if (fsize)
- {
- std::string str = quotes->GetLine(ServerInstance->GenRandomInt(fsize));
- if (!str.empty())
- user->WriteServ("NOTICE %s :%s%s%s",user->nick.c_str(),prefix.c_str(),str.c_str(),suffix.c_str());
- }
-
- return CMD_SUCCESS;
- }
-};
-
class ModuleRandQuote : public Module
{
private:
- CommandRandquote cmd;
- public:
- ModuleRandQuote()
- : cmd(this)
- {
- }
+ std::string prefix;
+ std::string suffix;
+ std::vector<std::string> quotes;
- void init()
+ public:
+ void init() CXX11_OVERRIDE
{
ConfigTag* conf = ServerInstance->Config->ConfValue("randquote");
-
- std::string q_file = conf->getString("file","quotes");
prefix = conf->getString("prefix");
suffix = conf->getString("suffix");
+ FileReader reader(conf->getString("file", "quotes"));
+ quotes = reader.GetVector();
- quotes = new FileReader(q_file);
- if (!quotes->Exists())
- {
- throw ModuleException("m_randquote: QuoteFile not Found!! Please check your config - module will not function.");
- }
- ServerInstance->Modules->AddService(cmd);
Implementation eventlist[] = { I_OnUserConnect };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
-
- virtual ~ModuleRandQuote()
+ void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
{
- delete quotes;
- }
-
- virtual Version GetVersion()
- {
- return Version("Provides random quotes on connect.",VF_VENDOR);
+ if (!quotes.empty())
+ {
+ unsigned long random = ServerInstance->GenRandomInt(quotes.size());
+ user->WriteNotice(prefix + quotes[random] + suffix);
+ }
}
- virtual void OnUserConnect(LocalUser* user)
+ Version GetVersion() CXX11_OVERRIDE
{
- cmd.Handle(std::vector<std::string>(), user);
+ return Version("Provides random quotes on connect.", VF_VENDOR);
}
};
{
if (IS_LOCAL(source))
{
- if (!ServerInstance->IsChannel(parameter.c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (!ServerInstance->IsChannel(parameter))
{
source->WriteNumeric(403, "%s %s :Invalid channel name", source->nick.c_str(), parameter.c_str());
parameter.clear();
}
}
- if (IS_LOCAL(source) && !IS_OPER(source))
+ if (IS_LOCAL(source) && !source->IsOper())
{
Channel* c = ServerInstance->FindChan(parameter);
if (!c)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
/* Setting this here so it isn't changable by rehasing the config later. */
UseUsermode = ServerInstance->Config->ConfValue("redirect")->getBool("antiredirect");
if (UseUsermode)
{
/* Log noting that this breaks compatability. */
- ServerInstance->Logs->Log("m_redirect", DEFAULT, "REDIRECT: Enabled usermode +L. This breaks linking with servers that do not have this enabled. This is disabled by default in the 2.0 branch but will be enabled in the next version.");
+ ServerInstance->Logs->Log("m_redirect", LOG_DEFAULT, "REDIRECT: Enabled usermode +L. This breaks linking with servers that do not have this enabled. This is disabled by default in the 2.0 branch but will be enabled in the next version.");
/* Try to add the usermode */
ServerInstance->Modules->AddService(re_u);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
if (chan)
{
std::string channel = chan->GetModeParameter('L');
/* sometimes broken ulines can make circular or chained +L, avoid this */
- Channel* destchan = NULL;
- destchan = ServerInstance->FindChan(channel);
+ Channel* destchan = ServerInstance->FindChan(channel);
if (destchan && destchan->IsModeSet('L'))
{
- user->WriteNumeric(470, "%s %s * :You may not join this channel. A redirect is set, but you may not be redirected as it is a circular loop.", user->nick.c_str(), cname);
+ user->WriteNumeric(470, "%s %s * :You may not join this channel. A redirect is set, but you may not be redirected as it is a circular loop.", user->nick.c_str(), cname.c_str());
return MOD_RES_DENY;
}
/* We check the bool value here to make sure we have it enabled, if we don't then
usermode +L might be assigned to something else. */
if (UseUsermode && user->IsModeSet('L'))
{
- user->WriteNumeric(470, "%s %s %s :Force redirection stopped.",
- user->nick.c_str(), cname, channel.c_str());
+ user->WriteNumeric(470, "%s %s %s :Force redirection stopped.", user->nick.c_str(), cname.c_str(), channel.c_str());
return MOD_RES_DENY;
}
else
{
- user->WriteNumeric(470, "%s %s %s :You may not join this channel, so you are automatically being transferred to the redirect channel.", user->nick.c_str(), cname, channel.c_str());
- Channel::JoinUser(user, channel.c_str(), false, "", false, ServerInstance->Time());
+ user->WriteNumeric(470, "%s %s %s :You may not join this channel, so you are automatically being transferred to the redirect channel.", user->nick.c_str(), cname.c_str(), channel.c_str());
+ Channel::JoinUser(user, channel);
return MOD_RES_DENY;
}
}
return MOD_RES_PASSTHRU;
}
- virtual ~ModuleRedirect()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +L (limit redirection) and user mode +L (no forced redirection)", VF_VENDOR);
}
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2008 Thomas Stagner <aquanight@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
- * 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/>.
- */
-
-
-#ifndef M_REGEX_H
-#define M_REGEX_H
-
-#include "inspircd.h"
-
-class Regex : public classbase
-{
-protected:
- std::string regex_string; // The raw uncompiled regex string.
-
- // Constructor may as well be protected, as this class is abstract.
- Regex(const std::string& rx) : regex_string(rx)
- {
- }
-
-public:
-
- virtual ~Regex()
- {
- }
-
- virtual bool Matches(const std::string& text) = 0;
-
- const std::string& GetRegexString() const
- {
- return regex_string;
- }
-};
-
-class RegexFactory : public DataProvider
-{
- public:
- RegexFactory(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) {}
-
- virtual Regex* Create(const std::string& expr) = 0;
-};
-
-#endif
*/
-#include "m_regex.h"
+#include "modules/regex.h"
#include "inspircd.h"
/* $ModDesc: Regex module using plain wildcard matching. */
{
}
- virtual ~GlobRegex()
- {
- }
-
- virtual bool Matches(const std::string& text)
+ bool Matches(const std::string& text)
{
return InspIRCd::Match(text, this->regex_string);
}
ServerInstance->Modules->AddService(gf);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Regex module using plain wildcard matching.", VF_VENDOR);
}
#include "inspircd.h"
-#include "account.h"
+#include "modules/account.h"
/* $ModDesc: Prevents users whose nicks are not registered from creating new channels */
class ModuleRegOnlyCreate : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnUserPreJoin };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
if (chan)
return MOD_RES_PASSTHRU;
- if (IS_OPER(user))
+ if (user->IsOper())
return MOD_RES_PASSTHRU;
if (user->IsModeSet('r'))
return MOD_RES_PASSTHRU;
// XXX. there may be a better numeric for this..
- user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have a registered nickname to create a new channel", user->nick.c_str(), cname);
+ user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have a registered nickname to create a new channel", user->nick.c_str(), cname.c_str());
return MOD_RES_DENY;
}
- ~ModuleRegOnlyCreate()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Prevents users whose nicks are not registered from creating new channels", VF_VENDOR);
}
*/
class RemoveBase : public Command
{
- private:
bool& supportnokicks;
public:
reason = "Removed by " + user->nick + ": " + reasonparam;
channel->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s removed %s from the channel", channel->name.c_str(), user->nick.c_str(), target->nick.c_str());
- target->WriteServ("NOTICE %s :*** %s removed you from %s with the message: %s", target->nick.c_str(), user->nick.c_str(), channel->name.c_str(), reasonparam.c_str());
+ target->WriteNotice("*** " + user->nick + " removed you from " + channel->name + " with the message: " + reasonparam);
channel->PartUser(target, reason);
}
return CMD_SUCCESS;
}
- virtual RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) = 0;
+ RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) = 0;
};
/** Handle /REMOVE
CommandFpart cmd2;
bool supportnokicks;
-
public:
ModuleRemove() : cmd1(this, supportnokicks), cmd2(this, supportnokicks)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd1);
ServerInstance->Modules->AddService(cmd2);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" REMOVE");
+ tokens["REMOVE"];
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
supportnokicks = ServerInstance->Config->ConfValue("remove")->getBool("supportnokicks");
}
- virtual ~ModuleRemove()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides a /remove command, this is mostly an alternative to /kick, except makes users appear to have parted the channel", VF_OPTCOMMON | VF_VENDOR);
}
-
};
MODULE_INIT(ModuleRemove)
}
public:
- void init()
+ void init() CXX11_OVERRIDE
{
ReadConfig();
Implementation eventlist[] = { I_OnUserPreJoin, I_OnRehash };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ReadConfig();
}
-
- virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
- irc::string x = cname;
- if (!IS_LOCAL(user))
- return MOD_RES_PASSTHRU;
+ irc::string x(cname.c_str());
// channel does not yet exist (record is null, about to be created IF we were to allow it)
if (!chan)
{
// user is not an oper and its not in the allow list
- if ((!IS_OPER(user)) && (allowchans.find(x) == allowchans.end()))
+ if ((!user->IsOper()) && (allowchans.find(x) == allowchans.end()))
{
- user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Only IRC operators may create new channels",user->nick.c_str(),cname);
+ user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Only IRC operators may create new channels",user->nick.c_str(),cname.c_str());
return MOD_RES_DENY;
}
}
return MOD_RES_PASSTHRU;
}
- virtual ~ModuleRestrictChans()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Only opers may create new channels if this module is loaded",VF_VENDOR);
}
/* $ModDesc: Forbids users from messaging each other. Users may still message opers and opers may message other opers. */
-
class ModuleRestrictMsg : public Module
{
-
public:
-
- void init()
+ void init() CXX11_OVERRIDE
{
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
+ ServerInstance->Modules->Attach(I_OnUserPreMessage, this);
}
-
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if ((target_type == TYPE_USER) && (IS_LOCAL(user)))
{
// (1) the sender is opered
// (2) the recipient is opered
// anything else, blocked.
- if (IS_OPER(u) || IS_OPER(user))
+ if (u->IsOper() || user->IsOper())
{
return MOD_RES_PASSTHRU;
}
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return this->OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
- }
-
- virtual ~ModuleRestrictMsg()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Forbids users from messaging each other. Users may still message opers and opers may message other opers.",VF_VENDOR);
}
#ifdef HAS_STDINT
#include <stdint.h>
#endif
-#include "hash.h"
+#include "modules/hash.h"
#define RMDsize 160
{
if (key)
{
- ServerInstance->Logs->Log("m_ripemd160.so", DEBUG, "initialize with custom mdbuf");
+ ServerInstance->Logs->Log("m_ripemd160.so", LOG_DEBUG, "initialize with custom mdbuf");
MDbuf[0] = key[0];
MDbuf[1] = key[1];
MDbuf[2] = key[2];
}
else
{
- ServerInstance->Logs->Log("m_ripemd160.so", DEBUG, "initialize with default mdbuf");
+ ServerInstance->Logs->Log("m_ripemd160.so", LOG_DEBUG, "initialize with default mdbuf");
MDbuf[0] = 0x67452301UL;
MDbuf[1] = 0xefcdab89UL;
MDbuf[2] = 0x98badcfeUL;
byte *RMD(byte *message, dword length, unsigned int* key)
{
- ServerInstance->Logs->Log("m_ripemd160", DEBUG, "RMD: '%s' length=%u", (const char*)message, length);
+ ServerInstance->Logs->Log("m_ripemd160", LOG_DEBUG, "RMD: '%s' length=%u", (const char*)message, length);
dword MDbuf[RMDsize/32]; /* contains (A, B, C, D(E)) */
static byte hashcode[RMDsize/8]; /* for final hash-value */
dword X[16]; /* current 16-word chunk */
return std::string(rv, RMDsize / 8);
}
- std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata)
- {
- return "";
- }
-
RIProv(Module* m) : HashProvider(m, "hash/ripemd160", 20, 64) {}
};
ServerInstance->Modules->AddService(mr);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides RIPEMD-160 hashing", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleRIPEMD160)
-
/* $ModDesc: RLINE: Regexp user banning. */
#include "inspircd.h"
-#include "m_regex.h"
+#include "modules/regex.h"
#include "xline.h"
static bool ZlineOnMatch = false;
bool Matches(User *u)
{
- if (u->exempt)
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu && lu->exempt)
return false;
std::string compare = u->nick + "!" + u->ident + "@" + u->host + " " + u->fullname;
DefaultApply(u, "R", false);
}
- void DisplayExpiry()
+ const std::string& Displayable()
{
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired R-line %s (set by %s %ld seconds ago)",
- this->matchtext.c_str(), this->source.c_str(), (long int)(ServerInstance->Time() - this->set_time));
- }
-
- const char* Displayable()
- {
- return matchtext.c_str();
+ return matchtext;
}
std::string matchtext;
RLineFactory(dynamic_reference<RegexFactory>& rx) : XLineFactory("R"), rxfactory(rx)
{
}
-
+
/** Generate a RLine
*/
XLine* Generate(time_t set_time, long duration, std::string source, std::string reason, std::string xline_specific_mask)
return new RLine(set_time, duration, source, reason, xline_specific_mask, rxfactory);
}
-
- ~RLineFactory()
- {
- }
};
/** Handle /RLINE
{
// Adding - XXX todo make this respect <insane> tag perhaps..
- long duration = ServerInstance->Duration(parameters[1]);
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
XLine *r = NULL;
try
else
{
delete r;
- user->WriteServ("NOTICE %s :*** R-Line for %s already exists", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** R-Line for " + parameters[0] + " already exists");
}
}
}
}
else
{
- user->WriteServ("NOTICE %s :*** R-Line %s not found in list, try /stats R.",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNotice("*** R-Line " + parameters[0] + " not found in list, try /stats R.");
}
}
class ModuleRLine : public Module
{
- private:
dynamic_reference<RegexFactory> rxfactory;
RLineFactory f;
CommandRLine r;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleRLine()
+ ~ModuleRLine()
{
ServerInstance->XLines->DelAll("R");
ServerInstance->XLines->UnregisterFactory(&f);
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("RLINE: Regexp user banning.", VF_COMMON | VF_VENDOR, rxfactory ? rxfactory->name : "");
}
- ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
// Apply lines on user connect
XLine *rl = ServerInstance->XLines->MatchesLine("R", user);
return MOD_RES_PASSTHRU;
}
- virtual void OnRehash(User *user)
+ void OnRehash(User *user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("rline");
initing = false;
}
- virtual ModResult OnStats(char symbol, User* user, string_list &results)
+ ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE
{
if (symbol != 'R')
return MOD_RES_PASSTHRU;
return MOD_RES_DENY;
}
- virtual void OnUserPostNick(User *user, const std::string &oldnick)
+ void OnUserPostNick(User *user, const std::string &oldnick) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return;
}
}
- virtual void OnBackgroundTimer(time_t curtime)
+ void OnBackgroundTimer(time_t curtime) CXX11_OVERRIDE
{
if (added_zline)
{
}
}
- void OnUnloadModule(Module* mod)
+ void OnUnloadModule(Module* mod) CXX11_OVERRIDE
{
// If the regex engine became unavailable or has changed, remove all rlines
if (!rxfactory)
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013 Daniel Vassdal <shutter@canternet.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
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "inspircd.h"
+#include "listmode.h"
+
+/* $ModDesc: Provides support for the RMODE command - Makes mass removal of chan listmodes by glob pattern possible */
+
+/** Handle /RMODE
+ */
+class CommandRMode : public Command
+{
+ public:
+ CommandRMode(Module* Creator) : Command(Creator,"RMODE", 2, 3)
+ {
+ allow_empty_last_param = false;
+ syntax = "<channel> <mode> [pattern]";
+ }
+
+ CmdResult Handle(const std::vector<std::string> ¶meters, User *user)
+ {
+ ModeHandler* mh;
+ Channel* chan = ServerInstance->FindChan(parameters[0]);
+ char modeletter = parameters[1][0];
+
+ if (chan == NULL)
+ {
+ user->WriteNotice("The channel " + parameters[0] + " does not exist.");
+ return CMD_FAILURE;
+ }
+
+ mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
+ if (mh == NULL || parameters[1].size() > 1)
+ {
+ user->WriteNotice(parameters[1] + " is not a valid channel mode.");
+ return CMD_FAILURE;
+ }
+
+ if (chan->GetPrefixValue(user) < mh->GetLevelRequired())
+ {
+ user->WriteNotice("You do not have access to unset " + ConvToStr(modeletter) + " on " + chan->name + ".");
+ return CMD_FAILURE;
+ }
+
+ unsigned int prefixrank;
+ char prefixchar;
+ std::string pattern = parameters.size() > 2 ? parameters[2] : "*";
+ ListModeBase* lm;
+ ListModeBase::ModeList* ml;
+ irc::modestacker modestack(false);
+
+ if (!mh->IsListMode())
+ {
+ if (chan->IsModeSet(modeletter))
+ modestack.Push(modeletter);
+ }
+ else if (((prefixrank = mh->GetPrefixRank()) && (prefixchar = mh->GetPrefix())))
+ {
+ // As user prefix modes don't have a GetList() method, let's iterate through the channel's users.
+ for (UserMembIter it = chan->userlist.begin(); it != chan->userlist.end(); ++it)
+ {
+ if (!InspIRCd::Match(it->first->nick, pattern))
+ continue;
+ if (((strchr(chan->GetAllPrefixChars(user), prefixchar)) != NULL) && !(it->first == user && prefixrank > VOICE_VALUE))
+ modestack.Push(modeletter, it->first->nick);
+ }
+ }
+ else if (((lm = dynamic_cast<ListModeBase*>(mh)) != NULL) && ((ml = lm->GetList(chan)) != NULL))
+ {
+ for (ListModeBase::ModeList::iterator it = ml->begin(); it != ml->end(); ++it)
+ {
+ if (!InspIRCd::Match(it->mask, pattern))
+ continue;
+ modestack.Push(modeletter, it->mask);
+ }
+ }
+ else
+ {
+ user->WriteNotice("Could not remove channel mode " + ConvToStr(modeletter));
+ return CMD_FAILURE;
+ }
+
+ parameterlist stackresult;
+ stackresult.push_back(chan->name);
+ while (modestack.GetStackedLine(stackresult))
+ {
+ ServerInstance->SendMode(stackresult, user);
+ stackresult.erase(stackresult.begin() + 1, stackresult.end());
+ }
+
+ return CMD_SUCCESS;
+ }
+};
+
+class ModuleRMode : public Module
+{
+ CommandRMode cmd;
+
+ public:
+ ModuleRMode() : cmd(this) { }
+
+ void init() CXX11_OVERRIDE
+ {
+ ServerInstance->Modules->AddService(cmd);
+ }
+
+ Version GetVersion() CXX11_OVERRIDE
+ {
+ return Version("Allows glob-based removal of list modes", VF_VENDOR);
+ }
+};
+
+MODULE_INIT(ModuleRMode)
user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an SA command on a u-lined client",user->nick.c_str());
return CMD_FAILURE;
}
- if (IS_LOCAL(user) && !ServerInstance->IsChannel(parameters[1].c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (IS_LOCAL(user) && !ServerInstance->IsChannel(parameters[1]))
{
/* we didn't need to check this for each character ;) */
- user->WriteServ("NOTICE "+user->nick+" :*** Invalid characters in channel name or name too long");
+ user->WriteNotice("*** Invalid characters in channel name or name too long");
return CMD_FAILURE;
}
- /* For local users, we send the JoinUser which may create a channel and set its TS.
+ /* For local users, we call Channel::JoinUser which may create a channel and set its TS.
* For non-local users, we just return CMD_SUCCESS, knowing this will propagate it where it needs to be
- * and then that server will generate the users JOIN or FJOIN instead.
+ * and then that server will handle the command.
*/
- if (IS_LOCAL(dest))
+ LocalUser* localuser = IS_LOCAL(dest);
+ if (localuser)
{
- Channel::JoinUser(dest, parameters[1].c_str(), true, "", false, ServerInstance->Time());
- /* Fix for dotslasher and w00t - if the join didnt succeed, return CMD_FAILURE so that it doesnt propagate */
- Channel* n = ServerInstance->FindChan(parameters[1]);
+ Channel* n = Channel::JoinUser(localuser, parameters[1], true);
if (n)
{
if (n->HasUser(dest))
}
else
{
- user->WriteServ("NOTICE "+user->nick+" :*** Could not join "+dest->nick+" to "+parameters[1]+" (User is probably banned, or blocking modes)");
+ user->WriteNotice("*** Could not join "+dest->nick+" to "+parameters[1]+" (User is probably banned, or blocking modes)");
return CMD_FAILURE;
}
}
else
{
- user->WriteServ("NOTICE "+user->nick+" :*** Could not join "+dest->nick+" to "+parameters[1]);
+ user->WriteNotice("*** Could not join "+dest->nick+" to "+parameters[1]);
return CMD_FAILURE;
}
}
}
else
{
- user->WriteServ("NOTICE "+user->nick+" :*** No such nickname "+parameters[0]);
+ user->WriteNotice("*** No such nickname "+parameters[0]);
return CMD_FAILURE;
}
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSajoin()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides command SAJOIN to allow opers to force-join users to channels", VF_OPTCOMMON | VF_VENDOR);
}
-
};
MODULE_INIT(ModuleSajoin)
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());
+ user->WriteNotice("*** Unable to kick " + dest->nick + " from " + parameters[0]);
return CMD_FAILURE;
}
}
}
else
{
- user->WriteServ("NOTICE %s :*** Invalid nickname or channel", user->nick.c_str());
+ user->WriteNotice("*** Invalid nickname or channel");
}
return CMD_FAILURE;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSakick()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides a SAKICK command", VF_OPTCOMMON|VF_VENDOR);
}
-
};
MODULE_INIT(ModuleSakick)
-
CmdResult Handle (const std::vector<std::string>& parameters, User *user)
{
+ User* target = ServerInstance->FindNick(parameters[0]);
+ if ((target) && (target != user))
+ {
+ if (!user->HasPrivPermission("users/samode-usermodes", true))
+ return CMD_FAILURE;
+ }
this->active = true;
ServerInstance->Parser->CallHandler("MODE", parameters, user);
if (ServerInstance->Modes->GetLastParse().length())
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->Attach(I_OnPreMode, this);
}
- ~ModuleSaMode()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides command SAMODE to allow opers to change modes on channels and users", VF_VENDOR);
}
- ModResult OnPreMode(User* source,User* dest,Channel* channel, const std::vector<std::string>& parameters)
+ ModResult OnPreMode(User* source,User* dest,Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
{
if (cmd.active)
return MOD_RES_ALLOW;
if ((!target) || (target->registered != REG_ALL))
{
- user->WriteServ("NOTICE %s :*** No such nickname: '%s'", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** No such nickname: '" + parameters[0] + "'");
return CMD_FAILURE;
}
- if (!ServerInstance->IsNick(parameters[1].c_str(), ServerInstance->Config->Limits.NickMax))
+ if (!ServerInstance->IsNick(parameters[1]))
{
- user->WriteServ("NOTICE %s :*** Invalid nickname '%s'", user->nick.c_str(), parameters[1].c_str());
+ user->WriteNotice("*** Invalid nickname '" + parameters[1] + "'");
return CMD_FAILURE;
}
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSanick()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for SANICK command", VF_OPTCOMMON | VF_VENDOR);
}
-
};
MODULE_INIT(ModuleSanick)
+
}
else
{
- user->WriteServ("NOTICE %s :*** Unable to make %s part %s",user->nick.c_str(), dest->nick.c_str(), parameters[1].c_str());
+ user->WriteNotice("*** Unable to make " + dest->nick + " part " + parameters[1]);
return CMD_FAILURE;
}
}
}
else
{
- user->WriteServ("NOTICE %s :*** Invalid nickname or channel", user->nick.c_str());
+ user->WriteNotice("*** Invalid nickname or channel");
}
return CMD_FAILURE;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSapart()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides command SAPART to force-part users from a channel.", VF_OPTCOMMON | VF_VENDOR);
}
-
};
MODULE_INIT(ModuleSapart)
-
// Pass the command on, so the client's server can quit it properly.
if (!IS_LOCAL(dest))
return CMD_SUCCESS;
-
+
ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAQUIT to make "+dest->nick+" quit with a reason of "+parameters[1]);
ServerInstance->Users->QuitUser(dest, parameters[1]);
}
else
{
- user->WriteServ("NOTICE %s :*** Invalid nickname '%s'", user->nick.c_str(), parameters[0].c_str());
+ user->WriteNotice("*** Invalid nickname '" + parameters[0] + "'");
return CMD_FAILURE;
}
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSaquit()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for an SAQUIT command, exits user with a reason", VF_OPTCOMMON | VF_VENDOR);
}
-
};
MODULE_INIT(ModuleSaquit)
+
#include "inspircd.h"
-#include "m_cap.h"
-#include "account.h"
-#include "sasl.h"
-#include "ssl.h"
+#include "modules/cap.h"
+#include "modules/account.h"
+#include "modules/sasl.h"
+#include "modules/ssl.h"
/* $ModDesc: Provides support for IRC Authentication Layer (aka: atheme SASL) via AUTHENTICATE. */
case SASL_DONE:
break;
default:
- ServerInstance->Logs->Log("m_sasl", DEFAULT, "WTF: SaslState is not a known state (%d)", this->state);
+ ServerInstance->Logs->Log("m_sasl", LOG_DEFAULT, "WTF: SaslState is not a known state (%d)", this->state);
break;
}
User* target = ServerInstance->FindNick(parameters[1]);
if ((!target) || (IS_SERVER(target)))
{
- ServerInstance->Logs->Log("m_sasl", DEBUG,"User not found in sasl ENCAP event: %s", parameters[1].c_str());
+ ServerInstance->Logs->Log("m_sasl", LOG_DEBUG, "User not found in sasl ENCAP event: %s", parameters[1].c_str());
return CMD_FAILURE;
}
GenericCap cap;
CommandAuthenticate auth;
CommandSASL sasl;
+
public:
ModuleSASL()
: authExt("sasl_auth", this), cap(this, "sasl"), auth(this, authExt, cap), sasl(this, authExt)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
Implementation eventlist[] = { I_OnEvent, I_OnUserRegister, I_OnRehash };
ServerInstance->Modules->AddServices(providelist, 3);
if (!ServerInstance->Modules->Find("m_services_account.so") || !ServerInstance->Modules->Find("m_cap.so"))
- ServerInstance->Logs->Log("m_sasl", DEFAULT, "WARNING: m_services_account.so and m_cap.so are not loaded! m_sasl.so will NOT function correctly until these two modules are loaded!");
+ ServerInstance->Logs->Log("m_sasl", LOG_DEFAULT, "WARNING: m_services_account.so and m_cap.so are not loaded! m_sasl.so will NOT function correctly until these two modules are loaded!");
}
- void OnRehash(User*)
+ void OnRehash(User*) CXX11_OVERRIDE
{
sasl_target = ServerInstance->Config->ConfValue("sasl")->getString("target", "*");
}
- ModResult OnUserRegister(LocalUser *user)
+ ModResult OnUserRegister(LocalUser *user) CXX11_OVERRIDE
{
SaslAuthenticator *sasl_ = authExt.get(user);
if (sasl_)
return MOD_RES_PASSTHRU;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for IRC Authentication Layer (aka: atheme SASL) via AUTHENTICATE.",VF_VENDOR);
}
- void OnEvent(Event &ev)
+ void OnEvent(Event &ev) CXX11_OVERRIDE
{
cap.HandleEvent(ev);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSATopic()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides a SATOPIC command", VF_VENDOR);
}
class ModuleSecureList : public Module
{
- private:
std::vector<std::string> allowlist;
time_t WaitTime;
+
public:
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
Implementation eventlist[] = { I_OnRehash, I_OnPreCommand, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleSecureList()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Disallows /LIST for recently connected clients to hinder spam bots", VF_VENDOR);
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
allowlist.clear();
* OnPreCommand()
* Intercept the LIST command.
*/
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
/* If the command doesnt appear to be valid, we dont want to mess with it. */
if (!validated)
return MOD_RES_PASSTHRU;
- if ((command == "LIST") && (ServerInstance->Time() < (user->signon+WaitTime)) && (!IS_OPER(user)))
+ if ((command == "LIST") && (ServerInstance->Time() < (user->signon+WaitTime)) && (!user->IsOper()))
{
/* Normally wouldnt be allowed here, are they exempt? */
for (std::vector<std::string>::iterator x = allowlist.begin(); x != allowlist.end(); x++)
return MOD_RES_PASSTHRU;
/* 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);
+ user->WriteNotice("*** You cannot list within the first " + ConvToStr(WaitTime) + " seconds of connecting. Please try again later.");
/* Some crap clients (read: 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.
*/
return MOD_RES_PASSTHRU;
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" SECURELIST");
+ tokens["SECURELIST"];
}
};
class ModuleSeeNicks : public Module
{
public:
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->SNO->EnableSnomask('n',"NICK");
Implementation eventlist[] = { I_OnUserPostNick };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for seeing local and remote nickchanges via snomasks", VF_VENDOR);
}
- virtual void OnUserPostNick(User* user, const std::string &oldnick)
+ void OnUserPostNick(User* user, const std::string &oldnick) CXX11_OVERRIDE
{
ServerInstance->SNO->WriteToSnoMask(IS_LOCAL(user) ? 'n' : 'N',"User %s changed their nickname to %s", oldnick.c_str(), user->nick.c_str());
}
class ModuleServerBan : public Module
{
- private:
public:
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnCheckBan, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleServerBan()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Extban 's' - server ban",VF_OPTCOMMON|VF_VENDOR);
}
- ModResult OnCheckBan(User *user, Channel *c, const std::string& mask)
+ ModResult OnCheckBan(User *user, Channel *c, const std::string& mask) CXX11_OVERRIDE
{
if ((mask.length() > 2) && (mask[0] == 's') && (mask[1] == ':'))
{
return MOD_RES_PASSTHRU;
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('s');
+ tokens["EXTBAN"].push_back('s');
}
};
-
MODULE_INIT(ModuleServerBan)
-
/* $ModDesc: Provides support for ircu-style services accounts, including chmode +R, etc. */
#include "inspircd.h"
-#include "account.h"
+#include "modules/account.h"
/** Channel mode +r - mark a channel as identified
*/
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServiceProvider* providerlist[] = { &m1, &m2, &m3, &m4, &m5, &accountname };
ServerInstance->Modules->AddServices(providerlist, sizeof(providerlist)/sizeof(ServiceProvider*));
- Implementation eventlist[] = { I_OnWhois, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreJoin, I_OnCheckBan,
+ Implementation eventlist[] = { I_OnWhois, I_OnUserPreMessage, I_OnUserPreJoin, I_OnCheckBan,
I_OnDecodeMetaData, I_On005Numeric, I_OnUserPostNick, I_OnSetConnectClass };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void On005Numeric(std::string &t)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- ServerInstance->AddExtBanChar('R');
- ServerInstance->AddExtBanChar('U');
+ tokens["EXTBAN"].push_back('R');
+ tokens["EXTBAN"].push_back('U');
}
/* <- :twisted.oscnet.org 330 w00t2 w00t2 w00t :is logged in as */
- void OnWhois(User* source, User* dest)
+ void OnWhois(User* source, User* dest) CXX11_OVERRIDE
{
std::string *account = accountname.get(dest);
}
}
- void OnUserPostNick(User* user, const std::string &oldnick)
+ void OnUserPostNick(User* user, const std::string &oldnick) CXX11_OVERRIDE
{
/* On nickchange, if they have +r, remove it */
if (user->IsModeSet('r') && assign(user->nick) != oldnick)
}
}
- ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask)
+ ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask) CXX11_OVERRIDE
{
static bool checking = false;
if (checking)
return MOD_RES_PASSTHRU;
}
- ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
- return OnUserPreMessage(user, dest, target_type, text, status, exempt_list);
- }
-
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
- {
- if (!IS_LOCAL(user))
- return MOD_RES_PASSTHRU;
-
std::string *account = accountname.get(user);
bool is_registered = account && !account->empty();
// In our case we're only sending a single string around, so we just construct a std::string.
// Some modules will probably get much more complex and format more detailed structs and classes
// in a textual way for sending over the link.
- void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata)
+ void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) CXX11_OVERRIDE
{
User* dest = dynamic_cast<User*>(target);
// check if its our metadata key, and its associated with a user
}
}
- ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass)
+ ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) CXX11_OVERRIDE
{
if (myclass->config->getBool("requireaccount") && !accountname.get(user))
return MOD_RES_DENY;
return MOD_RES_PASSTHRU;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for ircu-style services accounts, including chmode +R, etc.",VF_OPTCOMMON|VF_VENDOR);
}
};
MODULE_INIT(ModuleServicesAccount)
+
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(bm);
Implementation eventlist[] = { I_OnWhois, I_OnKill, I_OnWhoisLine, I_OnRawMode, I_OnUserPreKick };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
-
- ~ModuleServProtectMode()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides usermode +k to protect services from kicks, kills, and mode changes.", VF_VENDOR);
}
- void OnWhois(User* src, User* dst)
+ void OnWhois(User* user, User* dest) CXX11_OVERRIDE
{
- if (dst->IsModeSet('k'))
+ if (dest->IsModeSet('k'))
{
- ServerInstance->SendWhoisLine(src, dst, 310, src->nick+" "+dst->nick+" :is an "+ServerInstance->Config->Network+" Service");
+ ServerInstance->SendWhoisLine(user, dest, 310, user->nick+" "+dest->nick+" :is a Network Service on "+ServerInstance->Config->Network);
}
}
- ModResult OnRawMode(User* user, Channel* chan, const char mode, const std::string ¶m, bool adding, int pcnt)
+ ModResult OnRawMode(User* user, Channel* chan, const char mode, const std::string ¶m, bool adding, int pcnt) CXX11_OVERRIDE
{
/* Check that the mode is not a server mode, it is being removed, the user making the change is local, there is a parameter,
* and the user making the change is not a uline
return MOD_RES_PASSTHRU;
}
- ModResult OnKill(User* src, User* dst, const std::string &reason)
+ ModResult OnKill(User* src, User* dst, const std::string &reason) CXX11_OVERRIDE
{
if (src == NULL)
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
- ModResult OnUserPreKick(User *src, Membership* memb, const std::string &reason)
+ ModResult OnUserPreKick(User *src, Membership* memb, const std::string &reason) CXX11_OVERRIDE
{
if (memb->user->IsModeSet('k'))
{
return MOD_RES_PASSTHRU;
}
- ModResult OnWhoisLine(User* src, User* dst, int &numeric, std::string &text)
+ ModResult OnWhoisLine(User* src, User* dst, int &numeric, std::string &text) CXX11_OVERRIDE
{
return ((src != dst) && (numeric == 319) && dst->IsModeSet('k')) ? MOD_RES_DENY : MOD_RES_PASSTHRU;
}
*/
class CommandSethost : public Command
{
- private:
char* hostmap;
+
public:
CommandSethost(Module* Creator, char* hmap) : Command(Creator,"SETHOST", 1), hostmap(hmap)
{
{
if (!hostmap[(const unsigned char)*x])
{
- user->WriteServ("NOTICE "+user->nick+" :*** SETHOST: Invalid characters in hostname");
+ user->WriteNotice("*** SETHOST: Invalid characters in hostname");
return CMD_FAILURE;
}
}
if (len > 64)
{
- user->WriteServ("NOTICE %s :*** SETHOST: Host too long",user->nick.c_str());
+ user->WriteNotice("*** SETHOST: Host too long");
return CMD_FAILURE;
}
{
CommandSethost cmd;
char hostmap[256];
+
public:
ModuleSetHost()
: cmd(this, hostmap)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
std::string hmap = ServerInstance->Config->ConfValue("hostname")->getString("charmap", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_/0123456789");
hostmap[(unsigned char)*n] = 1;
}
- virtual ~ModuleSetHost()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the SETHOST command", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleSetHost)
{
if (parameters[0].size() > ServerInstance->Config->Limits.IdentMax)
{
- user->WriteServ("NOTICE %s :*** SETIDENT: Ident is too long", user->nick.c_str());
+ user->WriteNotice("*** SETIDENT: Ident is too long");
return CMD_FAILURE;
}
if (!ServerInstance->IsIdent(parameters[0].c_str()))
{
- user->WriteServ("NOTICE %s :*** SETIDENT: Invalid characters in ident", user->nick.c_str());
+ user->WriteNotice("*** SETIDENT: Invalid characters in ident");
return CMD_FAILURE;
}
}
};
-
class ModuleSetIdent : public Module
{
CommandSetident cmd;
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSetIdent()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the SETIDENT command", VF_VENDOR);
}
-
};
-
MODULE_INIT(ModuleSetIdent)
/** Handle /SETIDLE
*/
-class CommandSetidle : public Command
+class CommandSetidle : public SplitCommand
{
public:
- CommandSetidle(Module* Creator) : Command(Creator,"SETIDLE", 1)
+ CommandSetidle(Module* Creator) : SplitCommand(Creator,"SETIDLE", 1)
{
flags_needed = 'o'; syntax = "<duration>";
TRANSLATE2(TR_TEXT, TR_END);
}
- CmdResult Handle (const std::vector<std::string>& parameters, User *user)
+ CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user)
{
- time_t idle = ServerInstance->Duration(parameters[0]);
+ int idle = InspIRCd::Duration(parameters[0]);
if (idle < 1)
{
user->WriteNumeric(948, "%s :Invalid idle time.",user->nick.c_str());
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSetIdle()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows opers to set their idle time", VF_VENDOR);
}
{
if (parameters[0].size() > ServerInstance->Config->Limits.MaxGecos)
{
- user->WriteServ("NOTICE %s :*** SETNAME: GECOS too long", user->nick.c_str());
+ user->WriteNotice("*** SETNAME: GECOS too long");
return CMD_FAILURE;
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleSetName()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the SETNAME command", VF_VENDOR);
}
#ifdef HAS_STDINT
#include <stdint.h>
#endif
-#include "hash.h"
+#include "modules/hash.h"
#ifndef HAS_STDINT
typedef unsigned int uint32_t;
return std::string((char*)bytes, SHA256_DIGEST_SIZE);
}
- std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata)
- {
- return "";
- }
-
HashSHA256(Module* parent) : HashProvider(parent, "hash/sha256", 32, 64) {}
};
ServerInstance->Modules->AddService(sha);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements SHA-256 hashing", VF_VENDOR);
}
void HandleFast(User* dest, User* src)
{
- dest->WriteServ("NOTICE %s :*** %s (%s@%s) did a /whois on you",
- dest->nick.c_str(), src->nick.c_str(), src->ident.c_str(),
- dest->HasPrivPermission("users/auspex") ? src->host.c_str() : src->dhost.c_str());
+ dest->WriteNotice("*** " + src->nick + " (" + src->ident + "@" +
+ (dest->HasPrivPermission("users/auspex") ? src->host : src->dhost) +
+ ") did a /whois on you");
}
CmdResult Handle(const std::vector<std::string> ¶meters, User *user)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("showwhois");
delete sw;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows opers to set +W to see when a user uses WHOIS on them",VF_OPTCOMMON|VF_VENDOR);
}
- void OnWhois(User* source, User* dest)
+ void OnWhois(User* source, User* dest) CXX11_OVERRIDE
{
if (!dest->IsModeSet('W') || source == dest)
return;
- if (!ShowWhoisFromOpers && IS_OPER(source))
+ if (!ShowWhoisFromOpers && source->IsOper())
return;
if (IS_LOCAL(dest))
ServerInstance->PI->SendEncapsulatedData(params);
}
}
-
};
MODULE_INIT(ModuleShowwhois)
+
{
}
- ~Shun()
- {
- }
-
bool Matches(User *u)
{
// E: overrides shun
- if (u->exempt)
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu && lu->exempt)
return false;
if (InspIRCd::Match(u->GetFullHost(), matchtext) || InspIRCd::Match(u->GetFullRealHost(), matchtext) || InspIRCd::Match(u->nick+"!"+u->ident+"@"+u->GetIPString(), matchtext))
return false;
}
- void DisplayExpiry()
- {
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired shun %s (set by %s %ld seconds ago)",
- this->matchtext.c_str(), this->source.c_str(), (long int)(ServerInstance->Time() - this->set_time));
- }
-
- const char* Displayable()
+ const std::string& Displayable()
{
- return matchtext.c_str();
+ return matchtext;
}
};
/* 'time' is a human-readable timestring, like 2d3h2s. */
std::string target = parameters[0];
-
+
User *find = ServerInstance->FindNick(target);
if ((find) && (find->registered == REG_ALL))
target = std::string("*!*@") + find->GetIPString();
}
else
{
- user->WriteServ("NOTICE %s :*** Shun %s not found in list, try /stats H.",user->nick.c_str(),target.c_str());
+ user->WriteNotice("*** Shun " + target + " not found in list, try /stats H.");
return CMD_FAILURE;
}
}
else
{
// Adding - XXX todo make this respect <insane> tag perhaps..
- long duration;
+ unsigned long duration;
std::string expr;
if (parameters.size() > 2)
{
- duration = ServerInstance->Duration(parameters[1]);
+ duration = InspIRCd::Duration(parameters[1]);
expr = parameters[2];
}
else
else
{
delete r;
- user->WriteServ("NOTICE %s :*** Shun for %s already exists", user->nick.c_str(), target.c_str());
+ user->WriteNotice("*** Shun for " + target + " already exists");
return CMD_FAILURE;
}
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->XLines->RegisterFactory(&f);
ServerInstance->Modules->AddService(cmd);
OnRehash(NULL);
}
- virtual ~ModuleShun()
+ ~ModuleShun()
{
ServerInstance->XLines->DelAll("SHUN");
ServerInstance->XLines->UnregisterFactory(&f);
ServerInstance->Modules->SetPriority(this, I_OnPreCommand, PRIORITY_BEFORE, &alias);
}
- virtual ModResult OnStats(char symbol, User* user, string_list& out)
+ ModResult OnStats(char symbol, User* user, string_list& out) CXX11_OVERRIDE
{
if (symbol != 'H')
return MOD_RES_PASSTHRU;
return MOD_RES_DENY;
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("shun");
std::string cmds = tag->getString("enabledcommands");
affectopers = tag->getBool("affectopers", false);
}
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string>& parameters, LocalUser* user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string>& parameters, LocalUser* user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
if (validated)
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
- if (!affectopers && IS_OPER(user))
+ if (!affectopers && user->IsOper())
{
/* Don't do anything if the user is an operator and affectopers isn't set */
return MOD_RES_PASSTHRU;
if (i == ShunEnabledCommands.end())
{
if (NotifyOfShun)
- user->WriteServ("NOTICE %s :*** Command %s not processed, as you have been blocked from issuing commands (SHUN)", user->nick.c_str(), command.c_str());
+ user->WriteNotice("*** Command " + command + " not processed, as you have been blocked from issuing commands (SHUN)");
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the /SHUN command, which stops a user from executing all except configured commands.",VF_VENDOR|VF_COMMON);
}
};
MODULE_INIT(ModuleShun)
-
if (pattern == 0)
{
- user->WriteServ("NOTICE %s :Bad SILENCE pattern",user->nick.c_str());
+ user->WriteNotice("Bad SILENCE pattern");
return CMD_INVALID;
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->AddService(cmdsilence);
ServerInstance->Modules->AddService(cmdsvssilence);
ServerInstance->Modules->AddService(cmdsilence.ext);
- Implementation eventlist[] = { I_OnRehash, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnUserPreInvite };
+ Implementation eventlist[] = { I_OnRehash, I_On005Numeric, I_OnUserPreMessage, I_OnUserPreInvite };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
maxsilence = ServerInstance->Config->ConfValue("showwhois")->getInt("maxentries", 32);
if (!maxsilence)
maxsilence = 32;
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- // we don't really have a limit...
- output = output + " ESILENCE SILENCE=" + ConvToStr(maxsilence);
+ tokens["ESILENCE"];
+ tokens["SILENCE"] = ConvToStr(maxsilence);
}
void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text)
}
}
- ModResult PreText(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list, int silence_type)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (target_type == TYPE_USER && IS_LOCAL(((User*)dest)))
{
- return MatchPattern((User*)dest, user, silence_type);
+ return MatchPattern((User*)dest, user, ((msgtype == MSG_PRIVMSG) ? SILENCE_PRIVATE : SILENCE_NOTICE));
}
else if (target_type == TYPE_CHANNEL)
{
Channel* chan = (Channel*)dest;
if (chan)
{
- this->OnBuildExemptList((silence_type == SILENCE_PRIVATE ? MSG_PRIVMSG : MSG_NOTICE), chan, user, status, exempt_list, "");
+ this->OnBuildExemptList(msgtype, chan, user, status, exempt_list, "");
}
}
return MOD_RES_PASSTHRU;
}
- ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return PreText(user, dest, target_type, text, status, exempt_list, SILENCE_PRIVATE);
- }
-
- ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return PreText(user, dest, target_type, text, status, exempt_list, SILENCE_NOTICE);
- }
-
- ModResult OnUserPreInvite(User* source,User* dest,Channel* channel, time_t timeout)
+ ModResult OnUserPreInvite(User* source,User* dest,Channel* channel, time_t timeout) CXX11_OVERRIDE
{
return MatchPattern(dest, source, SILENCE_INVITE);
}
return MOD_RES_PASSTHRU;
}
- ~ModuleSilence()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the /SILENCE command", VF_OPTCOMMON | VF_VENDOR);
}
XLine* xl = NULL;
try
{
- xl = xlf->Generate(ServerInstance->Time(), atoi(params[4].c_str()), params[2], params[5], params[1]);
+ xl = xlf->Generate(ServerInstance->Time(), ConvToInt(params[4]), params[2], params[5], params[1]);
}
catch (ModuleException &e)
{
ServerInstance->SNO->WriteToSnoMask('d',"Unable to ADDLINE type %s from %s: %s", params[0].c_str(), setter.c_str(), e.GetReason());
return true;
}
- xl->SetCreateTime(atoi(params[3].c_str()));
+ xl->SetCreateTime(ConvToInt(params[3]));
if (ServerInstance->XLines->AddLine(xl, NULL))
{
if (xl->duration)
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
bool TreeSocket::Away(const std::string &prefix, parameterlist ¶ms)
FOREACH_MOD(I_OnSetAway, OnSetAway(u, params[params.size() - 1]));
if (params.size() > 1)
- u->awaytime = atoi(params[0].c_str());
+ u->awaytime = ConvToInt(params[0]);
else
u->awaytime = ServerInstance->Time();
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
- *
- * This file is part of InspIRCd. InspIRCd is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-
-#include "cachetimer.h"
-#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
-#include "link.h"
-#include "treesocket.h"
-
-/* $ModDep: m_spanningtree/cachetimer.h m_spanningtree/resolvers.h m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/link.h m_spanningtree/treesocket.h */
-
-CacheRefreshTimer::CacheRefreshTimer(SpanningTreeUtilities *Util) : Timer(3600, ServerInstance->Time(), true), Utils(Util)
-{
-}
-
-void CacheRefreshTimer::Tick(time_t TIME)
-{
- Utils->RefreshIPCache();
-}
-
*/
-#ifndef M_SPANNINGTREE_CACHETIMER_H
-#define M_SPANNINGTREE_CACHETIMER_H
+#pragma once
-#include "timer.h"
-
-class ModuleSpanningTree;
class SpanningTreeUtilities;
/** Create a timer which recurs every second, we inherit from Timer.
SpanningTreeUtilities *Utils;
public:
CacheRefreshTimer(SpanningTreeUtilities* Util);
- virtual void Tick(time_t TIME);
+ bool Tick(time_t TIME);
};
-
-#endif
#include "inspircd.h"
-#include "xline.h"
-#include "treesocket.h"
#include "treeserver.h"
#include "utils.h"
#include "link.h"
{
std::vector<std::string> modlist = ServerInstance->Modules->GetAllModuleNames(filter);
- if (filter == VF_COMMON && proto_version != ProtocolVersion)
- CompatAddModules(modlist);
-
std::string capabilities;
sort(modlist.begin(),modlist.end());
for (std::vector<std::string>::const_iterator i = modlist.begin(); i != modlist.end(); ++i)
{
if (i != modlist.begin())
- capabilities.push_back(proto_version > 1201 ? ' ' : ',');
+ capabilities.push_back(' ');
capabilities.append(*i);
Module* m = ServerInstance->Modules->Find(*i);
- if (m && proto_version > 1201)
+ Version v = m->GetVersion();
+ if (!v.link_data.empty())
{
- Version v = m->GetVersion();
- if (!v.link_data.empty())
- {
- capabilities.push_back('=');
- capabilities.append(v.link_data);
- }
+ capabilities.push_back('=');
+ capabilities.append(v.link_data);
}
}
return capabilities;
if (phase < 2)
return;
- char sep = proto_version > 1201 ? ' ' : ',';
+ const char sep = ' ';
irc::sepstream modulelist(MyModules(VF_COMMON), sep);
irc::sepstream optmodulelist(MyModules(VF_OPTCOMMON), sep);
/* Send module names, split at 509 length */
SetOurChallenge(ServerInstance->GenRandomStr(20));
extra = " CHALLENGE=" + this->GetOurChallenge();
}
- if (proto_version < 1202)
- extra += ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL) ? " HALFOP=1" : " HALFOP=0";
+
+ // 2.0 needs this key
+ if (proto_version == 1202)
+ extra.append(" PROTOCOL="+ConvToStr(ProtocolVersion));
this->WriteLine("CAPAB CAPABILITIES " /* Preprocessor does this one. */
":NICKMAX="+ConvToStr(ServerInstance->Config->Limits.NickMax)+
" MAXKICK="+ConvToStr(ServerInstance->Config->Limits.MaxKick)+
" MAXGECOS="+ConvToStr(ServerInstance->Config->Limits.MaxGecos)+
" MAXAWAY="+ConvToStr(ServerInstance->Config->Limits.MaxAway)+
- " IP6SUPPORT=1"+
- " PROTOCOL="+ConvToStr(ProtocolVersion)+extra+
+ extra+
" PREFIX="+ServerInstance->Modes->BuildPrefixes()+
" CHANMODES="+ServerInstance->Modes->GiveModeList(MASK_CHANNEL)+
- " USERMODES="+ServerInstance->Modes->GiveModeList(MASK_USER)+
- " SVSPART=1");
+ " USERMODES="+ServerInstance->Modes->GiveModeList(MASK_USER)
+ );
this->WriteLine("CAPAB END");
}
capab->OptModuleList.clear();
capab->CapKeys.clear();
if (params.size() > 1)
- proto_version = atoi(params[1].c_str());
+ proto_version = ConvToInt(params[1]);
+
+ if (proto_version < MinCompatProtocol)
+ {
+ SendError("CAPAB negotiation failed: Server is using protocol version " + (proto_version ? ConvToStr(proto_version) : "1201 or older")
+ + " which is too old to link with this server (version " + ConvToStr(ProtocolVersion)
+ + (ProtocolVersion != MinCompatProtocol ? ", links with " + ConvToStr(MinCompatProtocol) + " and above)" : ")"));
+ return false;
+ }
+
+ // Special case, may be removed in the future
+ if (proto_version == 1203 || proto_version == 1204)
+ {
+ SendError("CAPAB negotiation failed: InspIRCd 2.1 beta is not supported");
+ return false;
+ }
+
SendCapabilities(2);
}
else if (params[0] == "END")
if ((this->capab->ModuleList != this->MyModules(VF_COMMON)) && (this->capab->ModuleList.length()))
{
std::string diffIneed, diffUneed;
- ListDifference(this->capab->ModuleList, this->MyModules(VF_COMMON), proto_version > 1201 ? ' ' : ',', diffIneed, diffUneed);
+ ListDifference(this->capab->ModuleList, this->MyModules(VF_COMMON), ' ', diffIneed, diffUneed);
if (diffIneed.length() || diffUneed.length())
{
reason = "Modules incorrectly matched on these servers.";
}
}
- if (this->capab->CapKeys.find("PROTOCOL") == this->capab->CapKeys.end())
- {
- reason = "Protocol version not specified";
- }
- else
- {
- proto_version = atoi(capab->CapKeys.find("PROTOCOL")->second.c_str());
- if (proto_version < MinCompatProtocol)
- {
- reason = "Server is using protocol version " + ConvToStr(proto_version) +
- " which is too old to link with this server (version " + ConvToStr(ProtocolVersion)
- + (ProtocolVersion != MinCompatProtocol ? ", links with " + ConvToStr(MinCompatProtocol) + " and above)" : ")");
- }
- }
-
if(this->capab->CapKeys.find("PREFIX") != this->capab->CapKeys.end() && this->capab->CapKeys.find("PREFIX")->second != ServerInstance->Modes->BuildPrefixes())
reason = "One or more of the prefixes on the remote server are invalid on this server.";
}
else
{
- capab->ModuleList.push_back(proto_version > 1201 ? ' ' : ',');
+ capab->ModuleList.push_back(' ');
capab->ModuleList.append(params[1]);
}
}
*/
-#ifndef M_SPANNINGTREE_COMMANDS_H
-#define M_SPANNINGTREE_COMMANDS_H
+#pragma once
#include "main.h"
CommandRSQuit(Module* Callback, SpanningTreeUtilities* Util);
CmdResult Handle (const std::vector<std::string>& parameters, User *user);
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters);
- void NoticeUser(User* user, const std::string &msg);
};
class CommandSVSJoin : public Command
CmdResult Handle (const std::vector<std::string>& parameters, User *user);
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; }
};
+class TreeSocket;
class CommandFJoin : public Command
{
+ /** Remove all modes from a channel, including statusmodes (+qaovh etc), simplemodes, parameter modes.
+ * This does not update the timestamp of the target channel, this must be done seperately.
+ */
+ static void RemoveStatus(Channel* c);
+ static void ApplyModeStack(User* srcuser, Channel* c, irc::modestacker& stack);
+ bool ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack);
public:
CommandFJoin(Module* Creator) : Command(Creator, "FJOIN", 3) { flags_needed = FLAG_SERVERONLY; }
CmdResult Handle (const std::vector<std::string>& parameters, User *user);
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; }
- /** Remove all modes from a channel, including statusmodes (+qaovh etc), simplemodes, parameter modes.
- * This does not update the timestamp of the target channel, this must be done seperately.
- */
- void RemoveStatus(User* source, parameterlist ¶ms);
};
class CommandFMode : public Command
{
class CommandFTopic : public Command
{
public:
- CommandFTopic(Module* Creator) : Command(Creator, "FTOPIC", 4) { flags_needed = FLAG_SERVERONLY; }
+ CommandFTopic(Module* Creator) : Command(Creator, "FTOPIC", 5) { flags_needed = FLAG_SERVERONLY; }
CmdResult Handle (const std::vector<std::string>& parameters, User *user);
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; }
};
RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; }
};
+class CommandIJoin : public SplitCommand
+{
+ public:
+ CommandIJoin(Module* Creator) : SplitCommand(Creator, "IJOIN", 1) { flags_needed = FLAG_SERVERONLY; }
+ CmdResult HandleRemote(const std::vector<std::string>& parameters, RemoteUser* user);
+ RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) { return ROUTE_BROADCAST; }
+};
+
+class CommandResync : public SplitCommand
+{
+ public:
+ CommandResync(Module* Creator) : SplitCommand(Creator, "RESYNC", 1) { flags_needed = FLAG_SERVERONLY; }
+ CmdResult HandleServer(const std::vector<std::string>& parameters, FakeUser* user);
+};
+
class SpanningTreeCommands
{
public:
CommandUID uid;
CommandOpertype opertype;
CommandFJoin fjoin;
+ CommandIJoin ijoin;
+ CommandResync resync;
CommandFMode fmode;
CommandFTopic ftopic;
CommandFHost fhost;
CommandFName fname;
SpanningTreeCommands(ModuleSpanningTree* module);
};
-
-#endif
#include "inspircd.h"
#include "main.h"
#include "treesocket.h"
+#include "treeserver.h"
-static const char* const forge_common_1201[] = {
- "m_allowinvite.so",
- "m_alltime.so",
- "m_auditorium.so",
- "m_banexception.so",
- "m_blockcaps.so",
- "m_blockcolor.so",
- "m_botmode.so",
- "m_censor.so",
- "m_chanfilter.so",
- "m_chanhistory.so",
- "m_channelban.so",
- "m_chanprotect.so",
- "m_chghost.so",
- "m_chgname.so",
- "m_commonchans.so",
- "m_customtitle.so",
- "m_deaf.so",
- "m_delayjoin.so",
- "m_delaymsg.so",
- "m_exemptchanops.so",
- "m_gecosban.so",
- "m_globops.so",
- "m_helpop.so",
- "m_hidechans.so",
- "m_hideoper.so",
- "m_invisible.so",
- "m_inviteexception.so",
- "m_joinflood.so",
- "m_kicknorejoin.so",
- "m_knock.so",
- "m_messageflood.so",
- "m_muteban.so",
- "m_nickflood.so",
- "m_nicklock.so",
- "m_noctcp.so",
- "m_nokicks.so",
- "m_nonicks.so",
- "m_nonotice.so",
- "m_nopartmsg.so",
- "m_ojoin.so",
- "m_operprefix.so",
- "m_permchannels.so",
- "m_redirect.so",
- "m_regex_glob.so",
- "m_regex_pcre.so",
- "m_regex_posix.so",
- "m_regex_tre.so",
- "m_remove.so",
- "m_sajoin.so",
- "m_sakick.so",
- "m_sanick.so",
- "m_sapart.so",
- "m_saquit.so",
- "m_serverban.so",
- "m_services_account.so",
- "m_servprotect.so",
- "m_setident.so",
- "m_showwhois.so",
- "m_silence.so",
- "m_sslmodes.so",
- "m_stripcolor.so",
- "m_swhois.so",
- "m_uninvite.so",
- "m_watch.so"
-};
-
-static std::string wide_newline("\r\n");
static std::string newline("\n");
-void TreeSocket::CompatAddModules(std::vector<std::string>& modlist)
-{
- if (proto_version < 1202)
- {
- // you MUST have chgident loaded in order to be able to translate FIDENT
- modlist.push_back("m_chgident.so");
- for(int i=0; i * sizeof(char*) < sizeof(forge_common_1201); i++)
- {
- if (ServerInstance->Modules->Find(forge_common_1201[i]))
- modlist.push_back(forge_common_1201[i]);
- }
- // module was merged
- if (ServerInstance->Modules->Find("m_operchans.so"))
- {
- modlist.push_back("m_operchans.so");
- modlist.push_back("m_operinvex.so");
- }
- }
-}
-
void TreeSocket::WriteLine(std::string line)
{
if (LinkState == CONNECTED)
{
if (line[0] != ':')
{
- ServerInstance->Logs->Log("m_spanningtree", DEFAULT, "Sending line without server prefix!");
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Sending line without server prefix!");
line = ":" + ServerInstance->Config->GetSID() + " " + line;
}
if (proto_version != ProtocolVersion)
std::string command = line.substr(a + 1, b-a-1);
// now try to find a translation entry
// TODO a more efficient lookup method will be needed later
- if (proto_version < 1202 && command == "FIDENT")
- {
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Rewriting FIDENT for 1201-protocol server");
- line = ":" + ServerInstance->Config->GetSID() + " CHGIDENT " + line.substr(1,a-1) + line.substr(b);
- }
- else if (proto_version < 1202 && command == "SAVE")
- {
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Rewriting SAVE for 1201-protocol server");
- std::string::size_type c = line.find(' ', b + 1);
- std::string uid = line.substr(b, c - b);
- line = ":" + ServerInstance->Config->GetSID() + " SVSNICK" + uid + line.substr(b);
- }
- else if (proto_version < 1202 && command == "AWAY")
+ if (proto_version < 1205)
{
- if (b != std::string::npos)
+ if (command == "IJOIN")
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Stripping AWAY timestamp for 1201-protocol server");
+ // Convert
+ // :<uid> IJOIN <chan> [<ts> [<flags>]]
+ // to
+ // :<sid> FJOIN <chan> <ts> + [<flags>],<uuid>
std::string::size_type c = line.find(' ', b + 1);
- line.erase(b,c-b);
+ if (c == std::string::npos)
+ {
+ // No TS or modes in the command
+ // :22DAAAAAB IJOIN #chan
+ const std::string channame = line.substr(b+1, c-b-1);
+ Channel* chan = ServerInstance->FindChan(channame);
+ if (!chan)
+ return;
+
+ line.push_back(' ');
+ line.append(ConvToStr(chan->age));
+ line.append(" + ,");
+ }
+ else
+ {
+ std::string::size_type d = line.find(' ', c + 1);
+ if (d == std::string::npos)
+ {
+ // TS present, no modes
+ // :22DAAAAAC IJOIN #chan 12345
+ line.append(" + ,");
+ }
+ else
+ {
+ // Both TS and modes are present
+ // :22DAAAAAC IJOIN #chan 12345 ov
+ std::string::size_type e = line.find(' ', d + 1);
+ if (e != std::string::npos)
+ line.erase(e);
+
+ line.insert(d, " +");
+ line.push_back(',');
+ }
+ }
+
+ // Move the uuid to the end and replace the I with an F
+ line.append(line.substr(1, 9));
+ line.erase(4, 6);
+ line[5] = 'F';
}
- }
- else if (proto_version < 1202 && command == "ENCAP")
- {
- // :src ENCAP target command [args...]
- // A B C D
- // Therefore B and C cannot be npos in a valid command
- if (b == std::string::npos)
+ else if (command == "RESYNC")
return;
- std::string::size_type c = line.find(' ', b + 1);
- if (c == std::string::npos)
- return;
- std::string::size_type d = line.find(' ', c + 1);
- std::string subcmd = line.substr(c + 1, d - c - 1);
+ else if (command == "METADATA")
+ {
+ // Drop TS for channel METADATA
+ // :sid METADATA #target TS extname ...
+ // A B C D
+ if (b == std::string::npos)
+ return;
- if (subcmd == "CHGIDENT" && d != std::string::npos)
+ std::string::size_type c = line.find(' ', b + 1);
+ if (c == std::string::npos)
+ return;
+
+ if (line[b + 1] == '#')
+ {
+ // We're sending channel metadata
+ std::string::size_type d = line.find(' ', c + 1);
+ if (d == std::string::npos)
+ return;
+
+ line.erase(c, d-c);
+ }
+ }
+ else if (command == "FTOPIC")
{
- std::string::size_type e = line.find(' ', d + 1);
- if (e == std::string::npos)
- return; // not valid
- std::string target = line.substr(d + 1, e - d - 1);
+ // Drop channel TS for FTOPIC
+ // :sid FTOPIC #target TS TopicTS ...
+ // A B C D
+ if (b == std::string::npos)
+ return;
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Forging acceptance of CHGIDENT from 1201-protocol server");
- recvq.insert(0, ":" + target + " FIDENT " + line.substr(e) + "\n");
+ std::string::size_type c = line.find(' ', b + 1);
+ if (c == std::string::npos)
+ return;
+
+ std::string::size_type d = line.find(' ', c + 1);
+ if (d == std::string::npos)
+ return;
+
+ line.erase(c, d-c);
}
+ else if ((command == "PING") || (command == "PONG"))
+ {
+ // :22D PING 20D
+ if (line.length() < 13)
+ return;
- Command* thiscmd = ServerInstance->Parser->GetHandler(subcmd);
- if (thiscmd && subcmd != "WHOISNOTICE")
+ // Insert the source SID (and a space) between the command and the first parameter
+ line.insert(10, line.substr(1, 4));
+ }
+ else if (command == "OPERTYPE")
{
- Version ver = thiscmd->creator->GetVersion();
- if (ver.Flags & VF_OPTCOMMON)
+ std::string::size_type colon = line.find(':', b);
+ if (colon != std::string::npos)
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Removing ENCAP on '%s' for 1201-protocol server",
- subcmd.c_str());
- line.erase(a, c-a);
+ for (std::string::iterator i = line.begin()+colon; i != line.end(); ++i)
+ {
+ if (*i == ' ')
+ *i = '_';
+ }
+ line.erase(colon, 1);
}
}
}
}
}
- ServerInstance->Logs->Log("m_spanningtree", RAWIO, "S[%d] O %s", this->GetFd(), line.c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_RAWIO, "S[%d] O %s", this->GetFd(), line.c_str());
this->WriteData(line);
- if (proto_version < 1202)
- this->WriteData(wide_newline);
- else
- this->WriteData(newline);
+ this->WriteData(newline);
+}
+
+namespace
+{
+ bool InsertCurrentChannelTS(std::vector<std::string>& params)
+ {
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ return false;
+
+ // Insert the current TS of the channel between the first and the second parameters
+ params.insert(params.begin()+1, ConvToStr(chan->age));
+ return true;
+ }
+}
+
+bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, std::vector<std::string>& params)
+{
+ if ((cmd == "METADATA") && (params.size() >= 3))
+ {
+ // :20D METADATA #channel extname :extdata
+ return InsertCurrentChannelTS(params);
+ }
+ else if ((cmd == "FTOPIC") && (params.size() >= 4))
+ {
+ // :20D FTOPIC #channel 100 Attila :topic text
+ return InsertCurrentChannelTS(params);
+ }
+ else if ((cmd == "PING") || (cmd == "PONG"))
+ {
+ if (params.size() == 1)
+ {
+ // If it's a PING with 1 parameter, reply with a PONG now, if it's a PONG with 1 parameter (weird), do nothing
+ if (cmd[1] == 'I')
+ this->WriteData(":" + ServerInstance->Config->GetSID() + " PONG " + params[0] + newline);
+
+ // Don't process this message further
+ return false;
+ }
+
+ // :20D PING 20D 22D
+ // :20D PONG 20D 22D
+ // Drop the first parameter
+ params.erase(params.begin());
+
+ // If the target is a server name, translate it to a SID
+ if (!InspIRCd::IsSID(params[0]))
+ {
+ TreeServer* server = Utils->FindServer(params[0]);
+ if (!server)
+ {
+ // We've no idea what this is, log and stop processing
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Received a " + cmd + " with an unknown target: \"" + params[0] + "\", command dropped");
+ return false;
+ }
+
+ params[0] = server->GetID();
+ }
+ }
+
+ return true; // Passthru
}
#include "xline.h"
#include "treesocket.h"
-#include "treeserver.h"
#include "utils.h"
/** ENCAP */
ServerInstance->Parser->CallHandler(params[1], plist, who);
// discard return value, ENCAP shall succeed even if the command does not exist
}
-
+
params[params.size() - 1] = ":" + params[params.size() - 1];
if (params[0].find_first_of("*?") != std::string::npos)
CmdResult CommandFJoin::Handle(const std::vector<std::string>& params, User *srcuser)
{
SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
- /* 1.1 FJOIN works as follows:
+ /* 1.1+ FJOIN works as follows:
*
* Each FJOIN is sent along with a timestamp, and the side with the lowest
* timestamp 'wins'. From this point on we will refer to this side as the
* The winning side on the other hand will ignore all user modes from the
* losing side, so only its own modes get applied. Life is simple for those
* who succeed at internets. :-)
+ *
+ * Syntax:
+ * :<sid> FJOIN <chan> <TS> <modes> :[[modes,]<uuid> [[modes,]<uuid> ... ]]
+ * The last parameter is a list consisting of zero or more (modelist, uuid)
+ * pairs (permanent channels may have zero users). The mode list for each
+ * user is a concatenation of the mode letters the user has on the channel
+ * (e.g.: "ov" if the user is opped and voiced). The order of the mode letters
+ * are not important but if a server ecounters an unknown mode letter, it will
+ * drop the link to avoid desync.
+ *
+ * InspIRCd 2.0 and older required a comma before the uuid even if the user
+ * had no prefix modes on the channel, InspIRCd 2.2 and later does not require
+ * a comma in this case anymore.
+ *
*/
- irc::modestacker modestack(true); /* Modes to apply from the users in the user list */
- User* who = NULL; /* User we are currently checking */
- std::string channel = params[0]; /* Channel name, as a string */
- time_t TS = atoi(params[1].c_str()); /* Timestamp given to us for remote side */
- irc::tokenstream users((params.size() > 3) ? params[params.size() - 1] : ""); /* users from the user list */
- bool apply_other_sides_modes = true; /* True if we are accepting the other side's modes */
- Channel* chan = ServerInstance->FindChan(channel); /* The channel we're sending joins to */
- bool created = !chan; /* True if the channel doesnt exist here yet */
- std::string item; /* One item in the list of nicks */
-
- TreeSocket* src_socket = Utils->FindServer(srcuser->server)->GetRoute()->GetSocket();
-
+ time_t TS = ConvToInt(params[1]);
if (!TS)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"*** BUG? *** TS of 0 sent to FJOIN. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "*** BUG? *** TS of 0 sent to FJOIN. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
ServerInstance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FJOIN with a TS of zero. Total craq. Command was dropped.", srcuser->server.c_str());
return CMD_INVALID;
}
- if (created)
+ const std::string& channel = params[0];
+ Channel* chan = ServerInstance->FindChan(channel);
+ bool apply_other_sides_modes = true;
+
+ if (!chan)
{
chan = new Channel(channel, TS);
- ServerInstance->SNO->WriteToSnoMask('d', "Creation FJOIN received for %s, timestamp: %lu", chan->name.c_str(), (unsigned long)TS);
}
else
{
time_t ourTS = chan->age;
-
if (TS != ourTS)
+ {
ServerInstance->SNO->WriteToSnoMask('d', "Merge FJOIN received for %s, ourTS: %lu, TS: %lu, difference: %lu",
chan->name.c_str(), (unsigned long)ourTS, (unsigned long)TS, (unsigned long)(ourTS - TS));
- /* If our TS is less than theirs, we dont accept their modes */
- if (ourTS < TS)
- {
- ServerInstance->SNO->WriteToSnoMask('d', "NOT Applying modes from other side");
- apply_other_sides_modes = false;
- }
- else if (ourTS > TS)
- {
- /* Our TS greater than theirs, clear all our modes from the channel, accept theirs. */
- ServerInstance->SNO->WriteToSnoMask('d', "Removing our modes, accepting remote");
- parameterlist param_list;
- if (Utils->AnnounceTSChange)
- chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :TS for %s changed from %lu to %lu", chan->name.c_str(), channel.c_str(), (unsigned long) ourTS, (unsigned long) TS);
- // while the name is equal in case-insensitive compare, it might differ in case; use the remote version
- chan->name = channel;
- chan->age = TS;
- chan->ClearInvites();
- param_list.push_back(channel);
- this->RemoveStatus(ServerInstance->FakeClient, param_list);
-
- // XXX: If the channel does not exist in the chan hash at this point, create it so the remote modes can be applied on it.
- // This happens to 0-user permanent channels on the losing side, because those are removed (from the chan hash, then
- // deleted later) as soon as the permchan mode is removed from them.
- if (ServerInstance->FindChan(channel) == NULL)
+ /* If our TS is less than theirs, we dont accept their modes */
+ if (ourTS < TS)
{
- chan = new Channel(channel, TS);
+ apply_other_sides_modes = false;
+ }
+ else if (ourTS > TS)
+ {
+ /* Our TS greater than theirs, clear all our modes from the channel, accept theirs. */
+ if (Utils->AnnounceTSChange)
+ chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :TS for %s changed from %lu to %lu", chan->name.c_str(), channel.c_str(), (unsigned long) ourTS, (unsigned long) TS);
+
+ // while the name is equal in case-insensitive compare, it might differ in case; use the remote version
+ chan->name = channel;
+ chan->age = TS;
+ chan->ClearInvites();
+
+ CommandFJoin::RemoveStatus(chan);
+
+ // XXX: If the channel does not exist in the chan hash at this point, create it so the remote modes can be applied on it.
+ // This happens to 0-user permanent channels on the losing side, because those are removed (from the chan hash, then
+ // deleted later) as soon as the permchan mode is removed from them.
+ if (ServerInstance->FindChan(channel) == NULL)
+ {
+ chan = new Channel(channel, TS);
+ }
}
}
- // The silent case here is ourTS == TS, we don't need to remove modes here, just to merge them later on.
}
- /* First up, apply their modes if they won the TS war */
+ /* First up, apply their channel modes if they won the TS war */
if (apply_other_sides_modes)
{
- unsigned int idx = 2;
std::vector<std::string> modelist;
+ modelist.push_back(channel);
- // Mode parser needs to know what channel to act on.
- modelist.push_back(params[0]);
-
- /* Remember, params[params.size() - 1] is nicklist, and we don't want to apply *that* */
- for (idx = 2; idx != (params.size() - 1); idx++)
- {
- modelist.push_back(params[idx]);
- }
-
+ /* Remember, params[params.size() - 1] is userlist, and we don't want to apply *that* */
+ modelist.insert(modelist.end(), params.begin()+2, params.end()-1);
ServerInstance->SendMode(modelist, srcuser);
}
- /* Now, process every 'modes,nick' pair */
+ irc::modestacker modestack(true);
+ TreeSocket* src_socket = Utils->FindServer(srcuser->server)->GetRoute()->GetSocket();
+
+ /* Now, process every 'modes,uuid' pair */
+ irc::tokenstream users(*params.rbegin());
+ std::string item;
+ irc::modestacker* modestackptr = (apply_other_sides_modes ? &modestack : NULL);
while (users.GetToken(item))
{
- const char* usr = item.c_str();
- if (usr && *usr)
- {
- const char* unparsedmodes = usr;
- std::string modes;
-
-
- /* Iterate through all modes for this user and check they are valid. */
- while ((*unparsedmodes) && (*unparsedmodes != ','))
- {
- ModeHandler *mh = ServerInstance->Modes->FindMode(*unparsedmodes, MODETYPE_CHANNEL);
- if (!mh)
- {
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Unrecognised mode %c, dropping link", *unparsedmodes);
- return CMD_INVALID;
- }
-
- modes += *unparsedmodes;
- usr++;
- unparsedmodes++;
- }
+ if (!ProcessModeUUIDPair(item, src_socket, chan, modestackptr))
+ return CMD_INVALID;
+ }
- /* Advance past the comma, to the nick */
- usr++;
+ /* Flush mode stacker if we lost the FJOIN or had equal TS */
+ if (apply_other_sides_modes)
+ CommandFJoin::ApplyModeStack(srcuser, chan, modestack);
- /* Check the user actually exists */
- who = ServerInstance->FindUUID(usr);
- if (who)
- {
- /* Check that the user's 'direction' is correct */
- TreeServer* route_back_again = Utils->BestRouteTo(who->server);
- if ((!route_back_again) || (route_back_again->GetSocket() != src_socket))
- continue;
+ return CMD_SUCCESS;
+}
- /* Add any modes this user had to the mode stack */
- for (std::string::iterator x = modes.begin(); x != modes.end(); ++x)
- modestack.Push(*x, who->nick);
+bool CommandFJoin::ProcessModeUUIDPair(const std::string& item, TreeSocket* src_socket, Channel* chan, irc::modestacker* modestack)
+{
+ std::string::size_type comma = item.find(',');
- Channel::JoinUser(who, channel.c_str(), true, "", route_back_again->bursting, TS);
- }
- else
- {
- ServerInstance->Logs->Log("m_spanningtree",SPARSE, "Ignored nonexistant user %s in fjoin to %s (probably quit?)", usr, channel.c_str());
- continue;
- }
- }
+ // Comma not required anymore if the user has no modes
+ std::string uuid = ((comma == std::string::npos) ? item : item.substr(comma+1));
+ User* who = ServerInstance->FindUUID(uuid);
+ if (!who)
+ {
+ // Probably KILLed, ignore
+ return true;
}
- /* Flush mode stacker if we lost the FJOIN or had equal TS */
- if (apply_other_sides_modes)
+ /* Check that the user's 'direction' is correct */
+ SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
+ TreeServer* route_back_again = Utils->BestRouteTo(who->server);
+ if ((!route_back_again) || (route_back_again->GetSocket() != src_socket))
{
- parameterlist stackresult;
- stackresult.push_back(channel);
+ return true;
+ }
- while (modestack.GetStackedLine(stackresult))
+ /* Check if the user received at least one mode */
+ if ((modestack) && (comma > 0) && (comma != std::string::npos))
+ {
+ /* Iterate through the modes and see if they are valid here, if so, apply */
+ std::string::const_iterator commait = item.begin()+comma;
+ for (std::string::const_iterator i = item.begin(); i != commait; ++i)
{
- ServerInstance->SendMode(stackresult, srcuser);
- stackresult.erase(stackresult.begin() + 1, stackresult.end());
+ if (!ServerInstance->Modes->FindMode(*i, MODETYPE_CHANNEL))
+ {
+ ServerInstance->SNO->WriteToSnoMask('d', "Unrecognised mode '%c' for a user in FJOIN, dropping link", *i);
+ return false;
+ }
+
+ /* Add any modes this user had to the mode stack */
+ modestack->Push(*i, who->nick);
}
}
- return CMD_SUCCESS;
+
+ chan->ForceJoin(who, NULL, route_back_again->bursting);
+ return true;
}
-void CommandFJoin::RemoveStatus(User* srcuser, parameterlist ¶ms)
+void CommandFJoin::RemoveStatus(Channel* c)
{
- if (params.size() < 1)
- return;
-
- Channel* c = ServerInstance->FindChan(params[0]);
+ irc::modestacker stack(false);
- if (c)
+ for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter)
{
- irc::modestacker stack(false);
- parameterlist stackresult;
- stackresult.push_back(c->name);
+ ModeHandler* mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
+
+ /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack,
+ * rather than applied immediately. Module unloads require this to be done immediately,
+ * for this function we require tidyness instead. Fixes bug #493
+ */
+ if (mh)
+ mh->RemoveMode(c, stack);
+ }
- for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter)
- {
- ModeHandler* mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
-
- /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack,
- * rather than applied immediately. Module unloads require this to be done immediately,
- * for this function we require tidyness instead. Fixes bug #493
- */
- if (mh)
- mh->RemoveMode(c, &stack);
- }
+ ApplyModeStack(ServerInstance->FakeClient, c, stack);
+}
- while (stack.GetStackedLine(stackresult))
- {
- ServerInstance->SendMode(stackresult, srcuser);
- stackresult.erase(stackresult.begin() + 1, stackresult.end());
- }
+void CommandFJoin::ApplyModeStack(User* srcuser, Channel* c, irc::modestacker& stack)
+{
+ parameterlist stackresult;
+ stackresult.push_back(c->name);
+
+ while (stack.GetStackedLine(stackresult))
+ {
+ ServerInstance->SendMode(stackresult, srcuser);
+ stackresult.erase(stackresult.begin() + 1, stackresult.end());
}
}
-
#include "inspircd.h"
#include "commands.h"
-#include "treesocket.h"
-#include "treeserver.h"
-#include "utils.h"
-
/** FMODE command - server mode with timestamp checks */
CmdResult CommandFMode::Handle(const std::vector<std::string>& params, User *who)
{
- std::string sourceserv = who->server;
-
- std::vector<std::string> modelist;
- time_t TS = 0;
- for (unsigned int q = 0; (q < params.size()) && (q < 64); q++)
+ time_t TS = ConvToInt(params[1]);
+ if (!TS)
{
- if (q == 1)
- {
- /* The timestamp is in this position.
- * We don't want to pass that up to the
- * server->client protocol!
- */
- TS = atoi(params[q].c_str());
- }
- else
- {
- /* Everything else is fine to append to the modelist */
- modelist.push_back(params[q]);
- }
-
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "*** BUG? *** TS of 0 sent to FMODE. Are some services authors smoking craq, or is it 1970 again?. Dropping link.");
+ ServerInstance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FMODE with a TS of zero. Total craq, dropping link.", who->server.c_str());
+ return CMD_INVALID;
}
- /* Extract the TS value of the object, either User or Channel */
- User* dst = ServerInstance->FindNick(params[0]);
- Channel* chan = NULL;
- time_t ourTS = 0;
- if (dst)
+ /* Extract the TS value of the object, either User or Channel */
+ time_t ourTS;
+ if (params[0][0] == '#')
{
- ourTS = dst->age;
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ /* Oops, channel doesn't exist! */
+ return CMD_FAILURE;
+
+ ourTS = chan->age;
}
else
{
- chan = ServerInstance->FindChan(params[0]);
- if (chan)
- {
- ourTS = chan->age;
- }
- else
- /* Oops, channel doesnt exist! */
+ User* user = ServerInstance->FindUUID(params[0]);
+ if (!user)
return CMD_FAILURE;
- }
- if (!TS)
- {
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"*** BUG? *** TS of 0 sent to FMODE. Are some services authors smoking craq, or is it 1970 again?. Dropped.");
- ServerInstance->SNO->WriteToSnoMask('d', "WARNING: The server %s is sending FMODE with a TS of zero. Total craq. Mode was dropped.", sourceserv.c_str());
- return CMD_INVALID;
+ if (IS_SERVER(user))
+ return CMD_INVALID;
+
+ ourTS = user->age;
}
/* TS is equal or less: Merge the mode changes into ours and pass on.
*/
if (TS <= ourTS)
{
+ std::vector<std::string> modelist;
+ modelist.reserve(params.size()-1);
+ /* Insert everything into modelist except the TS (params[1]) */
+ modelist.push_back(params[0]);
+ modelist.insert(modelist.end(), params.begin()+2, params.end());
+
bool merge = (TS == ourTS) && IS_SERVER(who);
ServerInstance->Modes->Process(modelist, who, merge);
return CMD_SUCCESS;
#include "inspircd.h"
#include "commands.h"
-#include "treesocket.h"
-#include "treeserver.h"
-#include "utils.h"
-
/** FTOPIC command */
CmdResult CommandFTopic::Handle(const std::vector<std::string>& params, User *user)
{
- time_t ts = atoi(params[1].c_str());
Channel* c = ServerInstance->FindChan(params[0]);
- if (c)
+ if (!c)
+ return CMD_FAILURE;
+
+ time_t ChanTS = ConvToInt(params[1]);
+ if (!ChanTS)
+ return CMD_INVALID;
+
+ if (c->age < ChanTS)
+ // Our channel TS is older, nothing to do
+ return CMD_FAILURE;
+
+ time_t ts = ConvToInt(params[2]);
+ if (!ts)
+ return CMD_INVALID;
+
+ // Channel::topicset is initialized to 0 on channel creation, so their ts will always win if we never had a topic
+ if (ts < c->topicset)
+ return CMD_FAILURE;
+
+ /*
+ * If the topics were updated at the exact same second, accept
+ * the remote only when it's "bigger" than ours as defined by
+ * string comparision, so non-empty topics always overridde
+ * empty topics if their timestamps are equal
+ */
+ if ((ts == c->topicset) && (c->topic > params[4]))
+ return CMD_FAILURE; // Topics were set at the exact same time, keep our topic and setter
+
+ if (c->topic != params[4])
{
- if ((ts >= c->topicset) || (c->topic.empty()))
- {
- if (c->topic != params[3])
- {
- // Update topic only when it differs from current topic
- c->topic.assign(params[3], 0, ServerInstance->Config->Limits.MaxTopic);
- c->WriteChannel(user, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str());
- }
-
- // Always update setter and settime.
- c->setby.assign(params[2], 0, 127);
- c->topicset = ts;
- }
+ // Update topic only when it differs from current topic
+ c->topic.assign(params[4], 0, ServerInstance->Config->Limits.MaxTopic);
+ c->WriteChannel(user, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str());
}
+
+ // Update setter and settime
+ c->setby.assign(params[3], 0, 127);
+ c->topicset = ts;
+
return CMD_SUCCESS;
}
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "../hash.h"
-#include "../ssl.h"
-#include "socketengine.h"
+#include "modules/hash.h"
+#include "modules/ssl.h"
#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
#include "link.h"
#include "treesocket.h"
-#include "resolvers.h"
const std::string& TreeSocket::GetOurChallenge()
{
*/
HashProvider* sha256 = ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256");
if (Utils->ChallengeResponse && sha256 && !challenge.empty())
- {
- if (proto_version < 1202)
- {
- /* This is how HMAC is done in InspIRCd 1.2:
- *
- * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) )
- *
- * 5c and 36 were chosen as part of the HMAC standard, because they
- * flip the bits in a way likely to strengthen the function.
- */
- std::string hmac1, hmac2;
-
- for (size_t n = 0; n < password.length(); n++)
- {
- hmac1.push_back(static_cast<char>(password[n] ^ 0x5C));
- hmac2.push_back(static_cast<char>(password[n] ^ 0x36));
- }
-
- hmac2.append(challenge);
- hmac2 = sha256->hexsum(hmac2);
-
- std::string hmac = hmac1 + hmac2;
- hmac = sha256->hexsum(hmac);
+ return "AUTH:" + BinToBase64(sha256->hmac(password, challenge));
- return "HMAC-SHA256:"+ hmac;
- }
- else
- {
- return "AUTH:" + BinToBase64(sha256->hmac(password, challenge));
- }
- }
- else if (!challenge.empty() && !sha256)
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!");
+ if (!challenge.empty() && !sha256)
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!");
return password;
}
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
bool TreeSocket::Whois(const std::string &prefix, parameterlist ¶ms)
{
if (params.size() < 1)
return true;
- User* u = ServerInstance->FindNick(prefix);
- if (u)
+
+ /* If this is a request, this user did the /whois
+ * If this is a reply, this user's information is in params[1] and params[2]
+ */
+ User* issuer = ServerInstance->FindUUID(prefix);
+ if ((!issuer) || (IS_SERVER(issuer)))
+ return true;
+
+ /* If this is a request, this is the user whose idle information was requested
+ * If this is a reply, this user did the /whois
+ */
+ User* target = ServerInstance->FindUUID(params[0]);
+ if ((!target) || (IS_SERVER(target)))
+ return true;
+
+ LocalUser* localtarget = IS_LOCAL(target);
+ if (!localtarget)
{
- // an incoming request
- if (params.size() == 1)
- {
- User* x = ServerInstance->FindNick(params[0]);
- if ((x) && (IS_LOCAL(x)))
- {
- long idle = abs((long)((x->idle_lastmsg) - ServerInstance->Time()));
- parameterlist par;
- par.push_back(prefix);
- par.push_back(ConvToStr(x->signon));
- par.push_back(ConvToStr(idle));
- // ours, we're done, pass it BACK
- Utils->DoOneToOne(params[0], "IDLE", par, u->server);
- }
- else
- {
- // not ours pass it on
- if (x)
- Utils->DoOneToOne(prefix, "IDLE", params, x->server);
- }
- }
- else if (params.size() == 3)
- {
- std::string who_did_the_whois = params[0];
- User* who_to_send_to = ServerInstance->FindNick(who_did_the_whois);
- if ((who_to_send_to) && (IS_LOCAL(who_to_send_to)))
- {
- // an incoming reply to a whois we sent out
- std::string nick_whoised = prefix;
- unsigned long signon = atoi(params[1].c_str());
- unsigned long idle = atoi(params[2].c_str());
- if ((who_to_send_to) && (IS_LOCAL(who_to_send_to)))
- {
- ServerInstance->DoWhois(who_to_send_to, u, signon, idle, nick_whoised.c_str());
- }
- }
- else
- {
- // not ours, pass it on
- if (who_to_send_to)
- Utils->DoOneToOne(prefix, "IDLE", params, who_to_send_to->server);
- }
- }
+ // Forward to target's server
+ Utils->DoOneToOne(prefix, "IDLE", params, target->server);
+ return true;
}
- return true;
-}
+ if (params.size() >= 2)
+ {
+ ServerInstance->Parser->CallHandler("WHOIS", params, issuer);
+ }
+ else
+ {
+ // A server is asking us the idle time of our user
+ unsigned int idle;
+ if (localtarget->idle_lastmsg >= ServerInstance->Time())
+ // Possible case when our clock ticked backwards
+ idle = 0;
+ else
+ idle = ((unsigned int) (localtarget->idle_lastmsg - ServerInstance->Time()));
+
+ parameterlist reply;
+ reply.push_back(prefix);
+ reply.push_back(ConvToStr(target->signon));
+ reply.push_back(ConvToStr(idle));
+ Utils->DoOneToOne(params[0], "IDLE", reply, issuer->server);
+ }
+ return true;
+}
--- /dev/null
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2012-2013 Attila Molnar <attilamolnar@hush.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 "inspircd.h"
+#include "commands.h"
+#include "utils.h"
+#include "treeserver.h"
+#include "treesocket.h"
+
+CmdResult CommandIJoin::HandleRemote(const std::vector<std::string>& params, RemoteUser* user)
+{
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ {
+ // Desync detected, recover
+ // Ignore the join and send RESYNC, this will result in the remote server sending all channel data to us
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Received IJOIN for non-existant channel: " + params[0]);
+
+ parameterlist p;
+ p.push_back(params[0]);
+ SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
+ Utils->DoOneToOne(ServerInstance->Config->GetSID(), "RESYNC", p, user->server);
+
+ return CMD_FAILURE;
+ }
+
+ bool apply_modes;
+ if (params.size() > 1)
+ {
+ time_t RemoteTS = ConvToInt(params[1]);
+ if (!RemoteTS)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Invalid TS in IJOIN: " + params[1]);
+ return CMD_INVALID;
+ }
+
+ if (RemoteTS < chan->age)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Attempted to lower TS via IJOIN. Channel=" + params[0] + " RemoteTS=" + params[1] + " LocalTS=" + ConvToStr(chan->age));
+ return CMD_INVALID;
+ }
+ apply_modes = ((params.size() > 2) && (RemoteTS == chan->age));
+ }
+ else
+ apply_modes = false;
+
+ chan->ForceJoin(user, apply_modes ? ¶ms[2] : NULL);
+ return CMD_SUCCESS;
+}
+
+CmdResult CommandResync::HandleServer(const std::vector<std::string>& params, FakeUser* user)
+{
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Resyncing " + params[0]);
+ Channel* chan = ServerInstance->FindChan(params[0]);
+ if (!chan)
+ {
+ // This can happen for a number of reasons, safe to ignore
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Channel does not exist");
+ return CMD_FAILURE;
+ }
+
+ SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
+ TreeServer* server = Utils->FindServer(user->server);
+ if (!server)
+ return CMD_FAILURE;
+
+ TreeSocket* socket = server->GetSocket();
+ if (!socket)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Received RESYNC with a source that is not directly connected: " + user->uuid);
+ return CMD_INVALID;
+ }
+
+ // Send all known information about the channel
+ socket->SyncChannel(chan);
+ return CMD_SUCCESS;
+}
*/
-#ifndef M_SPANNINGTREE_LINK_H
-#define M_SPANNINGTREE_LINK_H
+#pragma once
class Link : public refcountbase
{
int position;
Autoconnect(ConfigTag* Tag) : tag(Tag) {}
};
-
-#endif
#include "socket.h"
#include "xline.h"
-#include "cachetimer.h"
#include "resolvers.h"
#include "main.h"
#include "utils.h"
#include "protocolinterface.h"
ModuleSpanningTree::ModuleSpanningTree()
+ : commands(NULL), DNS(this, "DNS"), Utils(NULL)
{
- Utils = new SpanningTreeUtilities(this);
- commands = new SpanningTreeCommands(this);
- RefreshTimer = NULL;
}
SpanningTreeCommands::SpanningTreeCommands(ModuleSpanningTree* module)
: rconnect(module, module->Utils), rsquit(module, module->Utils),
svsjoin(module), svspart(module), svsnick(module), metadata(module),
- uid(module), opertype(module), fjoin(module), fmode(module), ftopic(module),
- fhost(module), fident(module), fname(module)
+ uid(module), opertype(module), fjoin(module), ijoin(module), resync(module),
+ fmode(module), ftopic(module), fhost(module), fident(module), fname(module)
{
}
void ModuleSpanningTree::init()
{
+ Utils = new SpanningTreeUtilities(this);
+ commands = new SpanningTreeCommands(this);
ServerInstance->Modules->AddService(commands->rconnect);
ServerInstance->Modules->AddService(commands->rsquit);
ServerInstance->Modules->AddService(commands->svsjoin);
ServerInstance->Modules->AddService(commands->uid);
ServerInstance->Modules->AddService(commands->opertype);
ServerInstance->Modules->AddService(commands->fjoin);
+ ServerInstance->Modules->AddService(commands->ijoin);
+ ServerInstance->Modules->AddService(commands->resync);
ServerInstance->Modules->AddService(commands->fmode);
ServerInstance->Modules->AddService(commands->ftopic);
ServerInstance->Modules->AddService(commands->fhost);
ServerInstance->Modules->AddService(commands->fident);
ServerInstance->Modules->AddService(commands->fname);
- RefreshTimer = new CacheRefreshTimer(Utils);
- ServerInstance->Timers->AddTimer(RefreshTimer);
Implementation eventlist[] =
{
I_OnPreCommand, I_OnGetServerDescription, I_OnUserInvite, I_OnPostTopicChange,
- I_OnWallops, I_OnUserNotice, I_OnUserMessage, I_OnBackgroundTimer, I_OnUserJoin,
+ I_OnUserMessage, I_OnBackgroundTimer, I_OnUserJoin,
I_OnChangeHost, I_OnChangeName, I_OnChangeIdent, I_OnUserPart, I_OnUnloadModule,
I_OnUserQuit, I_OnUserPostNick, I_OnUserKick, I_OnRemoteKill, I_OnRehash, I_OnPreRehash,
I_OnOper, I_OnAddLine, I_OnDelLine, I_OnMode, I_OnLoadModule, I_OnStats,
loopCall = false;
// update our local user count
- Utils->TreeRoot->SetUserCount(ServerInstance->Users->local_users.size());
+ Utils->TreeRoot->UserCount = ServerInstance->Users->local_users.size();
}
void ModuleSpanningTree::ShowLinks(TreeServer* Current, User* user, int hops)
{
if ((Current->GetChild(q)->Hidden) || ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName()))))
{
- if (IS_OPER(user))
+ if (user->IsOper())
{
ShowLinks(Current->GetChild(q),user,hops+1);
}
}
}
/* Don't display the line if its a uline, hide ulines is on, and the user isnt an oper */
- if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName())) && (!IS_OPER(user)))
+ if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName())) && (!user->IsOper()))
return;
/* Or if the server is hidden and they're not an oper */
- else if ((Current->Hidden) && (!IS_OPER(user)))
+ else if ((Current->Hidden) && (!user->IsOper()))
return;
std::string servername = Current->GetName();
user->WriteNumeric(364, "%s %s %s :%d %s", user->nick.c_str(), servername.c_str(),
- (Utils->FlatLinks && (!IS_OPER(user))) ? ServerInstance->Config->ServerName.c_str() : Parent.c_str(),
- (Utils->FlatLinks && (!IS_OPER(user))) ? 0 : hops,
+ (Utils->FlatLinks && (!user->IsOper())) ? ServerInstance->Config->ServerName.c_str() : Parent.c_str(),
+ (Utils->FlatLinks && (!user->IsOper())) ? 0 : hops,
Current->GetDesc().c_str());
}
// ... if we can find a proper route to them
if (tsock)
{
- tsock->WriteLine(":" + ServerInstance->Config->GetSID() + " PING " +
- ServerInstance->Config->GetSID() + " " + s->GetID());
+ tsock->WriteLine(":" + ServerInstance->Config->GetSID() + " PING " + s->GetID());
s->LastPingMsec = ts;
}
}
return;
}
- QueryType start_type = DNS_QUERY_AAAA;
+ DNS::QueryType start_type = DNS::QUERY_AAAA;
if (strchr(x->IPAddr.c_str(),':'))
{
in6_addr n;
ServerInstance->GlobalCulls.AddItem(newsocket);
}
}
+ else if (!DNS)
+ {
+ ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Hostname given and m_dns.so is not loaded, unable to resolve.", x->Name.c_str());
+ }
else
{
+ ServernameResolver* snr = new ServernameResolver(Utils, *DNS, x->IPAddr, x, start_type, y);
try
{
- bool cached = false;
- ServernameResolver* snr = new ServernameResolver(Utils, x->IPAddr, x, cached, start_type, y);
- ServerInstance->AddResolver(snr, cached);
+ DNS->Process(snr);
}
- catch (ModuleException& e)
+ catch (DNS::Exception& e)
{
+ delete snr;
ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(), e.GetReason());
ConnectServer(y, false);
}
TreeServer* found = Utils->FindServerMask(parameters[0]);
if (found)
{
- std::string Version = found->GetVersion();
- user->WriteNumeric(351, "%s :%s",user->nick.c_str(),Version.c_str());
if (found == Utils->TreeRoot)
{
- ServerInstance->Config->Send005(user);
+ // Pass to default VERSION handler.
+ return MOD_RES_PASSTHRU;
}
+ std::string Version = found->GetVersion();
+ user->WriteNumeric(351, "%s :%s",user->nick.c_str(),Version.c_str());
}
else
{
*/
void ModuleSpanningTree::RemoteMessage(User* user, const char* format, ...)
{
- char text[MAXBUF];
- va_list argsPtr;
-
- va_start(argsPtr, format);
- vsnprintf(text, MAXBUF, format, argsPtr);
- va_end(argsPtr);
+ std::string text;
+ VAFORMAT(text, format, format);
if (IS_LOCAL(user))
- user->WriteServ("NOTICE %s :%s", user->nick.c_str(), text);
+ user->WriteNotice(text);
else
ServerInstance->PI->SendUserNotice(user, text);
}
Utils->DoOneToMany(user->uuid,"TOPIC",params);
}
-void ModuleSpanningTree::OnWallops(User* user, const std::string &text)
+void ModuleSpanningTree::LocalMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list, const char* message_type)
{
- if (IS_LOCAL(user))
- {
- parameterlist params;
- params.push_back(":"+text);
- Utils->DoOneToMany(user->uuid,"WALLOPS",params);
- }
-}
-
-void ModuleSpanningTree::OnUserNotice(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
-{
- /* Server origin */
- if (user == NULL)
+ /* Server or remote origin, dest should always be non-null */
+ if ((!user) || (!IS_LOCAL(user)) || (!dest))
return;
if (target_type == TYPE_USER)
{
- User* d = (User*)dest;
- if (!IS_LOCAL(d) && IS_LOCAL(user))
+ User* d = (User*) dest;
+ if (!IS_LOCAL(d))
{
parameterlist params;
params.push_back(d->uuid);
params.push_back(":"+text);
- Utils->DoOneToOne(user->uuid,"NOTICE",params,d->server);
+ Utils->DoOneToOne(user->uuid, message_type, params, d->server);
}
}
else if (target_type == TYPE_CHANNEL)
{
- if (IS_LOCAL(user))
- {
- Channel *c = (Channel*)dest;
- if (c)
- {
- std::string cname = c->name;
- if (status)
- cname = status + cname;
- TreeServerList list;
- Utils->GetListOfServersForChannel(c,list,status,exempt_list);
- for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
- {
- TreeSocket* Sock = i->second->GetSocket();
- if (Sock)
- Sock->WriteLine(":"+std::string(user->uuid)+" NOTICE "+cname+" :"+text);
- }
- }
- }
+ Utils->SendChannelMessage(user->uuid, (Channel*)dest, text, status, exempt_list, message_type);
}
else if (target_type == TYPE_SERVER)
{
- if (IS_LOCAL(user))
- {
- char* target = (char*)dest;
- parameterlist par;
- par.push_back(target);
- par.push_back(":"+text);
- Utils->DoOneToMany(user->uuid,"NOTICE",par);
- }
+ char* target = (char*) dest;
+ parameterlist par;
+ par.push_back(target);
+ par.push_back(":"+text);
+ Utils->DoOneToMany(user->uuid, message_type, par);
}
}
-void ModuleSpanningTree::OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
+void ModuleSpanningTree::OnUserMessage(User* user, void* dest, int target_type, const std::string& text, char status, const CUList& exempt_list, MessageType msgtype)
{
- /* Server origin */
- if (user == NULL)
- return;
-
- if (target_type == TYPE_USER)
- {
- // route private messages which are targetted at clients only to the server
- // which needs to receive them
- User* d = (User*)dest;
- if (!IS_LOCAL(d) && (IS_LOCAL(user)))
- {
- parameterlist params;
- params.push_back(d->uuid);
- params.push_back(":"+text);
- Utils->DoOneToOne(user->uuid,"PRIVMSG",params,d->server);
- }
- }
- else if (target_type == TYPE_CHANNEL)
- {
- if (IS_LOCAL(user))
- {
- Channel *c = (Channel*)dest;
- if (c)
- {
- std::string cname = c->name;
- if (status)
- cname = status + cname;
- TreeServerList list;
- Utils->GetListOfServersForChannel(c,list,status,exempt_list);
- for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
- {
- TreeSocket* Sock = i->second->GetSocket();
- if (Sock)
- Sock->WriteLine(":"+std::string(user->uuid)+" PRIVMSG "+cname+" :"+text);
- }
- }
- }
- }
- else if (target_type == TYPE_SERVER)
- {
- if (IS_LOCAL(user))
- {
- char* target = (char*)dest;
- parameterlist par;
- par.push_back(target);
- par.push_back(":"+text);
- Utils->DoOneToMany(user->uuid,"PRIVMSG",par);
- }
- }
+ LocalMessage(user, dest, target_type, text, status, exempt_list, (msgtype == MSG_PRIVMSG ? "PRIVMSG" : "NOTICE"));
}
void ModuleSpanningTree::OnBackgroundTimer(time_t curtime)
params.push_back(":"+user->fullname);
Utils->DoOneToMany(ServerInstance->Config->GetSID(), "UID", params);
- if (IS_OPER(user))
+ if (user->IsOper())
{
params.clear();
- params.push_back(user->oper->name);
+ params.push_back(":");
+ params[0].append(user->oper->name);
Utils->DoOneToMany(user->uuid,"OPERTYPE",params);
}
ServerInstance->PI->SendMetaData(user, item->name, value);
}
- Utils->TreeRoot->SetUserCount(1); // increment by 1
+ Utils->TreeRoot->UserCount++;
}
-void ModuleSpanningTree::OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts)
+void ModuleSpanningTree::OnUserJoin(Membership* memb, bool sync, bool created_by_local, CUList& excepts)
{
// Only do this for local users
if (IS_LOCAL(memb->user))
{
parameterlist params;
- // set up their permissions and the channel TS with FJOIN.
- // All users are FJOINed now, because a module may specify
- // new joining permissions for the user.
params.push_back(memb->chan->name);
- params.push_back(ConvToStr(memb->chan->age));
- params.push_back(std::string("+") + memb->chan->ChanModes(true));
- params.push_back(memb->modes+","+memb->user->uuid);
- Utils->DoOneToMany(ServerInstance->Config->GetSID(),"FJOIN",params);
+ if (created_by_local)
+ {
+ params.push_back(ConvToStr(memb->chan->age));
+ params.push_back(std::string("+") + memb->chan->ChanModes(true));
+ params.push_back(memb->modes+","+memb->user->uuid);
+ Utils->DoOneToMany(ServerInstance->Config->GetSID(),"FJOIN",params);
+ }
+ else
+ {
+ if (!memb->modes.empty())
+ {
+ params.push_back(ConvToStr(memb->chan->age));
+ params.push_back(memb->modes);
+ }
+ Utils->DoOneToMany(memb->user->uuid, "IJOIN", params);
+ }
}
}
TreeServer* SourceServer = Utils->FindServer(user->server);
if (SourceServer)
{
- SourceServer->SetUserCount(-1); // decrement by 1
+ SourceServer->UserCount--;
}
}
if (loopCall)
return; // Don't generate a REHASH here if we're in the middle of processing a message that generated this one
- ServerInstance->Logs->Log("remoterehash", DEBUG, "called with param %s", parameter.c_str());
+ ServerInstance->Logs->Log("remoterehash", LOG_DEBUG, "called with param %s", parameter.c_str());
// Send out to other servers
if (!parameter.empty() && parameter[0] != '-')
if (user->registered != REG_ALL || !IS_LOCAL(user))
return;
parameterlist params;
- params.push_back(opertype);
+ params.push_back(":");
+ params[0].append(opertype);
Utils->DoOneToMany(user->uuid,"OPERTYPE",params);
}
if (u)
s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA "+u->uuid+" "+extname+" :"+extdata);
else if (c)
- s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA "+c->name+" "+extname+" :"+extdata);
+ s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA "+c->name+" "+ConvToStr(c->age)+" "+extname+" :"+extdata);
else if (!target)
s->WriteLine(":"+ServerInstance->Config->GetSID()+" METADATA * "+extname+" :"+extdata);
}
CullResult ModuleSpanningTree::cull()
{
Utils->cull();
- ServerInstance->Timers->DelTimer(RefreshTimer);
return this->Module::cull();
}
*/
-#ifndef M_SPANNINGTREE_MAIN_H
-#define M_SPANNINGTREE_MAIN_H
+#pragma once
#include "inspircd.h"
-#include <stdarg.h>
+#include "modules/dns.h"
/** If you make a change which breaks the protocol, increment this.
* If you completely change the protocol, completely change the number.
*
* Failure to document your protocol changes will result in a painfully
* painful death by pain. You have been warned.
*/
-const long ProtocolVersion = 1202;
-const long MinCompatProtocol = 1201;
+const long ProtocolVersion = 1205;
+const long MinCompatProtocol = 1202;
/** Forward declarations
*/
class ModuleSpanningTree : public Module
{
SpanningTreeCommands* commands;
+ void LocalMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list, const char* message_type);
public:
+ dynamic_reference<DNS::Manager> DNS;
+
SpanningTreeUtilities* Utils;
- CacheRefreshTimer *RefreshTimer;
/** Set to true if inside a spanningtree call, to prevent sending
* xlines and other things back to their source
*/
/** Constructor
*/
ModuleSpanningTree();
- void init();
+ void init() CXX11_OVERRIDE;
/** Shows /LINKS
*/
** *** MODULE EVENTS ***
**/
- ModResult OnPreCommand(std::string &command, std::vector<std::string>& parameters, LocalUser *user, bool validated, const std::string &original_line);
- void OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line);
- void OnGetServerDescription(const std::string &servername,std::string &description);
- void OnUserConnect(LocalUser* source);
- void OnUserInvite(User* source,User* dest,Channel* channel, time_t);
- void OnPostTopicChange(User* user, Channel* chan, const std::string &topic);
- void OnWallops(User* user, const std::string &text);
- void OnUserNotice(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list);
- void OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list);
- void OnBackgroundTimer(time_t curtime);
- void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts);
- void OnChangeHost(User* user, const std::string &newhost);
- void OnChangeName(User* user, const std::string &gecos);
- void OnChangeIdent(User* user, const std::string &ident);
- void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts);
- void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message);
- void OnUserPostNick(User* user, const std::string &oldnick);
- void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts);
- void OnRemoteKill(User* source, User* dest, const std::string &reason, const std::string &operreason);
- void OnPreRehash(User* user, const std::string ¶meter);
- void OnRehash(User* user);
- void OnOper(User* user, const std::string &opertype);
+ ModResult OnPreCommand(std::string &command, std::vector<std::string>& parameters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE;
+ void OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line) CXX11_OVERRIDE;
+ void OnGetServerDescription(const std::string &servername,std::string &description) CXX11_OVERRIDE;
+ void OnUserConnect(LocalUser* source) CXX11_OVERRIDE;
+ void OnUserInvite(User* source,User* dest,Channel* channel, time_t) CXX11_OVERRIDE;
+ void OnPostTopicChange(User* user, Channel* chan, const std::string &topic) CXX11_OVERRIDE;
+ void OnUserMessage(User* user, void* dest, int target_type, const std::string& text, char status, const CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE;
+ void OnBackgroundTimer(time_t curtime) CXX11_OVERRIDE;
+ void OnUserJoin(Membership* memb, bool sync, bool created, CUList& excepts) CXX11_OVERRIDE;
+ void OnChangeHost(User* user, const std::string &newhost) CXX11_OVERRIDE;
+ void OnChangeName(User* user, const std::string &gecos) CXX11_OVERRIDE;
+ void OnChangeIdent(User* user, const std::string &ident) CXX11_OVERRIDE;
+ void OnUserPart(Membership* memb, std::string &partmessage, CUList& excepts) CXX11_OVERRIDE;
+ void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message) CXX11_OVERRIDE;
+ void OnUserPostNick(User* user, const std::string &oldnick) CXX11_OVERRIDE;
+ void OnUserKick(User* source, Membership* memb, const std::string &reason, CUList& excepts) CXX11_OVERRIDE;
+ void OnRemoteKill(User* source, User* dest, const std::string &reason, const std::string &operreason) CXX11_OVERRIDE;
+ void OnPreRehash(User* user, const std::string ¶meter) CXX11_OVERRIDE;
+ void OnRehash(User* user) CXX11_OVERRIDE;
+ void OnOper(User* user, const std::string &opertype) CXX11_OVERRIDE;
void OnLine(User* source, const std::string &host, bool adding, char linetype, long duration, const std::string &reason);
- void OnAddLine(User *u, XLine *x);
- void OnDelLine(User *u, XLine *x);
- void OnMode(User* user, void* dest, int target_type, const std::vector<std::string> &text, const std::vector<TranslateType> &translate);
- ModResult OnStats(char statschar, User* user, string_list &results);
- ModResult OnSetAway(User* user, const std::string &awaymsg);
+ void OnAddLine(User *u, XLine *x) CXX11_OVERRIDE;
+ void OnDelLine(User *u, XLine *x) CXX11_OVERRIDE;
+ void OnMode(User* user, void* dest, int target_type, const std::vector<std::string> &text, const std::vector<TranslateType> &translate) CXX11_OVERRIDE;
+ ModResult OnStats(char statschar, User* user, string_list &results) CXX11_OVERRIDE;
+ ModResult OnSetAway(User* user, const std::string &awaymsg) CXX11_OVERRIDE;
void ProtoSendMode(void* opaque, TargetTypeFlags target_type, void* target, const std::vector<std::string> &modeline, const std::vector<TranslateType> &translate);
void ProtoSendMetaData(void* opaque, Extensible* target, const std::string &extname, const std::string &extdata);
- void OnLoadModule(Module* mod);
- void OnUnloadModule(Module* mod);
- ModResult OnAcceptConnection(int newsock, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server);
+ void OnLoadModule(Module* mod) CXX11_OVERRIDE;
+ void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
+ ModResult OnAcceptConnection(int newsock, ListenSocket* from, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) CXX11_OVERRIDE;
CullResult cull();
~ModuleSpanningTree();
- Version GetVersion();
+ Version GetVersion() CXX11_OVERRIDE;
void Prioritize();
};
-
-#endif
#include "inspircd.h"
#include "commands.h"
-#include "treesocket.h"
-#include "treeserver.h"
-#include "utils.h"
-
CmdResult CommandMetadata::Handle(const std::vector<std::string>& params, User *srcuser)
{
- std::string value = params.size() < 3 ? "" : params[2];
- ExtensionItem* item = ServerInstance->Extensions.GetItem(params[1]);
if (params[0] == "*")
{
+ std::string value = params.size() < 3 ? "" : params[2];
FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(NULL,params[1],value));
+ return CMD_SUCCESS;
}
- else if (*(params[0].c_str()) == '#')
+
+ if (params[0][0] == '#')
{
+ // Channel METADATA has an additional parameter: the channel TS
+ // :22D METADATA #channel 12345 extname :extdata
+ if (params.size() < 3)
+ return CMD_INVALID;
+
Channel* c = ServerInstance->FindChan(params[0]);
- if (c)
- {
- if (item)
- item->unserialize(FORMAT_NETWORK, c, value);
- FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(c,params[1],value));
- }
+ if (!c)
+ return CMD_FAILURE;
+
+ time_t ChanTS = ConvToInt(params[1]);
+ if (!ChanTS)
+ return CMD_INVALID;
+
+ if (c->age < ChanTS)
+ // Their TS is newer than ours, discard this command and do not propagate
+ return CMD_FAILURE;
+
+ std::string value = params.size() < 4 ? "" : params[3];
+
+ ExtensionItem* item = ServerInstance->Extensions.GetItem(params[2]);
+ if (item)
+ item->unserialize(FORMAT_NETWORK, c, value);
+ FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(c,params[2],value));
}
- else if (*(params[0].c_str()) != '#')
+ else
{
User* u = ServerInstance->FindUUID(params[0]);
if ((u) && (!IS_SERVER(u)))
{
+ ExtensionItem* item = ServerInstance->Extensions.GetItem(params[1]);
+ std::string value = params.size() < 3 ? "" : params[2];
+
if (item)
item->unserialize(FORMAT_NETWORK, u, value);
FOREACH_MOD(I_OnDecodeMetaData,OnDecodeMetaData(u,params[1],value));
#include "inspircd.h"
#include "xline.h"
+#include "listmode.h"
#include "treesocket.h"
#include "treeserver.h"
-#include "utils.h"
#include "main.h"
/** This function is called when we want to send a netburst to a local
/* send our version string */
this->WriteLine(":" + ServerInstance->Config->GetSID() + " VERSION :"+ServerInstance->GetVersionString());
/* Send server tree */
- this->SendServers(Utils->TreeRoot,s,1);
+ this->SendServers(Utils->TreeRoot, s);
/* Send users and their oper status */
this->SendUsers();
- /* Send everything else (channel modes, xlines etc) */
- this->SendChannelModes();
+
+ for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); ++i)
+ SyncChannel(i->second);
+
this->SendXLines();
FOREACH_MOD(I_OnSyncNetwork,OnSyncNetwork(Utils->Creator,(void*)this));
this->WriteLine(":" + ServerInstance->Config->GetSID() + " ENDBURST");
ServerInstance->SNO->WriteToSnoMask('l',"Finished bursting to \2"+ s->GetName()+"\2.");
}
-/** Recursively send the server tree with distances as hops.
+/** Recursively send the server tree.
* This is used during network burst to inform the other server
* (and any of ITS servers too) of what servers we know about.
* If at any point any of these servers already exist on the other
- * end, our connection may be terminated. The hopcounts given
- * by this function are relative, this doesn't matter so long as
- * they are all >1, as all the remote servers re-calculate them
- * to be relative too, with themselves as hop 0.
+ * end, our connection may be terminated.
+ * The hopcount parameter (3rd) is deprecated, and is always 0.
*/
-void TreeSocket::SendServers(TreeServer* Current, TreeServer* s, int hops)
+void TreeSocket::SendServers(TreeServer* Current, TreeServer* s)
{
char command[MAXBUF];
for (unsigned int q = 0; q < Current->ChildCount(); q++)
if (recursive_server != s)
{
std::string recursive_servername = recursive_server->GetName();
- snprintf(command, MAXBUF, ":%s SERVER %s * %d %s :%s", Current->GetID().c_str(), recursive_servername.c_str(), hops,
+ snprintf(command, MAXBUF, ":%s SERVER %s * 0 %s :%s", Current->GetID().c_str(), recursive_servername.c_str(),
recursive_server->GetID().c_str(),
recursive_server->GetDesc().c_str());
this->WriteLine(command);
this->WriteLine(":"+recursive_server->GetID()+" VERSION :"+recursive_server->GetVersion());
/* down to next level */
- this->SendServers(recursive_server, s, hops+1);
+ this->SendServers(recursive_server, s);
}
}
}
/** Send one or more FJOINs for a channel of users.
* If the length of a single line is more than 480-NICKMAX
* in length, it is split over multiple lines.
+ * Send one or more FMODEs for a channel with the
+ * channel bans, if there's any.
*/
void TreeSocket::SendFJoins(Channel* c)
{
- std::string buffer;
- char list[MAXBUF];
-
- size_t curlen, headlen;
- curlen = headlen = snprintf(list,MAXBUF,":%s FJOIN %s %lu +%s :",
- ServerInstance->Config->GetSID().c_str(), c->name.c_str(), (unsigned long)c->age, c->ChanModes(true));
- int numusers = 0;
- char* ptr = list + curlen;
- bool looped_once = false;
+ std::string line(":");
+ line.append(ServerInstance->Config->GetSID()).append(" FJOIN ").append(c->name).append(1, ' ').append(ConvToStr(c->age)).append(" +");
+ std::string::size_type erase_from = line.length();
+ line.append(c->ChanModes(true)).append(" :");
const UserMembList *ulist = c->GetUsers();
- std::string modes;
- std::string params;
-
- for (UserMembCIter i = ulist->begin(); i != ulist->end(); i++)
- {
- size_t ptrlen = 0;
- std::string modestr = i->second->modes;
-
- if ((curlen + modestr.length() + i->first->uuid.length() + 4) > 480)
- {
- // remove the final space
- if (ptr[-1] == ' ')
- ptr[-1] = '\0';
- buffer.append(list).append("\r\n");
- curlen = headlen;
- ptr = list + headlen;
- numusers = 0;
- }
-
- ptrlen = snprintf(ptr, MAXBUF-curlen, "%s,%s ", modestr.c_str(), i->first->uuid.c_str());
-
- looped_once = true;
-
- curlen += ptrlen;
- ptr += ptrlen;
-
- numusers++;
- }
-
- // Okay, permanent channels will (of course) need this \r\n anyway, numusers check is if there
- // actually were people in the channel (looped_once == true)
- if (!looped_once || numusers > 0)
- {
- // remove the final space
- if (ptr[-1] == ' ')
- ptr[-1] = '\0';
- buffer.append(list).append("\r\n");
- }
- int linesize = 1;
- for (BanList::iterator b = c->bans.begin(); b != c->bans.end(); b++)
+ for (UserMembCIter i = ulist->begin(); i != ulist->end(); ++i)
{
- 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))
+ const std::string& modestr = i->second->modes;
+ if ((line.length() + modestr.length() + UIDGenerator::UUID_LENGTH + 2) > 480)
{
- /* Wrap at MAXMODES */
- 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;
+ this->WriteLine(line);
+ line.erase(erase_from);
+ line.append(" :");
}
+ line.append(modestr).append(1, ',').append(i->first->uuid).push_back(' ');
}
+ this->WriteLine(line);
- /* Only send these if there are any */
- if (!modes.empty())
- buffer.append(":").append(ServerInstance->Config->GetSID()).append(" FMODE ").append(c->name).append(" ").append(ConvToStr(c->age)).append(" +").append(modes).append(params);
-
- this->WriteLine(buffer);
+ ModeReference ban(NULL, "ban");
+ static_cast<ListModeBase*>(*ban)->DoSyncChannel(c, Utils->Creator, this);
}
/** Send all XLines we know about */
void TreeSocket::SendXLines()
{
char data[MAXBUF];
- std::string n = ServerInstance->Config->GetSID();
- const char* sn = n.c_str();
std::vector<std::string> types = ServerInstance->XLines->GetAllTypes();
- time_t current = ServerInstance->Time();
- for (std::vector<std::string>::iterator it = types.begin(); it != types.end(); ++it)
+ for (std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it)
{
+ /* Expired lines are removed in XLineManager::GetAll() */
XLineLookup* lookup = ServerInstance->XLines->GetAll(*it);
+ /* lookup cannot be NULL in this case but a check won't hurt */
if (lookup)
{
for (LookupIter i = lookup->begin(); i != lookup->end(); ++i)
if (!i->second->IsBurstable())
break;
- /* If it's expired, don't bother to burst it
- */
- if (i->second->duration && current > i->second->expiry)
- continue;
-
- snprintf(data,MAXBUF,":%s ADDLINE %s %s %s %lu %lu :%s",sn, it->c_str(), i->second->Displayable(),
+ snprintf(data, MAXBUF, ":%s ADDLINE %s %s %s %lu %lu :%s",
+ ServerInstance->Config->GetSID().c_str(),
+ it->c_str(),
+ i->second->Displayable().c_str(),
i->second->source.c_str(),
(unsigned long)i->second->set_time,
(unsigned long)i->second->duration,
}
/** Send channel topic, modes and metadata */
-void TreeSocket::SendChannelModes()
+void TreeSocket::SyncChannel(Channel* chan)
{
char data[MAXBUF];
- std::string n = ServerInstance->Config->GetSID();
- const char* sn = n.c_str();
- for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++)
- {
- SendFJoins(c->second);
- if (!c->second->topic.empty())
- {
- snprintf(data,MAXBUF,":%s FTOPIC %s %lu %s :%s", sn, c->second->name.c_str(), (unsigned long)c->second->topicset, c->second->setby.c_str(), c->second->topic.c_str());
- this->WriteLine(data);
- }
+ SendFJoins(chan);
- for(Extensible::ExtensibleStore::const_iterator i = c->second->GetExtList().begin(); i != c->second->GetExtList().end(); i++)
- {
- ExtensionItem* item = i->first;
- std::string value = item->serialize(FORMAT_NETWORK, c->second, i->second);
- if (!value.empty())
- Utils->Creator->ProtoSendMetaData(this, c->second, item->name, value);
- }
+ // If the topic was ever set, send it, even if it's empty now
+ // because a new empty topic should override an old non-empty topic
+ if (chan->topicset != 0)
+ {
+ snprintf(data,MAXBUF,":%s FTOPIC %s %lu %lu %s :%s", ServerInstance->Config->GetSID().c_str(), chan->name.c_str(), (unsigned long) chan->age, (unsigned long)chan->topicset, chan->setby.c_str(), chan->topic.c_str());
+ this->WriteLine(data);
+ }
- FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(c->second,Utils->Creator,this));
+ for (Extensible::ExtensibleStore::const_iterator i = chan->GetExtList().begin(); i != chan->GetExtList().end(); i++)
+ {
+ ExtensionItem* item = i->first;
+ std::string value = item->serialize(FORMAT_NETWORK, chan, i->second);
+ if (!value.empty())
+ Utils->Creator->ProtoSendMetaData(this, chan, item->name, value);
}
+
+ FOREACH_MOD(I_OnSyncChannel,OnSyncChannel(chan, Utils->Creator, this));
}
/** send all users and their oper state/modes */
u->second->host.c_str(), /* 3: Displayed Host */
u->second->dhost.c_str(), /* 4: Real host */
u->second->ident.c_str(), /* 5: Ident */
- u->second->GetIPString(), /* 6: IP string */
+ u->second->GetIPString().c_str(), /* 6: IP string */
(unsigned long)u->second->signon, /* 7: Signon time for WHOWAS */
u->second->FormatModes(true), /* 8...n: Modes and params */
u->second->fullname.c_str()); /* size-1: GECOS */
this->WriteLine(data);
- if (IS_OPER(u->second))
+ if (u->second->IsOper())
{
- snprintf(data,MAXBUF,":%s OPERTYPE %s", u->second->uuid.c_str(), u->second->oper->name.c_str());
+ snprintf(data,MAXBUF,":%s OPERTYPE :%s", u->second->uuid.c_str(), u->second->oper->name.c_str());
this->WriteLine(data);
}
- if (IS_AWAY(u->second))
+ if (u->second->IsAway())
{
snprintf(data,MAXBUF,":%s AWAY %ld :%s", u->second->uuid.c_str(), (long)u->second->awaytime, u->second->awaymsg.c_str());
this->WriteLine(data);
#include "inspircd.h"
-#include "xline.h"
#include "treesocket.h"
-#include "treeserver.h"
#include "utils.h"
-/* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treesocket.h */
/*
params.push_back(ConvToStr(u->age));
Utils->DoOneToMany(ServerInstance->Config->GetSID(),"SAVE",params);
- u->ForceNickChange(u->uuid.c_str());
+ u->ForceNickChange(u->uuid);
if (!bChangeRemote)
return 1;
if (remote)
{
/* nick change collide. Force change their nick. */
- remote->ForceNickChange(remoteuid.c_str());
+ remote->ForceNickChange(remoteuid);
}
if (!bChangeLocal)
#include "inspircd.h"
-#include "xline.h"
-
#include "treesocket.h"
-#include "treeserver.h"
#include "utils.h"
/* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
CmdResult CommandOpertype::Handle(const std::vector<std::string>& params, User *u)
{
SpanningTreeUtilities* Utils = ((ModuleSpanningTree*)(Module*)creator)->Utils;
- std::string opertype = params[0];
- if (!IS_OPER(u))
+ const std::string& opertype = params[0];
+ if (!u->IsOper())
ServerInstance->Users->all_opers.push_back(u);
u->modes[UM_OPERATOR] = 1;
OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + opertype);
return CMD_SUCCESS;
}
- ServerInstance->SNO->WriteToSnoMask('O',"From %s: User %s (%s@%s) is now an IRC operator of type %s",u->server.c_str(), u->nick.c_str(),u->ident.c_str(), u->host.c_str(), irc::Spacify(opertype.c_str()));
+ ServerInstance->SNO->WriteToSnoMask('O',"From %s: User %s (%s@%s) is now an IRC operator of type %s",u->server.c_str(), u->nick.c_str(),u->ident.c_str(), u->host.c_str(), opertype.c_str());
return CMD_SUCCESS;
}
*/
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h */
const std::string ModuleSpanningTree::MapOperInfo(TreeServer* Current)
{
void ModuleSpanningTree::ShowMap(TreeServer* Current, User* user, int depth, int &line, char* names, int &maxnamew, char* stats)
{
- ServerInstance->Logs->Log("map",DEBUG,"ShowMap depth %d on line %d", depth, line);
+ ServerInstance->Logs->Log("map", LOG_DEBUG, "ShowMap depth %d on line %d", depth, line);
float percent;
if (ServerInstance->Users->clientlist->size() == 0)
}
else
{
- percent = Current->GetUserCount() * 100.0 / ServerInstance->Users->clientlist->size();
+ percent = Current->UserCount * 100.0 / ServerInstance->Users->clientlist->size();
}
- const std::string operdata = IS_OPER(user) ? MapOperInfo(Current) : "";
+ const std::string operdata = user->IsOper() ? MapOperInfo(Current) : "";
char* myname = names + 100 * line;
char* mystat = stats + 50 * line;
int w = depth;
std::string servername = Current->GetName();
- if (IS_OPER(user))
+ if (user->IsOper())
{
w += snprintf(myname + depth, 99 - depth, "%s (%s)", servername.c_str(), Current->GetID().c_str());
}
memset(myname + w, ' ', 100 - w);
if (w > maxnamew)
maxnamew = w;
- snprintf(mystat, 49, "%5d [%5.2f%%]%s", Current->GetUserCount(), percent, operdata.c_str());
+ snprintf(mystat, 49, "%5d [%5.2f%%]%s", Current->UserCount, percent, operdata.c_str());
line++;
- if (IS_OPER(user) || !Utils->FlatLinks)
+ if (user->IsOper() || !Utils->FlatLinks)
depth = depth + 2;
for (unsigned int q = 0; q < Current->ChildCount(); q++)
{
TreeServer* child = Current->GetChild(q);
- if (!IS_OPER(user)) {
+ if (!user->IsOper()) {
if (child->Hidden)
continue;
if ((Utils->HideULines) && (ServerInstance->ULine(child->GetName())))
float avg_users = totusers * 1.0 / line;
- ServerInstance->Logs->Log("map",DEBUG,"local");
+ ServerInstance->Logs->Log("map", LOG_DEBUG, "local");
for (int t = 0; t < line; t++)
{
// terminate the string at maxnamew characters
#include "inspircd.h"
#include "socket.h"
-#include "xline.h"
#include "main.h"
#include "utils.h"
{
if (s == Utils->TreeRoot)
{
- user->WriteServ("NOTICE %s :*** SQUIT: Foolish mortal, you cannot make a server SQUIT itself! (%s matches local server name)",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNotice("*** SQUIT: Foolish mortal, you cannot make a server SQUIT itself! (" + parameters[0] + " matches local server name)");
return MOD_RES_DENY;
}
}
else
{
- user->WriteServ("NOTICE %s :*** SQUIT may not be used to remove remote servers. Please use RSQUIT instead.",user->nick.c_str());
+ user->WriteNotice("*** SQUIT may not be used to remove remote servers. Please use RSQUIT instead.");
}
}
else
{
- user->WriteServ("NOTICE %s :*** SQUIT: The server \002%s\002 does not exist on the network.",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNotice("*** SQUIT: The server \002" + parameters[0] + "\002 does not exist on the network.");
}
return MOD_RES_DENY;
}
*/
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "link.h"
-#include "treesocket.h"
ModResult ModuleSpanningTree::OnStats(char statschar, User* user, string_list &results)
{
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h */
ModResult ModuleSpanningTree::HandleRemoteWhois(const std::vector<std::string>& parameters, User* user)
{
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treesocket.h */
bool TreeSocket::LocalPing(const std::string &prefix, parameterlist ¶ms)
{
if (params.size() < 1)
return true;
- if (params.size() == 1)
+
+ const std::string& forwardto = params[0];
+ if (forwardto == ServerInstance->Config->GetSID())
{
- std::string stufftobounce = params[0];
- this->WriteLine(":"+ServerInstance->Config->GetSID()+" PONG "+stufftobounce);
- return true;
+ // PING for us, reply with a PONG
+ std::string reply = ":" + forwardto + " PONG " + prefix;
+ if (params.size() >= 2)
+ // If there is a second parameter, append it
+ reply.append(" :").append(params[1]);
+
+ this->WriteLine(reply);
}
else
{
- std::string forwardto = params[1];
- if (forwardto == ServerInstance->Config->ServerName || forwardto == ServerInstance->Config->GetSID())
- {
- // this is a ping for us, send back PONG to the requesting server
- params[1] = params[0];
- params[0] = forwardto;
- Utils->DoOneToOne(ServerInstance->Config->GetSID(),"PONG",params,params[1]);
- }
- else
- {
- // not for us, pass it on :)
- Utils->DoOneToOne(prefix,"PING",params,forwardto);
- }
- return true;
+ // not for us, pass it on :)
+ Utils->DoOneToOne(prefix,"PING",params,forwardto);
}
+ return true;
}
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
#include "treeserver.h"
#include "treesocket.h"
if (params.size() < 1)
return true;
- if (params.size() == 1)
+ const std::string& forwardto = params[0];
+ if (forwardto == ServerInstance->Config->GetSID())
{
+ // PONG for us
TreeServer* ServerSource = Utils->FindServer(prefix);
if (ServerSource)
{
- ServerSource->SetPingFlag();
long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
ServerSource->rtt = ts - ServerSource->LastPingMsec;
+ ServerSource->SetPingFlag();
}
}
else
{
- std::string forwardto = params[1];
- if (forwardto == ServerInstance->Config->GetSID() || forwardto == ServerInstance->Config->ServerName)
- {
- /*
- * this is a PONG for us
- * if the prefix is a user, check theyre local, and if they are,
- * dump the PONG reply back to their fd. If its a server, do nowt.
- * Services might want to send these s->s, but we dont need to yet.
- */
- User* u = ServerInstance->FindNick(prefix);
- if (u)
- {
- u->WriteServ("PONG %s %s",params[0].c_str(),params[1].c_str());
- }
-
- TreeServer *ServerSource = Utils->FindServer(params[0]);
-
- if (ServerSource)
- {
- long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
- ServerSource->rtt = ts - ServerSource->LastPingMsec;
- ServerSource->SetPingFlag();
- }
- }
- else
- {
- // not for us, pass it on :)
- Utils->DoOneToOne(prefix,"PONG",params,forwardto);
- }
+ // not for us, pass it on :)
+ Utils->DoOneToOne(prefix,"PONG",params,forwardto);
}
-
return true;
}
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h */
void ModuleSpanningTree::OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line)
{
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", LOG_DEFAULT, "Trying to route ENCAP to nonexistant server %s",
routing.serverdest.c_str());
return;
}
if (!(ver.Flags & (VF_COMMON | VF_CORE)) && srcmodule != Creator)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Routed command %s from non-VF_COMMON module %s",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Routed command %s from non-VF_COMMON module %s",
command.c_str(), srcmodule->ModuleSourceFile.c_str());
return;
}
data += " " + params[x];
for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
{
- TreeSocket* Sock = i->second->GetSocket();
+ TreeSocket* Sock = (*i)->GetSocket();
if (origin && origin->GetSocket() == Sock)
continue;
if (Sock)
*/
-/* $ModDesc: Provides a spanning tree server link protocol */
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
-#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/main.h */
ModResult ModuleSpanningTree::OnPreCommand(std::string &command, std::vector<std::string>& parameters, LocalUser *user, bool validated, const std::string &original_line)
{
}
else if ((command == "VERSION") && (parameters.size() > 0))
{
- this->HandleVersion(parameters,user);
- return MOD_RES_DENY;
+ return this->HandleVersion(parameters,user);
}
return MOD_RES_PASSTHRU;
}
#include "inspircd.h"
-#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
#include "protocolinterface.h"
/*
ps.servername = i->second->GetName();
TreeServer* s = i->second->GetParent();
ps.parentname = s ? s->GetName() : "";
- ps.usercount = i->second->GetUserCount();
- ps.opercount = i->second->GetOperCount();
+ ps.usercount = i->second->UserCount;
+ ps.opercount = i->second->OperCount;
ps.gecos = i->second->GetDesc();
ps.latencyms = i->second->rtt;
sl.push_back(ps);
if (u)
params.push_back(u->uuid);
else if (c)
+ {
params.push_back(c->name);
+ params.push_back(ConvToStr(c->age));
+ }
else
params.push_back("*");
parameterlist params;
params.push_back(channel->name);
+ params.push_back(ConvToStr(channel->age));
params.push_back(ConvToStr(ServerInstance->Time()));
params.push_back(ServerInstance->Config->ServerName);
params.push_back(":" + topic);
Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH", p, target->server);
}
-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);
- for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
- {
- TreeSocket* Sock = i->second->GetSocket();
- if (Sock)
- Sock->WriteLine(text);
- }
-}
-
-
void SpanningTreeProtocolInterface::SendChannelPrivmsg(Channel* target, char status, const std::string &text)
{
- SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" PRIVMSG "+target->name+" :"+text);
+ CUList exempt_list;
+ Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, exempt_list, "PRIVMSG");
}
void SpanningTreeProtocolInterface::SendChannelNotice(Channel* target, char status, const std::string &text)
{
- SendChannel(target, status, ":" + ServerInstance->Config->GetSID()+" NOTICE "+target->name+" :"+text);
+ CUList exempt_list;
+ Utils->SendChannelMessage(ServerInstance->Config->GetSID(), target, text, status, exempt_list, "NOTICE");
}
void SpanningTreeProtocolInterface::SendUserPrivmsg(User* target, const std::string &text)
*/
-#ifndef M_SPANNINGTREE_PROTOCOLINTERFACE_H
-#define M_SPANNINGTREE_PROTOCOLINTERFACE_H
+#pragma once
class SpanningTreeUtilities;
class ModuleSpanningTree;
void SendChannel(Channel* target, char status, const std::string &text);
public:
SpanningTreeProtocolInterface(SpanningTreeUtilities* util) : Utils(util) { }
- virtual ~SpanningTreeProtocolInterface() { }
- virtual bool SendEncapsulatedData(const parameterlist &encap);
- virtual void SendMetaData(Extensible* target, const std::string &key, const std::string &data);
- virtual void SendTopic(Channel* channel, std::string &topic);
- virtual void SendMode(const std::string &target, const parameterlist &modedata, const std::vector<TranslateType> &types);
- virtual void SendSNONotice(const std::string &snomask, const std::string &text);
- virtual void PushToClient(User* target, const std::string &rawline);
- virtual void SendChannelPrivmsg(Channel* target, char status, const std::string &text);
- virtual void SendChannelNotice(Channel* target, char status, const std::string &text);
- virtual void SendUserPrivmsg(User* target, const std::string &text);
- virtual void SendUserNotice(User* target, const std::string &text);
- virtual void GetServerList(ProtoServerList &sl);
+ bool SendEncapsulatedData(const parameterlist &encap);
+ void SendMetaData(Extensible* target, const std::string &key, const std::string &data);
+ void SendTopic(Channel* channel, std::string &topic);
+ void SendMode(const std::string &target, const parameterlist &modedata, const std::vector<TranslateType> &types);
+ void SendSNONotice(const std::string &snomask, const std::string &text);
+ void PushToClient(User* target, const std::string &rawline);
+ void SendChannelPrivmsg(Channel* target, char status, const std::string &text);
+ void SendChannelNotice(Channel* target, char status, const std::string &text);
+ void SendUserPrivmsg(User* target, const std::string &text);
+ void SendUserNotice(User* target, const std::string &text);
+ void GetServerList(ProtoServerList &sl);
};
-
-#endif
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treesocket.h */
bool TreeSocket::Push(const std::string &prefix, parameterlist ¶ms)
{
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "resolvers.h"
#include "main.h"
#include "utils.h"
-#include "treeserver.h"
-#include "link.h"
-#include "treesocket.h"
#include "commands.h"
CommandRConnect::CommandRConnect (Module* Creator, SpanningTreeUtilities* Util)
CmdResult CommandRConnect::Handle (const std::vector<std::string>& parameters, User *user)
{
- if (IS_LOCAL(user))
+ /* First see if the server which is being asked to connect to another server in fact exists */
+ if (!Utils->FindServerMask(parameters[0]))
{
- if (!Utils->FindServerMask(parameters[0]))
- {
- user->WriteServ("NOTICE %s :*** RCONNECT: Server \002%s\002 isn't connected to the network!", user->nick.c_str(), parameters[0].c_str());
- return CMD_FAILURE;
- }
- user->WriteServ("NOTICE %s :*** RCONNECT: Sending remote connect to \002%s\002 to connect server \002%s\002.",user->nick.c_str(),parameters[0].c_str(),parameters[1].c_str());
+ ((ModuleSpanningTree*)(Module*)creator)->RemoteMessage(user, "*** RCONNECT: Server \002%s\002 isn't connected to the network!", parameters[0].c_str());
+ return CMD_FAILURE;
}
/* Is this aimed at our server? */
para.push_back(parameters[1]);
((ModuleSpanningTree*)(Module*)creator)->HandleConnect(para, user);
}
+ else
+ {
+ /* It's not aimed at our server, but if the request originates from our user
+ * acknowledge that we sent the request.
+ *
+ * It's possible that we're asking a server for something that makes no sense
+ * (e.g. connect to itself or to an already connected server), but we don't check
+ * for those conditions here, as ModuleSpanningTree::HandleConnect() (which will run
+ * on the target) does all the checking and error reporting.
+ */
+ if (IS_LOCAL(user))
+ {
+ user->WriteNotice("*** RCONNECT: Sending remote connect to \002 " + parameters[0] + "\002 to connect server \002" + parameters[1] + "\002.");
+ }
+ }
return CMD_SUCCESS;
}
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
+#include "cachetimer.h"
#include "resolvers.h"
#include "main.h"
#include "utils.h"
* callback to OnLookupComplete or OnError when completed. Once it has completed we
* will have an IP address which we can then use to continue our connection.
*/
-ServernameResolver::ServernameResolver(SpanningTreeUtilities* Util, const std::string &hostname, Link* x, bool &cached, QueryType qt, Autoconnect* myac)
- : Resolver(hostname, qt, cached, Util->Creator), Utils(Util), query(qt), host(hostname), MyLink(x), myautoconnect(myac)
+ServernameResolver::ServernameResolver(SpanningTreeUtilities* Util, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt, Autoconnect* myac)
+ : DNS::Request(mgr, Util->Creator, hostname, qt), Utils(Util), query(qt), host(hostname), MyLink(x), myautoconnect(myac)
{
}
-void ServernameResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
+void ServernameResolver::OnLookupComplete(const DNS::Query *r)
{
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+
/* Initiate the connection, now that we have an IP to use.
* Passing a hostname directly to BufferedSocket causes it to
* just bail and set its FD to -1.
TreeServer* CheckDupe = Utils->FindServer(MyLink->Name.c_str());
if (!CheckDupe) /* Check that nobody tried to connect it successfully while we were resolving */
{
- TreeSocket* newsocket = new TreeSocket(Utils, MyLink, myautoconnect, result);
+ TreeSocket* newsocket = new TreeSocket(Utils, MyLink, myautoconnect, ans_record.rdata);
if (newsocket->GetFd() > -1)
{
/* We're all OK */
}
}
-void ServernameResolver::OnError(ResolverError e, const std::string &errormessage)
+void ServernameResolver::OnError(const DNS::Query *r)
{
/* Ooops! */
- if (query == DNS_QUERY_AAAA)
+ if (query == DNS::QUERY_AAAA)
{
- bool cached = false;
- ServernameResolver* snr = new ServernameResolver(Utils, host, MyLink, cached, DNS_QUERY_A, myautoconnect);
- ServerInstance->AddResolver(snr, cached);
- return;
+ ServernameResolver* snr = new ServernameResolver(Utils, this->manager, host, MyLink, DNS::QUERY_A, myautoconnect);
+ try
+ {
+ this->manager->Process(snr);
+ return;
+ }
+ catch (DNS::Exception &)
+ {
+ delete snr;
+ }
}
- ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s", MyLink->Name.c_str(), errormessage.c_str() );
+
+ ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: Unable to resolve hostname - %s", MyLink->Name.c_str(), this->manager->GetErrorStr(r->error).c_str());
Utils->Creator->ConnectServer(myautoconnect, false);
}
-SecurityIPResolver::SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt)
- : Resolver(hostname, qt, cached, me), MyLink(x), Utils(U), mine(me), host(hostname), query(qt)
+SecurityIPResolver::SecurityIPResolver(Module* me, SpanningTreeUtilities* U, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt)
+ : DNS::Request(mgr, me, hostname, qt), MyLink(x), Utils(U), mine(me), host(hostname), query(qt)
{
}
-void SecurityIPResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
+void SecurityIPResolver::OnLookupComplete(const DNS::Query *r)
{
+ const DNS::ResourceRecord &ans_record = r->answers[0];
+
for (std::vector<reference<Link> >::iterator i = Utils->LinkBlocks.begin(); i != Utils->LinkBlocks.end(); ++i)
{
Link* L = *i;
if (L->IPAddr == host)
{
- Utils->ValidIPs.push_back(result);
+ Utils->ValidIPs.push_back(ans_record.rdata);
break;
}
}
}
-void SecurityIPResolver::OnError(ResolverError e, const std::string &errormessage)
+void SecurityIPResolver::OnError(const DNS::Query *r)
{
- if (query == DNS_QUERY_AAAA)
+ if (query == DNS::QUERY_AAAA)
{
- bool cached = false;
- SecurityIPResolver* res = new SecurityIPResolver(mine, Utils, host, MyLink, cached, DNS_QUERY_A);
- ServerInstance->AddResolver(res, cached);
- return;
+ SecurityIPResolver* res = new SecurityIPResolver(mine, Utils, this->manager, host, MyLink, DNS::QUERY_A);
+ try
+ {
+ this->manager->Process(res);
+ return;
+ }
+ catch (DNS::Exception &)
+ {
+ delete res;
+ }
}
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Could not resolve IP associated with Link '%s': %s",
- MyLink->Name.c_str(),errormessage.c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Could not resolve IP associated with Link '%s': %s",
+ MyLink->Name.c_str(), this->manager->GetErrorStr(r->error).c_str());
+}
+
+CacheRefreshTimer::CacheRefreshTimer(SpanningTreeUtilities* Util)
+ : Timer(3600, ServerInstance->Time(), true), Utils(Util)
+{
+}
+
+bool CacheRefreshTimer::Tick(time_t TIME)
+{
+ Utils->RefreshIPCache();
+ return true;
}
*/
-#ifndef M_SPANNINGTREE_RESOLVERS_H
-#define M_SPANNINGTREE_RESOLVERS_H
+#pragma once
-#include "socket.h"
#include "inspircd.h"
-#include "xline.h"
+#include "modules/dns.h"
#include "utils.h"
#include "link.h"
/** Handle resolving of server IPs for the cache
*/
-class SecurityIPResolver : public Resolver
+class SecurityIPResolver : public DNS::Request
{
private:
reference<Link> MyLink;
SpanningTreeUtilities* Utils;
Module* mine;
std::string host;
- QueryType query;
+ DNS::QueryType query;
public:
- SecurityIPResolver(Module* me, SpanningTreeUtilities* U, const std::string &hostname, Link* x, bool &cached, QueryType qt);
- void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached);
- void OnError(ResolverError e, const std::string &errormessage);
+ SecurityIPResolver(Module* me, SpanningTreeUtilities* U, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt);
+ void OnLookupComplete(const DNS::Query *r) CXX11_OVERRIDE;
+ void OnError(const DNS::Query *q) CXX11_OVERRIDE;
};
/** This class is used to resolve server hostnames during /connect and autoconnect.
* callback to OnLookupComplete or OnError when completed. Once it has completed we
* will have an IP address which we can then use to continue our connection.
*/
-class ServernameResolver : public Resolver
+class ServernameResolver : public DNS::Request
{
private:
SpanningTreeUtilities* Utils;
- QueryType query;
+ DNS::QueryType query;
std::string host;
reference<Link> MyLink;
reference<Autoconnect> myautoconnect;
public:
- ServernameResolver(SpanningTreeUtilities* Util, const std::string &hostname, Link* x, bool &cached, QueryType qt, Autoconnect* myac);
- void OnLookupComplete(const std::string &result, unsigned int ttl, bool cached);
- void OnError(ResolverError e, const std::string &errormessage);
+ ServernameResolver(SpanningTreeUtilities* Util, DNS::Manager *mgr, const std::string &hostname, Link* x, DNS::QueryType qt, Autoconnect* myac);
+ void OnLookupComplete(const DNS::Query *r) CXX11_OVERRIDE;
+ void OnError(const DNS::Query *q) CXX11_OVERRIDE;
};
-
-#endif
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "treesocket.h"
#include "commands.h"
CommandRSQuit::CommandRSQuit (Module* Creator, SpanningTreeUtilities* Util)
server_target = Utils->FindServerMask(parameters[0]);
if (!server_target)
{
- user->WriteServ("NOTICE %s :*** RSQUIT: Server \002%s\002 isn't connected to the network!", user->nick.c_str(), parameters[0].c_str());
+ ((ModuleSpanningTree*)(Module*)creator)->RemoteMessage(user, "*** RSQUIT: Server \002%s\002 isn't connected to the network!", parameters[0].c_str());
return CMD_FAILURE;
}
if (server_target == Utils->TreeRoot)
{
- NoticeUser(user, "*** RSQUIT: Foolish mortal, you cannot make a server SQUIT itself! ("+parameters[0]+" matches local server name)");
+ ((ModuleSpanningTree*)(Module*)creator)->RemoteMessage(user, "*** RSQUIT: Foolish mortal, you cannot make a server SQUIT itself! (%s matches local server name)", parameters[0].c_str());
return CMD_FAILURE;
}
{
return ROUTE_UNICAST(parameters[0]);
}
-
-// XXX use protocol interface instead of rolling our own :)
-void CommandRSQuit::NoticeUser(User* user, const std::string &msg)
-{
- if (IS_LOCAL(user))
- {
- user->WriteServ("NOTICE %s :%s",user->nick.c_str(),msg.c_str());
- }
- else
- {
- parameterlist params;
- params.push_back(user->nick);
- params.push_back("NOTICE "+ConvToStr(user->nick)+" :"+msg);
- Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PUSH", params, user->server);
- }
-}
-
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
-#include "treeserver.h"
#include "treesocket.h"
-/* $ModDep: m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
+/* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
/**
* SAVE command - force nick change to UID on timestamp match
{
Utils->DoOneToAllButSender(prefix,"SAVE",params,prefix);
- if (!u->ForceNickChange(u->uuid.c_str()))
+ if (!u->ForceNickChange(u->uuid))
{
ServerInstance->Users->QuitUser(u, "Nickname collision");
}
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
#include "utils.h"
#include "link.h"
#include "treeserver.h"
this->SendError("Protocol error - Introduced remote server from unknown server "+prefix);
return false;
}
- if (!ServerInstance->IsSID(sid))
+ if (!InspIRCd::IsSID(sid))
{
this->SendError("Invalid format server ID: "+sid+"!");
return false;
std::string password = params[1];
std::string sid = params[3];
std::string description = params[4];
- int hops = atoi(params[2].c_str());
this->SendCapabilities(2);
- if (hops)
- {
- this->SendError("Server too far away for authentication");
- ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication");
- return false;
- }
-
if (!ServerInstance->IsSID(sid))
{
this->SendError("Invalid format server ID: "+sid+"!");
}
/* Check for fully initialized instances of the server by id */
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Looking for dupe SID %s", sid.c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Looking for dupe SID %s", sid.c_str());
CheckDupe = Utils->FindServerID(sid);
if (CheckDupe)
std::string password = params[1];
std::string sid = params[3];
std::string description = params[4];
- int hops = atoi(params[2].c_str());
this->SendCapabilities(2);
- if (hops)
- {
- this->SendError("Server too far away for authentication");
- ServerInstance->SNO->WriteToSnoMask('l',"Server connection from \2"+sname+"\2 denied, server is too far away for authentication");
- return false;
- }
-
if (!ServerInstance->IsSID(sid))
{
this->SendError("Invalid format server ID: "+sid+"!");
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
#include "commands.h"
CmdResult CommandSVSJoin::Handle(const std::vector<std::string>& parameters, User *user)
{
// Check for valid channel name
- if (!ServerInstance->IsChannel(parameters[1].c_str(), ServerInstance->Config->Limits.ChanMax))
+ if (!ServerInstance->IsChannel(parameters[1]))
return CMD_FAILURE;
// Check target exists
return CMD_FAILURE;
/* only join if it's local, otherwise just pass it on! */
- if (IS_LOCAL(u))
- Channel::JoinUser(u, parameters[1].c_str(), false, "", false, ServerInstance->Time());
+ LocalUser* localuser = IS_LOCAL(u);
+ if (localuser)
+ Channel::JoinUser(localuser, parameters[1]);
return CMD_SUCCESS;
}
#include "inspircd.h"
-#include "main.h"
-#include "utils.h"
#include "commands.h"
CmdResult CommandSVSNick::Handle(const std::vector<std::string>& parameters, User *user)
if (isdigit(nick[0]))
nick = u->uuid;
- if (!u->ForceNickChange(nick.c_str()))
+ if (!u->ForceNickChange(nick))
{
/* buh. UID them */
- if (!u->ForceNickChange(u->uuid.c_str()))
+ if (!u->ForceNickChange(u->uuid))
{
ServerInstance->Users->QuitUser(u, "Nickname collision");
return CMD_SUCCESS;
}
}
- u->age = atoi(parameters[2].c_str());
+ u->age = ConvToInt(parameters[2]);
}
return CMD_SUCCESS;
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
-#include "main.h"
-#include "utils.h"
-#include "treeserver.h"
#include "commands.h"
CmdResult CommandSVSPart::Handle(const std::vector<std::string>& parameters, User *user)
#include "inspircd.h"
-#include "socket.h"
#include "xline.h"
#include "main.h"
-#include "../spanningtree.h"
+#include "modules/spanningtree.h"
#include "utils.h"
#include "treeserver.h"
bursting = false;
Parent = NULL;
VersionString.clear();
- ServerUserCount = ServerOperCount = 0;
+ UserCount = OperCount = 0;
VersionString = ServerInstance->GetVersionString();
Route = NULL;
Socket = NULL; /* Fix by brain */
age = ServerInstance->Time();
bursting = true;
VersionString.clear();
- ServerUserCount = ServerOperCount = 0;
+ UserCount = OperCount = 0;
SetNextPingTime(ServerInstance->Time() + Utils->PingFreq);
SetPingFlag();
Warned = false;
long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000);
this->StartBurst = ts;
- ServerInstance->Logs->Log("m_spanningtree",DEBUG, "Started bursting at time %lu", ts);
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Started bursting at time %lu", ts);
/* find the 'route' for this server (e.g. the one directly connected
* to the local server, which we can use to reach it)
void TreeServer::SetID(const std::string &id)
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG, "Setting SID to " + id);
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Setting SID to " + id);
sid = id;
Utils->sidlist[sid] = this;
}
LastPingWasGood = true;
}
-unsigned int TreeServer::GetUserCount()
-{
- return ServerUserCount;
-}
-
-void TreeServer::SetUserCount(int diff)
-{
- ServerUserCount += diff;
-}
-
-void TreeServer::SetOperCount(int diff)
-{
- ServerOperCount += diff;
-}
-
-unsigned int TreeServer::GetOperCount()
-{
- return ServerOperCount;
-}
-
TreeSocket* TreeServer::GetSocket()
{
return Socket;
*/
-#ifndef M_SPANNINGTREE_TREESERVER_H
-#define M_SPANNINGTREE_TREESERVER_H
+#pragma once
#include "treesocket.h"
irc::string ServerName; /* Server's name */
std::string ServerDesc; /* Server's description */
std::string VersionString; /* Version string or empty string */
- unsigned int ServerUserCount; /* How many users are on this server? [note: doesn't care about +i] */
- unsigned int ServerOperCount; /* How many opers are on this server? */
TreeSocket* Socket; /* For directly connected servers this points at the socket object */
time_t NextPing; /* After this time, the server should be PINGed*/
bool LastPingWasGood; /* True if the server responded to the last PING with a PONG */
bool Warned; /* True if we've warned opers about high latency on this server */
bool bursting; /* whether or not this server is bursting */
+ unsigned int UserCount; /* How many users are on this server? [note: doesn't care about +i] */
+ unsigned int OperCount; /* How many opers are on this server? */
+
/** We use this constructor only to create the 'root' item, Utils->TreeRoot, which
* represents our own server. Therefore, it has no route, no parent, and
* no socket associated with it. Its version string is our own local version.
*/
void SetPingFlag();
- /** Get the number of users on this server.
- */
- unsigned int GetUserCount();
-
- /** Increment or decrement the user count by diff.
- */
- void SetUserCount(int diff);
-
- /** Gets the numbers of opers on this server.
- */
- unsigned int GetOperCount();
-
- /** Increment or decrement the oper count by diff.
- */
- void SetOperCount(int diff);
-
/** Get the TreeSocket pointer for local servers.
* For remote servers, this returns NULL.
*/
*/
~TreeServer();
};
-
-#endif
*/
-#ifndef M_SPANNINGTREE_TREESOCKET_H
-#define M_SPANNINGTREE_TREESOCKET_H
+#pragma once
-#include "socket.h"
#include "inspircd.h"
-#include "xline.h"
#include "utils.h"
* to server docs on the inspircd.org site, the other side
* will then send back its own server string.
*/
- virtual void OnConnected();
+ void OnConnected();
/** Handle socket error event
*/
- virtual void OnError(BufferedSocketError e);
+ void OnError(BufferedSocketError e) CXX11_OVERRIDE;
/** Sends an error to the remote server, and displays it locally to show
* that it was sent.
/** Recursively send the server tree with distances as hops.
* This is used during network burst to inform the other server
* (and any of ITS servers too) of what servers we know about.
- * If at any point any of these servers already exist on the other
- * end, our connection may be terminated. The hopcounts given
- * by this function are relative, this doesn't matter so long as
- * they are all >1, as all the remote servers re-calculate them
- * to be relative too, with themselves as hop 0.
*/
- void SendServers(TreeServer* Current, TreeServer* s, int hops);
+ void SendServers(TreeServer* Current, TreeServer* s);
/** Returns module list as a string, filtered by filter
* @param filter a module version bitmask, such as VF_COMMON or VF_OPTCOMMON
*/
void SendCapabilities(int phase);
- /** Add modules to VF_COMMON list for backwards compatability */
- void CompatAddModules(std::vector<std::string>& modlist);
-
/* Isolate and return the elements that are different between two lists */
void ListDifference(const std::string &one, const std::string &two, char sep,
std::string& mleft, std::string& mright);
/** Send G, Q, Z and E lines */
void SendXLines();
- /** Send channel modes and topics */
- void SendChannelModes();
+ /** Send all known information about a channel */
+ void SyncChannel(Channel* chan);
/** send all users and their oper state/modes */
void SendUsers();
/** Handle socket timeout from connect()
*/
- virtual void OnTimeout();
+ void OnTimeout();
/** Handle server quit on close
*/
- virtual void Close();
+ void Close();
/** Returns true if this server was introduced to the rest of the network
*/
bool Introduced();
-};
-
-#endif
+ /** Fixes messages coming from old servers so the new command handlers understand them
+ */
+ bool PreProcessOldProtocolMessage(User*& who, std::string& cmd, std::vector<std::string>& params);
+};
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
-#include "../spanningtree.h"
+#include "modules/spanningtree.h"
#include "utils.h"
#include "treeserver.h"
#include "link.h"
#include "treesocket.h"
-#include "resolvers.h"
/** Because most of the I/O gubbins are encapsulated within
* BufferedSocket, we just call the superclass constructor for
void TreeSocket::SquitServer(std::string &from, TreeServer* Current, int& num_lost_servers, int& num_lost_users)
{
std::string servername = Current->GetName();
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"SquitServer for %s from %s",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "SquitServer for %s from %s",
servername.c_str(), from.c_str());
/* recursively squit the servers attached to 'Current'.
* We're going backwards so we don't remove users
if (!Current->GetSocket() || Current->GetSocket()->Introduced())
{
parameterlist params;
- params.push_back(Current->GetName());
+ params.push_back(Current->GetID());
params.push_back(":"+reason);
- Utils->DoOneToAllButSender(Current->GetParent()->GetName(),"SQUIT",params,Current->GetName());
+ Utils->DoOneToAllButSender(Current->GetParent()->GetID(),"SQUIT",params,Current->GetName());
}
if (Current->GetParent() == Utils->TreeRoot)
}
}
else
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Squit from unknown server");
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Squit from unknown server");
}
/** This function is called when we receive data from a remote
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "link.h"
#include "treesocket.h"
#include "resolvers.h"
if (!tokens.GetToken(prefix))
return;
-
+
if (prefix[0] == ':')
{
prefix = prefix.substr(1);
std::string command;
parameterlist params;
- ServerInstance->Logs->Log("m_spanningtree", RAWIO, "S[%d] I %s", this->GetFd(), line.c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_RAWIO, "S[%d] I %s", this->GetFd(), line.c_str());
Split(line, prefix, command, params);
{
if (params.size())
{
- time_t them = atoi(params[0].c_str());
+ time_t them = ConvToInt(params[0]);
time_t delta = them - ServerInstance->Time();
if ((delta < -600) || (delta > 600))
{
* crossing the users QUIT further upstream from the server. Thanks jilles!
*/
- if ((prefix.length() == UUID_LENGTH-1) && (isdigit(prefix[0])) &&
+ if ((prefix.length() == UIDGenerator::UUID_LENGTH) && (isdigit(prefix[0])) &&
((command == "FMODE") || (command == "MODE") || (command == "KICK") || (command == "TOPIC") || (command == "KILL") || (command == "ADDLINE") || (command == "DELLINE")))
{
/* Special case, we cannot drop these commands as they've been committed already on a
}
else
{
- ServerInstance->Logs->Log("m_spanningtree", DEBUG, "Command '%s' from unknown prefix '%s'! Dropping entire command.",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Command '%s' from unknown prefix '%s'! Dropping entire command.",
command.c_str(), prefix.c_str());
return;
}
if ((!route_back_again) || (route_back_again->GetSocket() != this))
{
if (route_back_again)
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Protocol violation: Fake direction '%s' from connection '%s'",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "Protocol violation: Fake direction '%s' from connection '%s'",
prefix.c_str(),linkID.c_str());
return;
}
if (command == "SVSMODE") // This isn't in an "else if" so we still force FMODE for changes on channels.
command = "MODE";
+ if (proto_version < ProtocolVersion)
+ {
+ if (!PreProcessOldProtocolMessage(who, command, params))
+ return;
+ }
+
// TODO move all this into Commands
if (command == "MAP")
{
}
/* Update timestamp on user when they change nicks */
- who->age = atoi(params[1].c_str());
+ who->age = ConvToInt(params[1]);
/*
* On nick messages, check that the nick doesnt already exist here.
return;
}
}
- who->ForceNickChange(params[0].c_str());
+ who->ForceNickChange(params[0]);
Utils->RouteCommand(route_back_again, command, params, who);
}
else
{
Command* cmd = ServerInstance->Parser->GetHandler(command);
-
+
if (!cmd)
{
irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Unrecognised S2S command :%s %s %s",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_SPARSE, "Unrecognised S2S command :%s %s %s",
who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str());
SendError("Unrecognised command '" + command + "' -- possibly loaded mismatched modules");
return;
if (params.size() < cmd->min_params)
{
irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Insufficient parameters for S2S command :%s %s %s",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_SPARSE, "Insufficient parameters for S2S command :%s %s %s",
who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str());
SendError("Insufficient parameters for command '" + command + "'");
return;
if (res == CMD_INVALID)
{
irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
- ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Error handling S2S command :%s %s %s",
+ ServerInstance->Logs->Log("m_spanningtree", LOG_SPARSE, "Error handling S2S command :%s %s %s",
who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str());
SendError("Error handling '" + command + "' -- possibly loaded mismatched modules");
}
#include "commands.h"
#include "utils.h"
-#include "link.h"
-#include "treesocket.h"
#include "treeserver.h"
-#include "resolvers.h"
CmdResult CommandUID::Handle(const parameterlist ¶ms, User* serversrc)
{
time_t age_t = ConvToInt(params[1]);
time_t signon = ConvToInt(params[7]);
std::string empty;
- std::string modestr(params[8]);
+ const std::string& modestr = params[8];
TreeServer* remoteserver = Utils->FindServer(serversrc->server);
* Nick collision.
*/
int collide = sock->DoCollision(iter->second, age_t, params[5], params[6], params[0]);
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"*** Collision on %s, collide=%d", params[2].c_str(), collide);
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "*** Collision on %s, collide=%d", params[2].c_str(), collide);
if (collide != 1)
{
}
catch (...)
{
- ServerInstance->Logs->Log("m_spanningtree", DEFAULT, "Duplicate UUID %s in client introduction", params[0].c_str());
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Duplicate UUID %s in client introduction", params[0].c_str());
return CMD_INVALID;
}
(*(ServerInstance->Users->clientlist))[params[2]] = _new;
_new->signon = signon;
_new->age = age_t;
- /* we need to remove the + from the modestring, so we can do our stuff */
- std::string::size_type pos_after_plus = modestr.find_first_not_of('+');
- if (pos_after_plus != std::string::npos)
- modestr = modestr.substr(pos_after_plus);
-
unsigned int paramptr = 9;
- for (std::string::iterator v = modestr.begin(); v != modestr.end(); v++)
+
+ for (std::string::const_iterator v = modestr.begin(); v != modestr.end(); ++v)
{
- /* For each mode thats set, increase counter */
+ // Accept more '+' chars, for now
+ if (*v == '+')
+ continue;
+
+ /* For each mode thats set, find the mode handler and set it on the new user */
ModeHandler* mh = ServerInstance->Modes->FindMode(*v, MODETYPE_USER);
+ if (!mh)
+ {
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Unrecognised mode '%c' for a user in UID, dropping link", *v);
+ return CMD_INVALID;
+ }
- if (mh)
+ if (mh->GetNumParams(true))
{
- if (mh->GetNumParams(true))
- {
- if (paramptr >= params.size() - 1)
- return CMD_INVALID;
- std::string mp = params[paramptr++];
- /* IMPORTANT NOTE:
- * All modes are assumed to succeed here as they are being set by a remote server.
- * Modes CANNOT FAIL here. If they DO fail, then the failure is ignored. This is important
- * to note as all but one modules currently cannot ever fail in this situation, except for
- * m_servprotect which specifically works this way to prevent the mode being set ANYWHERE
- * but here, at client introduction. You may safely assume this behaviour is standard and
- * will not change in future versions if you want to make use of this protective behaviour
- * yourself.
- */
- mh->OnModeChange(_new, _new, NULL, mp, true);
- }
- else
- mh->OnModeChange(_new, _new, NULL, empty, true);
- _new->SetMode(*v, true);
+ if (paramptr >= params.size() - 1)
+ return CMD_INVALID;
+ std::string mp = params[paramptr++];
+ /* IMPORTANT NOTE:
+ * All modes are assumed to succeed here as they are being set by a remote server.
+ * Modes CANNOT FAIL here. If they DO fail, then the failure is ignored. This is important
+ * to note as all but one modules currently cannot ever fail in this situation, except for
+ * m_servprotect which specifically works this way to prevent the mode being set ANYWHERE
+ * but here, at client introduction. You may safely assume this behaviour is standard and
+ * will not change in future versions if you want to make use of this protective behaviour
+ * yourself.
+ */
+ mh->OnModeChange(_new, _new, NULL, mp, true);
}
+ else
+ mh->OnModeChange(_new, _new, NULL, empty, true);
+ _new->SetMode(*v, true);
}
- /* now we've done with modes processing, put the + back for remote servers */
- if (modestr[0] != '+')
- modestr = "+" + modestr;
-
_new->SetClientIP(params[6].c_str());
ServerInstance->Users->AddGlobalClone(_new);
- remoteserver->SetUserCount(1); // increment by 1
+ remoteserver->UserCount++;
bool dosend = true;
dosend = false;
if (dosend)
- ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s (%s) [%s]", _new->server.c_str(), _new->GetFullRealHost().c_str(), _new->GetIPString(), _new->fullname.c_str());
+ ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s (%s) [%s]", _new->server.c_str(), _new->GetFullRealHost().c_str(), _new->GetIPString().c_str(), _new->fullname.c_str());
FOREACH_MOD(I_OnPostConnect,OnPostConnect(_new));
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
#include "utils.h"
#include "treeserver.h"
-#include "link.h"
#include "treesocket.h"
#include "resolvers.h"
*/
TreeServer* SpanningTreeUtilities::FindServer(const std::string &ServerName)
{
- if (ServerInstance->IsSID(ServerName))
+ if (InspIRCd::IsSID(ServerName))
return this->FindServerID(ServerName);
server_hash::iterator iter = serverlist.find(ServerName.c_str());
return NULL;
}
-SpanningTreeUtilities::SpanningTreeUtilities(ModuleSpanningTree* C) : Creator(C)
+SpanningTreeUtilities::SpanningTreeUtilities(ModuleSpanningTree* C)
+ : RefreshTimer(this), Creator(C)
{
- ServerInstance->Logs->Log("m_spanningtree",DEBUG,"***** Using SID for hash: %s *****", ServerInstance->Config->GetSID().c_str());
+ ServerInstance->Timers->AddTimer(&RefreshTimer);
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEBUG, "***** Using SID for hash: %s *****", ServerInstance->Config->GetSID().c_str());
this->TreeRoot = new TreeServer(this, ServerInstance->Config->ServerName, ServerInstance->Config->ServerDesc, ServerInstance->Config->GetSID());
this->ReadConfiguration();
delete TreeRoot;
}
-void SpanningTreeUtilities::AddThisServer(TreeServer* server, TreeServerList &list)
-{
- if (list.find(server) == list.end())
- list[server] = server;
-}
-
/* returns a list of DIRECT servernames for a specific channel */
void SpanningTreeUtilities::GetListOfServersForChannel(Channel* c, TreeServerList &list, char status, const CUList &exempt_list)
{
{
TreeServer* best = this->BestRouteTo(i->first->server);
if (best)
- AddThisServer(best,list);
+ list.insert(best);
}
}
return;
}
-bool SpanningTreeUtilities::DoOneToAllButSender(const std::string &prefix, const std::string &command, const parameterlist ¶ms, const std::string& omit)
+std::string SpanningTreeUtilities::ConstructLine(const std::string& prefix, const std::string& command, const parameterlist& params)
{
- TreeServer* omitroute = this->BestRouteTo(omit);
- std::string FullLine = ":" + prefix + " " + command;
- unsigned int words = params.size();
- for (unsigned int x = 0; x < words; x++)
+ std::string FullLine;
+ FullLine.reserve(MAXBUF);
+ FullLine = ":" + prefix + " " + command;
+ for (parameterlist::const_iterator x = params.begin(); x != params.end(); ++x)
{
- FullLine = FullLine + " " + params[x];
+ FullLine.push_back(' ');
+ FullLine.append(*x);
}
+ return FullLine;
+}
+
+bool SpanningTreeUtilities::DoOneToAllButSender(const std::string& prefix, const std::string& command, const parameterlist& params, const std::string& omit)
+{
+ TreeServer* omitroute = this->BestRouteTo(omit);
+ std::string FullLine = ConstructLine(prefix, command, params);
+
unsigned int items = this->TreeRoot->ChildCount();
for (unsigned int x = 0; x < items; x++)
{
bool SpanningTreeUtilities::DoOneToMany(const std::string &prefix, const std::string &command, const parameterlist ¶ms)
{
- std::string FullLine = ":" + prefix + " " + command;
- unsigned int words = params.size();
- for (unsigned int x = 0; x < words; x++)
- {
- FullLine = FullLine + " " + params[x];
- }
+ std::string FullLine = ConstructLine(prefix, command, params);
+
unsigned int items = this->TreeRoot->ChildCount();
for (unsigned int x = 0; x < items; x++)
{
return true;
}
-bool SpanningTreeUtilities::DoOneToOne(const std::string &prefix, const std::string &command, const parameterlist ¶ms, const std::string& target)
+bool SpanningTreeUtilities::DoOneToOne(const std::string& prefix, const std::string& command, const parameterlist& params, const std::string& target)
{
TreeServer* Route = this->BestRouteTo(target);
if (Route)
{
- std::string FullLine = ":" + prefix + " " + command;
- unsigned int words = params.size();
- for (unsigned int x = 0; x < words; x++)
- {
- FullLine = FullLine + " " + params[x];
- }
if (Route && Route->GetSocket())
{
TreeSocket* Sock = Route->GetSocket();
if (Sock)
- Sock->WriteLine(FullLine);
+ Sock->WriteLine(ConstructLine(prefix, command, params));
}
return true;
}
Link* L = *i;
if (!L->Port)
{
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"m_spanningtree: Ignoring a link block without a port.");
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "m_spanningtree: Ignoring a link block without a port.");
/* Invalid link block */
continue;
}
bool ipvalid = irc::sockets::aptosa(L->IPAddr, L->Port, dummy);
if ((L->IPAddr == "*") || (ipvalid))
ValidIPs.push_back(L->IPAddr);
- else
+ else if (this->Creator->DNS)
{
+ SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, *this->Creator->DNS, L->IPAddr, L, DNS::QUERY_AAAA);
try
{
- bool cached = false;
- SecurityIPResolver* sr = new SecurityIPResolver(Creator, this, L->IPAddr, L, cached, DNS_QUERY_AAAA);
- ServerInstance->AddResolver(sr, cached);
+ this->Creator->DNS->Process(sr);
}
- catch (...)
+ catch (DNS::Exception &)
{
+ delete sr;
}
}
}
if (L->IPAddr.empty())
{
L->IPAddr = "*";
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want.");
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Configuration warning: Link block '" + assign(L->Name) + "' has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want.");
}
if (!L->Port)
- ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Configuration warning: Link block '" + assign(L->Name) + "' has no port defined, you will not be able to /connect it.");
+ ServerInstance->Logs->Log("m_spanningtree", LOG_DEFAULT, "Configuration warning: Link block '" + assign(L->Name) + "' has no port defined, you will not be able to /connect it.");
L->Fingerprint.erase(std::remove(L->Fingerprint.begin(), L->Fingerprint.end(), ':'), L->Fingerprint.end());
LinkBlocks.push_back(L);
}
return NULL;
}
+
+void SpanningTreeUtilities::SendChannelMessage(const std::string& prefix, Channel* target, const std::string &text, char status, const CUList& exempt_list, const char* message_type)
+{
+ std::string raw(":");
+ raw.append(prefix).append(1, ' ').append(message_type).push_back(' ');
+ if (status)
+ raw.push_back(status);
+ raw.append(target->name).append(" :").append(text);
+
+ TreeServerList list;
+ this->GetListOfServersForChannel(target, list, status, exempt_list);
+ for (TreeServerList::iterator i = list.begin(); i != list.end(); ++i)
+ {
+ TreeSocket* Sock = (*i)->GetSocket();
+ if (Sock)
+ Sock->WriteLine(raw);
+ }
+}
*/
-#ifndef M_SPANNINGTREE_UTILS_H
-#define M_SPANNINGTREE_UTILS_H
+#pragma once
#include "inspircd.h"
+#include "cachetimer.h"
/* Foward declarations */
class TreeServer;
/* This hash_map holds the hash equivalent of the server
* tree, used for rapid linear lookups.
*/
-#ifdef HASHMAP_DEPRECATED
- typedef nspace::hash_map<std::string, TreeServer*, nspace::insensitive, irc::StrHashComp> server_hash;
-#else
- typedef nspace::hash_map<std::string, TreeServer*, nspace::hash<std::string>, irc::StrHashComp> server_hash;
-#endif
+typedef TR1NS::unordered_map<std::string, TreeServer*, irc::insensitive, irc::StrHashComp> server_hash;
-typedef std::map<TreeServer*,TreeServer*> TreeServerList;
+typedef std::set<TreeServer*> TreeServerList;
/** Contains helper functions and variables for this module,
* and keeps them out of the global namespace
*/
class SpanningTreeUtilities : public classbase
{
+ /** Creates a line in the :<prefix> <command> [<params>] format
+ */
+ std::string ConstructLine(const std::string& prefix, const std::string& command, const parameterlist& params);
+
+ CacheRefreshTimer RefreshTimer;
+
public:
/** Creator module
*/
/** Send a message from this server to one other local or remote
*/
- bool DoOneToOne(const std::string &prefix, const std::string &command, const parameterlist ¶ms, const std::string& target);
+ bool DoOneToOne(const std::string& prefix, const std::string& command, const parameterlist& params, const std::string& target);
/** Send a message from this server to all but one other, local or remote
*/
- bool DoOneToAllButSender(const std::string &prefix, const std::string &command, const parameterlist ¶ms, const std::string& omit);
+ bool DoOneToAllButSender(const std::string &prefix, const std::string &command, const parameterlist& params, const std::string& omit);
/** Send a message from this server to all others
*/
*/
void ReadConfiguration();
- /** Add a server to the server list for GetListOfServersForChannel
- */
- void AddThisServer(TreeServer* server, TreeServerList &list);
-
/** Compile a list of servers which contain members of channel c
*/
void GetListOfServersForChannel(Channel* c, TreeServerList &list, char status, const CUList &exempt_list);
/** Refresh the IP cache used for allowing inbound connections
*/
void RefreshIPCache();
-};
-#endif
+ /** Sends a PRIVMSG or a NOTICE to a channel obeying an exempt list and an optional prefix
+ */
+ void SendChannelMessage(const std::string& prefix, Channel* target, const std::string &text, char status, const CUList& exempt_list, const char* message_type);
+};
#include "inspircd.h"
-#include "socket.h"
-#include "xline.h"
-#include "socketengine.h"
#include "main.h"
#include "utils.h"
#include "inspircd.h"
-#include "sql.h"
-#include "hash.h"
+#include "modules/sql.h"
+#include "modules/hash.h"
/* $ModDesc: Allow/Deny connections based upon an arbitrary SQL table */
: SQLQuery(me), uid(u), pendingExt(e), verbose(v)
{
}
-
- void OnResult(SQLResult& res)
+
+ void OnResult(SQLResult& res) CXX11_OVERRIDE
{
User* user = ServerInstance->FindNick(uid);
if (!user)
}
}
- void OnError(SQLerror& error)
+ void OnError(SQLerror& error) CXX11_OVERRIDE
{
User* user = ServerInstance->FindNick(uid);
if (!user)
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(pendingExt);
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* conf = ServerInstance->Config->ConfValue("sqlauth");
std::string dbid = conf->getString("dbid");
verbose = conf->getBool("verbose");
}
- ModResult OnUserRegister(LocalUser* user)
+ ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
{
// Note this is their initial (unresolved) connect block
ConfigTag* tag = user->MyClass->config;
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckReady(LocalUser* user)
+ ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
{
switch (pendingExt.get(user))
{
return MOD_RES_PASSTHRU;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allow/Deny connections based upon an arbitrary SQL table", VF_VENDOR);
}
#include "inspircd.h"
-#include "sql.h"
-#include "hash.h"
+#include "modules/sql.h"
+#include "modules/hash.h"
/* $ModDesc: Allows storage of oper credentials in an SQL table */
-static bool OneOfMatches(const char* host, const char* ip, const std::string& hostlist)
-{
- std::stringstream hl(hostlist);
- std::string xhost;
- while (hl >> xhost)
- {
- if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
- {
- return true;
- }
- }
- return false;
-}
-
class OpMeQuery : public SQLQuery
{
public:
{
}
- void OnResult(SQLResult& res)
+ void OnResult(SQLResult& res) CXX11_OVERRIDE
{
- ServerInstance->Logs->Log("m_sqloper",DEBUG, "SQLOPER: result for %s", uid.c_str());
+ ServerInstance->Logs->Log("m_sqloper", LOG_DEBUG, "SQLOPER: result for %s", uid.c_str());
User* user = ServerInstance->FindNick(uid);
if (!user)
return;
SQLEntries row;
while (res.GetRow(row))
{
-#if 0
- parameterlist cols;
- res.GetCols(cols);
-
- std::vector<KeyVal>* items;
- reference<ConfigTag> tag = ConfigTag::create("oper", "<m_sqloper>", 0, items);
- for(unsigned int i=0; i < cols.size(); i++)
- {
- if (!row[i].nul)
- items->insert(std::make_pair(cols[i], row[i]));
- }
-#else
if (OperUser(user, row[0], row[1]))
return;
-#endif
}
- ServerInstance->Logs->Log("m_sqloper",DEBUG, "SQLOPER: no matches for %s (checked %d rows)", uid.c_str(), res.Rows());
+ ServerInstance->Logs->Log("m_sqloper", LOG_DEBUG, "SQLOPER: no matches for %s (checked %d rows)", uid.c_str(), res.Rows());
// nobody succeeded... fall back to OPER
fallback();
}
- void OnError(SQLerror& error)
+ void OnError(SQLerror& error) CXX11_OVERRIDE
{
- ServerInstance->Logs->Log("m_sqloper",DEFAULT, "SQLOPER: query failed (%s)", error.Str());
+ ServerInstance->Logs->Log("m_sqloper", LOG_DEFAULT, "SQLOPER: query failed (%s)", error.Str());
fallback();
}
}
else
{
- ServerInstance->Logs->Log("m_sqloper",SPARSE, "BUG: WHAT?! Why do we have no OPER command?!");
+ ServerInstance->Logs->Log("m_sqloper", LOG_SPARSE, "BUG: WHAT?! Why do we have no OPER command?!");
}
}
OperIndex::iterator iter = ServerInstance->Config->oper_blocks.find(" " + type);
if (iter == ServerInstance->Config->oper_blocks.end())
{
- ServerInstance->Logs->Log("m_sqloper",DEFAULT, "SQLOPER: bad type '%s' in returned row for oper %s", type.c_str(), username.c_str());
+ ServerInstance->Logs->Log("m_sqloper", LOG_DEFAULT, "SQLOPER: bad type '%s' in returned row for oper %s", type.c_str(), username.c_str());
return false;
}
OperInfo* ifo = iter->second;
hostname.append("@").append(user->host);
- if (OneOfMatches(hostname.c_str(), user->GetIPString(), pattern))
+ if (InspIRCd::MatchMask(pattern, hostname, user->GetIPString()))
{
/* Opertype and host match, looks like this is it. */
public:
ModuleSQLOper() : SQL(this, "SQL") {}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
ConfigTag* tag = ServerInstance->Config->ConfValue("sqloper");
query = tag->getString("query", "SELECT hostname as host, type FROM ircd_opers WHERE username='$username' AND password='$password'");
}
- ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
if (validated && command == "OPER" && parameters.size() >= 2)
{
/* Query is in progress, it will re-invoke OPER if needed */
return MOD_RES_DENY;
}
- ServerInstance->Logs->Log("m_sqloper",DEFAULT, "SQLOPER: database not present");
+ ServerInstance->Logs->Log("m_sqloper", LOG_DEFAULT, "SQLOPER: database not present");
}
return MOD_RES_PASSTHRU;
}
SQL->submit(new OpMeQuery(this, user->uuid, username, password), query, userinfo);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Allows storage of oper credentials in an SQL table", VF_VENDOR);
}
-
};
MODULE_INIT(ModuleSQLOper)
#include "inspircd.h"
-#include "ssl.h"
+#include "modules/ssl.h"
/* $ModDesc: Provides SSL metadata, including /WHOIS information and /SSLINFO command */
return CMD_FAILURE;
}
bool operonlyfp = ServerInstance->Config->ConfValue("sslinfo")->getBool("operonly");
- if (operonlyfp && !IS_OPER(user) && target != user)
+ if (operonlyfp && !user->IsOper() && target != user)
{
- user->WriteServ("NOTICE %s :*** You cannot view SSL certificate information for other users", user->nick.c_str());
+ user->WriteNotice("*** You cannot view SSL certificate information for other users");
return CMD_FAILURE;
}
ssl_cert* cert = CertExt.get(target);
if (!cert)
{
- user->WriteServ("NOTICE %s :*** No SSL certificate for this user", user->nick.c_str());
+ user->WriteNotice("*** No SSL certificate for this user");
}
else if (cert->GetError().length())
{
- user->WriteServ("NOTICE %s :*** No SSL certificate information for this user (%s).", user->nick.c_str(), cert->GetError().c_str());
+ user->WriteNotice("*** No SSL certificate information for this user (" + cert->GetError() + ").");
}
else
{
- user->WriteServ("NOTICE %s :*** Distinguished Name: %s", user->nick.c_str(), cert->GetDN().c_str());
- user->WriteServ("NOTICE %s :*** Issuer: %s", user->nick.c_str(), cert->GetIssuer().c_str());
- user->WriteServ("NOTICE %s :*** Key Fingerprint: %s", user->nick.c_str(), cert->GetFingerprint().c_str());
+ user->WriteNotice("*** Distinguished Name: " + cert->GetDN());
+ user->WriteNotice("*** Issuer: " + cert->GetIssuer());
+ user->WriteNotice("*** Key Fingerprint: " + cert->GetFingerprint());
}
return CMD_SUCCESS;
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("SSL Certificate Utilities", VF_VENDOR);
}
- void OnWhois(User* source, User* dest)
+ void OnWhois(User* source, User* dest) CXX11_OVERRIDE
{
ssl_cert* cert = cmd.CertExt.get(dest);
if (cert)
{
ServerInstance->SendWhoisLine(source, dest, 671, "%s %s :is using a secure connection", source->nick.c_str(), dest->nick.c_str());
bool operonlyfp = ServerInstance->Config->ConfValue("sslinfo")->getBool("operonly");
- if ((!operonlyfp || source == dest || IS_OPER(source)) && !cert->fingerprint.empty())
+ if ((!operonlyfp || source == dest || source->IsOper()) && !cert->fingerprint.empty())
ServerInstance->SendWhoisLine(source, dest, 276, "%s %s :has client certificate fingerprint %s",
source->nick.c_str(), dest->nick.c_str(), cert->fingerprint.c_str());
}
}
- bool OneOfMatches(const char* host, const char* ip, const char* hostlist)
- {
- std::stringstream hl(hostlist);
- std::string xhost;
- while (hl >> xhost)
- {
- if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
- {
- return true;
- }
- }
- return false;
- }
-
- ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
if ((command == "OPER") && (validated))
{
return MOD_RES_PASSTHRU;
}
- void OnUserConnect(LocalUser* user)
+ void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
{
SocketCertificateRequest req(&user->eh, this);
if (!req.cert)
cmd.CertExt.set(user, req.cert);
}
- void OnPostConnect(User* user)
+ void OnPostConnect(User* user) CXX11_OVERRIDE
{
ssl_cert *cert = cmd.CertExt.get(user);
if (!cert || cert->fingerprint.empty())
}
}
- ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass)
+ ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass) CXX11_OVERRIDE
{
SocketCertificateRequest req(&user->eh, this);
bool ok = true;
return MOD_RES_PASSTHRU;
}
- void OnRequest(Request& request)
+ void OnRequest(Request& request) CXX11_OVERRIDE
{
if (strcmp("GET_USER_CERT", request.id) == 0)
{
};
MODULE_INIT(ModuleSSLInfo)
-
#include "inspircd.h"
-#include "ssl.h"
+#include "modules/ssl.h"
/* $ModDesc: Provides channel mode +z to allow for Secure/SSL only channels */
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(sslm);
Implementation eventlist[] = { I_OnUserPreJoin, I_OnCheckBan, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
+ ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
{
if(chan && chan->IsModeSet('z'))
{
else
{
// Deny
- user->WriteServ( "489 %s %s :Cannot join channel; SSL users only (+z)", user->nick.c_str(), cname);
+ user->WriteServ( "489 %s %s :Cannot join channel; SSL users only (+z)", user->nick.c_str(), cname.c_str());
return MOD_RES_DENY;
}
}
return MOD_RES_PASSTHRU;
}
- ModResult OnCheckBan(User *user, Channel *c, const std::string& mask)
+ ModResult OnCheckBan(User *user, Channel *c, const std::string& mask) CXX11_OVERRIDE
{
if ((mask.length() > 2) && (mask[0] == 'z') && (mask[1] == ':'))
{
return MOD_RES_PASSTHRU;
}
- ~ModuleSSLModes()
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
+ tokens["EXTBAN"].push_back('z');
}
- void On005Numeric(std::string &output)
- {
- ServerInstance->AddExtBanChar('z');
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel mode +z to allow for Secure/SSL only channels", VF_VENDOR);
}
};
-
MODULE_INIT(ModuleSSLModes)
-
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(usc);
ServerInstance->Modules->AddService(csc);
- Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_On005Numeric };
+ Implementation eventlist[] = { I_OnUserPreMessage, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ~ModuleStripColor()
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
+ tokens["EXTBAN"].push_back('S');
}
- virtual void On005Numeric(std::string &output)
- {
- ServerInstance->AddExtBanChar('S');
- }
-
- virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
+ ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return MOD_RES_PASSTHRU;
return MOD_RES_PASSTHRU;
}
- virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
- {
- return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides channel +S mode (strip ansi color)", VF_VENDOR);
}
class SVSHold : public XLine
{
public:
- irc::string nickname;
+ std::string nickname;
SVSHold(time_t s_time, long d, const std::string& src, const std::string& re, const std::string& nick)
: XLine(s_time, d, src, re, "SVSHOLD")
{
- this->nickname = nick.c_str();
- }
-
- ~SVSHold()
- {
+ this->nickname = nick;
}
bool Matches(User *u)
bool Matches(const std::string &s)
{
- if (nickname == s)
- return true;
- return false;
- }
-
- void DisplayExpiry()
- {
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired SVSHOLD %s (set by %s %ld seconds ago)",
- this->nickname.c_str(), this->source.c_str(), (long int)(ServerInstance->Time() - this->set_time));
+ return InspIRCd::Match(s, nickname);
}
- const char* Displayable()
+ const std::string& Displayable()
{
- return nickname.c_str();
+ return nickname;
}
};
}
else
{
- user->WriteServ("NOTICE %s :*** SVSHOLD %s not found in list, try /stats S.",user->nick.c_str(),parameters[0].c_str());
+ user->WriteNotice("*** SVSHOLD " + parameters[0] + " not found in list, try /stats S.");
}
}
else
if (parameters.size() < 3)
return CMD_FAILURE;
- // Adding - XXX todo make this respect <insane> tag perhaps..
- long duration = ServerInstance->Duration(parameters[1]);
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
SVSHold* r = new SVSHold(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str());
if (ServerInstance->XLines->AddLine(r, user))
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->XLines->RegisterFactory(&s);
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual ModResult OnStats(char symbol, User* user, string_list &out)
+ ModResult OnStats(char symbol, User* user, string_list &out) CXX11_OVERRIDE
{
if(symbol != 'S')
return MOD_RES_PASSTHRU;
return MOD_RES_DENY;
}
- virtual ModResult OnUserPreNick(User *user, const std::string &newnick)
+ ModResult OnUserPreNick(User *user, const std::string &newnick) CXX11_OVERRIDE
{
XLine *rl = ServerInstance->XLines->MatchesLine("SVSHOLD", newnick);
return MOD_RES_PASSTHRU;
}
- virtual ~ModuleSVSHold()
+ ~ModuleSVSHold()
{
ServerInstance->XLines->DelAll("SVSHOLD");
ServerInstance->XLines->UnregisterFactory(&s);
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements SVSHOLD. Like Q:Lines, but can only be added/removed by Services.", VF_COMMON | VF_VENDOR);
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->AddService(cmd.swhois);
}
// :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games.
- ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text)
+ ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text) CXX11_OVERRIDE
{
/* We use this and not OnWhois because this triggers for remote, too */
if (numeric == 312)
return MOD_RES_PASSTHRU;
}
- void OnPostOper(User* user, const std::string &opertype, const std::string &opername)
+ void OnPostOper(User* user, const std::string &opertype, const std::string &opername) CXX11_OVERRIDE
{
if (!IS_LOCAL(user))
return;
ServerInstance->PI->SendMetaData(user, "swhois", swhois);
}
- ~ModuleSWhois()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the SWHOIS command which allows setting of arbitrary WHOIS lines", VF_OPTCOMMON | VF_VENDOR);
}
CHK(OnUserPreInvite);
CHK(OnUserInvite);
CHK(OnUserPreMessage);
- CHK(OnUserPreNotice);
CHK(OnUserPreNick);
CHK(OnUserMessage);
- CHK(OnUserNotice);
CHK(OnMode);
CHK(OnGetServerDescription);
CHK(OnSyncUser);
CHK(OnSyncChannel);
CHK(OnDecodeMetaData);
- CHK(OnWallops);
CHK(OnAcceptConnection);
CHK(OnChangeHost);
CHK(OnChangeName);
CHK(OnEvent);
CHK(OnGlobalOper);
CHK(OnPostConnect);
- CHK(OnAddBan);
- CHK(OnDelBan);
CHK(OnChangeLocalUserGECOS);
CHK(OnUserRegister);
CHK(OnChannelPreDelete);
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
if (!strstr(ServerInstance->Config->ServerName.c_str(), ".test"))
throw ModuleException("Don't load modules without reading their descriptions!");
ServerInstance->Modules->AddService(cmd);
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides a module for testing the server while linked in a network", VF_VENDOR|VF_OPTCOMMON);
}
};
MODULE_INIT(ModuleTest)
-
user->WriteNumeric(482, "%s %s :You do not have permission to set bans on this channel",
user->nick.c_str(), channel->name.c_str());
return CMD_FAILURE;
- }
+ }
TimedBan T;
std::string channelname = parameters[0];
- long duration = ServerInstance->Duration(parameters[1]);
+ unsigned long duration = InspIRCd::Duration(parameters[1]);
unsigned long expire = duration + ServerInstance->Time();
if (duration < 1)
{
- user->WriteServ("NOTICE "+user->nick+" :Invalid ban time");
+ user->WriteNotice("Invalid ban time");
return CMD_FAILURE;
}
std::string mask = parameters[2];
bool isextban = ((mask.size() > 2) && (mask[1] == ':'));
if (!isextban && !ServerInstance->IsValidMask(mask))
mask.append("!*@*");
- if ((mask.length() > 250) || (!ServerInstance->IsValidMask(mask) && !isextban))
- {
- user->WriteServ("NOTICE "+user->nick+" :Invalid ban mask");
- return CMD_FAILURE;
- }
+
setban.push_back(mask);
// use CallHandler to make it so that the user sets the mode
// themselves
ServerInstance->Parser->CallHandler("MODE",setban,user);
- for (BanList::iterator i = channel->bans.begin(); i != channel->bans.end(); i++)
- if (!strcasecmp(i->data.c_str(), mask.c_str()))
- goto found;
- return CMD_FAILURE;
-found:
+ if (ServerInstance->Modes->GetLastParse().empty())
+ {
+ user->WriteNotice("Invalid ban mask");
+ return CMD_FAILURE;
+ }
+
CUList tmp;
T.channel = channelname;
T.mask = mask;
}
};
-class ModuleTimedBans : public Module
+class BanWatcher : public ModeWatcher
{
- CommandTban cmd;
public:
- ModuleTimedBans()
- : cmd(this)
+ BanWatcher(Module* parent)
+ : ModeWatcher(parent, "ban", MODETYPE_CHANNEL)
{
}
- void init()
+ void AfterMode(User* source, User* dest, Channel* chan, const std::string& banmask, bool adding)
{
- ServerInstance->Modules->AddService(cmd);
- Implementation eventlist[] = { I_OnDelBan, I_OnBackgroundTimer };
- ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
- }
+ if (adding)
+ return;
- virtual ModResult OnDelBan(User* source, Channel* chan, const std::string &banmask)
- {
irc::string listitem = banmask.c_str();
irc::string thischan = chan->name.c_str();
- for (timedbans::iterator i = TimedBanList.begin(); i != TimedBanList.end(); i++)
+ for (timedbans::iterator i = TimedBanList.begin(); i != TimedBanList.end(); ++i)
{
irc::string target = i->mask.c_str();
irc::string tchan = i->channel.c_str();
break;
}
}
- return MOD_RES_PASSTHRU;
}
+};
- virtual void OnBackgroundTimer(time_t curtime)
+class ModuleTimedBans : public Module
+{
+ CommandTban cmd;
+ BanWatcher banwatcher;
+
+ public:
+ ModuleTimedBans()
+ : cmd(this)
+ , banwatcher(this)
+ {
+ }
+
+ void init() CXX11_OVERRIDE
+ {
+ ServerInstance->Modules->AddService(cmd);
+ Implementation eventlist[] = { I_OnBackgroundTimer };
+ ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
+ ServerInstance->Modes->AddModeWatcher(&banwatcher);
+ }
+
+ ~ModuleTimedBans()
+ {
+ ServerInstance->Modes->DelModeWatcher(&banwatcher);
+ }
+
+ void OnBackgroundTimer(time_t curtime) CXX11_OVERRIDE
{
timedbans expired;
for (timedbans::iterator i = TimedBanList.begin(); i != TimedBanList.end();)
}
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Adds timed bans", VF_COMMON | VF_VENDOR);
}
};
MODULE_INIT(ModuleTimedBans)
-
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleTLine()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides /tline command used to test who a mask matches", VF_VENDOR);
}
};
MODULE_INIT(ModuleTLine)
-
time_t topicts = ConvToInt(parameters[1]);
if (!topicts)
{
- ServerInstance->Logs->Log("m_topiclock", DEFAULT, "Received SVSTOPIC with a 0 topicts, dropped.");
+ ServerInstance->Logs->Log("m_topiclock", LOG_DEFAULT, "Received SVSTOPIC with a 0 topicts, dropped.");
return CMD_INVALID;
}
{
}
- virtual ~FlagExtItem()
+ ~FlagExtItem()
{
}
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
ServerInstance->Modules->AddService(topiclock);
ServerInstance->Modules->Attach(I_OnPreTopicChange, this);
}
- ModResult OnPreTopicChange(User* user, Channel* chan, const std::string &topic)
+ ModResult OnPreTopicChange(User* user, Channel* chan, const std::string &topic) CXX11_OVERRIDE
{
// Only fired for local users currently, but added a check anyway
if ((IS_LOCAL(user)) && (topiclock.get(chan)))
return MOD_RES_PASSTHRU;
}
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Implements server-side topic locks and the server-to-server command SVSTOPIC", VF_COMMON | VF_VENDOR);
}
#include "inspircd.h"
-#include "m_cap.h"
+#include "modules/cap.h"
/* $ModDesc: Provides the UHNAMES facility. */
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
Implementation eventlist[] = { I_OnEvent, I_OnPreCommand, I_OnNamesListItem, I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- ~ModuleUHNames()
- {
- }
-
- Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the UHNAMES facility.",VF_VENDOR);
}
- void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output.append(" UHNAMES");
+ tokens["UHNAMES"];
}
- ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
+ ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE
{
/* We don't actually create a proper command handler class for PROTOCTL,
* because other modules might want to have PROTOCTL hooks too.
return MOD_RES_PASSTHRU;
}
- void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick)
+ void OnNamesListItem(User* issuer, Membership* memb, std::string &prefixes, std::string &nick) CXX11_OVERRIDE
{
if (!cap.ext.get(issuer))
return;
nick = memb->user->GetFullHost();
}
- void OnEvent(Event& ev)
+ void OnEvent(Event& ev) CXX11_OVERRIDE
{
cap.HandleEvent(ev);
}
LocalUser* lu = IS_LOCAL(u);
if (lu)
{
- irc::string xname(c->name.c_str());
- if (!lu->IsInvited(xname))
+ if (!lu->RemoveInvite(c))
{
user->SendText(":%s 505 %s %s %s :Is not invited to channel %s", user->server.c_str(), user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
return CMD_FAILURE;
}
user->SendText(":%s 494 %s %s %s :Uninvited", user->server.c_str(), user->nick.c_str(), c->name.c_str(), u->nick.c_str());
- lu->RemoveInvite(xname);
lu->WriteNumeric(493, "%s :You were uninvited from %s by %s", u->nick.c_str(), c->name.c_str(), user->nick.c_str());
std::string msg = "*** " + user->nick + " uninvited " + u->nick + ".";
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleUninvite()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides the UNINVITE command which lets users un-invite other users from channels", VF_VENDOR | VF_OPTCOMMON);
}
};
MODULE_INIT(ModuleUninvite)
-
continue;
}
- retbuf = retbuf + u->nick + (IS_OPER(u) ? "*" : "") + "=";
- if (IS_AWAY(u))
+ retbuf = retbuf + u->nick + (u->IsOper() ? "*" : "") + "=";
+ if (u->IsAway())
retbuf += "-";
else
retbuf += "+";
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
Implementation eventlist[] = { I_On005Numeric };
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- output = output + " USERIP";
+ tokens["USERIP"];
}
- virtual ~ModuleUserIP()
- {
- }
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for USERIP command",VF_VENDOR);
}
-
};
MODULE_INIT(ModuleUserIP)
-
{
if (!mask.empty())
{
- user->WriteServ("NOTICE "+user->nick+" :Setting your VHost: " + mask);
+ user->WriteNotice("Setting your VHost: " + mask);
user->ChangeDisplayedHost(mask.c_str());
return CMD_SUCCESS;
}
}
}
- user->WriteServ("NOTICE "+user->nick+" :Invalid username or password.");
+ user->WriteNotice("Invalid username or password.");
return CMD_FAILURE;
}
};
class ModuleVHost : public Module
{
- private:
CommandVhost cmd;
public:
{
}
- void init()
+ void init() CXX11_OVERRIDE
{
ServerInstance->Modules->AddService(cmd);
}
- virtual ~ModuleVHost()
- {
- }
-
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides masking of user hostnames via traditional /VHOST command",VF_VENDOR);
}
-
};
MODULE_INIT(ModuleVHost)
-
* of users using WATCH.
*/
-/*
- * Before you start screaming, this definition is only used here, so moving it to a header is pointless.
- * Yes, it's horrid. Blame cl for being different. -- w00t
- */
-
-typedef nspace::hash_map<irc::string, std::deque<User*>, irc::hash> watchentries;
+typedef TR1NS::unordered_map<irc::string, std::deque<User*>, irc::hash> watchentries;
typedef std::map<irc::string, std::string> watchlist;
/* Who's watching each nickname.
CmdResult remove_watch(User* user, const char* nick)
{
// removing an item from the list
- if (!ServerInstance->IsNick(nick, ServerInstance->Config->Limits.NickMax))
+ if (!ServerInstance->IsNick(nick))
{
user->WriteNumeric(942, "%s %s :Invalid nickname", user->nick.c_str(), nick);
return CMD_FAILURE;
CmdResult add_watch(User* user, const char* nick)
{
- if (!ServerInstance->IsNick(nick, ServerInstance->Config->Limits.NickMax))
+ if (!ServerInstance->IsNick(nick))
{
user->WriteNumeric(942, "%s %s :Invalid nickname",user->nick.c_str(),nick);
return CMD_FAILURE;
{
(*wl)[nick] = std::string(target->ident).append(" ").append(target->dhost).append(" ").append(ConvToStr(target->age));
user->WriteNumeric(604, "%s %s %s :is online",user->nick.c_str(), nick, (*wl)[nick].c_str());
- if (IS_AWAY(target))
+ if (target->IsAway())
{
user->WriteNumeric(609, "%s %s %s %s %lu :is away", user->nick.c_str(), target->nick.c_str(), target->ident.c_str(), target->dhost.c_str(), (unsigned long) target->awaytime);
}
{
user->WriteNumeric(604, "%s %s %s :is online", user->nick.c_str(), q->first.c_str(), q->second.c_str());
User *targ = ServerInstance->FindNick(q->first.c_str());
- if (IS_AWAY(targ))
+ if (targ->IsAway())
{
user->WriteNumeric(609, "%s %s %s %s %lu :is away", user->nick.c_str(), targ->nick.c_str(), targ->ident.c_str(), targ->dhost.c_str(), (unsigned long) targ->awaytime);
}
whos_watching_me = new watchentries();
}
- void init()
+ void init() CXX11_OVERRIDE
{
OnRehash(NULL);
ServerInstance->Modules->AddService(cmdw);
ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user) CXX11_OVERRIDE
{
maxwatch = ServerInstance->Config->ConfValue("watch")->getInt("maxentries", 32);
if (!maxwatch)
maxwatch = 32;
}
- virtual ModResult OnSetAway(User *user, const std::string &awaymsg)
+ ModResult OnSetAway(User *user, const std::string &awaymsg) CXX11_OVERRIDE
{
std::string numeric;
int inum;
return MOD_RES_PASSTHRU;
}
- virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
+ void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message) CXX11_OVERRIDE
{
watchentries::iterator x = whos_watching_me->find(user->nick.c_str());
if (x != whos_watching_me->end())
}
}
- virtual void OnGarbageCollect()
+ void OnGarbageCollect()
{
watchentries* old_watch = whos_watching_me;
whos_watching_me = new watchentries();
delete old_watch;
}
- virtual void OnPostConnect(User* user)
+ void OnPostConnect(User* user) CXX11_OVERRIDE
{
watchentries::iterator x = whos_watching_me->find(user->nick.c_str());
if (x != whos_watching_me->end())
}
}
- virtual void OnUserPostNick(User* user, const std::string &oldnick)
+ void OnUserPostNick(User* user, const std::string &oldnick) CXX11_OVERRIDE
{
watchentries::iterator new_offline = whos_watching_me->find(oldnick.c_str());
watchentries::iterator new_online = whos_watching_me->find(user->nick.c_str());
}
}
- virtual void On005Numeric(std::string &output)
+ void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
{
- // we don't really have a limit...
- output = output + " WATCH=" + ConvToStr(maxwatch);
+ tokens["WATCH"] = ConvToStr(maxwatch);
}
- virtual ~Modulewatch()
+ ~Modulewatch()
{
delete whos_watching_me;
}
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Provides support for the /WATCH command", VF_OPTCOMMON | VF_VENDOR);
}
};
MODULE_INIT(Modulewatch)
-
bool dirty;
std::string xlinedbpath;
public:
- void init()
+ void init() CXX11_OVERRIDE
{
/* Load the configuration
* Note:
dirty = false;
}
- virtual ~ModuleXLineDB()
- {
- }
-
/** Called whenever an xline is added by a local user.
* This method is triggered after the line is added.
* @param source The sender of the line or NULL for local server
* @param line The xline being added
*/
- void OnAddLine(User* source, XLine* line)
+ void OnAddLine(User* source, XLine* line) CXX11_OVERRIDE
{
dirty = true;
}
* @param source The user removing the line or NULL for local server
* @param line the line being deleted
*/
- void OnDelLine(User* source, XLine* line)
+ void OnDelLine(User* source, XLine* line) CXX11_OVERRIDE
{
dirty = true;
}
- void OnExpireLine(XLine *line)
+ void OnExpireLine(XLine *line) CXX11_OVERRIDE
{
dirty = true;
}
- void OnBackgroundTimer(time_t now)
+ void OnBackgroundTimer(time_t now) CXX11_OVERRIDE
{
if (dirty)
{
* Technically, that means that this can block, but I have *never* seen that.
* -- w00t
*/
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Opening temporary database");
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Opening temporary database");
std::string xlinenewdbpath = xlinedbpath + ".new";
f = fopen(xlinenewdbpath.c_str(), "w");
if (!f)
{
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Cannot create database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Cannot create database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot create new db: %s (%d)", strerror(errno), errno);
return false;
}
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Opened. Writing..");
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Opened. Writing..");
/*
* Now, much as I hate writing semi-unportable formats, additional
for (LookupIter i = lookup->begin(); i != lookup->end(); ++i)
{
XLine* line = i->second;
- fprintf(f, "LINE %s %s %s %lu %lu :%s\n", line->type.c_str(), line->Displayable(),
- ServerInstance->Config->ServerName.c_str(), (unsigned long)line->set_time, (unsigned long)line->duration, line->reason.c_str());
+ fprintf(f, "LINE %s %s %s %lu %lu :%s\n",
+ line->type.c_str(),
+ line->Displayable().c_str(),
+ ServerInstance->Config->ServerName.c_str(),
+ (unsigned long)line->set_time,
+ (unsigned long)line->duration, line->reason.c_str());
}
}
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Finished writing XLines. Checking for error..");
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Finished writing XLines. Checking for error..");
int write_error = 0;
write_error = ferror(f);
write_error |= fclose(f);
if (write_error)
{
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Cannot write to new database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Cannot write to new database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot write to new db: %s (%d)", strerror(errno), errno);
return false;
}
#ifdef _WIN32
if (remove(xlinedbpath.c_str()))
{
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Cannot remove old database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Cannot remove old database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot remove old database: %s (%d)", strerror(errno), errno);
return false;
}
// Use rename to move temporary to new db - this is guarenteed not to fuck up, even in case of a crash.
if (rename(xlinenewdbpath.c_str(), xlinedbpath.c_str()) < 0)
{
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Cannot move new to old database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Cannot move new to old database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot replace old with new db: %s (%d)", strerror(errno), errno);
return false;
}
else
{
/* this might be slightly more problematic. */
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Cannot read database! %s (%d)", strerror(errno), errno);
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Cannot read database! %s (%d)", strerror(errno), errno);
ServerInstance->SNO->WriteToSnoMask('a', "database: cannot read db: %s (%d)", strerror(errno), errno);
return false;
}
items++;
}
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Processing %s", linebuf);
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Processing %s", linebuf);
if (command_p[0] == "VERSION")
{
if (command_p[1] == "1")
{
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Reading db version %s", command_p[1].c_str());
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: Reading db version %s", command_p[1].c_str());
}
else
{
fclose(f);
- ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: I got database version %s - I don't understand it", command_p[1].c_str());
+ ServerInstance->Logs->Log("m_xline_db", LOG_DEBUG, "xlinedb: I got database version %s - I don't understand it", command_p[1].c_str());
ServerInstance->SNO->WriteToSnoMask('a', "database: I got a database version (%s) I don't understand", command_p[1].c_str());
return false;
}
return true;
}
-
-
- virtual Version GetVersion()
+ Version GetVersion() CXX11_OVERRIDE
{
return Version("Keeps a dynamic log of all XLines created, and stores them in a separate conf file (xline.db).", VF_VENDOR);
}
};
MODULE_INIT(ModuleXLineDB)
-
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 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
- * 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/>.
- */
-
-
-#ifndef SASL_H
-#define SASL_H
-
-class SASLFallback : public Event
-{
- public:
- const parameterlist& params;
- SASLFallback(Module* me, const parameterlist& p)
- : Event(me, "sasl_fallback"), params(p)
- {
- Send();
- }
-};
-
-#endif
+++ /dev/null
-/*
- * 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
- * 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/>.
- */
-
-
-#ifndef SPANNINGTREE_H
-#define SPANNINGTREE_H
-
-struct AddServerEvent : public Event
-{
- const std::string servername;
- AddServerEvent(Module* me, const std::string& name)
- : Event(me, "new_server"), servername(name)
- {
- Send();
- }
-};
-
-struct DelServerEvent : public Event
-{
- const std::string servername;
- DelServerEvent(Module* me, const std::string& name)
- : Event(me, "lost_server"), servername(name)
- {
- Send();
- }
-};
-
-#endif
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 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
- * 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/>.
- */
-
-
-#ifndef INSPIRCD_SQLAPI_3
-#define INSPIRCD_SQLAPI_3
-
-/** Defines the error types which SQLerror may be set to
- */
-enum SQLerrorNum { SQL_NO_ERROR, SQL_BAD_DBID, SQL_BAD_CONN, SQL_QSEND_FAIL, SQL_QREPLY_FAIL };
-
-/** A list of format parameters for an SQLquery object.
- */
-typedef std::vector<std::string> ParamL;
-
-typedef std::map<std::string, std::string> ParamM;
-
-class SQLEntry
-{
- public:
- std::string value;
- bool nul;
- SQLEntry() : nul(true) {}
- SQLEntry(const std::string& v) : value(v), nul(false) {}
- inline operator std::string&() { return value; }
-};
-
-typedef std::vector<SQLEntry> SQLEntries;
-
-/**
- * Result of an SQL query. Only valid inside OnResult
- */
-class SQLResult : public classbase
-{
- public:
- /**
- * Return the number of rows in the result.
- *
- * Note that if you have perfomed an INSERT or UPDATE query or other
- * query which will not return rows, this will return the number of
- * affected rows. In this case you SHOULD NEVER access any of the result
- * set rows, as there aren't any!
- * @returns Number of rows in the result set.
- */
- virtual int Rows() = 0;
-
- /**
- * Return a single row (result of the query). The internal row counter
- * is incremented by one.
- *
- * @param result Storage for the result data.
- * @returns true if there was a row, false if no row exists (end of
- * iteration)
- */
- virtual bool GetRow(SQLEntries& result) = 0;
-
- /** Returns column names for the items in this row
- */
- virtual void GetCols(std::vector<std::string>& result) = 0;
-};
-
-/** SQLerror holds the error state of a request.
- * The error string varies from database software to database software
- * and should be used to display informational error messages to users.
- */
-class SQLerror
-{
- public:
- /** The error id
- */
- SQLerrorNum id;
-
- /** The error string
- */
- std::string str;
-
- /** Initialize an SQLerror
- * @param i The error ID to set
- * @param s The (optional) error string to set
- */
- SQLerror(SQLerrorNum i, const std::string &s = "")
- : id(i), str(s)
- {
- }
-
- /** Return the error string for an error
- */
- const char* Str()
- {
- if(str.length())
- return str.c_str();
-
- switch(id)
- {
- case SQL_BAD_DBID:
- return "Invalid database ID";
- case SQL_BAD_CONN:
- return "Invalid connection";
- case SQL_QSEND_FAIL:
- return "Sending query failed";
- case SQL_QREPLY_FAIL:
- return "Getting query result failed";
- default:
- return "Unknown error";
- }
- }
-};
-
-/**
- * Object representing an SQL query. This should be allocated on the heap and
- * passed to an SQLProvider, which will free it when the query is complete or
- * when the querying module is unloaded.
- *
- * You should store whatever information is needed to have the callbacks work in
- * this object (UID of user, channel name, etc).
- */
-class SQLQuery : public classbase
-{
- public:
- ModuleRef creator;
-
- SQLQuery(Module* Creator) : creator(Creator) {}
- virtual ~SQLQuery() {}
-
- virtual void OnResult(SQLResult& result) = 0;
- /**
- * Called when the query fails
- */
- virtual void OnError(SQLerror& error) { }
-};
-
-/**
- * Provider object for SQL servers
- */
-class SQLProvider : public DataProvider
-{
- public:
- SQLProvider(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) {}
- /** Submit an asynchronous SQL request
- * @param callback The result reporting point
- * @param query The hardcoded query string. If you have parameters to substitute, see below.
- */
- virtual void submit(SQLQuery* callback, const std::string& query) = 0;
-
- /** Submit an asynchronous SQL request
- * @param callback The result reporting point
- * @param format The simple parameterized query string ('?' parameters)
- * @param p Parameters to fill in for the '?' entries
- */
- virtual void submit(SQLQuery* callback, const std::string& format, const ParamL& p) = 0;
-
- /** Submit an asynchronous SQL request.
- * @param callback The result reporting point
- * @param format The parameterized query string ('$name' parameters)
- * @param p Parameters to fill in for the '$name' entries
- */
- virtual void submit(SQLQuery* callback, const std::string& format, const ParamM& p) = 0;
-
- /** Convenience function to prepare a map from a User* */
- void PopulateUserInfo(User* user, ParamM& userinfo)
- {
- userinfo["nick"] = user->nick;
- userinfo["host"] = user->host;
- userinfo["ip"] = user->GetIPString();
- userinfo["gecos"] = user->fullname;
- userinfo["ident"] = user->ident;
- userinfo["server"] = user->server;
- userinfo["uuid"] = user->uuid;
- }
-};
-
-#endif
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2006 Craig Edwards <craigedwards@brainbox.cc>
- *
- * 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/>.
- */
-
-
-#ifndef SSL_H
-#define SSL_H
-
-#include <map>
-#include <string>
-
-/** ssl_cert is a class which abstracts SSL certificate
- * and key information.
- *
- * Because gnutls and openssl represent key information in
- * wildly different ways, this class allows it to be accessed
- * in a unified manner. These classes are attached to ssl-
- * connected local users using SSLCertExt
- */
-class ssl_cert : public refcountbase
-{
- public:
- std::string dn;
- std::string issuer;
- std::string error;
- std::string fingerprint;
- bool trusted, invalid, unknownsigner, revoked;
-
- ssl_cert() : trusted(false), invalid(true), unknownsigner(true), revoked(false) {}
-
- /** Get certificate distinguished name
- * @return Certificate DN
- */
- const std::string& GetDN()
- {
- return dn;
- }
-
- /** Get Certificate issuer
- * @return Certificate issuer
- */
- const std::string& GetIssuer()
- {
- return issuer;
- }
-
- /** Get error string if an error has occured
- * @return The error associated with this users certificate,
- * or an empty string if there is no error.
- */
- const std::string& GetError()
- {
- return error;
- }
-
- /** Get key fingerprint.
- * @return The key fingerprint as a hex string.
- */
- const std::string& GetFingerprint()
- {
- return fingerprint;
- }
-
- /** Get trust status
- * @return True if this is a trusted certificate
- * (the certificate chain validates)
- */
- bool IsTrusted()
- {
- return trusted;
- }
-
- /** Get validity status
- * @return True if the certificate itself is
- * correctly formed.
- */
- bool IsInvalid()
- {
- return invalid;
- }
-
- /** Get signer status
- * @return True if the certificate appears to be
- * self-signed.
- */
- bool IsUnknownSigner()
- {
- return unknownsigner;
- }
-
- /** Get revokation status.
- * @return True if the certificate is revoked.
- * Note that this only works properly for GnuTLS
- * right now.
- */
- bool IsRevoked()
- {
- return revoked;
- }
-
- bool IsCAVerified()
- {
- return trusted && !invalid && !revoked && !unknownsigner && error.empty();
- }
-
- std::string GetMetaLine()
- {
- std::stringstream value;
- bool hasError = !error.empty();
- value << (IsInvalid() ? "v" : "V") << (IsTrusted() ? "T" : "t") << (IsRevoked() ? "R" : "r")
- << (IsUnknownSigner() ? "s" : "S") << (hasError ? "E" : "e") << " ";
- if (hasError)
- value << GetError();
- else
- value << GetFingerprint() << " " << GetDN() << " " << GetIssuer();
- return value.str();
- }
-};
-
-/** Get certificate from a socket (only useful with an SSL module) */
-struct SocketCertificateRequest : public Request
-{
- StreamSocket* const sock;
- ssl_cert* cert;
-
- SocketCertificateRequest(StreamSocket* ss, Module* Me)
- : Request(Me, ss->GetIOHook(), "GET_SSL_CERT"), sock(ss), cert(NULL)
- {
- Send();
- }
-
- std::string GetFingerprint()
- {
- if (cert)
- return cert->GetFingerprint();
- return "";
- }
-};
-
-/** Get certificate from a user (requires m_sslinfo) */
-struct UserCertificateRequest : public Request
-{
- User* const user;
- ssl_cert* cert;
-
- UserCertificateRequest(User* u, Module* Me, Module* info = ServerInstance->Modules->Find("m_sslinfo.so"))
- : Request(Me, info, "GET_USER_CERT"), user(u), cert(NULL)
- {
- Send();
- }
-
- std::string GetFingerprint()
- {
- if (cert)
- return cert->GetFingerprint();
- return "";
- }
-};
-
-#endif
+++ /dev/null
-/*
- * 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
- * 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/>.
- */
-
-
-#ifndef INSPIRCD_LISTMODE_PROVIDER
-#define INSPIRCD_LISTMODE_PROVIDER
-
-/** Get the time as a string
- */
-inline std::string stringtime()
-{
- std::ostringstream TIME;
- TIME << ServerInstance->Time();
- return TIME.str();
-}
-
-/** An item in a listmode's list
- */
-class ListItem
-{
-public:
- std::string nick;
- std::string mask;
- std::string time;
-};
-
-/** The number of items a listmode's list may contain
- */
-class ListLimit
-{
-public:
- std::string mask;
- unsigned int limit;
-};
-
-/** Items stored in the channel's list
- */
-typedef std::list<ListItem> modelist;
-/** Max items per channel by name
- */
-typedef std::list<ListLimit> limitlist;
-
-/** The base class for list modes, should be inherited.
- */
-class ListModeBase : public ModeHandler
-{
- protected:
- /** Numeric to use when outputting the list
- */
- unsigned int listnumeric;
- /** Numeric to indicate end of list
- */
- unsigned int endoflistnumeric;
- /** String to send for end of list
- */
- std::string endofliststring;
- /** Automatically tidy up entries
- */
- bool tidy;
- /** Config tag to check for max items per channel
- */
- std::string configtag;
- /** Limits on a per-channel basis read from the tag
- * specified in ListModeBase::configtag
- */
- limitlist chanlimits;
-
- public:
- /** Storage key
- */
- SimpleExtItem<modelist> extItem;
-
- /** Constructor.
- * @param Instance The creator of this class
- * @param modechar Mode character
- * @param eolstr End of list string
- * @pram lnum List numeric
- * @param eolnum End of list numeric
- * @param autotidy Automatically tidy list entries on add
- * @param ctag Configuration tag to get limits from
- */
- ListModeBase(Module* Creator, const std::string& Name, char modechar, const std::string &eolstr, unsigned int lnum, unsigned int eolnum, bool autotidy, const std::string &ctag = "banlist")
- : ModeHandler(Creator, Name, modechar, PARAM_ALWAYS, MODETYPE_CHANNEL),
- listnumeric(lnum), endoflistnumeric(eolnum), endofliststring(eolstr), tidy(autotidy),
- configtag(ctag), extItem("listbase_mode_" + name + "_list", Creator)
- {
- list = true;
- }
-
- /** See mode.h
- */
- std::pair<bool,std::string> ModeSet(User*, User*, Channel* channel, const std::string ¶meter)
- {
- modelist* el = extItem.get(channel);
- if (el)
- {
- for (modelist::iterator it = el->begin(); it != el->end(); it++)
- {
- if(parameter == it->mask)
- {
- return std::make_pair(true, parameter);
- }
- }
- }
- return std::make_pair(false, parameter);
- }
-
- /** Display the list for this mode
- * @param user The user to send the list to
- * @param channel The channel the user is requesting the list for
- */
- virtual void DisplayList(User* user, Channel* channel)
- {
- modelist* el = extItem.get(channel);
- if (el)
- {
- for (modelist::reverse_iterator it = el->rbegin(); it != el->rend(); ++it)
- {
- user->WriteNumeric(listnumeric, "%s %s %s %s %s", user->nick.c_str(), channel->name.c_str(), it->mask.c_str(), (it->nick.length() ? it->nick.c_str() : ServerInstance->Config->ServerName.c_str()), it->time.c_str());
- }
- }
- user->WriteNumeric(endoflistnumeric, "%s %s :%s", user->nick.c_str(), channel->name.c_str(), endofliststring.c_str());
- }
-
- virtual void DisplayEmptyList(User* user, Channel* channel)
- {
- user->WriteNumeric(endoflistnumeric, "%s %s :%s", user->nick.c_str(), channel->name.c_str(), endofliststring.c_str());
- }
-
- /** Remove all instances of the mode from a channel.
- * See mode.h
- * @param channel The channel to remove all instances of the mode from
- */
- virtual void RemoveMode(Channel* channel, irc::modestacker* stack)
- {
- modelist* el = extItem.get(channel);
- if (el)
- {
- irc::modestacker modestack(false);
-
- for (modelist::iterator it = el->begin(); it != el->end(); it++)
- {
- if (stack)
- stack->Push(this->GetModeChar(), it->mask);
- else
- modestack.Push(this->GetModeChar(), it->mask);
- }
-
- if (stack)
- return;
-
- std::vector<std::string> stackresult;
- stackresult.push_back(channel->name);
- while (modestack.GetStackedLine(stackresult))
- {
- ServerInstance->SendMode(stackresult, ServerInstance->FakeClient);
- stackresult.clear();
- stackresult.push_back(channel->name);
- }
- }
- }
-
- /** See mode.h
- */
- virtual void RemoveMode(User*, irc::modestacker* stack)
- {
- /* Listmodes dont get set on users */
- }
-
- /** Perform a rehash of this mode's configuration data
- */
- virtual void DoRehash()
- {
- ConfigTagList tags = ServerInstance->Config->ConfTags(configtag);
-
- chanlimits.clear();
-
- for (ConfigIter i = tags.first; i != tags.second; i++)
- {
- // For each <banlist> tag
- ConfigTag* c = i->second;
- ListLimit limit;
- limit.mask = c->getString("chan");
- limit.limit = c->getInt("limit");
-
- if (limit.mask.size() && limit.limit > 0)
- chanlimits.push_back(limit);
- }
- if (chanlimits.empty())
- {
- ListLimit limit;
- limit.mask = "*";
- limit.limit = 64;
- chanlimits.push_back(limit);
- }
- }
-
- /** Populate the Implements list with the correct events for a List Mode
- */
- virtual void DoImplements(Module* m)
- {
- ServerInstance->Modules->AddService(extItem);
- this->DoRehash();
- Implementation eventlist[] = { I_OnSyncChannel, I_OnRehash };
- ServerInstance->Modules->Attach(eventlist, m, sizeof(eventlist)/sizeof(Implementation));
- }
-
- /** Handle the list mode.
- * See mode.h
- */
- virtual ModeAction OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding)
- {
- // Try and grab the list
- modelist* el = extItem.get(channel);
-
- if (adding)
- {
- if (tidy)
- ModeParser::CleanMask(parameter);
-
- if (parameter.length() > 250)
- return MODEACTION_DENY;
-
- // If there was no list
- if (!el)
- {
- // Make one
- el = new modelist;
- extItem.set(channel, el);
- }
-
- // Check if the item already exists in the list
- for (modelist::iterator it = el->begin(); it != el->end(); it++)
- {
- if (parameter == it->mask)
- {
- /* Give a subclass a chance to error about this */
- TellAlreadyOnList(source, channel, parameter);
-
- // it does, deny the change
- return MODEACTION_DENY;
- }
- }
-
- unsigned int maxsize = 0;
-
- for (limitlist::iterator it = chanlimits.begin(); it != chanlimits.end(); it++)
- {
- if (InspIRCd::Match(channel->name, it->mask))
- {
- // We have a pattern matching the channel...
- maxsize = el->size();
- if (!IS_LOCAL(source) || (maxsize < it->limit))
- {
- /* Ok, it *could* be allowed, now give someone subclassing us
- * a chance to validate the parameter.
- * The param is passed by reference, so they can both modify it
- * and tell us if we allow it or not.
- *
- * eg, the subclass could:
- * 1) allow
- * 2) 'fix' parameter and then allow
- * 3) deny
- */
- if (ValidateParam(source, channel, parameter))
- {
- // And now add the mask onto the list...
- ListItem e;
- e.mask = parameter;
- e.nick = source->nick;
- e.time = stringtime();
-
- el->push_back(e);
- return MODEACTION_ALLOW;
- }
- else
- {
- /* If they deny it they have the job of giving an error message */
- return MODEACTION_DENY;
- }
- }
- }
- }
-
- /* List is full, give subclass a chance to send a custom message */
- if (!TellListTooLong(source, channel, parameter))
- {
- source->WriteNumeric(478, "%s %s %s :Channel ban/ignore list is full", source->nick.c_str(), channel->name.c_str(), parameter.c_str());
- }
-
- parameter.clear();
- return MODEACTION_DENY;
- }
- else
- {
- // We're taking the mode off
- if (el)
- {
- for (modelist::iterator it = el->begin(); it != el->end(); it++)
- {
- if (parameter == it->mask)
- {
- el->erase(it);
- if (el->empty())
- {
- extItem.unset(channel);
- }
- return MODEACTION_ALLOW;
- }
- }
- /* Tried to remove something that wasn't set */
- TellNotSet(source, channel, parameter);
- parameter.clear();
- return MODEACTION_DENY;
- }
- else
- {
- /* Hmm, taking an exception off a non-existant list, DIE */
- TellNotSet(source, channel, parameter);
- parameter.clear();
- return MODEACTION_DENY;
- }
- }
- return MODEACTION_DENY;
- }
-
- /** Syncronize channel item list with another server.
- * See modules.h
- * @param chan Channel to syncronize
- * @param proto Protocol module pointer
- * @param opaque Opaque connection handle
- */
- virtual void DoSyncChannel(Channel* chan, Module* proto, void* opaque)
- {
- modelist* mlist = extItem.get(chan);
- irc::modestacker modestack(true);
- std::vector<std::string> stackresult;
- std::vector<TranslateType> types;
- types.push_back(TR_TEXT);
- if (mlist)
- {
- for (modelist::iterator it = mlist->begin(); it != mlist->end(); it++)
- {
- modestack.Push(std::string(1, mode)[0], it->mask);
- }
- }
- while (modestack.GetStackedLine(stackresult))
- {
- types.assign(stackresult.size(), this->GetTranslateType());
- proto->ProtoSendMode(opaque, TYPE_CHANNEL, chan, stackresult, types);
- stackresult.clear();
- }
- }
-
- /** Clean up module on unload
- * @param target_type Type of target to clean
- * @param item Item to clean
- */
- virtual void DoCleanup(int, void*)
- {
- }
-
- /** Validate parameters.
- * Overridden by implementing module.
- * @param source Source user adding the parameter
- * @param channel Channel the parameter is being added to
- * @param parameter The actual parameter being added
- * @return true if the parameter is valid
- */
- virtual bool ValidateParam(User*, Channel*, std::string&)
- {
- return true;
- }
-
- /** Tell the user the list is too long.
- * Overridden by implementing module.
- * @param source Source user adding the parameter
- * @param channel Channel the parameter is being added to
- * @param parameter The actual parameter being added
- * @return Ignored
- */
- virtual bool TellListTooLong(User*, Channel*, std::string&)
- {
- return false;
- }
-
- /** Tell the user an item is already on the list.
- * Overridden by implementing module.
- * @param source Source user adding the parameter
- * @param channel Channel the parameter is being added to
- * @param parameter The actual parameter being added
- */
- virtual void TellAlreadyOnList(User*, Channel*, std::string&)
- {
- }
-
- /** Tell the user that the parameter is not in the list.
- * Overridden by implementing module.
- * @param source Source user removing the parameter
- * @param channel Channel the parameter is being removed from
- * @param parameter The actual parameter being removed
- */
- virtual void TellNotSet(User*, Channel*, std::string&)
- {
- }
-};
-
-#endif
#include <signal.h>
#include "exitcodes.h"
#include "inspircd.h"
-#include "inspircd_version.h"
void InspIRCd::SignalHandler(int signal)
{
void RehashHandler::Call(const std::string &reason)
{
ServerInstance->SNO->WriteToSnoMask('a', "Rehashing config file %s %s",ServerConfig::CleanFilename(ServerInstance->ConfigFileName.c_str()), reason.c_str());
- ServerInstance->RehashUsersAndChans();
FOREACH_MOD(I_OnGarbageCollect, OnGarbageCollect());
if (!ServerInstance->ConfigThread)
{
}
}
-std::string InspIRCd::GetVersionString(bool operstring)
+std::string InspIRCd::GetVersionString(bool getFullVersion)
{
- char versiondata[MAXBUF];
- if (operstring)
- {
- std::string sename = SE->GetName();
- snprintf(versiondata,MAXBUF,"%s %s :%s [%s,%s,%s]",VERSION, Config->ServerName.c_str(), SYSTEM,REVISION, sename.c_str(), Config->sid.c_str());
- }
- else
- snprintf(versiondata,MAXBUF,"%s %s :%s",BRANCH,Config->ServerName.c_str(),Config->CustomVersion.c_str());
- return versiondata;
+ if (getFullVersion)
+ return VERSION " " + Config->ServerName + " :" SYSTEM " [" REVISION "," + SE->GetName() + "," + Config->sid + "]";
+ return BRANCH " " + Config->ServerName + " :" + Config->CustomVersion;
}
-const char InspIRCd::LogHeader[] =
- "Log started for " VERSION " (" REVISION ", " MODULE_INIT_STR ")"
- " - compiled on " SYSTEM;
-
-void InspIRCd::BuildISupport()
+std::string UIDGenerator::GenerateSID(const std::string& servername, const std::string& serverdesc)
{
- // the neatest way to construct the initial 005 numeric, considering the number of configure constants to go in it...
- std::stringstream v;
- v << "WALLCHOPS WALLVOICES MODES=" << Config->Limits.MaxModes << " CHANTYPES=# PREFIX=" << this->Modes->BuildPrefixes() << " MAP MAXCHANNELS=" << Config->MaxChans << " MAXBANS=60 VBANLIST NICKLEN=" << Config->Limits.NickMax;
- v << " CASEMAPPING=rfc1459 STATUSMSG=" << Modes->BuildPrefixes(false) << " CHARSET=ascii TOPICLEN=" << Config->Limits.MaxTopic << " KICKLEN=" << Config->Limits.MaxKick << " MAXTARGETS=" << Config->MaxTargets;
- v << " AWAYLEN=" << Config->Limits.MaxAway << " CHANMODES=" << this->Modes->GiveModeList(MASK_CHANNEL) << " FNC NETWORK=" << Config->Network << " MAXPARA=32 ELIST=MU" << " CHANNELLEN=" << Config->Limits.ChanMax;
- Config->data005 = v.str();
- FOREACH_MOD(I_On005Numeric,On005Numeric(Config->data005));
- Config->Update005();
+ unsigned int sid = 0;
+
+ for (std::string::const_iterator i = servername.begin(); i != servername.end(); ++i)
+ sid = 5 * sid + *i;
+ for (std::string::const_iterator i = serverdesc.begin(); i != serverdesc.end(); ++i)
+ sid = 5 * sid + *i;
+
+ std::string sidstr = ConvToStr(sid % 1000);
+ sidstr.insert(0, 3 - sidstr.length(), '0');
+ return sidstr;
}
-void InspIRCd::IncrementUID(int pos)
+void UIDGenerator::IncrementUID(unsigned int pos)
{
/*
* Okay. The rules for generating a UID go like this...
* A again, in an iterative fashion.. so..
* AAA9 -> AABA, and so on. -- w00t
*/
- if ((pos == 3) && (current_uid[3] == '9'))
+
+ // If we hit Z, wrap around to 0.
+ if (current_uid[pos] == 'Z')
+ {
+ current_uid[pos] = '0';
+ }
+ else if (current_uid[pos] == '9')
{
- // At pos 3, if we hit '9', we've run out of available UIDs, and need to reset to AAA..AAA.
- for (int i = 3; i < UUID_LENGTH-1; i++)
+ /*
+ * Or, if we hit 9, wrap around to pos = 'A' and (pos - 1)++,
+ * e.g. A9 -> BA -> BB ..
+ */
+ current_uid[pos] = 'A';
+ if (pos == 3)
{
- current_uid[i] = 'A';
+ // At pos 3, if we hit '9', we've run out of available UIDs, and reset to AAA..AAA.
+ return;
}
+ this->IncrementUID(pos - 1);
}
else
{
- // If we hit Z, wrap around to 0.
- if (current_uid[pos] == 'Z')
- {
- current_uid[pos] = '0';
- }
- else if (current_uid[pos] == '9')
- {
- /*
- * Or, if we hit 9, wrap around to pos = 'A' and (pos - 1)++,
- * e.g. A9 -> BA -> BB ..
- */
- current_uid[pos] = 'A';
- this->IncrementUID(pos - 1);
- }
- else
- {
- // Anything else, nobody gives a shit. Just increment.
- current_uid[pos]++;
- }
+ // Anything else, nobody gives a shit. Just increment.
+ current_uid[pos]++;
}
}
-/*
- * Retrieve the next valid UUID that is free for this server.
- */
-std::string InspIRCd::GetUID()
+void UIDGenerator::init(const std::string& sid)
{
- static bool inited = false;
-
/*
- * If we're setting up, copy SID into the first three digits, 9's to the rest, null term at the end
+ * Copy SID into the first three digits, 9's to the rest, null term at the end
* Why 9? Well, we increment before we find, otherwise we have an unnecessary copy, and I want UID to start at AAA..AA
* and not AA..AB. So by initialising to 99999, we force it to rollover to AAAAA on the first IncrementUID call.
* Kind of silly, but I like how it looks.
* -- w
*/
- if (!inited)
- {
- inited = true;
- current_uid[0] = Config->sid[0];
- current_uid[1] = Config->sid[1];
- current_uid[2] = Config->sid[2];
- for (int i = 3; i < (UUID_LENGTH - 1); i++)
- current_uid[i] = '9';
-
- // Null terminator. Important.
- current_uid[UUID_LENGTH - 1] = '\0';
- }
+ current_uid.resize(UUID_LENGTH, '9');
+ current_uid[0] = sid[0];
+ current_uid[1] = sid[1];
+ current_uid[2] = sid[2];
+}
+/*
+ * Retrieve the next valid UUID that is free for this server.
+ */
+std::string UIDGenerator::GetUID()
+{
while (1)
{
// Add one to the last UID
- this->IncrementUID(UUID_LENGTH - 2);
+ this->IncrementUID(UUID_LENGTH - 1);
- if (this->FindUUID(current_uid))
- {
- /*
- * It's in use. We need to try the loop again.
- */
- continue;
- }
+ if (!ServerInstance->FindUUID(current_uid))
+ break;
- return current_uid;
+ /*
+ * It's in use. We need to try the loop again.
+ */
}
- /* not reached. */
- return "";
+ return current_uid;
}
+void ISupportManager::Build()
+{
+ /**
+ * This is currently the neatest way we can build the initial ISUPPORT map. In
+ * the future we can use an initializer list here.
+ */
+ std::map<std::string, std::string> tokens;
+
+ tokens["AWAYLEN"] = ConvToStr(ServerInstance->Config->Limits.MaxAway);
+ tokens["CASEMAPPING"] = "rfc1459";
+ tokens["CHANMODES"] = ServerInstance->Modes->GiveModeList(MASK_CHANNEL);
+ tokens["CHANNELLEN"] = ConvToStr(ServerInstance->Config->Limits.ChanMax);
+ tokens["CHANTYPES"] = "#";
+ tokens["CHARSET"] = "ascii";
+ tokens["ELIST"] = "MU";
+ tokens["KICKLEN"] = ConvToStr(ServerInstance->Config->Limits.MaxKick);
+ tokens["MAXBANS"] = "64"; // TODO: make this a config setting.
+ tokens["MAXCHANNELS"] = ConvToStr(ServerInstance->Config->MaxChans);
+ tokens["MAXTARGETS"] = ConvToStr(ServerInstance->Config->MaxTargets);
+ tokens["MODES"] = ConvToStr(ServerInstance->Config->Limits.MaxModes);
+ tokens["NETWORK"] = ServerInstance->Config->Network;
+ tokens["NICKLEN"] = ConvToStr(ServerInstance->Config->Limits.NickMax);
+ tokens["PREFIX"] = ServerInstance->Modes->BuildPrefixes();
+ tokens["STATUSMSG"] = ServerInstance->Modes->BuildPrefixes(false);
+ tokens["TOPICLEN"] = ConvToStr(ServerInstance->Config->Limits.MaxTopic);
+
+ tokens["FNC"] = tokens["MAP"] = tokens["VBANLIST"] =
+ tokens["WALLCHOPS"] = tokens["WALLVOICES"];
+
+ // Modules can add new tokens and also edit or remove existing tokens
+ FOREACH_MOD(I_On005Numeric, On005Numeric(tokens));
+
+ // EXTBAN is a special case as we need to sort it and prepend a comma.
+ std::map<std::string, std::string>::iterator extban = tokens.find("EXTBAN");
+ if (extban != tokens.end())
+ {
+ sort(extban->second.begin(), extban->second.end());
+ extban->second.insert(0, ",");
+ }
+
+ // Transform the map into a list of lines, ready to be sent to clients
+ std::vector<std::string>& lines = this->Lines;
+ std::string line;
+ unsigned int token_count = 0;
+ lines.clear();
+
+ for (std::map<std::string, std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
+ {
+ line.append(it->first);
+
+ // If this token has a value then append a '=' char after the name and then the value itself
+ if (!it->second.empty())
+ line.append(1, '=').append(it->second);
+ // Always append a space, even if it's the last token because all lines will be suffixed
+ line.push_back(' ');
+ token_count++;
+ if (token_count % 13 == 12 || it == --tokens.end())
+ {
+ // Reached maximum number of tokens for this line or the current token
+ // is the last one; finalize the line and store it for later use
+ line.append(":are supported by this server");
+ lines.push_back(line);
+ line.clear();
+ }
+ }
+}
+
+void ISupportManager::SendTo(LocalUser* user)
+{
+ for (std::vector<std::string>::const_iterator i = this->Lines.begin(); i != this->Lines.end(); ++i)
+ user->WriteNumeric(RPL_ISUPPORT, "%s %s", user->nick.c_str(), i->c_str());
+}
void SnomaskManager::WriteToSnoMask(char letter, const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteToSnoMask(letter, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteToSnoMask(letter, textbuffer);
}
void SnomaskManager::WriteGlobalSno(char letter, const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteGlobalSno(letter, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteGlobalSno(letter, textbuffer);
}
SnomaskManager::SnomaskManager()
if (isupper(mysnomask))
desc = "REMOTE" + desc;
ModResult MOD_RESULT;
- ServerInstance->Logs->Log("snomask", DEFAULT, "%s: %s", desc.c_str(), message.c_str());
+ ServerInstance->Logs->Log("snomask", LOG_DEFAULT, "%s: %s", desc.c_str(), message.c_str());
FIRST_MOD_RESULT(OnSendSnotice, MOD_RESULT, (mysnomask, desc, message));
User* a = *i;
if (IS_LOCAL(a) && a->IsModeSet('s') && a->IsNoticeMaskSet(mysnomask) && !a->quitting)
{
- a->WriteServ("NOTICE %s :*** %s: %s", a->nick.c_str(), desc.c_str(), message.c_str());
+ a->WriteNotice("*** " + desc + ": " + message);
}
i++;
desc = "REMOTE" + desc;
std::string mesg = "(last message repeated "+ConvToStr(Count)+" times)";
- ServerInstance->Logs->Log("snomask", DEFAULT, "%s: %s", desc.c_str(), mesg.c_str());
+ ServerInstance->Logs->Log("snomask", LOG_DEFAULT, "%s: %s", desc.c_str(), mesg.c_str());
FOREACH_MOD(I_OnSendSnotice, OnSendSnotice(LastLetter, desc, mesg));
User* a = *i;
if (IS_LOCAL(a) && a->IsModeSet('s') && a->IsNoticeMaskSet(LastLetter) && !a->quitting)
{
- a->WriteServ("NOTICE %s :*** %s: %s", a->nick.c_str(), desc.c_str(), mesg.c_str());
+ a->WriteNotice("*** " + desc + ": " + mesg);
}
i++;
{
if (SE->Listen(sockfd, Config->MaxConn) == -1)
{
- this->Logs->Log("SOCKET",DEFAULT,"ERROR in listen(): %s",strerror(errno));
+ this->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR in listen(): %s",strerror(errno));
return false;
}
else
{
- this->Logs->Log("SOCKET",DEBUG,"New socket binding for %d with listen: %s:%d", sockfd, addr, port);
+ this->Logs->Log("SOCKET", LOG_DEBUG, "New socket binding for %d with listen: %s:%d", sockfd, addr, port);
SE->NonBlocking(sockfd);
return true;
}
}
else
{
- this->Logs->Log("SOCKET",DEBUG,"New socket binding for %d without listen: %s:%d", sockfd, addr, port);
+ this->Logs->Log("SOCKET", LOG_DEBUG, "New socket binding for %d without listen: %s:%d", sockfd, addr, port);
return true;
}
}
std::string Addr = tag->getString("address");
if (strncasecmp(Addr.c_str(), "::ffff:", 7) == 0)
- this->Logs->Log("SOCKET",DEFAULT, "Using 4in6 (::ffff:) isn't recommended. You should bind IPv4 addresses directly instead.");
+ this->Logs->Log("SOCKET", LOG_DEFAULT, "Using 4in6 (::ffff:) isn't recommended. You should bind IPv4 addresses directly instead.");
irc::portparser portrange(porttag, false);
int portno = -1;
n++;
if (n == ports.end())
{
- this->Logs->Log("SOCKET",DEFAULT,"Port bindings slipped out of vector, aborting close!");
+ this->Logs->Log("SOCKET", LOG_DEFAULT, "Port bindings slipped out of vector, aborting close!");
break;
}
- this->Logs->Log("SOCKET",DEFAULT, "Port binding %s was removed from the config file, closing.",
+ this->Logs->Log("SOCKET", LOG_DEFAULT, "Port binding %s was removed from the config file, closing.",
(**n).bind_desc.c_str());
delete *n;
new_m &= ~FD_WANT_READ_MASK;
if (change & FD_WANT_WRITE_MASK)
new_m &= ~FD_WANT_WRITE_MASK;
-
+
// if adding a trial read/write, insert it into the set
if (change & FD_TRIAL_NOTE_MASK && !(old_m & FD_TRIAL_NOTE_MASK))
trials.insert(eh->GetFd());
}
else
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl;
ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
}
if (EngineHandle == -1)
{
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: Could not initialize socket engine: %s", strerror(errno));
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Could not initialize socket engine: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.");
std::cout << "ERROR: Could not initialize epoll socket engine: " << strerror(errno) << std::endl;
std::cout << "ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now." << std::endl;
ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
int fd = eh->GetFd();
if ((fd < 0) || (fd > GetMaxFds() - 1))
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
return false;
}
if (ref[fd])
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Attempt to add duplicate fd: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd);
return false;
}
int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev);
if (i < 0)
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Error adding fd: %d to socketengine: %s", fd, strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Error adding fd: %d to socketengine: %s", fd, strerror(errno));
return false;
}
- ServerInstance->Logs->Log("SOCKET",DEBUG,"New file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
ref[fd] = eh;
SocketEngine::SetEventMask(eh, event_mask);
int fd = eh->GetFd();
if ((fd < 0) || (fd > GetMaxFds() - 1))
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
return;
}
if (i < 0)
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"epoll_ctl can't remove socket: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "epoll_ctl can't remove socket: %s", strerror(errno));
}
ref[fd] = NULL;
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Remove file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d", fd);
CurrentSetSize--;
}
EventHandler* eh = ref[events[j].data.fd];
if (!eh)
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Got event on unknown fd: %d", events[j].data.fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Got event on unknown fd: %d", events[j].data.fd);
epoll_ctl(EngineHandle, EPOLL_CTL_DEL, events[j].data.fd, &events[j]);
continue;
}
sysctl(mib, 2, &MAX_DESCRIPTORS, &len, NULL, 0);
if (MAX_DESCRIPTORS <= 0)
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl;
ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
}
EngineHandle = kqueue();
if (EngineHandle == -1)
{
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features.");
- ServerInstance->Logs->Log("SOCKET",DEFAULT, "ERROR: this is a fatal error, exiting now.");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features.");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: this is a fatal error, exiting now.");
std::cout << "ERROR: Could not initialize socket engine. Your kernel probably does not have the proper features." << std::endl;
std::cout << "ERROR: this is a fatal error, exiting now." << std::endl;
ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (i == -1)
{
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"Failed to add fd: %d %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to add fd: %d %s",
fd, strerror(errno));
return false;
}
OnSetEvent(eh, 0, event_mask);
CurrentSetSize++;
- ServerInstance->Logs->Log("SOCKET",DEBUG,"New file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
return true;
}
if ((fd < 0) || (fd > GetMaxFds() - 1))
{
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"DelFd() on invalid fd: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "DelFd() on invalid fd: %d", fd);
return;
}
if (j < 0)
{
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"Failed to remove fd: %d %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to remove fd: %d %s",
fd, strerror(errno));
}
CurrentSetSize--;
ref[fd] = NULL;
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Remove file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d", fd);
}
void KQueueEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_ADD, 0, 0, NULL);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (i < 0) {
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"Failed to mark for writing: %d %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to mark for writing: %d %s",
eh->GetFd(), strerror(errno));
}
}
EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (i < 0) {
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"Failed to mark for writing: %d %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to mark for writing: %d %s",
eh->GetFd(), strerror(errno));
}
}
EV_SET(&ke, eh->GetFd(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, NULL);
int i = kevent(EngineHandle, &ke, 1, 0, 0, NULL);
if (i < 0) {
- ServerInstance->Logs->Log("SOCKET",DEFAULT,"Failed to mark for writing: %d %s",
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "Failed to mark for writing: %d %s",
eh->GetFd(), strerror(errno));
}
}
*/
-#include "inspircd.h"
-#include "exitcodes.h"
-
#ifndef SOCKETENGINE_POLL
#define SOCKETENGINE_POLL
#include <vector>
#include <string>
#include <map>
-#include "inspircd_config.h"
+#include "exitcodes.h"
#include "inspircd.h"
#include "socketengine.h"
}
else
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets: %s", strerror(errno));
std::cout << "ERROR: Can't determine maximum number of open sockets: " << strerror(errno) << std::endl;
ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
}
int fd = eh->GetFd();
if ((fd < 0) || (fd > GetMaxFds() - 1))
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "AddFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
return false;
}
if (fd_mappings.find(fd) != fd_mappings.end())
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Attempt to add duplicate fd: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Attempt to add duplicate fd: %d", fd);
return false;
}
events[index].fd = fd;
events[index].events = mask_to_poll(event_mask);
- ServerInstance->Logs->Log("SOCKET", DEBUG,"New file descriptor: %d (%d; index %d)", fd, events[fd].events, index);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d (%d; index %d)", fd, events[fd].events, index);
SocketEngine::SetEventMask(eh, event_mask);
CurrentSetSize++;
return true;
std::map<int, unsigned int>::iterator it = fd_mappings.find(eh->GetFd());
if (it == fd_mappings.end())
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"SetEvents() on unknown fd: %d", eh->GetFd());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "SetEvents() on unknown fd: %d", eh->GetFd());
return;
}
int fd = eh->GetFd();
if ((fd < 0) || (fd > MAX_DESCRIPTORS))
{
- ServerInstance->Logs->Log("SOCKET", DEBUG, "DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd out of range: (fd: %d, max: %d)", fd, GetMaxFds());
return;
}
std::map<int, unsigned int>::iterator it = fd_mappings.find(fd);
if (it == fd_mappings.end())
{
- ServerInstance->Logs->Log("SOCKET",DEBUG,"DelFd() on unknown fd: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "DelFd() on unknown fd: %d", fd);
return;
}
CurrentSetSize--;
- ServerInstance->Logs->Log("SOCKET", DEBUG, "Remove file descriptor: %d (index: %d) "
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d (index: %d) "
"(Filled gap with: %d (index: %d))", fd, index, last_fd, last_index);
}
// whoops, deleted out from under us
continue;
}
-
+
if (events[index].revents & POLLOUT)
{
int mask = eh->GetEventMask();
#include <vector>
#include <string>
#include <map>
-#include "inspircd_config.h"
#include "inspircd.h"
#include "socketengine.h"
#include <port.h>
}
else
{
- ServerInstance->Logs->Log("SOCKET", DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
+ ServerInstance->Logs->Log("SOCKET", LOG_DEFAULT, "ERROR: Can't determine maximum number of open sockets!");
std::cout << "ERROR: Can't determine maximum number of open sockets!" << std::endl;
ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
}
if (EngineHandle == -1)
{
- ServerInstance->Logs->Log("SOCKET",SPARSE,"ERROR: Could not initialize socket engine: %s", strerror(errno));
- ServerInstance->Logs->Log("SOCKET",SPARSE,"ERROR: This is a fatal error, exiting now.");
+ ServerInstance->Logs->Log("SOCKET", LOG_SPARSE, "ERROR: Could not initialize socket engine: %s", strerror(errno));
+ ServerInstance->Logs->Log("SOCKET", LOG_SPARSE, "ERROR: This is a fatal error, exiting now.");
std::cout << "ERROR: Could not initialize socket engine: " << strerror(errno) << std::endl;
std::cout << "ERROR: This is a fatal error, exiting now." << std::endl;
ServerInstance->Exit(EXIT_STATUS_SOCKETENGINE);
SocketEngine::SetEventMask(eh, event_mask);
port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(event_mask), eh);
- ServerInstance->Logs->Log("SOCKET",DEBUG,"New file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
CurrentSetSize++;
return true;
}
CurrentSetSize--;
ref[fd] = NULL;
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Remove file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d", fd);
}
int PortsEngine::DispatchEvents()
*/
-#include "inspircd_config.h"
-
#include "inspircd.h"
#include "socketengine.h"
CurrentSetSize++;
- ServerInstance->Logs->Log("SOCKET",DEBUG,"New file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "New file descriptor: %d", fd);
return true;
}
if (fd == MaxFD)
--MaxFD;
- ServerInstance->Logs->Log("SOCKET",DEBUG,"Remove file descriptor: %d", fd);
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "Remove file descriptor: %d", fd);
}
void SelectEngine::OnSetEvent(EventHandler* eh, int old_mask, int new_mask)
bool TestSuite::DoGenerateUIDTests()
{
- bool success = RealGenerateUIDTests();
+ const unsigned int UUID_LENGTH = UIDGenerator::UUID_LENGTH;
+ UIDGenerator uidgen;
+ uidgen.init(ServerInstance->Config->GetSID());
+ std::string first_uid = uidgen.GetUID();
- // Reset the UID generation state so running the tests multiple times won't mess things up
- for (unsigned int i = 0; i < 3; i++)
- ServerInstance->current_uid[i] = ServerInstance->Config->sid[i];
- for (unsigned int i = 3; i < UUID_LENGTH-1; i++)
- ServerInstance->current_uid[i] = '9';
-
- ServerInstance->current_uid[UUID_LENGTH-1] = '\0';
-
- return success;
-}
-
-bool TestSuite::RealGenerateUIDTests()
-{
- std::string first_uid = ServerInstance->GetUID();
- if (first_uid.length() != UUID_LENGTH-1)
+ if (first_uid.length() != UUID_LENGTH)
{
std::cout << "GENERATEUID: Generated UID is " << first_uid.length() << " characters long instead of " << UUID_LENGTH-1 << std::endl;
return false;
}
- if (ServerInstance->current_uid[UUID_LENGTH-1] != '\0')
+ if (uidgen.current_uid.c_str()[UUID_LENGTH] != '\0')
{
std::cout << "GENERATEUID: The null terminator is missing from the end of current_uid" << std::endl;
return false;
}
// The correct UID when generating one for the first time is ...AAAAAA
- std::string correct_uid = ServerInstance->Config->sid + std::string(UUID_LENGTH - 4, 'A');
+ std::string correct_uid = ServerInstance->Config->sid + std::string(UUID_LENGTH - 3, 'A');
if (first_uid != correct_uid)
{
std::cout << "GENERATEUID: Generated an invalid first UID: " << first_uid << " instead of " << correct_uid << std::endl;
}
// Set current_uid to be ...Z99999
- ServerInstance->current_uid[3] = 'Z';
- for (unsigned int i = 4; i < UUID_LENGTH-1; i++)
- ServerInstance->current_uid[i] = '9';
+ uidgen.current_uid[3] = 'Z';
+ for (unsigned int i = 4; i < UUID_LENGTH; i++)
+ uidgen.current_uid[i] = '9';
// Store the UID we'll be incrementing so we can display what's wrong later if necessary
- std::string before_increment(ServerInstance->current_uid);
- std::string generated_uid = ServerInstance->GetUID();
+ std::string before_increment(uidgen.current_uid);
+ std::string generated_uid = uidgen.GetUID();
// Correct UID after incrementing ...Z99999 is ...0AAAAA
- correct_uid = ServerInstance->Config->sid + "0" + std::string(UUID_LENGTH - 5, 'A');
+ correct_uid = ServerInstance->Config->sid + "0" + std::string(UUID_LENGTH - 4, 'A');
if (generated_uid != correct_uid)
{
}
// Set current_uid to be ...999999 to see if it rolls over correctly
- for (unsigned int i = 3; i < UUID_LENGTH-1; i++)
- ServerInstance->current_uid[i] = '9';
+ for (unsigned int i = 3; i < UUID_LENGTH; i++)
+ uidgen.current_uid[i] = '9';
- before_increment.assign(ServerInstance->current_uid);
- generated_uid = ServerInstance->GetUID();
+ before_increment.assign(uidgen.current_uid);
+ generated_uid = uidgen.GetUID();
// Correct UID after rolling over is the first UID we've generated (...AAAAAA)
if (generated_uid != first_uid)
#include "inspircd.h"
#include "timer.h"
-TimerManager::TimerManager()
+void Timer::SetInterval(time_t newinterval)
{
+ ServerInstance->Timers->DelTimer(this);
+ secs = newinterval;
+ SetTrigger(ServerInstance->Time() + newinterval);
+ ServerInstance->Timers->AddTimer(this);
}
-TimerManager::~TimerManager()
+Timer::~Timer()
{
- for(std::vector<Timer *>::iterator i = Timers.begin(); i != Timers.end(); i++)
- delete *i;
+ ServerInstance->Timers->DelTimer(this);
}
void TimerManager::TickTimers(time_t TIME)
{
- while ((Timers.size()) && (TIME > (*Timers.begin())->GetTimer()))
+ for (TimerMap::iterator i = Timers.begin(); i != Timers.end(); )
{
- std::vector<Timer *>::iterator i = Timers.begin();
- Timer *t = (*i);
+ Timer* t = i->second;
+ if (t->GetTrigger() > TIME)
+ break;
- // Probable fix: move vector manipulation to *before* we modify the vector.
- Timers.erase(i);
+ Timers.erase(i++);
- t->Tick(TIME);
- if (t->GetRepeat())
+ if (!t->Tick(TIME))
+ delete t;
+ else if (t->GetRepeat())
{
- t->SetTimer(TIME + t->GetSecs());
+ t->SetTrigger(TIME + t->GetInterval());
AddTimer(t);
}
- else
- delete t;
}
}
-void TimerManager::DelTimer(Timer* T)
+void TimerManager::DelTimer(Timer* t)
{
- std::vector<Timer *>::iterator i = std::find(Timers.begin(), Timers.end(), T);
+ std::pair<TimerMap::iterator, TimerMap::iterator> itpair = Timers.equal_range(t->GetTrigger());
- if (i != Timers.end())
+ for (TimerMap::iterator i = itpair.first; i != itpair.second; ++i)
{
- delete (*i);
- Timers.erase(i);
+ if (i->second == t)
+ {
+ Timers.erase(i);
+ break;
+ }
}
}
-void TimerManager::AddTimer(Timer* T)
-{
- Timers.push_back(T);
- sort(Timers.begin(), Timers.end(), TimerManager::TimerComparison);
-}
-
-bool TimerManager::TimerComparison( Timer *one, Timer *two)
+void TimerManager::AddTimer(Timer* t)
{
- return (one->GetTimer()) < (two->GetTimer());
+ Timers.insert(std::make_pair(t->GetTrigger(), t));
}
+++ /dev/null
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
- * Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
- *
- * This file is part of InspIRCd. InspIRCd is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "inspircd.h"
-UserResolver::UserResolver(LocalUser* user, std::string to_resolve, QueryType qt, bool &cache) :
- Resolver(to_resolve, qt, cache, NULL), uuid(user->uuid)
-{
- this->fwd = (qt == DNS_QUERY_A || qt == DNS_QUERY_AAAA);
-}
-
-void UserResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached)
-{
- UserResolver *res_forward; // for forward-resolution
- LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
- if (!bound_user)
- {
- ServerInstance->Logs->Log("RESOLVER", DEBUG, "Resolution finished for user '%s' who is gone", uuid.c_str());
- return;
- }
-
- ServerInstance->Logs->Log("RESOLVER", DEBUG, "DNS result for %s: '%s' -> '%s'", uuid.c_str(), input.c_str(), result.c_str());
-
- if (!fwd)
- {
- // first half of resolution is done. We now need to verify that the host matches.
- bound_user->stored_host = result;
- try
- {
- /* Check we didnt time out */
- if (bound_user->registered != REG_ALL)
- {
- bool lcached = false;
- if (bound_user->client_sa.sa.sa_family == AF_INET6)
- {
- /* IPV6 forward lookup */
- res_forward = new UserResolver(bound_user, result, DNS_QUERY_AAAA, lcached);
- }
- else
- {
- /* IPV4 lookup */
- res_forward = new UserResolver(bound_user, result, DNS_QUERY_A, lcached);
- }
- ServerInstance->AddResolver(res_forward, lcached);
- }
- }
- catch (CoreException& e)
- {
- ServerInstance->Logs->Log("RESOLVER", DEBUG,"Error in resolver: %s",e.GetReason());
- }
- }
- else
- {
- /* Both lookups completed */
-
- irc::sockets::sockaddrs* user_ip = &bound_user->client_sa;
- bool rev_match = false;
- if (user_ip->sa.sa_family == AF_INET6)
- {
- struct in6_addr res_bin;
- if (inet_pton(AF_INET6, result.c_str(), &res_bin))
- {
- rev_match = !memcmp(&user_ip->in6.sin6_addr, &res_bin, sizeof(res_bin));
- }
- }
- else
- {
- struct in_addr res_bin;
- if (inet_pton(AF_INET, result.c_str(), &res_bin))
- {
- rev_match = !memcmp(&user_ip->in4.sin_addr, &res_bin, sizeof(res_bin));
- }
- }
-
- if (rev_match)
- {
- std::string hostname = bound_user->stored_host;
- if (hostname.length() < 65)
- {
- /* Check we didnt time out */
- if ((bound_user->registered != REG_ALL) && (!bound_user->dns_done))
- {
- /* Hostnames starting with : are not a good thing (tm) */
- if (hostname[0] == ':')
- hostname.insert(0, "0");
-
- bound_user->WriteServ("NOTICE Auth :*** Found your hostname (%s)%s", hostname.c_str(), (cached ? " -- cached" : ""));
- bound_user->dns_done = true;
- bound_user->dhost.assign(hostname, 0, 64);
- bound_user->host.assign(hostname, 0, 64);
- /* Invalidate cache */
- bound_user->InvalidateCache();
- }
- }
- else
- {
- if (!bound_user->dns_done)
- {
- bound_user->WriteServ("NOTICE Auth :*** Your hostname is longer than the maximum of 64 characters, using your IP address (%s) instead.", bound_user->GetIPString());
- bound_user->dns_done = true;
- }
- }
- }
- else
- {
- if (!bound_user->dns_done)
- {
- bound_user->WriteServ("NOTICE Auth :*** Your hostname does not match up with your IP address. Sorry, using your IP address (%s) instead.", bound_user->GetIPString());
- bound_user->dns_done = true;
- }
- }
-
- // Save some memory by freeing this up; it's never used again in the user's lifetime.
- bound_user->stored_host.resize(0);
- }
-}
-
-void UserResolver::OnError(ResolverError e, const std::string &errormessage)
-{
- LocalUser* bound_user = (LocalUser*)ServerInstance->FindUUID(uuid);
- if (bound_user)
- {
- bound_user->WriteServ("NOTICE Auth :*** Could not resolve your hostname: %s; using your IP address (%s) instead.", errormessage.c_str(), bound_user->GetIPString());
- bound_user->dns_done = true;
- bound_user->stored_host.resize(0);
- ServerInstance->stats->statsDnsBad++;
- }
-}
}
catch (...)
{
- ServerInstance->Logs->Log("USERS", DEFAULT,"*** WTF *** Duplicated UUID! -- Crack smoking monkeys have been unleashed.");
+ ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "*** WTF *** Duplicated UUID! -- Crack smoking monkeys have been unleashed.");
ServerInstance->SNO->WriteToSnoMask('a', "WARNING *** Duplicate UUID allocated!");
return;
}
}
catch (CoreException& modexcept)
{
- ServerInstance->Logs->Log("SOCKET", DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason());
+ ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason());
}
}
- ServerInstance->Logs->Log("USERS", DEBUG,"New user fd: %d", socket);
+ ServerInstance->Logs->Log("USERS", LOG_DEBUG, "New user fd: %d", socket);
this->unregistered_count++;
if (!b->Type.empty() && !New->exempt)
{
/* user banned */
- ServerInstance->Logs->Log("BANCACHE", DEBUG, std::string("BanCache: Positive hit for ") + New->GetIPString());
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Positive hit for " + New->GetIPString());
if (!ServerInstance->Config->MoronBanner.empty())
- New->WriteServ("NOTICE %s :*** %s", New->nick.c_str(), ServerInstance->Config->MoronBanner.c_str());
+ New->WriteNotice("*** " + ServerInstance->Config->MoronBanner);
this->QuitUser(New, b->Reason);
return;
}
else
{
- ServerInstance->Logs->Log("BANCACHE", DEBUG, std::string("BanCache: Negative hit for ") + New->GetIPString());
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Negative hit for " + New->GetIPString());
}
}
else
if (!ServerInstance->SE->AddFd(eh, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE))
{
- ServerInstance->Logs->Log("USERS", DEBUG,"Internal error on new connection");
+ ServerInstance->Logs->Log("USERS", LOG_DEBUG, "Internal error on new connection");
this->QuitUser(New, "Internal error handling connection");
}
- /* NOTE: even if dns lookups are *off*, we still need to display this.
- * BOPM and other stuff requires it.
- */
- New->WriteServ("NOTICE Auth :*** Looking up your hostname...");
if (ServerInstance->Config->RawLog)
- New->WriteServ("NOTICE Auth :*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.");
+ New->WriteNotice("*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.");
FOREACH_MOD(I_OnSetUserIP,OnSetUserIP(New));
if (New->quitting)
return;
FOREACH_MOD(I_OnUserInit,OnUserInit(New));
-
- if (ServerInstance->Config->NoUserDns)
- {
- New->WriteServ("NOTICE %s :*** Skipping host resolution (disabled by server administrator)", New->nick.c_str());
- New->dns_done = true;
- }
- else
- {
- New->StartDNSLookup();
- }
}
void UserManager::QuitUser(User *user, const std::string &quitreason, const char* operreason)
{
if (user->quitting)
{
- ServerInstance->Logs->Log("USERS", DEFAULT, "ERROR: Tried to quit quitting user: " + user->nick);
+ ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "ERROR: Tried to quit quitting user: " + user->nick);
return;
}
if (IS_SERVER(user))
{
- ServerInstance->Logs->Log("USERS", DEFAULT, "ERROR: Tried to quit server user: " + user->nick);
+ ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "ERROR: Tried to quit server user: " + user->nick);
return;
}
user->quitting = true;
- ServerInstance->Logs->Log("USERS", DEBUG, "QuitUser: %s=%s '%s'", user->uuid.c_str(), user->nick.c_str(), quitreason.c_str());
+ ServerInstance->Logs->Log("USERS", LOG_DEBUG, "QuitUser: %s=%s '%s'", user->uuid.c_str(), user->nick.c_str(), quitreason.c_str());
user->Write("ERROR :Closing link: (%s@%s) [%s]", user->ident.c_str(), user->host.c_str(), *operreason ? operreason : quitreason.c_str());
std::string reason;
if (!user->quietquit)
{
ServerInstance->SNO->WriteToSnoMask('q',"Client exiting: %s (%s) [%s]",
- user->GetFullRealHost().c_str(), user->GetIPString(), oper_reason.c_str());
+ user->GetFullRealHost().c_str(), user->GetIPString().c_str(), oper_reason.c_str());
}
}
else
if ((!ServerInstance->SilentULine(user->server)) && (!user->quietquit))
{
ServerInstance->SNO->WriteToSnoMask('Q',"Client exiting on server %s: %s (%s) [%s]",
- user->server.c_str(), user->GetFullRealHost().c_str(), user->GetIPString(), oper_reason.c_str());
+ user->server.c_str(), user->GetFullRealHost().c_str(), user->GetIPString().c_str(), oper_reason.c_str());
}
}
- user->AddToWhoWas();
}
user_hash::iterator iter = this->clientlist->find(user->nick);
if (iter != this->clientlist->end())
this->clientlist->erase(iter);
else
- ServerInstance->Logs->Log("USERS", DEFAULT, "ERROR: Nick not found in clientlist, cannot remove: " + user->nick);
+ ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "ERROR: Nick not found in clientlist, cannot remove: " + user->nick);
ServerInstance->Users->uuidlist->erase(user->uuid);
}
void UserManager::ServerNoticeAll(const char* text, ...)
{
- if (!text)
- return;
-
- char textbuffer[MAXBUF];
- char formatbuffer[MAXBUF];
- va_list argsPtr;
- va_start (argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- snprintf(formatbuffer,MAXBUF,"NOTICE $%s :%s", ServerInstance->Config->ServerName.c_str(), textbuffer);
+ std::string message;
+ VAFORMAT(message, text, text);
+ message = "NOTICE $" + ServerInstance->Config->ServerName + " :" + message;
for (LocalUserList::const_iterator i = local_users.begin(); i != local_users.end(); i++)
{
User* t = *i;
- t->WriteServ(std::string(formatbuffer));
+ t->WriteServ(message);
}
}
-void UserManager::ServerPrivmsgAll(const char* text, ...)
-{
- if (!text)
- return;
-
- char textbuffer[MAXBUF];
- char formatbuffer[MAXBUF];
- va_list argsPtr;
- va_start (argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- snprintf(formatbuffer,MAXBUF,"PRIVMSG $%s :%s", ServerInstance->Config->ServerName.c_str(), textbuffer);
-
- for (LocalUserList::const_iterator i = local_users.begin(); i != local_users.end(); i++)
- {
- User* t = *i;
- t->WriteServ(std::string(formatbuffer));
- }
-}
-
-
/* return how many users have a given mode e.g. 'a' */
int UserManager::ModeCount(const char mode)
{
}
return c;
}
+
+void UserManager::GarbageCollect()
+{
+ // Reset the already_sent IDs so we don't wrap it around and drop a message
+ LocalUser::already_sent_id = 0;
+ for (LocalUserList::const_iterator i = this->local_users.begin(); i != this->local_users.end(); i++)
+ {
+ (**i).already_sent = 0;
+ (**i).RemoveExpiredInvites();
+ }
+}
#include "socketengine.h"
#include "command_parse.h"
-void FloodQuitUserHandler::Call(User* current)
-{
- ServerInstance->Logs->Log("USERS",DEFAULT,"Excess flood from: %s@%s", current->ident.c_str(), current->host.c_str());
- ServerInstance->SNO->WriteToSnoMask('f',"Excess flood from: %s%s%s@%s",
- current->registered == REG_ALL ? current->nick.c_str() : "",
- current->registered == REG_ALL ? "!" : "", current->ident.c_str(), current->host.c_str());
- ServerInstance->Users->QuitUser(current, "Excess flood");
-
- if (current->registered != REG_ALL)
- {
- ZLine* zl = new ZLine(ServerInstance->Time(), 0, ServerInstance->Config->ServerName, "Flood from unregistered connection", current->GetIPString());
- if (ServerInstance->XLines->AddLine(zl,NULL))
- ServerInstance->XLines->ApplyLines();
- else
- delete zl;
- }
-}
-
/**
* This function is called once a second from the mainloop.
* It is intended to do background checking on all the user structs, e.g.
if (!curr->lastping)
{
time_t time = this->Time() - (curr->nping - curr->MyClass->GetPingTime());
- char message[MAXBUF];
- snprintf(message, MAXBUF, "Ping timeout: %ld second%s", (long)time, time > 1 ? "s" : "");
+ const std::string message = "Ping timeout: " + ConvToStr(time) + (time == 1 ? " seconds" : " second");
curr->lastping = 1;
curr->nping = Time() + curr->MyClass->GetPingTime();
this->Users->QuitUser(curr, message);
}
break;
case REG_NICKUSER:
- if (AllModulesReportReady(curr) && curr->dns_done)
+ if (AllModulesReportReady(curr))
{
/* User has sent NICK/USER, modules are okay, DNS finished. */
curr->FullConnect();
#include "socketengine.h"
#include "xline.h"
#include "bancache.h"
-#include "commands/cmd_whowas.h"
already_sent_t LocalUser::already_sent_id = 0;
return output;
}
-void LocalUser::StartDNSLookup()
-{
- try
- {
- bool cached = false;
- const char* sip = this->GetIPString();
- UserResolver *res_reverse;
-
- QueryType resolvtype = this->client_sa.sa.sa_family == AF_INET6 ? DNS_QUERY_PTR6 : DNS_QUERY_PTR4;
- res_reverse = new UserResolver(this, sip, resolvtype, cached);
-
- ServerInstance->AddResolver(res_reverse, cached);
- }
- catch (CoreException& e)
- {
- ServerInstance->Logs->Log("USERS", DEBUG,"Error in resolver: %s",e.GetReason());
- dns_done = true;
- ServerInstance->stats->statsDnsBad++;
- }
-}
-
bool User::IsNoticeMaskSet(unsigned char sm)
{
if (!isalpha(sm))
const char* User::FormatModes(bool showparameters)
{
- static char data[MAXBUF];
+ static std::string data;
std::string params;
- int offset = 0;
+ data.clear();
for (unsigned char n = 0; n < 64; n++)
{
if (modes[n])
{
- data[offset++] = n + 65;
+ data.push_back(n + 65);
ModeHandler* mh = ServerInstance->Modes->FindMode(n + 65, MODETYPE_USER);
if (showparameters && mh && mh->GetNumParams(true))
{
}
}
}
- data[offset] = 0;
- strlcat(data, params.c_str(), MAXBUF);
- return data;
+ data += params;
+ return data.c_str();
}
User::User(const std::string &uid, const std::string& sid, int type)
: uuid(uid), server(sid), usertype(type)
{
age = ServerInstance->Time();
- signon = idle_lastmsg = 0;
+ signon = 0;
registered = 0;
- quietquit = quitting = exempt = dns_done = false;
- quitting_sendq = false;
+ quietquit = quitting = false;
client_sa.sa.sa_family = AF_UNSPEC;
- ServerInstance->Logs->Log("USERS", DEBUG, "New UUID for user: %s", uuid.c_str());
+ ServerInstance->Logs->Log("USERS", LOG_DEBUG, "New UUID for user: %s", uuid.c_str());
user_hash::iterator finduuid = ServerInstance->Users->uuidlist->find(uuid);
if (finduuid == ServerInstance->Users->uuidlist->end())
}
LocalUser::LocalUser(int myfd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* servaddr)
- : User(ServerInstance->GetUID(), ServerInstance->Config->ServerName, USERTYPE_LOCAL), eh(this),
+ : User(ServerInstance->UIDGen.GetUID(), ServerInstance->Config->ServerName, USERTYPE_LOCAL), eh(this),
localuseriter(ServerInstance->Users->local_users.end()),
bytes_in(0), bytes_out(0), cmds_in(0), cmds_out(0), nping(0), CommandFloodPenalty(0),
already_sent(0)
{
+ exempt = quitting_sendq = false;
+ idle_lastmsg = 0;
ident = "unknown";
lastping = 0;
eh.SetFd(myfd);
User::~User()
{
if (ServerInstance->Users->uuidlist->find(uuid) != ServerInstance->Users->uuidlist->end())
- ServerInstance->Logs->Log("USERS", DEFAULT, "User destructor for %s called without cull", uuid.c_str());
+ ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "User destructor for %s called without cull", uuid.c_str());
}
const std::string& User::MakeHost()
for(const char* n = ident.c_str(); *n; n++)
*t++ = *n;
*t++ = '@';
- for(const char* n = this->GetIPString(); *n; n++)
+ for(const char* n = this->GetIPString().c_str(); *n; n++)
*t++ = *n;
*t = 0;
return this->cached_fullrealhost;
}
-bool LocalUser::IsInvited(const irc::string &channel)
-{
- Channel* chan = ServerInstance->FindChan(channel.c_str());
- if (!chan)
- return false;
-
- return (Invitation::Find(chan, this) != NULL);
-}
-
InviteList& LocalUser::GetInviteList()
{
RemoveExpiredInvites();
return invites;
}
-void LocalUser::InviteTo(const irc::string &channel, time_t invtimeout)
-{
- Channel* chan = ServerInstance->FindChan(channel.c_str());
- if (chan)
- Invitation::Create(chan, this, invtimeout);
-}
-
-void LocalUser::RemoveInvite(const irc::string &channel)
+bool LocalUser::RemoveInvite(Channel* chan)
{
- Channel* chan = ServerInstance->FindChan(channel.c_str());
- if (chan)
+ Invitation* inv = Invitation::Find(chan, this);
+ if (inv)
{
- Invitation* inv = Invitation::Find(chan, this);
- if (inv)
- {
- inv->cull();
- delete inv;
- }
+ inv->cull();
+ delete inv;
+ return true;
}
+ return false;
}
void LocalUser::RemoveExpiredInvites()
bool LocalUser::HasModePermission(unsigned char mode, ModeType type)
{
- if (!IS_OPER(this))
+ if (!this->IsOper())
return false;
if (mode < 'A' || mode > ('A' + 64)) return false;
bool LocalUser::HasPermission(const std::string &command)
{
// are they even an oper at all?
- if (!IS_OPER(this))
+ if (!this->IsOper())
{
return false;
}
bool LocalUser::HasPrivPermission(const std::string &privstr, bool noisy)
{
- if (!IS_OPER(this))
+ if (!this->IsOper())
{
if (noisy)
- this->WriteServ("NOTICE %s :You are not an oper", this->nick.c_str());
+ this->WriteNotice("You are not an oper");
return false;
}
}
if (noisy)
- this->WriteServ("NOTICE %s :Oper type %s does not have access to priv %s", this->nick.c_str(), oper->NameStr(), privstr.c_str());
+ this->WriteNotice("Oper type " + oper->name + " does not have access to priv " + privstr);
+
return false;
}
ServerInstance->Users->local_users.erase(localuseriter);
}
else
- ServerInstance->Logs->Log("USERS", DEFAULT, "ERROR: LocalUserIter does not point to a valid entry for " + this->nick);
+ ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "ERROR: LocalUserIter does not point to a valid entry for " + this->nick);
ClearInvites();
eh.cull();
}
ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')",
- nick.c_str(), ident.c_str(), host.c_str(), oper->NameStr(), opername.c_str());
- this->WriteNumeric(381, "%s :You are now %s %s", nick.c_str(), strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->NameStr());
+ nick.c_str(), ident.c_str(), host.c_str(), oper->name.c_str(), opername.c_str());
+ this->WriteNumeric(381, "%s :You are now %s %s", nick.c_str(), strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->name.c_str());
- ServerInstance->Logs->Log("OPER", DEFAULT, "%s opered as type: %s", GetFullRealHost().c_str(), oper->NameStr());
+ ServerInstance->Logs->Log("OPER", LOG_DEFAULT, "%s opered as type: %s", GetFullRealHost().c_str(), oper->name.c_str());
ServerInstance->Users->all_opers.push_back(this);
// Expand permissions from config for faster lookup
void User::UnOper()
{
- if (!IS_OPER(this))
+ if (!this->IsOper())
return;
/*
this->modes[UM_OPERATOR] = 0;
}
-/* adds or updates an entry in the whowas list */
-void User::AddToWhoWas()
-{
- Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so");
- if (whowas)
- {
- WhowasRequest req(NULL, whowas, WhowasRequest::WHOWAS_ADD);
- req.user = this;
- req.Send();
- }
-}
-
/*
* Check class restrictions
*/
{
ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (local)");
if (a->maxconnwarn)
- ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString());
+ ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString().c_str());
return;
}
else if ((a->GetMaxGlobal()) && (ServerInstance->Users->GlobalCloneCount(this) > a->GetMaxGlobal()))
{
ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (global)");
if (a->maxconnwarn)
- ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s", a->GetMaxGlobal(), this->GetIPString());
+ ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s", a->GetMaxGlobal(), this->GetIPString().c_str());
return;
}
this->nping = ServerInstance->Time() + a->GetPingTime() + ServerInstance->Config->dns_timeout;
}
-bool User::CheckLines(bool doZline)
+bool LocalUser::CheckLines(bool doZline)
{
const char* check[] = { "G" , "K", (doZline) ? "Z" : NULL, NULL };
if (quitting)
return;
- if (ServerInstance->Config->WelcomeNotice)
- this->WriteServ("NOTICE Auth :Welcome to \002%s\002!",ServerInstance->Config->Network.c_str());
this->WriteNumeric(RPL_WELCOME, "%s :Welcome to the %s IRC Network %s",this->nick.c_str(), ServerInstance->Config->Network.c_str(), GetFullRealHost().c_str());
this->WriteNumeric(RPL_YOURHOSTIS, "%s :Your host is %s, running version %s",this->nick.c_str(),ServerInstance->Config->ServerName.c_str(),BRANCH);
this->WriteNumeric(RPL_SERVERCREATED, "%s :This server was created %s %s", this->nick.c_str(), __TIME__, __DATE__);
- std::string umlist = ServerInstance->Modes->UserModeList();
- std::string cmlist = ServerInstance->Modes->ChannelModeList();
- std::string pmlist = ServerInstance->Modes->ParaModeList();
- this->WriteNumeric(RPL_SERVERVERSION, "%s %s %s %s %s %s", this->nick.c_str(), ServerInstance->Config->ServerName.c_str(), BRANCH, umlist.c_str(), cmlist.c_str(), pmlist.c_str());
+ const std::string& modelist = ServerInstance->Modes->GetModeListFor004Numeric();
+ this->WriteNumeric(RPL_SERVERVERSION, "%s %s %s %s", this->nick.c_str(), ServerInstance->Config->ServerName.c_str(), BRANCH, modelist.c_str());
- ServerInstance->Config->Send005(this);
+ ServerInstance->ISupport.SendTo(this);
this->WriteNumeric(RPL_YOURUUID, "%s %s :your unique ID", this->nick.c_str(), this->uuid.c_str());
/* Now registered */
/* Trigger MOTD and LUSERS output, give modules a chance too */
ModResult MOD_RESULT;
- std::string command("MOTD");
+ std::string command("LUSERS");
std::vector<std::string> parameters;
FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true, command));
if (!MOD_RESULT)
ServerInstance->Parser->CallHandler(command, parameters, this);
MOD_RESULT = MOD_RES_PASSTHRU;
- command = "LUSERS";
+ command = "MOTD";
FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true, command));
if (!MOD_RESULT)
ServerInstance->Parser->CallHandler(command, parameters, this);
FOREACH_MOD(I_OnPostConnect,OnPostConnect(this));
ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d (class %s): %s (%s) [%s]",
- this->GetServerPort(), this->MyClass->name.c_str(), GetFullRealHost().c_str(), this->GetIPString(), this->fullname.c_str());
- ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCache: Adding NEGATIVE hit for %s", this->GetIPString());
+ this->GetServerPort(), this->MyClass->name.c_str(), GetFullRealHost().c_str(), this->GetIPString().c_str(), this->fullname.c_str());
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Adding NEGATIVE hit for " + this->GetIPString());
ServerInstance->BanCache->AddHit(this->GetIPString(), "", "");
// reset the flood penalty (which could have been raised due to things like auto +x)
CommandFloodPenalty = 0;
{
if (quitting)
{
- ServerInstance->Logs->Log("USERS", DEFAULT, "ERROR: Attempted to change nick of a quitting user: " + this->nick);
+ ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "ERROR: Attempted to change nick of a quitting user: " + this->nick);
return false;
}
- ModResult MOD_RESULT;
-
- if (force)
- ServerInstance->NICKForced.set(this, 1);
- FIRST_MOD_RESULT(OnUserPreNick, MOD_RESULT, (this, newnick));
- ServerInstance->NICKForced.set(this, 0);
-
- if (MOD_RESULT == MOD_RES_DENY)
+ if (!force)
{
- ServerInstance->stats->statsCollisions++;
- return false;
+ ModResult MOD_RESULT;
+ FIRST_MOD_RESULT(OnUserPreNick, MOD_RESULT, (this, newnick));
+
+ if (MOD_RESULT == MOD_RES_DENY)
+ {
+ ServerInstance->stats->statsCollisions++;
+ return false;
+ }
}
if (assign(newnick) == assign(nick))
return 0;
}
-const char* User::GetIPString()
+const std::string& User::GetIPString()
{
int port;
if (cachedip.empty())
{
irc::sockets::satoap(client_sa, cachedip, port);
/* IP addresses starting with a : on irc are a Bad Thing (tm) */
- if (cachedip.c_str()[0] == ':')
+ if (cachedip[0] == ':')
cachedip.insert(0,1,'0');
}
- return cachedip.c_str();
+ return cachedip;
}
irc::sockets::cidr_mask User::GetCIDRMask()
return;
}
- ServerInstance->Logs->Log("USEROUTPUT", RAWIO, "C[%s] O %s", uuid.c_str(), text.c_str());
+ ServerInstance->Logs->Log("USEROUTPUT", LOG_RAWIO, "C[%s] O %s", uuid.c_str(), text.c_str());
eh.AddWriteBuf(text);
eh.AddWriteBuf(wide_newline);
*/
void LocalUser::Write(const char *text, ...)
{
- va_list argsPtr;
- char textbuffer[MAXBUF];
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->Write(std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->Write(textbuffer);
}
void User::WriteServ(const std::string& text)
*/
void User::WriteServ(const char* text, ...)
{
- va_list argsPtr;
- char textbuffer[MAXBUF];
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteServ(std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteServ(textbuffer);
}
+void User::WriteNotice(const std::string& text)
+{
+ this->WriteServ("NOTICE " + (this->registered == REG_ALL ? this->nick : "*") + " :" + text);
+}
void User::WriteNumeric(unsigned int numeric, const char* text, ...)
{
- va_list argsPtr;
- char textbuffer[MAXBUF];
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteNumeric(numeric, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteNumeric(numeric, textbuffer);
}
void User::WriteNumeric(unsigned int numeric, const std::string &text)
void User::WriteFrom(User *user, const std::string &text)
{
- char tb[MAXBUF];
-
- snprintf(tb,MAXBUF,":%s %s",user->GetFullHost().c_str(),text.c_str());
-
- this->Write(std::string(tb));
+ const std::string message = ":" + user->GetFullHost() + " " + text;
+ this->Write(message);
}
void User::WriteFrom(User *user, const char* text, ...)
{
- va_list argsPtr;
- char textbuffer[MAXBUF];
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteFrom(user, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ this->WriteFrom(user, textbuffer);
}
void User::WriteTo(User *dest, const char *data, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
- va_start(argsPtr, data);
- vsnprintf(textbuffer, MAXBUF, data, argsPtr);
- va_end(argsPtr);
-
- this->WriteTo(dest, std::string(textbuffer));
+ std::string textbuffer;
+ VAFORMAT(textbuffer, data, data);
+ this->WriteTo(dest, textbuffer);
}
void User::WriteTo(User *dest, const std::string &data)
void User::WriteCommon(const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
if (this->registered != REG_ALL || quitting)
return;
- int len = snprintf(textbuffer,MAXBUF,":%s ",this->GetFullHost().c_str());
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer + len, MAXBUF - len, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteCommonRaw(std::string(textbuffer), true);
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ textbuffer = ":" + this->GetFullHost() + " " + textbuffer;
+ this->WriteCommonRaw(textbuffer, true);
}
void User::WriteCommonExcept(const char* text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
-
if (this->registered != REG_ALL || quitting)
return;
- int len = snprintf(textbuffer,MAXBUF,":%s ",this->GetFullHost().c_str());
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer + len, MAXBUF - len, text, argsPtr);
- va_end(argsPtr);
-
- this->WriteCommonRaw(std::string(textbuffer), false);
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ textbuffer = ":" + this->GetFullHost() + " " + textbuffer;
+ this->WriteCommonRaw(textbuffer, false);
}
void User::WriteCommonRaw(const std::string &line, bool include_self)
void User::WriteCommonQuit(const std::string &normal_text, const std::string &oper_text)
{
- char tb1[MAXBUF];
- char tb2[MAXBUF];
-
if (this->registered != REG_ALL)
return;
already_sent_t uniq_id = ++LocalUser::already_sent_id;
- snprintf(tb1,MAXBUF,":%s QUIT :%s",this->GetFullHost().c_str(),normal_text.c_str());
- snprintf(tb2,MAXBUF,":%s QUIT :%s",this->GetFullHost().c_str(),oper_text.c_str());
- std::string out1 = tb1;
- std::string out2 = tb2;
+ const std::string normalMessage = ":" + this->GetFullHost() + " QUIT :" + normal_text;
+ const std::string operMessage = ":" + this->GetFullHost() + " QUIT :" + oper_text;
UserChanList include_c(chans);
std::map<User*,bool> exceptions;
{
u->already_sent = uniq_id;
if (i->second)
- u->Write(IS_OPER(u) ? out2 : out1);
+ u->Write(u->IsOper() ? operMessage : normalMessage);
}
}
for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
if (u && !u->quitting && (u->already_sent != uniq_id))
{
u->already_sent = uniq_id;
- u->Write(IS_OPER(u) ? out2 : out1);
+ u->Write(u->IsOper() ? operMessage : normalMessage);
}
}
}
void User::SendText(const char *text, ...)
{
- va_list argsPtr;
- char line[MAXBUF];
-
- va_start(argsPtr, text);
- vsnprintf(line, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- SendText(std::string(line));
+ std::string line;
+ VAFORMAT(line, text, text);
+ SendText(line);
}
void User::SendText(const std::string &LinePrefix, std::stringstream &TextStream)
void User::DoHostCycle(const std::string &quitline)
{
- char buffer[MAXBUF];
-
if (!ServerInstance->Config->CycleHosts)
return;
for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
{
Channel* c = *v;
- snprintf(buffer, MAXBUF, ":%s JOIN %s", GetFullHost().c_str(), c->name.c_str());
- std::string joinline(buffer);
Membership* memb = c->GetUser(this);
- std::string modeline = memb->modes;
- if (modeline.length() > 0)
+ const std::string joinline = ":" + GetFullHost() + " JOIN " + c->name;
+ std::string modeline;
+
+ if (!memb->modes.empty())
{
- for(unsigned int i=0; i < memb->modes.length(); i++)
+ modeline = ":" + (ServerInstance->Config->CycleHostsFromUser ? GetFullHost() : ServerInstance->Config->ServerName)
+ + " MODE " + c->name + " +" + memb->modes;
+
+ for (size_t i = 0; i < memb->modes.length(); i++)
modeline.append(" ").append(nick);
- snprintf(buffer, MAXBUF, ":%s MODE %s +%s",
- ServerInstance->Config->CycleHostsFromUser ? GetFullHost().c_str() : ServerInstance->Config->ServerName.c_str(),
- c->name.c_str(), modeline.c_str());
- modeline = buffer;
}
const UserMembList *ulist = c->GetUsers();
u->already_sent = seen_id;
}
u->Write(joinline);
- if (modeline.length() > 0)
+ if (!memb->modes.empty())
u->Write(modeline);
}
}
void User::SendAll(const char* command, const char* text, ...)
{
- char textbuffer[MAXBUF];
- char formatbuffer[MAXBUF];
- va_list argsPtr;
-
- va_start(argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
- snprintf(formatbuffer,MAXBUF,":%s %s $* :%s", this->GetFullHost().c_str(), command, textbuffer);
- std::string fmt = formatbuffer;
+ std::string textbuffer;
+ VAFORMAT(textbuffer, text, text);
+ const std::string message = ":" + this->GetFullHost() + " " + command + " $* :" + textbuffer;
for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); i++)
{
if ((*i)->registered == REG_ALL)
- (*i)->Write(fmt);
- }
-}
-
-
-std::string User::ChannelList(User* source, bool spy)
-{
- std::string list;
-
- for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
- {
- Channel* c = *i;
- /* If the target is the sender, neither +p nor +s is set, or
- * the channel contains the user, it is not a spy channel
- */
- if (spy != (source == this || !(c->IsModeSet('p') || c->IsModeSet('s')) || c->HasUser(source)))
- list.append(c->GetPrefixChar(this)).append(c->name).append(" ");
- }
-
- return list;
-}
-
-void User::SplitChanList(User* dest, const std::string &cl)
-{
- std::string line;
- std::ostringstream prefix;
- std::string::size_type start, pos, length;
-
- prefix << this->nick << " " << dest->nick << " :";
- line = prefix.str();
- int namelen = ServerInstance->Config->ServerName.length() + 6;
-
- for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
- {
- length = (pos == std::string::npos) ? cl.length() : pos;
-
- if (line.length() + namelen + length - start > 510)
- {
- ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str());
- line = prefix.str();
- }
-
- if(pos == std::string::npos)
- {
- line.append(cl.substr(start, length - start));
- break;
- }
- else
- {
- line.append(cl.substr(start, length - start + 1));
- }
- }
-
- if (line.length() != prefix.str().length())
- {
- ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str());
+ (*i)->Write(message);
}
}
{
ConnectClass *found = NULL;
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Setting connect class for UID %s", this->uuid.c_str());
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Setting connect class for UID %s", this->uuid.c_str());
if (!explicit_name.empty())
{
if (explicit_name == c->name)
{
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Explicitly set to %s", explicit_name.c_str());
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Explicitly set to %s", explicit_name.c_str());
found = c;
}
}
for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
{
ConnectClass* c = *i;
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Checking %s", c->GetName().c_str());
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Checking %s", c->GetName().c_str());
ModResult MOD_RESULT;
FIRST_MOD_RESULT(OnSetConnectClass, MOD_RESULT, (this,c));
continue;
if (MOD_RESULT == MOD_RES_ALLOW)
{
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Class forced by module to %s", c->GetName().c_str());
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Class forced by module to %s", c->GetName().c_str());
found = c;
break;
}
if (!InspIRCd::MatchCIDR(this->GetIPString(), c->GetHost(), NULL) &&
!InspIRCd::MatchCIDR(this->host, c->GetHost(), NULL))
{
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "No host match (for %s)", c->GetHost().c_str());
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "No host match (for %s)", c->GetHost().c_str());
continue;
}
*/
if (c->limit && (c->GetReferenceCount() >= c->limit))
{
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "OOPS: Connect class limit (%lu) hit, denying", c->limit);
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "OOPS: Connect class limit (%lu) hit, denying", c->limit);
continue;
}
int port = c->config->getInt("port");
if (port)
{
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Requires port (%d)", port);
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Requires port (%d)", port);
/* and our port doesn't match, fail. */
if (this->GetServerPort() != port)
{
if (ServerInstance->PassCompare(this, c->config->getString("password"), password, c->config->getString("hash")))
{
- ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Bad password, skipping");
+ ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Bad password, skipping");
continue;
}
}
ConnectClass::ConnectClass(ConfigTag* tag, char t, const std::string& mask)
: config(tag), type(t), fakelag(true), name("unnamed"), registration_timeout(0), host(mask),
pingtime(0), softsendqmax(0), hardsendqmax(0), recvqmax(0),
- penaltythreshold(0), commandrate(0), maxlocal(0), maxglobal(0), maxconnwarn(true), maxchans(0), limit(0)
+ penaltythreshold(0), commandrate(0), maxlocal(0), maxglobal(0), maxconnwarn(true), maxchans(0),
+ limit(0), nouserdns(false)
{
}
softsendqmax(parent.softsendqmax), hardsendqmax(parent.hardsendqmax), recvqmax(parent.recvqmax),
penaltythreshold(parent.penaltythreshold), commandrate(parent.commandrate),
maxlocal(parent.maxlocal), maxglobal(parent.maxglobal), maxconnwarn(parent.maxconnwarn), maxchans(parent.maxchans),
- limit(parent.limit)
+ limit(parent.limit), nouserdns(parent.nouserdns)
{
}
maxconnwarn = src->maxconnwarn;
maxchans = src->maxchans;
limit = src->limit;
+ nouserdns = src->nouserdns;
}
#!/bin/sh
-echo "InspIRCd-2.0.13"
+echo "InspIRCd-2.2.0+pre"
+++ /dev/null
-/*
- * 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
- * License as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "inspircd.h"
-
-void InspIRCd::DoWhois(User* user, User* dest,unsigned long signon, unsigned long idle, const char* nick)
-{
- this->SendWhoisLine(user, dest, 311, "%s %s %s %s * :%s",user->nick.c_str(), dest->nick.c_str(), dest->ident.c_str(), dest->dhost.c_str(), dest->fullname.c_str());
- if (user == dest || user->HasPrivPermission("users/auspex"))
- {
- this->SendWhoisLine(user, dest, 378, "%s %s :is connecting from %s@%s %s", user->nick.c_str(), dest->nick.c_str(), dest->ident.c_str(), dest->host.c_str(), dest->GetIPString());
- }
-
- std::string cl = dest->ChannelList(user, false);
- const ServerConfig::OperSpyWhoisState state = user->HasPrivPermission("users/auspex") ? ServerInstance->Config->OperSpyWhois : ServerConfig::SPYWHOIS_NONE;
-
- if (state == ServerConfig::SPYWHOIS_SINGLEMSG)
- cl.append(dest->ChannelList(user, true));
-
- user->SplitChanList(dest,cl);
-
- if (state == ServerConfig::SPYWHOIS_SPLITMSG)
- {
- std::string scl = dest->ChannelList(user, true);
- if (scl.length())
- {
- SendWhoisLine(user, dest, 336, "%s %s :is on private/secret channels:",user->nick.c_str(), dest->nick.c_str());
- user->SplitChanList(dest,scl);
- }
- }
- if (user != dest && !this->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"))
- {
- this->SendWhoisLine(user, dest, 312, "%s %s %s :%s",user->nick.c_str(), dest->nick.c_str(), this->Config->HideWhoisServer.c_str(), this->Config->Network.c_str());
- }
- else
- {
- std::string serverdesc = GetServerDescription(dest->server);
- this->SendWhoisLine(user, dest, 312, "%s %s %s :%s",user->nick.c_str(), dest->nick.c_str(), dest->server.c_str(), serverdesc.c_str());
- }
-
- if (IS_AWAY(dest))
- {
- this->SendWhoisLine(user, dest, 301, "%s %s :%s",user->nick.c_str(), dest->nick.c_str(), dest->awaymsg.c_str());
- }
-
- if (IS_OPER(dest))
- {
- if (this->Config->GenericOper)
- this->SendWhoisLine(user, dest, 313, "%s %s :is an IRC operator",user->nick.c_str(), dest->nick.c_str());
- else
- this->SendWhoisLine(user, dest, 313, "%s %s :is %s %s on %s",user->nick.c_str(), dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->NameStr(), this->Config->Network.c_str());
- }
-
- if (user == dest || user->HasPrivPermission("users/auspex"))
- {
- if (dest->IsModeSet('s') != 0)
- {
- this->SendWhoisLine(user, dest, 379, "%s %s :is using modes +%s +%s", user->nick.c_str(), dest->nick.c_str(), dest->FormatModes(), dest->FormatNoticeMasks());
- }
- else
- {
- this->SendWhoisLine(user, dest, 379, "%s %s :is using modes +%s", user->nick.c_str(), dest->nick.c_str(), dest->FormatModes());
- }
- }
-
- FOREACH_MOD(I_OnWhois,OnWhois(user,dest));
-
- /*
- * We only send these if we've been provided them. That is, if hidewhois is turned off, and user is local, or
- * if remote whois is queried, too. This is to keep the user hidden, and also since you can't reliably tell remote time. -- w00t
- */
- if ((idle) || (signon))
- {
- this->SendWhoisLine(user, dest, 317, "%s %s %lu %lu :seconds idle, signon time",user->nick.c_str(), dest->nick.c_str(), idle, signon);
- }
-
- this->SendWhoisLine(user, dest, 318, "%s %s :End of /WHOIS list.",user->nick.c_str(), dest->nick.c_str());
-}
-
-
-
* Below here is all wrappers around match_internal
********************************************************************/
-CoreExport bool InspIRCd::Match(const std::string &str, const std::string &mask, unsigned const char *map)
+bool InspIRCd::Match(const std::string &str, const std::string &mask, unsigned const char *map)
{
if (!map)
map = national_case_insensitive_map;
return match_internal((const unsigned char *)str.c_str(), (const unsigned char *)mask.c_str(), map);
}
-CoreExport bool InspIRCd::Match(const char *str, const char *mask, unsigned const char *map)
+bool InspIRCd::Match(const char *str, const char *mask, unsigned const char *map)
{
if (!map)
map = national_case_insensitive_map;
return match_internal((const unsigned char *)str, (const unsigned char *)mask, map);
}
-CoreExport bool InspIRCd::MatchCIDR(const std::string &str, const std::string &mask, unsigned const char *map)
+bool InspIRCd::MatchCIDR(const std::string &str, const std::string &mask, unsigned const char *map)
{
if (irc::sockets::MatchCIDR(str, mask, true))
return true;
return InspIRCd::Match(str, mask, map);
}
-CoreExport bool InspIRCd::MatchCIDR(const char *str, const char *mask, unsigned const char *map)
+bool InspIRCd::MatchCIDR(const char *str, const char *mask, unsigned const char *map)
{
if (irc::sockets::MatchCIDR(str, mask, true))
return true;
return InspIRCd::Match(str, mask, map);
}
+bool InspIRCd::MatchMask(const std::string& masks, const std::string& hostname, const std::string& ipaddr)
+{
+ std::stringstream masklist(masks);
+ std::string mask;
+ while (masklist >> mask)
+ {
+ if (InspIRCd::Match(hostname, mask, ascii_case_insensitive_map) ||
+ InspIRCd::MatchCIDR(ipaddr, mask, ascii_case_insensitive_map))
+ {
+ return true;
+ }
+ }
+ return false;
+}
for (LocalUserList::const_iterator u2 = ServerInstance->Users->local_users.begin(); u2 != ServerInstance->Users->local_users.end(); u2++)
{
- User* u = (User*)(*u2);
+ LocalUser* u = *u2;
/* This uses safe iteration to ensure that if a line expires here, it doenst trash the iterator */
LookupIter safei;
ContainerIter x = lookup_lines.find(line->type);
if (x != lookup_lines.end())
{
- LookupIter i = x->second.find(line->Displayable());
+ LookupIter i = x->second.find(line->Displayable().c_str());
if (i != x->second.end())
{
// XLine propagation bug was here, if the line to be added already exists and
if (xlf->AutoApplyToUserList(line))
pending_lines.push_back(line);
- lookup_lines[line->type][line->Displayable()] = line;
+ lookup_lines[line->type][line->Displayable().c_str()] = line;
line->OnAdd();
FOREACH_MOD(I_OnAddLine,OnAddLine(user, line));
/* remove exempt from everyone and force recheck after deleting eline */
for (LocalUserList::const_iterator u2 = ServerInstance->Users->local_users.begin(); u2 != ServerInstance->Users->local_users.end(); u2++)
{
- User* u = (User*)(*u2);
+ LocalUser* u = *u2;
u->exempt = false;
}
LocalUserList::reverse_iterator u2 = ServerInstance->Users->local_users.rbegin();
while (u2 != ServerInstance->Users->local_users.rend())
{
- User* u = *u2++;
+ LocalUser* u = *u2++;
// Don't ban people who are exempt.
if (u->exempt)
void XLine::DefaultApply(User* u, const std::string &line, bool bancache)
{
- char sreason[MAXBUF];
- snprintf(sreason, MAXBUF, "%s-Lined: %s", line.c_str(), this->reason.c_str());
+ const std::string banReason = line + "-Lined: " + reason;
+
if (!ServerInstance->Config->MoronBanner.empty())
- u->WriteServ("NOTICE %s :*** %s", u->nick.c_str(), ServerInstance->Config->MoronBanner.c_str());
+ u->WriteNotice("*** " + ServerInstance->Config->MoronBanner);
if (ServerInstance->Config->HideBans)
- ServerInstance->Users->QuitUser(u, line + "-Lined", sreason);
+ ServerInstance->Users->QuitUser(u, line + "-Lined", banReason.c_str());
else
- ServerInstance->Users->QuitUser(u, sreason);
+ ServerInstance->Users->QuitUser(u, banReason);
if (bancache)
{
- ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCache: Adding positive hit (" + line + ") for " + u->GetIPString());
- if (this->duration > 0)
- ServerInstance->BanCache->AddHit(u->GetIPString(), this->type, line + "-Lined: " + this->reason, this->duration);
- else
- ServerInstance->BanCache->AddHit(u->GetIPString(), this->type, line + "-Lined: " + this->reason);
+ ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Adding positive hit (" + line + ") for " + u->GetIPString());
+ ServerInstance->BanCache->AddHit(u->GetIPString(), this->type, line + "-Lined: " + this->reason, this->duration);
}
}
bool KLine::Matches(User *u)
{
- if (u->exempt)
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu && lu->exempt)
return false;
if (InspIRCd::Match(u->ident, this->identmask, ascii_case_insensitive_map))
bool GLine::Matches(User *u)
{
- if (u->exempt)
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu && lu->exempt)
return false;
if (InspIRCd::Match(u->ident, this->identmask, ascii_case_insensitive_map))
bool ELine::Matches(User *u)
{
- if (u->exempt)
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu && lu->exempt)
return false;
if (InspIRCd::Match(u->ident, this->identmask, ascii_case_insensitive_map))
bool ZLine::Matches(User *u)
{
- if (u->exempt)
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu && lu->exempt)
return false;
if (InspIRCd::MatchCIDR(u->GetIPString(), this->ipaddr))
void QLine::Apply(User* u)
{
/* Force to uuid on apply of qline, no need to disconnect any more :) */
- u->ForceNickChange(u->uuid.c_str());
+ u->ForceNickChange(u->uuid);
}
/* When adding one eline, only check the one eline */
for (LocalUserList::const_iterator u2 = ServerInstance->Users->local_users.begin(); u2 != ServerInstance->Users->local_users.end(); u2++)
{
- User* u = (User*)(*u2);
+ LocalUser* u = *u2;
if (this->Matches(u))
u->exempt = true;
}
}
-void ELine::DisplayExpiry()
-{
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired E-Line %s@%s (set by %s %ld seconds ago)",
- identmask.c_str(),hostmask.c_str(),source.c_str(),(long)(ServerInstance->Time() - this->set_time));
-}
-
-void QLine::DisplayExpiry()
-{
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired Q-Line %s (set by %s %ld seconds ago)",
- nick.c_str(),source.c_str(),(long)(ServerInstance->Time() - this->set_time));
-}
-
-void ZLine::DisplayExpiry()
-{
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired Z-Line %s (set by %s %ld seconds ago)",
- ipaddr.c_str(),source.c_str(),(long)(ServerInstance->Time() - this->set_time));
-}
-
-void KLine::DisplayExpiry()
-{
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired K-Line %s@%s (set by %s %ld seconds ago)",
- identmask.c_str(),hostmask.c_str(),source.c_str(),(long)(ServerInstance->Time() - this->set_time));
-}
-
-void GLine::DisplayExpiry()
+void XLine::DisplayExpiry()
{
- ServerInstance->SNO->WriteToSnoMask('x',"Removing expired G-Line %s@%s (set by %s %ld seconds ago)",
- identmask.c_str(),hostmask.c_str(),source.c_str(),(long)(ServerInstance->Time() - this->set_time));
+ bool onechar = (type.length() == 1);
+ ServerInstance->SNO->WriteToSnoMask('x', "Removing expired %s%s %s (set by %s %ld seconds ago)",
+ type.c_str(), (onechar ? "-Line" : ""), Displayable().c_str(), source.c_str(), (long)(ServerInstance->Time() - set_time));
}
-const char* ELine::Displayable()
+const std::string& ELine::Displayable()
{
- return matchtext.c_str();
+ return matchtext;
}
-const char* KLine::Displayable()
+const std::string& KLine::Displayable()
{
- return matchtext.c_str();
+ return matchtext;
}
-const char* GLine::Displayable()
+const std::string& GLine::Displayable()
{
- return matchtext.c_str();
+ return matchtext;
}
-const char* ZLine::Displayable()
+const std::string& ZLine::Displayable()
{
- return ipaddr.c_str();
+ return ipaddr;
}
-const char* QLine::Displayable()
+const std::string& QLine::Displayable()
{
- return nick.c_str();
+ return nick;
}
bool KLine::IsBurstable()
+++ /dev/null
-#!/usr/bin/perl
-
-#
-# InspIRCd -- Internet Relay Chat Daemon
-#
-# Copyright (C) 2007 Craig Edwards <craigedwards@brainbox.cc>
-#
-# 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/>.
-#
-
-
-use strict;
-use warnings;
-
-my $maxparams = shift;
-
-die "You must supply a number of parameters to generate headers allowing for!" unless(defined $maxparams);
-die "You must request a non-negative parameter limit!" unless($maxparams >= 0);
-
-print STDERR "Generating headerfile for a maximium of $maxparams parameters\n";
-
-# First generate the HanderBase family
-
-my @templatetypes = ('ReturnType');
-for(my $i = 0; $i <= $maxparams; $i++)
-{
- push @templatetypes, "Param" . $i if($i > 0);
- print "template <typename " . join(', typename ', @templatetypes) . "> class CoreExport HandlerBase" . $i . "\n";
- print "{\n";
- print " public:\n";
- print " virtual ReturnType Call(" . join(', ', @templatetypes[1..$#templatetypes]) . ") = 0;\n";
- print " virtual ~HandlerBase" . $i . "() { }\n";
- print "};\n\n";
-}
-
-# And now the caller family
-
-print "template <typename HandlerType> class CoreExport caller\n";
-print "{\n";
-print " public:\n";
-print " HandlerType* target;\n\n";
-print " caller(HandlerType* initial)\n";
-print " : target(initial)\n";
-print " { }\n\n";
-print " virtual ~caller() { }\n\n";
-print " caller& operator=(HandlerType* newtarget)\n";
-print " {\n";
-print " target = newtarget;\n";
-print " return *this;\n";
-print " }\n";
-print "};\n\n";
-
-
-
-
-@templatetypes = ('ReturnType');
-for(my $i = 0; $i <= $maxparams; $i++)
-{
- push @templatetypes, "Param" . $i if($i > 0);
-
- my $handlertype = "HandlerBase" . $i . "<" . join(', ', @templatetypes) . ">";
- my @templatetypepairs = map { $_ . " " . lc($_) } @templatetypes;
- my @lctemplatetypes = map(lc, @templatetypes);
-
- print "template <typename " . join(', typename ', @templatetypes) . "> class CoreExport caller" . $i . " : public caller< " . $handlertype . " >\n";
- print "{\n";
- print " public:\n";
- print " caller" . $i . "(" . $handlertype . "* initial)\n";
- print " : caller< " . $handlertype. " >::caller(initial)\n";
- print " { }\n\n";
- print " virtual ReturnType operator() (" . join(', ', @templatetypepairs[1..$#templatetypepairs]) . ")\n";
- print " {\n";
- print " return this->target->Call(" . join(', ', @lctemplatetypes[1..$#lctemplatetypes]) . ");\n";
- print " }\n";
- print "};\n\n";
-}
-
--- /dev/null
+#!/usr/bin/env perl
+#
+# InspIRCd -- Internet Relay Chat Daemon
+#
+# Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+# Copyright (C) 2007 Craig Edwards <craigedwards@brainbox.cc>
+# Copyright (C) 2013 Peter Powell <petpow@saberuk.com>
+#
+# This file is part of InspIRCd. InspIRCd is free software: you can
+# redistribute it and/or modify it under the terms of the GNU General Public
+# 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/>.
+#
+
+
+BEGIN {
+ require 5.8.0;
+}
+
+use strict;
+use warnings FATAL => qw(all);
+
+use File::Temp();
+
+# IMPORTANT: This script has to be able to run by itself so that it can be used
+# by binary distributions where the make/utilities.pm module will not
+# be available!
+
+sub prompt($$) {
+ my ($question, $default) = @_;
+ print "$question\n";
+ print "[$default] => ";
+ chomp(my $answer = <STDIN>);
+ print "\n";
+ return $answer ? $answer : $default;
+}
+
+if ($#ARGV != 0 || $ARGV[0] !~ /gnutls|openssl/i) {
+ print "Syntax: genssl <gnutls|openssl>\n";
+ exit 1;
+}
+
+my $common_name = prompt('What is the hostname of your server?', 'irc.example.com');
+my $email = prompt('What email address can you be contacted at?', 'example@example.com');
+my $unit = prompt('What is the name of your unit?', 'Server Admins');
+my $organization = prompt('What is the name of your organization?', 'Example IRC Network');
+my $city = prompt('What city are you located in?', 'Example City');
+my $state = prompt('What state are you located in?', 'Example State');
+my $country = prompt('What is the ISO 3166-1 code for the country you are located in?', 'XZ');
+my $days = prompt('How many days do you want your certificate to be valid for?', '365');
+
+# Contains the exit code of openssl/gnutls-certtool.
+my $status = 0;
+
+if (lc $ARGV[0] eq 'gnutls') {
+ my $tmp = new File::Temp();
+ print $tmp <<__GNUTLS_END__;
+cn = "$common_name"
+email = "$email"
+unit = "$unit"
+organization = "$organization"
+locality = "$city"
+state = "$state"
+country = "$country"
+expiration_days = $days
+tls_www_client
+tls_www_server
+signing_key
+encryption_key
+cert_signing_key
+crl_signing_key
+code_signing_key
+ocsp_signing_key
+time_stamping_key
+__GNUTLS_END__
+ close($tmp);
+ my $certtool = `uname -s` eq "Darwin\n" ? 'gnutls-certtool' : 'certtool';
+ $status ||= system "$certtool --version >/dev/null 2>&1";
+ $status ||= system "$certtool --generate-privkey --outfile key.pem";
+ $status ||= system "$certtool --generate-self-signed --load-privkey key.pem --outfile cert.pem --template $tmp";
+ $status ||= system "$certtool --generate-dh-params --bits 2048 --outfile dhparams.pem";
+} elsif (lc $ARGV[0] eq 'openssl') {
+ my $tmp = new File::Temp();
+ print $tmp <<__OPENSSL_END__;
+$country
+$state
+$city
+$organization
+$unit
+$common_name
+$email
+__OPENSSL_END__
+ close($tmp);
+ $status ||= system 'openssl version >/dev/null 2>&1';
+ $status ||= system "cat $tmp | openssl req -x509 -nodes -newkey rsa:2048 -keyout key.pem -out cert.pem -days $days 2>/dev/null";
+ $status ||= system 'openssl dhparam -out dhparams.pem 2048';
+}
+
+if ($status) {
+ print "SSL generation failed! Are you missing an $ARGV[0] binary package?\n";
+ exit 1;
+}
+
-inspircd_version.h\r
-inspircd_config.h\r
+config.h\r
inspircd.rc\r
endif(MSVC)
configure_file("${INSPIRCD_BASE}/win/inspircd.rc.cmake" "${INSPIRCD_BASE}/win/inspircd.rc")
-configure_file("${INSPIRCD_BASE}/win/inspircd_version.h.cmake" "${INSPIRCD_BASE}/win/inspircd_version.h")
-configure_file("${INSPIRCD_BASE}/win/inspircd_config.h.cmake" "${INSPIRCD_BASE}/win/inspircd_config.h")
+configure_file("${INSPIRCD_BASE}/win/config.h.cmake" "${INSPIRCD_BASE}/win/config.h")
add_executable(inspircd ${INSPIRCD_SOURCES} "${INSPIRCD_BASE}/win/inspircd.rc")
target_link_libraries(inspircd win32_memory)
--- /dev/null
+#pragma once\r
+\r
+#define BRANCH "@MAJOR_VERSION@.@MINOR_VERSION@"\r
+#define VERSION "@FULL_VERSION@"\r
+#define REVISION "0"\r
+#define SYSTEM "@CMAKE_SYSTEM@"\r
+\r
+#define CONFIG_PATH "@CONF_PATH@"\r
+#define MOD_PATH "@MODULE_PATH@"\r
+#define DATA_PATH "@DATA_PATH@"\r
+#define LOG_PATH "@LOG_PATH@"\r
+#define MAXBUF 514\r
+\r
+#include "inspircd_win32wrapper.h"\r
+#include "threadengines/threadengine_win32.h"\r
+++ /dev/null
-#ifndef INSPIRCD_CONFIG_H\r
-#define INSPIRCD_CONFIG_H\r
-\r
-#define CONFIG_PATH "@CONF_PATH@"\r
-#define MOD_PATH "@MODULE_PATH@"\r
-#define DATA_PATH "@DATA_PATH@"\r
-#define LOG_PATH "@LOG_PATH@"\r
-#define MAXBUF 514\r
-\r
-#include "inspircd_win32wrapper.h"\r
-#include "threadengines/threadengine_win32.h"\r
-\r
-#endif
\ No newline at end of file
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include <windows.h>
#include <exception>
#include <new>
+++ /dev/null
-#define BRANCH "@MAJOR_VERSION@.@MINOR_VERSION@"\r
-#define VERSION "@FULL_VERSION@"\r
-#define REVISION "0"\r
-#define SYSTEM "@CMAKE_SYSTEM@"
\ No newline at end of file
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include "inspircd_win32wrapper.h"
#include "inspircd.h"
#include "configreader.h"
}
return 1;
}
-
+
return 0;
}
// optind++; // Trash this next argument, we won't be needing it.
par = ___argv[optind-1];
}
- }
+ }
// increment the argument for next time
// optind++;
{
if (__longopts[i].val == -1 || par == 0)
return 1;
-
+
return __longopts[i].val;
- }
+ }
break;
}
}
}
#include "../src/modules/m_spanningtree/link.h"
-#include "../src/modules/ssl.h"
+#include "modules/ssl.h"
template class reference<Link>;
template class reference<Autoconnect>;
template class reference<ssl_cert>;
*/
+#pragma once
+
/* Windows Port
Wrapper Functions/Definitions
By Burlex */
-
-#ifndef INSPIRCD_WIN32WRAPPER_H
-#define INSPIRCD_WIN32WRAPPER_H
-
/*
* Starting with PSAPI version 2 for Windows 7 and Windows Server 2008 R2, this function is defined as K32GetProcessMemoryInfo in Psapi.h and exported
* in Kernel32.lib and Kernel32.dll. However, you should always call this function as GetProcessMemoryInfo. To ensure correct resolution of symbols
#define VC_EXTRALEAN
#define WIN32_LEAN_AND_MEAN
-/* They just have to be *different*, don't they. */
-#define PATH_MAX MAX_PATH
-
/* Macros for exporting symbols - dependant on what is being compiled */
#ifdef DLL_BUILD
#include <direct.h>
#include <process.h>
+/* Windows defines this already. */
+#undef ERROR
+
/* strcasecmp is not defined on windows by default */
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define snprintf _snprintf
#define vsnprintf _vsnprintf
+#ifndef va_copy
+#define va_copy(dest, src) (dest = src)
+#endif
+
/* Unix-style sleep (argument is in seconds) */
__inline void sleep(int seconds) { Sleep(seconds * 1000); }
char szErrorString[500];
DWORD dwErrorCode;
};
-
-#endif
-
*/
-#include "inspircd_config.h"
+#include "config.h"
#include "inspircd.h"
#include "exitcodes.h"
#include <windows.h>
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#pragma once
+
#ifdef _WIN32
/* Hook for win32service.cpp to exit properly with the service specific error code */