summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/bancache.h39
-rw-r--r--include/base.h38
-rw-r--r--include/builtinmodes.h178
-rw-r--r--include/caller.h76
-rw-r--r--include/channels.h216
-rw-r--r--include/command_parse.h94
-rw-r--r--include/commands/cmd_whowas.h66
-rw-r--r--include/compat.h114
-rw-r--r--include/configparser.h6
-rw-r--r--include/configreader.h250
-rw-r--r--include/consolecolors.h6
-rw-r--r--include/ctables.h61
-rw-r--r--include/cull_list.h6
-rw-r--r--include/dns.h443
-rw-r--r--include/dynamic.h6
-rw-r--r--include/dynref.h99
-rw-r--r--include/exitcodes.h33
-rw-r--r--include/extensible.h30
-rw-r--r--include/filelogger.h26
-rw-r--r--include/fileutils.h87
-rw-r--r--include/hash_map.h59
-rw-r--r--include/hashcomp.h303
-rw-r--r--include/inspircd.h427
-rw-r--r--include/inspsocket.h29
-rw-r--r--include/inspstring.h52
-rw-r--r--include/intrusive_list.h162
-rw-r--r--include/iohook.h89
-rw-r--r--include/listmode.h206
-rw-r--r--include/logger.h35
-rw-r--r--include/membership.h52
-rw-r--r--include/mode.h405
-rw-r--r--include/modes/cmode_b.h41
-rw-r--r--include/modes/cmode_l.h30
-rw-r--r--include/modes/cmode_v.h37
-rw-r--r--include/modes/simplemodes.h100
-rw-r--r--include/modes/umode_s.h34
-rw-r--r--include/modules.h619
-rw-r--r--include/modules/account.h (renamed from include/modes/cmode_o.h)30
-rw-r--r--include/modules/cap.h88
-rw-r--r--include/modules/dns.h193
-rw-r--r--include/modules/hash.h58
-rw-r--r--include/modules/httpd.h239
-rw-r--r--include/modules/ldap.h199
-rw-r--r--include/modules/regex.h62
-rw-r--r--include/modules/sasl.h (renamed from include/modes/umode_o.h)18
-rw-r--r--include/modules/spanningtree.h (renamed from include/modes/cmode_k.h)29
-rw-r--r--include/modules/sql.h184
-rw-r--r--include/modules/ssl.h246
-rw-r--r--include/numerics.h233
-rw-r--r--include/parammode.h75
-rw-r--r--include/protocol.h133
-rw-r--r--include/server.h68
-rw-r--r--include/snomasks.h52
-rw-r--r--include/socket.h29
-rw-r--r--include/socketengine.h173
-rw-r--r--include/stdalgo.h97
-rw-r--r--include/testsuite.h6
-rw-r--r--include/threadengine.h8
-rw-r--r--include/threadengines/threadengine_pthread.h6
-rw-r--r--include/threadengines/threadengine_win32.h8
-rw-r--r--include/timer.h65
-rw-r--r--include/typedefs.h44
-rw-r--r--include/uid.h44
-rw-r--r--include/usermanager.h145
-rw-r--r--include/users.h331
-rw-r--r--include/xline.h31
66 files changed, 4266 insertions, 3182 deletions
diff --git a/include/bancache.h b/include/bancache.h
index a7aac7f17..7f51ca75e 100644
--- a/include/bancache.h
+++ b/include/bancache.h
@@ -18,8 +18,7 @@
*/
-#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
@@ -37,68 +36,50 @@ class CoreExport BanCacheHit
/** 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
diff --git a/include/base.h b/include/base.h
index 0a4456f3a..dcbb2e5c7 100644
--- a/include/base.h
+++ b/include/base.h
@@ -20,8 +20,7 @@
*/
-#ifndef BASE_H
-#define BASE_H
+#pragma once
#include <map>
#include <deque>
@@ -180,21 +179,23 @@ class reference
*/
class CoreExport CoreException : public std::exception
{
- public:
+ protected:
/** Holds the error message to be displayed
*/
const std::string err;
/** Source of the exception
*/
const std::string source;
- /** Default constructor, just uses the error mesage 'Core threw an exception'.
- */
- CoreException() : err("Core threw an exception"), source("The core") {}
+
+ public:
/** This constructor can be used to specify an error message before throwing.
+ * @param message Human readable error message
*/
CoreException(const std::string &message) : err(message), source("The core") {}
/** This constructor can be used to specify an error message before throwing,
* and to specify the source of the exception.
+ * @param message Human readable error message
+ * @param src Source of the exception
*/
CoreException(const std::string &message, const std::string &src) : err(message), source(src) {}
/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
@@ -203,17 +204,14 @@ class CoreExport CoreException : public std::exception
*/
virtual ~CoreException() throw() {};
/** Returns the reason for the exception.
- * The module should probably put something informative here as the user will see this upon failure.
+ * @return Human readable description of the error
*/
- virtual const char* GetReason()
- {
- return err.c_str();
- }
+ const std::string& GetReason() const { return err; }
- virtual const char* GetSource()
- {
- return source.c_str();
- }
+ /** Returns the source of the exception
+ * @return Source of the exception
+ */
+ const std::string& GetSource() const { return source; }
};
class Module;
@@ -250,10 +248,10 @@ class CoreExport ServiceProvider : public classbase
const std::string name;
/** Type of service (must match object type) */
const ServiceType service;
- ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type)
- : creator(Creator), name(Name), service(Type) {}
+ ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type);
virtual ~ServiceProvider();
-};
-
-#endif
+ /** If called, this ServiceProvider won't be registered automatically
+ */
+ void DisableAutoRegister();
+};
diff --git a/include/builtinmodes.h b/include/builtinmodes.h
new file mode 100644
index 000000000..e78e68b11
--- /dev/null
+++ b/include/builtinmodes.h
@@ -0,0 +1,178 @@
+/*
+ * 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 ParamMode<ModeChannelKey, LocalStringExt>
+{
+ public:
+ ModeChannelKey();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
+ void SerializeParam(Channel* chan, const std::string* key, std::string& out);
+ ModeAction OnSet(User* source, Channel* chan, std::string& param);
+};
+
+/** Channel mode +l
+ */
+class ModeChannelLimit : public ParamMode<ModeChannelLimit, LocalIntExt>
+{
+ public:
+ ModeChannelLimit();
+ bool ResolveModeConflict(std::string &their_param, const std::string &our_param, Channel* channel);
+ void SerializeParam(Channel* chan, intptr_t n, std::string& out);
+ ModeAction OnSet(User* source, Channel* channel, std::string& parameter);
+};
+
+/** 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 PrefixMode
+{
+ public:
+ ModeChannelOp();
+};
+
+/** 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 PrefixMode
+{
+ public:
+ ModeChannelVoice();
+};
+
+/** User mode +i
+ */
+class ModeUserInvisible : public SimpleUserModeHandler
+{
+ public:
+ ModeUserInvisible() : SimpleUserModeHandler(NULL, "invisible", 'i')
+ {
+ }
+};
+
+/** User mode +s
+ */
+class ModeUserServerNoticeMask : public ModeHandler
+{
+ /** Process a snomask modifier string, e.g. +abc-de
+ * @param user The target user
+ * @param input A sequence of notice mask characters
+ * @return The cleaned mode sequence which can be output,
+ * e.g. in the above example if masks c and e are not
+ * valid, this function will return +ab-d
+ */
+ std::string ProcessNoticeMasks(User* user, const std::string& input);
+
+ public:
+ ModeUserServerNoticeMask();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
+ void OnParameterMissing(User* user, User* dest, Channel* channel);
+
+ /** Create a displayable mode string of the snomasks set on a given user
+ * @param user The user whose notice masks to format
+ * @return The notice mask character sequence
+ */
+ std::string GetUserParameter(User* user);
+};
+
+/** User mode +o
+ */
+class ModeUserOperator : public ModeHandler
+{
+ public:
+ ModeUserOperator();
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
+};
diff --git a/include/caller.h b/include/caller.h
index 64b37611f..c3a29e8c2 100644
--- a/include/caller.h
+++ b/include/caller.h
@@ -3,6 +3,7 @@
*
* 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
@@ -18,8 +19,79 @@
*/
-#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
diff --git a/include/channels.h b/include/channels.h
index dda53f69d..628f34f9f 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -20,75 +20,60 @@
*/
-#ifndef CHANNELS_H
-#define CHANNELS_H
+#pragma once
#include "membership.h"
#include "mode.h"
+#include "parammode.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,
* etc, and an instance of the BanList type.
*/
-class CoreExport Channel : public Extensible, public InviteBase
+class CoreExport Channel : public Extensible, public InviteBase<Channel>
{
- /** 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
- * for mode +A, index 0. Use modechar-65 to calculate which
- * field to check.
+ * It is a bitset where each item in it represents if a mode is set.
+ * To see if a mode is set, inspect modes[mh->modeid]
*/
- std::bitset<64> modes;
+ std::bitset<ModeParser::MODEID_MAX> modes;
- /** Parameters for custom modes.
- * One for each custom mode letter.
+ /** 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
*/
- CustomModeList custom_mode_params;
+ void DelUser(const UserMembIter& membiter);
public:
/** Creates a channel record and initialises it with default values
- * @throw Nothing at present.
+ * @param name The name of the channel
+ * @param ts The creation time of the channel
+ * @throw CoreException if this channel name is in use
*/
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;
@@ -116,32 +101,19 @@ class CoreExport Channel : public Extensible, public InviteBase
*/
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
*/
void SetMode(ModeHandler* mode, bool value);
- void SetMode(char mode,bool mode_on);
-
- /** Sets or unsets a custom mode in the channels info
- * @param mode The mode character to set or unset
- * @param parameter The parameter string to associate with this mode character.
- * If it is empty, the mode is unset; if it is nonempty, the mode is set.
- */
- void SetModeParam(ModeHandler* mode, const std::string& parameter);
- void SetModeParam(char mode, const std::string& parameter);
/** Returns true if a mode is set on a channel
* @param mode The mode character you wish to query
* @return True if the custom mode is set, false if otherwise
*/
- inline bool IsModeSet(char mode) { return modes[mode-'A']; }
- inline bool IsModeSet(ModeHandler* mode) { return modes[mode->GetModeChar()-'A']; }
-
+ bool IsModeSet(ModeHandler* mode) { return ((mode->GetId() != ModeParser::MODEID_MAX) && (modes[mode->GetId()])); }
+ bool IsModeSet(ModeHandler& mode) { return IsModeSet(&mode); }
+ bool IsModeSet(ChanModeReference& mode);
/** Returns the parameter for a custom mode on a channel.
* @param mode The mode character you wish to query
@@ -153,24 +125,22 @@ class CoreExport Channel : public Extensible, public InviteBase
*
* @return The parameter for this mode is returned, or an empty string
*/
- std::string GetModeParameter(char mode);
std::string GetModeParameter(ModeHandler* mode);
+ std::string GetModeParameter(ChanModeReference& mode);
+ std::string GetModeParameter(ParamModeBase* pm);
/** Sets the channel topic.
- * @param u The user setting the topic
- * @param t The topic to set it to. Non-const, as it may be modified by a hook.
- * @param forceset If set to true then all access checks will be bypassed.
+ * @param user The user setting the topic.
+ * @param topic The topic to set it to.
*/
- int SetTopic(User *u, std::string &t, bool forceset = false);
+ void SetTopic(User* user, const std::string& topic);
/** 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
@@ -196,7 +166,7 @@ class CoreExport Channel : public Extensible, public InviteBase
*
* @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
@@ -210,8 +180,9 @@ class CoreExport Channel : public Extensible, public InviteBase
* @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.
@@ -220,16 +191,24 @@ class CoreExport Channel : public Extensible, public InviteBase
*/
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(User *user, const char* cn, bool override, const char* key, bool bursting, time_t TS = 0);
+ 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_by_local True if this channel was just created by a local user (passed to modules in the OnUserJoin hook)
+ */
+ 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
@@ -301,49 +280,18 @@ class CoreExport Channel : public Extensible, public InviteBase
/** 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 '&lt;KEY&gt;'
* @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.
- * Unlike GetStatus and GetStatusFlags which will only return the
- * core specified modes @, % and + (op, halfop and voice), GetPrefixChar
- * will also return module-defined prefixes. If the user has to prefix,
- * an empty but non-null string is returned. If the user has multiple
- * prefixes, the highest is returned. If you do not recognise the prefix
- * character you can get, you can deal with it in a 'proprtional' manner
- * compared to known prefixes, using GetPrefixValue().
- */
- const char* GetPrefixChar(User *user);
-
- /** Return all of a users mode prefixes into a char* string.
- * @param user The user to look up
- * @return A list of all prefix characters. The prefixes will always
- * be in rank order, greatest first, as certain IRC clients require
- * this when multiple prefixes are used names lists.
- */
- const char* GetAllPrefixChars(User* user);
-
/** Get the value of a users prefix on this channel.
* @param user The user to look up
* @return The module or core-defined value of the users prefix.
@@ -357,24 +305,6 @@ class CoreExport Channel : public Extensible, public InviteBase
*/
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
- * the channel (to grant ops to them)
- * @param user The user to associate the privilage with
- * @param prefix The prefix character to associate
- * @param adding True if adding the prefix, false when removing
- * @return True if a change was made
- */
- bool SetPrefix(User* user, char prefix, bool adding);
-
/** Check if a user is banned on this channel
* @param user A user to check against the banlist
* @returns True if the user given is banned
@@ -388,10 +318,40 @@ class CoreExport Channel : public Extensible, public InviteBase
/** 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());
+}
+
+inline std::string Channel::GetModeParameter(ChanModeReference& mode)
+{
+ if (!mode)
+ return "";
+ return GetModeParameter(*mode);
+}
+
+inline std::string Channel::GetModeParameter(ModeHandler* mh)
+{
+ std::string out;
+ ParamModeBase* pm = mh->IsParameterMode();
+ if (pm && this->IsModeSet(pm))
+ pm->GetParameter(this, out);
+ return out;
+}
+
+inline std::string Channel::GetModeParameter(ParamModeBase* pm)
+{
+ std::string out;
+ if (this->IsModeSet(pm))
+ pm->GetParameter(this, out);
+ return out;
+}
+
+inline bool Channel::IsModeSet(ChanModeReference& mode)
+{
+ if (!mode)
+ return false;
+ return IsModeSet(*mode);
+}
diff --git a/include/command_parse.h b/include/command_parse.h
index f9e3a740c..70544b0c8 100644
--- a/include/command_parse.h
+++ b/include/command_parse.h
@@ -20,8 +20,7 @@
*/
-#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,
@@ -31,18 +30,11 @@
class CoreExport CommandParser
{
private:
- /** Process a parameter string into a list of items
- * @param command_p The output list of items
- * @param parameters The input string
- * @return The number of parameters parsed into command_p
- */
- int ProcessParameters(std::vector<std::string>& command_p, char* parameters);
-
/** Process a command from a user.
* @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*
@@ -57,13 +49,15 @@ class CoreExport CommandParser
* @param commandname The command to find. This should be in uppercase.
* @param parameters Parameter list
* @param user The user to call the handler on behalf of
+ * @param cmd If non-NULL and the command was executed it is set to the command handler,
+ * otherwise it isn't written to.
* @return This method will return CMD_SUCCESS if the command handler was found and called,
* and the command completeld successfully. It will return CMD_FAILURE if the command handler was found
* and called, but the command did not complete successfully, and it will return CMD_INVALID if the
* command simply did not exist at all or the wrong number of parameters were given, or the user
* was not privilaged enough to execute the command.
*/
- CmdResult CallHandler(const std::string &commandname, const std::vector<std::string>& parameters, User *user);
+ CmdResult CallHandler(const std::string& commandname, const std::vector<std::string>& parameters, User* user, Command** cmd = NULL);
/** Get the handler function for a command.
* @param commandname The command required. Always use uppercase for this parameter.
@@ -71,44 +65,50 @@ class CoreExport CommandParser
*/
Command* GetHandler(const std::string &commandname);
- /** This function returns true if a command is valid with the given number of parameters and user.
- * @param commandname The command name to check
- * @param pcnt The parameter count
- * @param user The user to check against
- * @return If the user given has permission to execute the command, and the parameter count is
- * equal to or greater than the minimum number of parameters to the given command, then this
- * function will return true, otherwise it will return false.
- */
- bool IsValidCommand(const std::string &commandname, unsigned int pcnt, User * user);
-
- /** LoopCall is used to call a command classes handler repeatedly based on the contents of a comma seperated list.
- * There are two overriden versions of this method, one of which takes two potential lists and the other takes one.
- * We need a version which takes two potential lists for JOIN, because a JOIN may contain two lists of items at once,
+ /** LoopCall is used to call a command handler repeatedly based on the contents of a comma seperated list.
+ * There are two ways to call this method, either with one potential list or with two potential lists.
+ * We need to handle two potential lists for JOIN, because a JOIN may contain two lists of items at once:
* the channel names and their keys as follows:
*
* JOIN \#chan1,\#chan2,\#chan3 key1,,key3
*
- * Therefore, we need to deal with both lists concurrently. The first instance of this method does that by creating
- * two instances of irc::commasepstream and reading them both together until the first runs out of tokens.
- * The second version is much simpler and just has the one stream to read, and is used in NAMES, WHOIS, PRIVMSG etc.
- * Both will only parse until they reach ServerInstance->Config->MaxTargets number of targets, to stop abuse via spam.
+ * Therefore, we need to deal with both lists concurrently. If there are two lists then the method reads
+ * them both together until the first runs out of tokens.
+ * With one list it is much simpler, and is used in NAMES, WHOIS, PRIVMSG etc.
+ *
+ * If there is only one list and there are duplicates in it, then the command handler is only called for
+ * unique items. Entries are compared using "irc comparision" (see irc::string).
+ * If the usemax parameter is true (the default) the function only parses until it reaches
+ * ServerInstance->Config->MaxTargets number of targets, to stop abuse via spam.
+ *
+ * The OnPostCommand hook is executed for each item after it has been processed by the handler, with the
+ * original line parameter being empty (to indicate that the command in that form was created by this function).
+ * This only applies if the user executing the command is local.
+ *
+ * If there are two lists and the second list runs out of tokens before the first list then parameters[extra]
+ * will be an EMPTY string when Handle() is called for the remaining tokens in the first list, even if it is
+ * in the middle of parameters[]! Moreover, empty tokens in the second list are allowed, and those will also
+ * result in the appropiate entry being empty in parameters[].
+ * This is different than what command handlers usually expect; the command parser only allows an empty param
+ * as the last item in the vector.
*
* @param user The user who sent the command
- * @param CommandObj the command object to call for each parameter in the list
- * @param parameters Parameter list as an array of array of char (that's not a typo).
+ * @param handler The command handler to call for each parameter in the list
+ * @param parameters Parameter list as a vector of strings
* @param splithere The first parameter index to split as a comma seperated list
- * @param extra The second parameter index to split as a comma seperated list
- * @param usemax Limit the command to MaxTargets targets
- * @return This function will return 1 when there are no more parameters to process. When this occurs, its
- * caller should return without doing anything, otherwise it should continue into its main section of code.
+ * @param extra The second parameter index to split as a comma seperated list, or -1 (the default) if there is only one list
+ * @param usemax True to limit the command to MaxTargets targets (default), or false to process all tokens
+ * @return This function returns true when it identified a list in the given parameter and finished calling the
+ * command handler for each entry on the list. When this occurs, the caller should return without doing anything,
+ * otherwise it should continue into its main section of code.
*/
- int LoopCall(User* user, Command* CommandObj, const std::vector<std::string>& parameters, unsigned int splithere, int extra = -1, bool usemax = true);
+ static bool LoopCall(User* user, Command* handler, const std::vector<std::string>& parameters, unsigned int splithere, int extra = -1, bool usemax = true);
/** Take a raw input buffer from a recvq, and process it on behalf of a user.
* @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
@@ -120,23 +120,23 @@ class CoreExport CommandParser
*/
void RemoveCommand(Command* x);
- /** Translate nicknames in a string into UIDs, based on the TranslationType given.
- * @param to The translation type to use for the process.
- * @param source The input string
- * @param dest The output string, it is safe to pass source and dest as the same variable only for translation type TR_TEXT.
- * @return returns the number of substitutions made. Will always be 0 or 1
+ /** Translate a single item based on the TranslationType given.
+ * @param to The translation type to use for the process
+ * @param item The input string
+ * @param dest The output string. The translation result will be appended to this string
+ * @param custom_translator Used to translate the parameter if the translation type is TR_CUSTOM, if NULL, TR_CUSTOM will act like TR_TEXT
+ * @param paramnumber The index of the parameter we are translating.
*/
- int TranslateUIDs(TranslateType to, const std::string &source, std::string &dest);
+ static void TranslateSingleParam(TranslateType to, const std::string& item, std::string& dest, CommandBase* custom_translator = NULL, unsigned int paramnumber = 0);
/** Translate nicknames in a list of strings into UIDs, based on the TranslateTypes given.
* @param to The translation types to use for the process. If this list is too short, TR_TEXT is assumed for the rest.
* @param source The strings to translate
- * @param dest The output string
* @param prefix_final True if the final source argument should have a colon prepended (if it could contain a space)
- * @param custom_translator Used to translate the parameter if the TR_CUSTOM type is found in to
- * @return returns the number of substitutions made.
+ * @param custom_translator Used to translate the parameter if the translation type is TR_CUSTOM, if NULL, TR_CUSTOM will act like TR_TEXT
+ * @return dest The output string
*/
- int TranslateUIDs(const std::vector<TranslateType> to, const std::vector<std::string> &source, std::string &dest, bool prefix_final = false, Command* custom_translator = NULL);
+ static std::string TranslateUIDs(const std::vector<TranslateType>& to, const std::vector<std::string>& source, bool prefix_final = false, CommandBase* custom_translator = NULL);
};
/** A lookup table of values for multiplier characters used by
@@ -165,5 +165,3 @@ const int duration_multi[] =
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
diff --git a/include/commands/cmd_whowas.h b/include/commands/cmd_whowas.h
index d33354122..0a38b44f1 100644
--- a/include/commands/cmd_whowas.h
+++ b/include/commands/cmd_whowas.h
@@ -19,39 +19,13 @@
*/
-#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;
@@ -72,15 +46,28 @@ typedef std::deque<std::pair<time_t,irc::string> > whowas_users_fifo;
class CommandWhowas : public Command
{
private:
- /** Whowas container, contains a map of vectors of users tracked by WHOWAS
+ /** Primary container, links nicknames tracked by WHOWAS to a list of records
*/
whowas_users whowas;
- /** Whowas container, contains a map of time_t to users tracked by WHOWAS
+ /** List of nicknames in the order they were inserted into the map
*/
whowas_users_fifo whowas_fifo;
public:
+ /** Max number of WhoWas entries per user.
+ */
+ unsigned int GroupSize;
+
+ /** Max number of cumulative user-entries in WhoWas.
+ * When max reached and added to, push out oldest entry FIFO style.
+ */
+ unsigned int MaxGroups;
+
+ /** Max seconds a user is kept in WhoWas before being pruned.
+ */
+ unsigned int MaxKeep;
+
CommandWhowas(Module* parent);
/** Handle command.
* @param parameters The parameters to the comamnd
@@ -91,8 +78,8 @@ class CommandWhowas : public Command
CmdResult Handle(const std::vector<std::string>& parameters, User *user);
void AddToWhoWas(User* user);
std::string GetStats();
- void PruneWhoWas(time_t t);
- void MaintainWhoWas(time_t t);
+ void Prune();
+ void Maintain();
~CommandWhowas();
};
@@ -123,19 +110,4 @@ class WhoWasGroup
/** Initialize this WhoWasFroup with a user
*/
WhoWasGroup(User* user);
- /** Destructor
- */
- ~WhoWasGroup();
};
-
-class WhoWasMaintainTimer : public Timer
-{
- public:
- WhoWasMaintainTimer(long interval)
- : Timer(interval, ServerInstance->Time(), true)
- {
- }
- virtual void Tick(time_t TIME);
-};
-
-#endif
diff --git a/include/compat.h b/include/compat.h
new file mode 100644
index 000000000..fa75cd754
--- /dev/null
+++ b/include/compat.h
@@ -0,0 +1,114 @@
+/*
+ * 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
+# 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
+# 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 __attribute__ ((visibility ("default")))
+# define CoreExport __attribute__ ((visibility ("default")))
+#endif
diff --git a/include/configparser.h b/include/configparser.h
index 999d79e24..8292fdda5 100644
--- a/include/configparser.h
+++ b/include/configparser.h
@@ -17,6 +17,8 @@
*/
+#pragma once
+
struct fpos
{
std::string filename;
@@ -31,7 +33,7 @@ struct fpos
enum ParseFlags
{
- FLAG_USE_XML = 1,
+ FLAG_USE_COMPAT = 1,
FLAG_NO_EXEC = 2,
FLAG_NO_INC = 4
};
@@ -76,5 +78,3 @@ struct FileWrapper
}
}
};
-
-
diff --git a/include/configreader.h b/include/configreader.h
index 1edacfe13..ec9932658 100644
--- a/include/configreader.h
+++ b/include/configreader.h
@@ -21,8 +21,7 @@
*/
-#ifndef INSPIRCD_CONFIGREADER
-#define INSPIRCD_CONFIGREADER
+#pragma once
#include <sstream>
#include <string>
@@ -45,12 +44,22 @@ class CoreExport ConfigTag : public refcountbase
/** Get the value of an option, using def if it does not exist */
std::string getString(const std::string& key, const std::string& def = "");
/** Get the value of an option, using def if it does not exist */
- long getInt(const std::string& key, long def = 0);
+ long getInt(const std::string& key, long def = 0, long min = LONG_MIN, long max = LONG_MAX);
/** Get the value of an option, using def if it does not exist */
double getFloat(const std::string& key, double def = 0);
/** Get the value of an option, using def if it does not exist */
bool getBool(const std::string& key, bool def = false);
+ /** Get the value in seconds of a duration that is in the user-friendly "1h2m3s" format,
+ * using a default value if it does not exist or is out of bounds.
+ * @param key The config key name
+ * @param def Default value (optional)
+ * @param min Minimum acceptable value (optional)
+ * @param max Maximum acceptable value (optional)
+ * @return The duration in seconds
+ */
+ long getDuration(const std::string& key, long def = 0, long min = LONG_MIN, long max = LONG_MAX);
+
/** Get the value of an option
* @param key The option to get
* @param value The location to store the value (unmodified if does not exist)
@@ -59,6 +68,16 @@ class CoreExport ConfigTag : public refcountbase
*/
bool readString(const std::string& key, std::string& value, bool allow_newline = false);
+ /** Check for an out of range value. If the value falls outside the boundaries a warning is
+ * logged and the value is corrected (set to def).
+ * @param key The key name, used in the warning message
+ * @param res The value to verify and modify if needed
+ * @param def The default value, res will be set to this if (min <= res <= max) doesn't hold true
+ * @param min Minimum accepted value for res
+ * @param max Maximum accepted value for res
+ */
+ void CheckRange(const std::string& key, long& res, long def, long min, long max);
+
std::string getTagLocation();
inline const std::vector<KeyVal>& getItems() const { return items; }
@@ -93,14 +112,18 @@ class ServerLimits
size_t MaxGecos;
/** Maximum away message length */
size_t MaxAway;
+ /** Maximum line length */
+ size_t MaxLine;
+ /** Maximum hostname length */
+ size_t MaxHost;
/** Creating the class initialises it to the defaults
* as in 1.1's ./configure script. Reading other values
* from the config will change these values.
*/
- ServerLimits() : NickMax(31), ChanMax(64), MaxModes(20), IdentMax(12), MaxQuit(255), MaxTopic(307), MaxKick(255), MaxGecos(128), MaxAway(200)
- {
- }
+ ServerLimits() : NickMax(31), ChanMax(64), MaxModes(20), IdentMax(12),
+ MaxQuit(255), MaxTopic(307), MaxKick(255), MaxGecos(128), MaxAway(200),
+ MaxLine(512), MaxHost(64) { }
};
struct CommandLineConf
@@ -130,11 +153,6 @@ struct CommandLineConf
*/
bool writelog;
- /** True if we have been told to run the testsuite from the commandline,
- * rather than entering the mainloop.
- */
- bool TestSuite;
-
/** Saved argc from startup
*/
int argc;
@@ -142,8 +160,6 @@ struct CommandLineConf
/** Saved argv from startup
*/
char** argv;
-
- std::string startup_log;
};
class CoreExport OperInfo : public refcountbase
@@ -170,11 +186,6 @@ 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.
@@ -189,6 +200,32 @@ class CoreExport ServerConfig
void CrossCheckConnectBlocks(ServerConfig* current);
public:
+ class ServerPaths
+ {
+ public:
+ /** Config path */
+ std::string Config;
+
+ /** Data path */
+ std::string Data;
+
+ /** Log path */
+ std::string Log;
+
+ /** Module path */
+ std::string Module;
+
+ ServerPaths()
+ : Config(CONFIG_PATH)
+ , Data(DATA_PATH)
+ , Log(LOG_PATH)
+ , Module(MOD_PATH) { }
+
+ std::string PrependConfig(const std::string& fn) const { return FileSystem::ExpandPath(Config, fn); }
+ std::string PrependData(const std::string& fn) const { return FileSystem::ExpandPath(Data, fn); }
+ std::string PrependLog(const std::string& fn) const { return FileSystem::ExpandPath(Log, fn); }
+ std::string PrependModule(const std::string& fn) const { return FileSystem::ExpandPath(Module, fn); }
+ };
/** Get a configuration tag
* @param tag The name of the tag to get
@@ -225,6 +262,9 @@ class CoreExport ServerConfig
*/
ServerLimits Limits;
+ /** Locations of various types of file (config, module, etc). */
+ ServerPaths Paths;
+
/** Configuration parsed from the command line.
*/
CommandLineConf cmdline;
@@ -239,27 +279,14 @@ class CoreExport ServerConfig
*/
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 ServerName;
- /** Notice to give to users when they are Xlined
+ /** Notice to give to users when they are banned by an XLine
*/
- std::string MoronBanner;
+ std::string XLineMessage;
/* Holds the network name the local server
* belongs to. This is an arbitary field defined
@@ -272,71 +299,6 @@ class CoreExport ServerConfig
*/
std::string ServerDesc;
- /** Holds the admin's name, for output in
- * the /ADMIN command.
- */
- std::string AdminName;
-
- /** Holds the email address of the admin,
- * for output in the /ADMIN command.
- */
- std::string AdminEmail;
-
- /** Holds the admin's nickname, for output
- * in the /ADMIN command
- */
- std::string AdminNick;
-
- /** The admin-configured /DIE password
- */
- std::string diepass;
-
- /** The admin-configured /RESTART password
- */
- std::string restartpass;
-
- /** The hash method for *BOTH* the die and restart passwords.
- */
- std::string powerhash;
-
- /** The pathname and filename of the message of the
- * day file, as defined by the administrator.
- */
- std::string motd;
-
- /** The pathname and filename of the rules file,
- * as defined by the administrator.
- */
- std::string rules;
-
- /** The quit prefix in use, or an empty string
- */
- std::string PrefixQuit;
-
- /** The quit suffix in use, or an empty string
- */
- std::string SuffixQuit;
-
- /** The fixed quit message in use, or an empty string
- */
- std::string FixedQuit;
-
- /** The part prefix in use, or an empty string
- */
- std::string PrefixPart;
-
- /** The part suffix in use, or an empty string
- */
- std::string SuffixPart;
-
- /** The fixed part message in use, or an empty string
- */
- std::string FixedPart;
-
- /** The DNS server to use for DNS queries
- */
- std::string DNSServer;
-
/** Pretend disabled commands don't exist.
*/
bool DisabledDontExist;
@@ -355,13 +317,6 @@ class CoreExport ServerConfig
*/
char DisabledCModes[64];
- /** The full path to the modules directory.
- * This is either set at compile time, or
- * overridden in the configuration file via
- * the \<path> tag.
- */
- std::string ModPath;
-
/** If set to true, then all opers on this server are
* shown with a generic 'is an IRC operator' line rather
* than the oper type. Oper types are still used internally.
@@ -395,6 +350,13 @@ class CoreExport ServerConfig
*/
int MaxConn;
+ /** If we should check for clones during CheckClass() in AddUser()
+ * Setting this to false allows to not trigger on maxclones for users
+ * that may belong to another class after DNS-lookup is complete.
+ * It does, however, make the server spend more time on users we may potentially not want.
+ */
+ bool CCOnConnect;
+
/** The soft limit value assigned to the irc server.
* The IRC server will not allow more than this
* number of local users.
@@ -444,16 +406,6 @@ class CoreExport ServerConfig
*/
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.
*/
@@ -467,27 +419,10 @@ class CoreExport ServerConfig
*/
std::string CustomVersion;
- /** List of u-lined servers
- */
- 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;
- /** If set to true, users appear to quit then rejoin when their hosts change.
- * This keeps clients synchronized properly.
- */
- bool CycleHosts;
-
/** If set to true, the CycleHosts mode change will be sourced from the user,
* rather than the server
*/
@@ -503,11 +438,14 @@ class CoreExport ServerConfig
*/
bool FullHostInTopic;
- /** Oper block and type index.
- * For anonymous oper blocks (type only), prefix with a space.
+ /** Oper blocks keyed by their name
*/
OperIndex oper_blocks;
+ /** Oper types keyed by their name
+ */
+ OperIndex OperTypes;
+
/** Max channels per user
*/
unsigned int MaxChans;
@@ -529,15 +467,7 @@ class CoreExport ServerConfig
/** 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
@@ -552,23 +482,13 @@ class CoreExport ServerConfig
void Fill();
- /** Returns true if the given string starts with a windows drive letter
- */
- bool StartsWithWindowsDriveLetter(const std::string &path);
-
bool ApplyDisabledCommands(const std::string& data);
- /** Clean a filename, stripping the directories (and drives) from string.
- * @param name Directory to tidy
- * @return The cleaned filename
- */
- static const char* CleanFilename(const char* name);
-
- /** Check if a file exists.
- * @param file The full path to a file
- * @return True if the file exists and is readable.
+ /** Escapes a value for storage in a configuration key.
+ * @param str The string to escape.
+ * @param xml Are we using the XML config format?
*/
- static bool FileExists(const char* file);
+ static std::string Escape(const std::string& str, bool xml = true);
/** If this value is true, invites will bypass more than just +i
*/
@@ -577,11 +497,6 @@ class CoreExport ServerConfig
/** 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
@@ -609,4 +524,13 @@ class CoreExport ConfigReaderThread : public Thread
bool IsDone() { return done; }
};
-#endif
+class CoreExport ConfigStatus
+{
+ public:
+ User* const srcuser;
+
+ ConfigStatus(User* user = NULL)
+ : srcuser(user)
+ {
+ }
+};
diff --git a/include/consolecolors.h b/include/consolecolors.h
index f7ca1335e..9b7e0670a 100644
--- a/include/consolecolors.h
+++ b/include/consolecolors.h
@@ -14,8 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CONSOLECOLORS_H
-#define CONSOLECOLORS_H
+
+#pragma once
#include <ostream>
@@ -96,5 +96,3 @@ inline std::ostream& con_reset(std::ostream &s)
}
#endif
-
-#endif
diff --git a/include/ctables.h b/include/ctables.h
index f9cd08cb3..a69f5c86f 100644
--- a/include/ctables.h
+++ b/include/ctables.h
@@ -21,8 +21,7 @@
*/
-#ifndef CTABLES_H
-#define CTABLES_H
+#pragma once
/** Used to indicate command success codes
*/
@@ -44,7 +43,6 @@ const char FLAG_SERVERONLY = 7; // technically anything nonzero below 'A' works
*/
enum TranslateType
{
- TR_END, /* End of known parameters, everything after this is TR_TEXT */
TR_TEXT, /* Raw text, leave as-is */
TR_NICK, /* Nickname, translate to UUID for server->server */
TR_CUSTOM /* Custom translation handled by EncodeParameter/DecodeParameter */
@@ -77,10 +75,17 @@ struct RouteDescriptor
*/
std::string serverdest;
+ /** For unicast, the destination Server
+ */
+ Server* server;
+
/** Create a RouteDescriptor
*/
RouteDescriptor(RouteType t, const std::string &d)
- : type(t), serverdest(d) { }
+ : type(t), serverdest(d), server(NULL) { }
+
+ RouteDescriptor(RouteType t, Server* srv)
+ : type(t), server(srv) { }
};
/** Do not route this command */
@@ -99,7 +104,7 @@ struct RouteDescriptor
/** A structure that defines a command. Every command available
* in InspIRCd must be defined as derived from Command.
*/
-class CoreExport Command : public ServiceProvider
+class CoreExport CommandBase : public ServiceProvider
{
public:
/** User flags needed to execute the command or 0
@@ -120,10 +125,6 @@ class CoreExport Command : public ServiceProvider
*/
unsigned long use_count;
- /** used by /stats m
- */
- unsigned long total_bytes;
-
/** True if the command is disabled to non-opers
*/
bool disabled;
@@ -162,20 +163,13 @@ class CoreExport Command : public ServiceProvider
* @param maxpara Maximum number of parameters this command may have - extra parameters
* will be tossed into one last space-seperated param.
*/
- Command(Module* me, const std::string &cmd, int minpara = 0, int maxpara = 0) :
+ CommandBase(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)
{
}
- /** Handle the command from a user.
- * @param parameters The parameters for the command.
- * @param user The user who issued the command.
- * @return Return CMD_SUCCESS on success, or CMD_FAILURE on failure.
- */
- virtual CmdResult Handle(const std::vector<std::string>& parameters, User* user) = 0;
-
virtual RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
{
return ROUTE_LOCALONLY;
@@ -224,7 +218,34 @@ class CoreExport Command : public ServiceProvider
return works_before_reg;
}
- virtual ~Command();
+ virtual ~CommandBase();
+};
+
+class CoreExport Command : public CommandBase
+{
+ public:
+ /** If true, the command will not be forwarded by the linking module even if it comes via ENCAP.
+ * Can be used to forward commands before their effects.
+ */
+ bool force_manual_route;
+
+ Command(Module* me, const std::string& cmd, unsigned int minpara = 0, unsigned int maxpara = 0)
+ : CommandBase(me, cmd, minpara, maxpara)
+ , force_manual_route(false)
+ {
+ }
+
+ /** Handle the command from a user.
+ * @param parameters The parameters for the command.
+ * @param user The user who issued the command.
+ * @return Return CMD_SUCCESS on success, or CMD_FAILURE on failure.
+ */
+ virtual CmdResult Handle(const std::vector<std::string>& parameters, User* user) = 0;
+
+ /** Destructor
+ * Removes this command from the command parser
+ */
+ ~Command();
};
class CoreExport SplitCommand : public Command
@@ -252,5 +273,3 @@ class CoreExport SplitCommand : public Command
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
diff --git a/include/cull_list.h b/include/cull_list.h
index 75b08b7a3..ac64dced2 100644
--- a/include/cull_list.h
+++ b/include/cull_list.h
@@ -20,8 +20,7 @@
*/
-#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
@@ -58,6 +57,3 @@ class CoreExport ActionList
void Run();
};
-
-#endif
-
diff --git a/include/dns.h b/include/dns.h
deleted file mode 100644
index 27c3c8848..000000000
--- a/include/dns.h
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * 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
-
diff --git a/include/dynamic.h b/include/dynamic.h
index 5e66ddbb0..d42cf61bf 100644
--- a/include/dynamic.h
+++ b/include/dynamic.h
@@ -20,8 +20,7 @@
*/
-#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.
@@ -65,6 +64,3 @@ class CoreExport DLLManager : public classbase
/** Get detailed version information from the module file */
std::string GetVersion();
};
-
-#endif
-
diff --git a/include/dynref.h b/include/dynref.h
new file mode 100644
index 000000000..02474b67e
--- /dev/null
+++ b/include/dynref.h
@@ -0,0 +1,99 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com>
+ * 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
+
+#include "base.h"
+
+class CoreExport dynamic_reference_base : public interfacebase, public intrusive_list_node<dynamic_reference_base>
+{
+ private:
+ std::string name;
+ void resolve();
+ protected:
+ ServiceProvider* value;
+ public:
+ ModuleRef creator;
+ dynamic_reference_base(Module* Creator, const std::string& Name);
+ ~dynamic_reference_base();
+ inline const std::string& GetProvider() { return name; }
+ void SetProvider(const std::string& newname);
+ 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->()
+ {
+ 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 ModeHandler;
+class ChanModeReference : public dynamic_reference_nocheck<ModeHandler>
+{
+ public:
+ ChanModeReference(Module* mod, const std::string& modename)
+ : dynamic_reference_nocheck<ModeHandler>(mod, "mode/" + modename) {}
+};
+
+class UserModeReference : public dynamic_reference_nocheck<ModeHandler>
+{
+ public:
+ UserModeReference(Module* mod, const std::string& modename)
+ : dynamic_reference_nocheck<ModeHandler>(mod, "umode/" + modename) {}
+};
diff --git a/include/exitcodes.h b/include/exitcodes.h
index d4890c94d..b1090d141 100644
--- a/include/exitcodes.h
+++ b/include/exitcodes.h
@@ -19,8 +19,7 @@
*/
-#ifndef EXITCODE_H
-#define EXITCODE_H
+#pragma once
/** Valid exit codes to be used with InspIRCd::Exit()
*/
@@ -28,30 +27,18 @@ enum ExitStatus
{
EXIT_STATUS_NOERROR = 0, /* No error */
EXIT_STATUS_DIE = 1, /* Operator issued DIE */
- EXIT_STATUS_FAILED_EXEC = 2, /* execv() failed */
- EXIT_STATUS_INTERNAL = 3, /* Internal error */
- EXIT_STATUS_CONFIG = 4, /* Config error */
- EXIT_STATUS_LOG = 5, /* Log file error */
- EXIT_STATUS_FORK = 6, /* fork() failed */
- EXIT_STATUS_ARGV = 7, /* Invalid program arguments */
- EXIT_STATUS_BIND = 8, /* Port binding failed on all ports */
- EXIT_STATUS_PID = 9, /* Couldn't write PID file */
- EXIT_STATUS_SOCKETENGINE = 10, /* Couldn't start socket engine */
- EXIT_STATUS_ROOT = 11, /* Refusing to start as root */
- EXIT_STATUS_DIETAG = 12, /* Found a die tag in the config file */
- EXIT_STATUS_MODULE = 13, /* Couldn't load a required module */
- EXIT_STATUS_CREATEPROCESS = 14, /* CreateProcess failed (windows) */
- EXIT_STATUS_SIGTERM = 15, /* Note: dont move this value. It corresponds with the value of #define SIGTERM. */
- EXIT_STATUS_BADHANDLER = 16, /* Bad command handler loaded */
- EXIT_STATUS_RSCH_FAILED = 17, /* Windows service specific failure, will name these later */
- EXIT_STATUS_UPDATESCM_FAILED = 18, /* Windows service specific failure, will name these later */
- EXIT_STATUS_CREATE_EVENT_FAILED = 19 /* Windows service specific failure, will name these later */
+ EXIT_STATUS_CONFIG = 2, /* Config error */
+ EXIT_STATUS_LOG = 3, /* Log file error */
+ EXIT_STATUS_FORK = 4, /* fork() failed */
+ EXIT_STATUS_ARGV = 5, /* Invalid program arguments */
+ EXIT_STATUS_PID = 6, /* Couldn't write PID file */
+ EXIT_STATUS_SOCKETENGINE = 7, /* Couldn't start socket engine */
+ EXIT_STATUS_ROOT = 8, /* Refusing to start as root */
+ EXIT_STATUS_MODULE = 9, /* Couldn't load a required module */
+ EXIT_STATUS_SIGTERM = 10 /* Received SIGTERM */
};
/** Array that maps exit codes (ExitStatus types) to
* human-readable strings to be shown on shutdown.
*/
extern const char * ExitCodes[];
-
-#endif
-
diff --git a/include/extensible.h b/include/extensible.h
index bcc4992bb..87fe65ccb 100644
--- a/include/extensible.h
+++ b/include/extensible.h
@@ -17,8 +17,7 @@
*/
-#ifndef EXTENSIBLE_H
-#define EXTENSIBLE_H
+#pragma once
#include <stdint.h>
@@ -85,6 +84,11 @@ class CoreExport Extensible : public classbase
* Holds all extensible metadata for the class.
*/
ExtensibleStore extensions;
+
+ /** True if this Extensible has been culled.
+ * A warning is generated if false on destruction.
+ */
+ unsigned int culled:1;
public:
/**
* Get the extension items for iteraton (i.e. for metadata sync during netburst)
@@ -95,6 +99,11 @@ class CoreExport Extensible : public classbase
virtual CullResult cull();
virtual ~Extensible();
void doUnhookExtensions(const std::vector<reference<ExtensionItem> >& toRemove);
+
+ /**
+ * Free all extension items attached to this Extensible
+ */
+ void FreeAllExtItems();
};
class CoreExport ExtensionManager
@@ -117,7 +126,7 @@ class CoreExport LocalExtItem : public ExtensionItem
virtual void free(void* item) = 0;
};
-template<typename T>
+template <typename T, typename Del = stdalgo::defaultdeleter<T> >
class SimpleExtItem : public LocalExtItem
{
public:
@@ -138,24 +147,28 @@ class SimpleExtItem : public LocalExtItem
{
T* ptr = new T(value);
T* old = static_cast<T*>(set_raw(container, ptr));
- delete old;
+ Del del;
+ del(old);
}
inline void set(Extensible* container, T* value)
{
T* old = static_cast<T*>(set_raw(container, value));
- delete old;
+ Del del;
+ del(old);
}
inline void unset(Extensible* container)
{
T* old = static_cast<T*>(unset_raw(container));
- delete old;
+ Del del;
+ del(old);
}
virtual void free(void* item)
{
- delete static_cast<T*>(item);
+ Del del;
+ del(static_cast<T*>(item));
}
};
@@ -175,6 +188,7 @@ class CoreExport LocalIntExt : public LocalExtItem
std::string serialize(SerializeFormat format, const Extensible* container, void* item) const;
intptr_t get(const Extensible* container) const;
intptr_t set(Extensible* container, intptr_t value);
+ void unset(Extensible* container) { set(container, 0); }
void free(void* item);
};
@@ -190,5 +204,3 @@ class CoreExport StringExtItem : public ExtensionItem
void unset(Extensible* container);
void free(void* item);
};
-
-#endif
diff --git a/include/filelogger.h b/include/filelogger.h
index 22a94c934..ce571c3ae 100644
--- a/include/filelogger.h
+++ b/include/filelogger.h
@@ -18,27 +18,10 @@
*/
-#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
@@ -46,12 +29,9 @@ 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
-
diff --git a/include/fileutils.h b/include/fileutils.h
new file mode 100644
index 000000000..89f92f97f
--- /dev/null
+++ b/include/fileutils.h
@@ -0,0 +1,87 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013 Peter Powell <petpow@saberuk.com>
+ *
+ * This file is part of InspIRCd. InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * 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
+
+/** Provides an easy method of reading a text file into memory. */
+class CoreExport FileReader
+{
+ /** The lines of text in the file. */
+ std::vector<std::string> lines;
+
+ /** File size in bytes. */
+ unsigned long totalSize;
+
+ public:
+ /** Initializes a new file reader. */
+ FileReader() : totalSize(0) { }
+
+ /** Initializes a new file reader and reads the specified file.
+ * @param filename The file to read into memory.
+ */
+ FileReader(const std::string& filename);
+
+ /** Loads a text file from disk.
+ * @param filename The file to read into memory.
+ * @throw CoreException The file can not be loaded.
+ */
+ void Load(const std::string& filename);
+
+ /** Retrieves the entire contents of the file cache as a single string. */
+ std::string GetString() const;
+
+ /** Retrieves the entire contents of the file cache as a vector of strings. */
+ const std::vector<std::string>& GetVector() const { return lines; }
+
+ /** Retrieves the total size in bytes of the file. */
+ unsigned long TotalSize() const { return totalSize; }
+};
+
+/** Implements methods for file system access */
+class CoreExport FileSystem
+{
+private:
+ FileSystem() { }
+
+public:
+ /** Expands a path fragment to a full path.
+ * @param base The base path to expand from
+ * @param fragment The path fragment to expand on top of base.
+ */
+ static std::string ExpandPath(const std::string& base, const std::string& fragment);
+
+ /**
+ * Checks whether a file with the specified name exists on the filesystem.
+ * @param path The path to a file.
+ * @return True if the file exists; otherwise, false.
+ */
+ static bool FileExists(const std::string& path);
+
+ /** Gets the file name segment of a path.
+ * @param path The path to extract the file name from.
+ * @return The file name segment of a path.
+ */
+ static std::string GetFileName(const std::string& path);
+
+ /** Determines whether the given path starts with a Windows drive letter.
+ * @param path The path to validate.
+ * @returns True if the path begins with a Windows drive letter; otherwise, false.
+ */
+ static bool StartsWithWindowsDriveLetter(const std::string& path);
+};
diff --git a/include/hash_map.h b/include/hash_map.h
deleted file mode 100644
index 1b43f0118..000000000
--- a/include/hash_map.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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
diff --git a/include/hashcomp.h b/include/hashcomp.h
index 78d7ee878..6cd3fc3c0 100644
--- a/include/hashcomp.h
+++ b/include/hashcomp.h
@@ -22,8 +22,7 @@
*/
-#ifndef HASHCOMP_H
-#define HASHCOMP_H
+#pragma once
#include <cstring>
#include <string>
@@ -31,7 +30,7 @@
#include <deque>
#include <map>
#include <set>
-#include "hash_map.h"
+#include "inspircd.h"
/*******************************************************
* This file contains classes and templates that deal
@@ -110,12 +109,22 @@ namespace irc
bool operator()(const std::string& s1, const std::string& s2) const;
};
+ struct insensitive
+ {
+ size_t CoreExport operator()(const std::string &s) const;
+ };
+
+ struct insensitive_swo
+ {
+ bool CoreExport operator()(const std::string& a, const std::string& b) 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.
*/
- struct irc_char_traits : std::char_traits<char> {
-
+ struct CoreExport irc_char_traits : public std::char_traits<char>
+ {
/** Check if two chars match.
* @param c1st First character
* @param c2nd Second character
@@ -144,7 +153,7 @@ namespace irc
* @return similar to strcmp, zero for equal, less than zero for str1
* being less and greater than zero for str1 being greater than str2.
*/
- static CoreExport int compare(const char* str1, const char* str2, size_t n);
+ static int compare(const char* str1, const char* str2, size_t n);
/** Find a char within a string up to position n.
* @param s1 String to find in
@@ -152,65 +161,18 @@ namespace irc
* @param c Character to search for
* @return Pointer to the first occurance of c in s1
*/
- static CoreExport const char* find(const char* s1, int n, char c);
+ static 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.
- * This class can join a vector of std::string, a deque of
- * std::string, or a const char* const* array, using overloaded
- * constructors.
+ /** Joins the contents of a vector to a string.
+ * @param sequence Zero or more items to join.
+ * @separator The character to place between the items.
*/
- class CoreExport stringjoiner
- {
- private:
-
- /** Output string
- */
- std::string joined;
-
- 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 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);
-
- /** Get the joined sequence
- * @return A reference to the joined string
- */
- std::string& GetJoined();
- };
+ std::string CoreExport stringjoiner(const std::vector<std::string>& sequence, char separator = ' ');
/** irc::modestacker stacks mode sequences into a list.
* It can then reproduce this list, clamped to a maximum of MAXMODES
@@ -281,80 +243,6 @@ namespace irc
*/
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.
@@ -364,43 +252,39 @@ namespace irc
*/
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
@@ -408,9 +292,9 @@ namespace irc
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)
{
}
};
@@ -420,13 +304,57 @@ namespace irc
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
@@ -481,12 +409,6 @@ namespace irc
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
@@ -590,72 +512,3 @@ inline std::string& trim(std::string &str)
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
diff --git a/include/inspircd.h b/include/inspircd.h
index e2eaf8292..db13b2ab3 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -23,63 +23,43 @@
*/
-#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 <climits>
+#include <cmath>
#include <csignal>
-#include <ctime>
#include <cstdarg>
-#include <algorithm>
-#include <cmath>
-#include <cstring>
-#include <climits>
#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 "intrusive_list.h"
+#include "compat.h"
#include "typedefs.h"
-#include "consolecolors.h"
+#include "stdalgo.h"
CoreExport extern InspIRCd* ServerInstance;
+#include "config.h"
+#include "dynref.h"
+#include "consolecolors.h"
#include "caller.h"
#include "cull_list.h"
#include "extensible.h"
+#include "fileutils.h"
#include "numerics.h"
#include "uid.h"
+#include "server.h"
#include "users.h"
#include "channels.h"
#include "timer.h"
@@ -99,43 +79,27 @@ CoreExport extern InspIRCd* ServerInstance;
#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)
{
- if (in == 0) return "0";
- char res[MAXBUF];
- char* out = res;
+ if (in == 0)
+ return "0";
T quotient = in;
- while (quotient) {
- *out = "0123456789"[ std::abs( (long)quotient % 10 ) ];
- ++out;
+ std::string out;
+ while (quotient)
+ {
+ out += "0123456789"[ std::abs( (long)quotient % 10 ) ];
quotient /= 10;
}
if (in < 0)
- *out++ = '-';
- *out = 0;
- std::reverse(res,out);
- return res;
+ out += '-';
+ std::reverse(out.begin(), out.end());
+ return out;
}
/** Template function to convert any input type to std::string
@@ -260,17 +224,33 @@ class serverstats
}
};
-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(RehashHandler, void, const std::string&);
+DEFINE_HANDLER1(IsIdentHandler, bool, const std::string&);
+DEFINE_HANDLER1(IsChannelHandler, bool, 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
@@ -280,10 +260,6 @@ class TestSuite;
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();
@@ -293,25 +269,6 @@ class CoreExport InspIRCd
*/
bool DaemonSeed();
- /** Iterate the list of BufferedSocket objects, removing ones which have timed out
- * @param TIME the current time
- */
- 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();
-
- /** Returns true when all modules have done pre-registration checks on a user
- * @param user The user to verify
- * @return True if all modules have finished checking this user
- */
- bool AllModulesReportReady(LocalUser* user);
-
/** The current time, updated in the mainloop
*/
struct timespec TIME;
@@ -321,8 +278,15 @@ class CoreExport InspIRCd
*/
char ReadBuffer[65535];
+ /** Check we aren't running as root, and exit if we are
+ * with exit code EXIT_STATUS_ROOT.
+ */
+ void CheckRoot();
+
public:
+ UIDGenerator UIDGen;
+
/** Global cull list, will be processed on next iteration
*/
CullList GlobalCulls;
@@ -333,11 +297,8 @@ class CoreExport InspIRCd
IsNickHandler HandleIsNick;
IsIdentHandler HandleIsIdent;
- FloodQuitUserHandler HandleFloodQuitUser;
OnCheckExemptionHandler HandleOnCheckExemption;
IsChannelHandler HandleIsChannel;
- IsSIDHandler HandleIsSID;
- RehashHandler HandleRehash;
GenRandomHandler HandleGenRandom;
/** Globally accessible fake user record. This is used to force mode changes etc across s2s, etc.. bit ugly, but.. better than how this was done in 1.1
@@ -350,28 +311,12 @@ class CoreExport InspIRCd
*/
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;
@@ -390,10 +335,6 @@ class CoreExport InspIRCd
*/
CommandParser* Parser;
- /** Socket engine, handles socket activity events
- */
- SocketEngine* SE;
-
/** Thread engine, Handles threading where required
*/
ThreadEngine* Threads;
@@ -429,13 +370,9 @@ class CoreExport InspIRCd
*/
SnomaskManager* SNO;
- /** DNS class, provides resolver facilities to the core and modules
- */
- DNS* Res;
-
/** Timer manager class, triggers Timer timer events
*/
- TimerManager* Timers;
+ TimerManager Timers;
/** X-Line manager. Handles G/K/Q/E line setting, removal and matching
*/
@@ -447,7 +384,7 @@ class CoreExport InspIRCd
/** Channel list, a hash_map containing all channels XXX move to channel manager class
*/
- chan_hash* chanlist;
+ chan_hash chanlist;
/** List of the open ports
*/
@@ -461,13 +398,12 @@ class CoreExport InspIRCd
*/
ProtocolInterface* PI;
- /** Holds extensible for user nickforced
- */
- LocalIntExt NICKForced;
-
/** Holds extensible for user operquit
*/
- LocalStringExt OperQuit;
+ StringExtItem 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,
@@ -508,15 +444,6 @@ class CoreExport InspIRCd
*/
bool BindSocket(int sockfd, int port, const char* addr, bool dolisten = true);
- /** Gets the GECOS (description) field of the given server.
- * If the servername is not that of the local server, the name
- * is passed to handling modules which will attempt to determine
- * the GECOS that bleongs to the given servername.
- * @param servername The servername to find the description of
- * @return The description of this server, or of the local server
- */
- std::string GetServerDescription(const std::string& servername);
-
/** 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
@@ -524,17 +451,6 @@ class CoreExport InspIRCd
*/
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);
@@ -545,38 +461,21 @@ class CoreExport InspIRCd
*/
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
+ /** Get a hash map containing all channels, keyed by their name
+ * @return A hash map mapping channel names to Channel pointers
*/
- bool OpenLog(char** argv, int argc);
+ chan_hash& GetChans() { return chanlist; }
/** 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;
-
- /** Rehash the local server
+ * @param sid string to check against
*/
- caller1<void, const std::string&> Rehash;
+ static bool IsSID(const std::string& sid);
/** Handles incoming signals after being set
* @param signal the signal recieved
@@ -601,10 +500,13 @@ class CoreExport InspIRCd
*/
static void QuickExit(int status);
- /** Return a count of channels on the network
- * @return The number of channels
- */
- long ChannelCount();
+ /** Formats the input string with the specified arguments.
+ * @param formatString The string to format
+ * @param ... A variable number of format arguments.
+ * @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);
/** Send an error notice to all local users, opered and unopered
* @param s The error string to send
@@ -615,56 +517,13 @@ class CoreExport InspIRCd
* @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);
-
- /** Add a command to this server's command parser
- * @param f A Command command handler object to add
- * @throw ModuleException Will throw ModuleExcption if the command already exists
- */
- inline void AddCommand(Command *f)
- {
- Modules->AddService(*f);
- }
-
- /** Send a modechange.
- * The parameters provided are identical to that sent to the
- * handler for class cmd_mode.
- * @param parameters The mode parameters
- * @param user The user to send error messages to
- */
- void SendMode(const std::vector<std::string>& parameters, User *user);
-
- /** Send a modechange and route it to the network.
- * The parameters provided are identical to that sent to the
- * handler for class cmd_mode.
- * @param parameters The mode parameters
- * @param user The user to send error messages to
- */
- void SendGlobalMode(const std::vector<std::string>& parameters, User *user);
+ caller1<bool, const std::string&> IsIdent;
/** 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.
@@ -672,8 +531,8 @@ class CoreExport InspIRCd
* @param mask The glob pattern to match against.
* @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 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);
/** 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.
@@ -682,30 +541,21 @@ class CoreExport InspIRCd
* @param mask The glob or CIDR pattern to match against.
* @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);
+ 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
+ /** 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.
*/
- CmdResult CallCommandHandler(const std::string &commandname, const std::vector<std::string>& parameters, User* user);
-
- /** 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
- */
- 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
* @return True i the mask is valid
*/
- bool IsValidMask(const std::string &mask);
+ static bool IsValidMask(const std::string& mask);
/** Strips all color codes from the given string
* @param sentence The string to strip from
@@ -718,36 +568,16 @@ class CoreExport InspIRCd
static void ProcessColors(file_cache& input);
/** Rehash the local server
+ * @param uuid The uuid of the user who started the rehash, can be empty
*/
- void RehashServer();
-
- /** Check if the given nickmask matches too many users, send errors to the given user
- * @param nick A nickmask to match against
- * @param user A user to send error text to
- * @return True if the nick matches too many users
- */
- bool NickMatchesEveryone(const std::string &nick, User* user);
-
- /** Check if the given IP mask matches too many users, send errors to the given user
- * @param ip An ipmask to match against
- * @param user A user to send error text to
- * @return True if the ip matches too many users
- */
- bool IPMatchesEveryone(const std::string &ip, User* user);
-
- /** Check if the given hostmask matches too many users, send errors to the given user
- * @param mask A hostmask to match against
- * @param user A user to send error text to
- * @return True if the host matches too many users
- */
- bool HostMatchesEveryone(const std::string &mask, User* user);
+ void Rehash(const std::string& uuid = "");
/** Calculate a duration in seconds from a string in the form 1y2w3d4h6m5s
* @param str A string containing a time in the form 1y2w3d4h6m5s
* (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
@@ -756,26 +586,14 @@ class CoreExport InspIRCd
* @param data The data from the config file
* @param input The data input by the oper
* @param hashtype The hash from the config file
- * @return 0 if the strings match, 1 or -1 if they do not
- */
- int PassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype);
-
- /** Check if a given server is a uline.
- * An empty string returns true, this is by design.
- * @param server The server to check for uline status
- * @return True if the server is a uline OR the string is empty
+ * @return True if the strings match, false if they do not
*/
- bool ULine(const std::string& server);
-
- /** Returns true if the uline is 'silent' (doesnt generate
- * remote connect notices etc).
- */
- bool SilentULine(const std::string& server);
+ bool PassCompare(Extensible* ex, const std::string& data, const std::string& input, const std::string& hashtype);
/** 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
@@ -809,16 +627,6 @@ class CoreExport InspIRCd
*/
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
@@ -826,52 +634,26 @@ class CoreExport InspIRCd
*/
caller3<ModResult, User*, Channel*, const std::string&> OnCheckExemption;
- /** Restart the server.
- * This function will not return. If an error occurs,
- * it will throw an instance of CoreException.
- * @param reason The restart reason to show to all clients
- * @throw CoreException An instance of CoreException indicating the error from execv().
- */
- void Restart(const std::string &reason);
-
/** Prepare the ircd for restart or shutdown.
* This function unloads all modules which can be unloaded,
* closes all open sockets, and closes the logfile.
*/
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);
+ static std::string TimeString(time_t curtime);
/** Begin execution of the server.
* NOTE: this function NEVER returns. Internally,
* it will repeatedly loop.
- * @return The return value for this function is undefined.
*/
- int Run();
-
- /** Adds an extban char to the 005 token.
- */
- void AddExtBanChar(char c);
+ void Run();
char* GetReadBuffer()
{
return this->ReadBuffer;
}
-
- friend class TestSuite;
};
ENTRYPOINT;
@@ -885,15 +667,14 @@ class CommandModule : public Module
{
}
- void init()
- {
- ServerInstance->Modules->AddService(cmd);
- }
-
Version GetVersion()
{
return Version(cmd.name, VF_VENDOR|VF_CORE);
}
};
-#endif
+inline void stdalgo::culldeleter::operator()(classbase* item)
+{
+ if (item)
+ ServerInstance->GlobalCulls.AddItem(item);
+}
diff --git a/include/inspsocket.h b/include/inspsocket.h
index c62c5a250..720489b77 100644
--- a/include/inspsocket.h
+++ b/include/inspsocket.h
@@ -21,11 +21,12 @@
*/
-#ifndef INSPSOCKET_H
-#define INSPSOCKET_H
+#pragma once
#include "timer.h"
+class IOHook;
+
/**
* States which a socket may be in
*/
@@ -93,7 +94,7 @@ class CoreExport SocketTimeout : public Timer
/** Handle tick event
*/
- virtual void Tick(time_t now);
+ virtual bool Tick(time_t now);
};
/**
@@ -102,8 +103,9 @@ class CoreExport SocketTimeout : public Timer
*/
class CoreExport StreamSocket : public EventHandler
{
- /** Module that handles raw I/O for this socket, or NULL */
- reference<Module> IOHook;
+ /** The IOHook that handles raw I/O for this socket, or NULL */
+ IOHook* iohook;
+
/** Private send queue. Note that individual strings may be shared
*/
std::deque<std::string> sendq;
@@ -114,10 +116,10 @@ class CoreExport StreamSocket : public EventHandler
protected:
std::string recvq;
public:
- StreamSocket() : sendq_len(0) {}
- inline Module* GetIOHook();
- inline void AddIOHook(Module* m);
- inline void DelIOHook();
+ StreamSocket() : iohook(NULL), sendq_len(0) {}
+ IOHook* GetIOHook() const;
+ void AddIOHook(IOHook* hook);
+ void DelIOHook();
/** Handle event from socket engine.
* This will call OnDataReady if there is *new* data in recvq
*/
@@ -229,9 +231,6 @@ class CoreExport BufferedSocket : public StreamSocket
BufferedSocketError BeginConnect(const std::string &ipaddr, int aport, unsigned long maxtime, const std::string &connectbindip);
};
-#include "modules.h"
-
-inline Module* StreamSocket::GetIOHook() { return IOHook; }
-inline void StreamSocket::AddIOHook(Module* m) { IOHook = m; }
-inline void StreamSocket::DelIOHook() { IOHook = NULL; }
-#endif
+inline IOHook* StreamSocket::GetIOHook() const { return iohook; }
+inline void StreamSocket::AddIOHook(IOHook* hook) { iohook = hook; }
+inline void StreamSocket::DelIOHook() { iohook = NULL; }
diff --git a/include/inspstring.h b/include/inspstring.h
index a6ef5e552..ccc77da66 100644
--- a/include/inspstring.h
+++ b/include/inspstring.h
@@ -18,40 +18,38 @@
*/
-#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());
+}
diff --git a/include/intrusive_list.h b/include/intrusive_list.h
new file mode 100644
index 000000000..399dc33e8
--- /dev/null
+++ b/include/intrusive_list.h
@@ -0,0 +1,162 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2013-2014 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/>.
+ */
+
+
+#pragma once
+
+#include <iterator>
+
+struct intrusive_list_def_tag { };
+
+template <typename T, typename Tag = intrusive_list_def_tag> class intrusive_list;
+
+template <typename T, typename Tag = intrusive_list_def_tag>
+struct intrusive_list_node
+{
+ T* ptr_next;
+ T* ptr_prev;
+
+ void unlink()
+ {
+ if (ptr_next)
+ ptr_next->intrusive_list_node<T, Tag>::ptr_prev = this->ptr_prev;
+ if (ptr_prev)
+ ptr_prev->intrusive_list_node<T, Tag>::ptr_next = this->ptr_next;
+ ptr_next = ptr_prev = NULL;
+ }
+
+ public:
+ intrusive_list_node()
+ : ptr_next(NULL)
+ , ptr_prev(NULL)
+ {
+ }
+
+ friend class intrusive_list<T, Tag>;
+};
+
+template <typename T, typename Tag>
+class intrusive_list
+{
+ public:
+ class iterator : public std::iterator<std::bidirectional_iterator_tag, T*>
+ {
+ T* curr;
+
+ public:
+ iterator(T* i = NULL)
+ : curr(i)
+ {
+ }
+
+ iterator& operator++()
+ {
+ curr = curr->intrusive_list_node<T, Tag>::ptr_next;
+ return *this;
+ }
+
+ iterator operator++(int)
+ {
+ iterator ret(*this);
+ operator++();
+ return ret;
+ }
+
+ void operator--()
+ {
+ curr = curr->intrusive_list_node<T, Tag>::ptr_prev;
+ return *this;
+ }
+
+ iterator operator--(int)
+ {
+ iterator ret(*this);
+ operator--();
+ return ret;
+ }
+
+ bool operator==(const iterator& other) const { return (curr == other.curr); }
+ bool operator!=(const iterator& other) const { return (curr != other.curr); }
+ T* operator*() const { return curr; }
+ };
+
+ typedef iterator const_iterator;
+
+ intrusive_list()
+ : listhead(NULL)
+ , listsize(0)
+ {
+ }
+
+ bool empty() const
+ {
+ return (size() == 0);
+ }
+
+ size_t size() const
+ {
+ return listsize;
+ }
+
+ iterator begin() const
+ {
+ return iterator(listhead);
+ }
+
+ iterator end() const
+ {
+ return iterator();
+ }
+
+ void pop_front()
+ {
+ erase(listhead);
+ }
+
+ T* front() const
+ {
+ return listhead;
+ }
+
+ void push_front(T* x)
+ {
+ if (listsize++)
+ {
+ x->intrusive_list_node<T, Tag>::ptr_next = listhead;
+ listhead->intrusive_list_node<T, Tag>::ptr_prev = x;
+ }
+ listhead = x;
+ }
+
+ void erase(const iterator& it)
+ {
+ erase(*it);
+ }
+
+ void erase(T* x)
+ {
+ if (listhead == x)
+ listhead = x->intrusive_list_node<T, Tag>::ptr_next;
+ x->intrusive_list_node<T, Tag>::unlink();
+ listsize--;
+ }
+
+ private:
+ T* listhead;
+ size_t listsize;
+};
diff --git a/include/iohook.h b/include/iohook.h
new file mode 100644
index 000000000..ce7ca2a1b
--- /dev/null
+++ b/include/iohook.h
@@ -0,0 +1,89 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 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/>.
+ */
+
+
+#pragma once
+
+class StreamSocket;
+
+class IOHookProvider : public ServiceProvider
+{
+ public:
+ enum Type
+ {
+ IOH_UNKNOWN,
+ IOH_SSL
+ };
+
+ const Type type;
+
+ IOHookProvider(Module* mod, const std::string& Name, Type hooktype = IOH_UNKNOWN)
+ : ServiceProvider(mod, Name, SERVICE_IOHOOK), type(hooktype) { }
+
+ /** Called immediately after a connection is accepted. This is intended for raw socket
+ * processing (e.g. modules which wrap the tcp connection within another library) and provides
+ * no information relating to a user record as the connection has not been assigned yet.
+ * @param sock The socket in question
+ * @param client The client IP address and port
+ * @param server The server IP address and port
+ */
+ virtual void OnAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server) = 0;
+
+ /** Called immediately upon connection of an outbound BufferedSocket which has been hooked
+ * by a module.
+ * @param sock The socket in question
+ */
+ virtual void OnConnect(StreamSocket* sock) = 0;
+};
+
+class IOHook : public classbase
+{
+ public:
+ /** The IOHookProvider for this hook, contains information about the hook,
+ * such as the module providing it and the hook type.
+ */
+ IOHookProvider* const prov;
+
+ IOHook(IOHookProvider* provider)
+ : prov(provider) { }
+
+ /**
+ * Called when a hooked stream has data to write, or when the socket
+ * engine returns it as writable
+ * @param sock The socket in question
+ * @param sendq Data to send to the socket
+ * @return 1 if the sendq has been completely emptied, 0 if there is
+ * still data to send, and -1 if there was an error
+ */
+ virtual int OnStreamSocketWrite(StreamSocket* sock, std::string& sendq) = 0;
+
+ /** Called immediately before any socket is closed. When this event is called, shutdown()
+ * has not yet been called on the socket.
+ * @param sock The socket in question
+ */
+ virtual void OnStreamSocketClose(StreamSocket* sock) = 0;
+
+ /**
+ * Called when the stream socket has data to read
+ * @param sock The socket that is ready
+ * @param recvq The receive queue that new data should be appended to
+ * @return 1 if new data has been read, 0 if no new data is ready (but the
+ * socket is still connected), -1 if there was an error or close
+ */
+ virtual int OnStreamSocketRead(StreamSocket* sock, std::string& recvq) = 0;
+};
diff --git a/include/listmode.h b/include/listmode.h
new file mode 100644
index 000000000..75385588b
--- /dev/null
+++ b/include/listmode.h
@@ -0,0 +1,206 @@
+/*
+ * 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 Creator The creator of this class
+ * @param Name Mode name
+ * @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();
+
+ /** Handle the list mode.
+ * See mode.h
+ */
+ virtual ModeAction OnModeChange(User* source, User*, Channel* channel, std::string &parameter, bool adding);
+
+ /** Validate parameters.
+ * Overridden by implementing module.
+ * @param user 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;
+}
diff --git a/include/logger.h b/include/logger.h
index 0fa4bc7cd..2ea280be8 100644
--- a/include/logger.h
+++ b/include/logger.h
@@ -18,8 +18,18 @@
*/
-#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.
*/
@@ -77,9 +87,11 @@ class CoreExport FileWriter
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)
{
}
@@ -91,13 +103,13 @@ class CoreExport LogStream : public classbase
/** 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;
@@ -127,7 +139,6 @@ class CoreExport LogManager
FileLogMap FileLogs;
public:
-
LogManager();
~LogManager();
@@ -199,17 +210,15 @@ class CoreExport 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
diff --git a/include/membership.h b/include/membership.h
index 436a9371c..44eaf1eb6 100644
--- a/include/membership.h
+++ b/include/membership.h
@@ -1,6 +1,7 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
+ * Copyright (C) 2012-2014 Attila Molnar <attilamolnar@hush.com>
* Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
*
* This file is part of InspIRCd. InspIRCd is free software: you can
@@ -17,10 +18,9 @@
*/
-#ifndef MEMBERSHIP_H
-#define MEMBERSHIP_H
+#pragma once
-class CoreExport Membership : public Extensible
+class CoreExport Membership : public Extensible, public intrusive_list_node<Membership>
{
public:
User* const user;
@@ -33,12 +33,39 @@ class CoreExport Membership : public Extensible
return modes.find(m) != std::string::npos;
}
unsigned int getRank();
+
+ /** 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
+ * the channel (to grant the default privs to them)
+ * @param mh The mode handler of the prefix mode to associate
+ * @param adding True if adding the prefix, false when removing
+ * @return True if a change was made
+ */
+ bool SetPrefix(PrefixMode* mh, bool adding);
+
+ /** Get the highest prefix this user has on the channel
+ * @return A character containing the highest prefix.
+ * If the user has no prefix, 0 is returned. If the user has multiple prefixes,
+ * the highest is returned. If you do not recognise the prefix character you
+ * can get, you can deal with it in a 'proportional' manner compared to known
+ * prefixes, using GetPrefixValue().
+ */
+ char GetPrefixChar() const;
+
+ /** Return all prefix chars this member has.
+ * @return A list of all prefix characters. The prefixes will always
+ * be in rank order, greatest first, as certain IRC clients require
+ * this when multiple prefixes are used names lists.
+ */
+ const char* GetAllPrefixChars() const;
};
-class CoreExport InviteBase
+template <typename T>
+class InviteBase
{
protected:
- InviteList invites;
+ intrusive_list<Invitation, T> invites;
public:
void ClearInvites();
@@ -46,7 +73,7 @@ class CoreExport InviteBase
friend class Invitation;
};
-class Invitation : public classbase
+class CoreExport Invitation : public intrusive_list_node<Invitation, Channel>, public intrusive_list_node<Invitation, LocalUser>
{
Invitation(Channel* c, LocalUser* u, time_t timeout) : user(u), chan(c), expiry(timeout) {}
@@ -60,4 +87,15 @@ class Invitation : public classbase
static Invitation* Find(Channel* c, LocalUser* u, bool check_expired = true);
};
-#endif
+typedef intrusive_list<Invitation, LocalUser> InviteList;
+
+template<typename T>
+inline void InviteBase<T>::ClearInvites()
+{
+ for (typename intrusive_list<Invitation, T>::iterator i = invites.begin(); i != invites.end(); )
+ {
+ Invitation* inv = *i;
+ ++i;
+ delete inv;
+ }
+}
diff --git a/include/mode.h b/include/mode.h
index 1dab442d4..7c5682135 100644
--- a/include/mode.h
+++ b/include/mode.h
@@ -20,8 +20,7 @@
*/
-#ifndef MODE_H
-#define MODE_H
+#pragma once
#include "ctables.h"
@@ -47,17 +46,6 @@ enum ModeAction
};
/**
- * Used to mask off the mode types in the mode handler
- * array. Used in a simple two instruction hashing function
- * "(modeletter - 65) OR mask"
- */
-enum ModeMasks
-{
- MASK_USER = 128, /* A user mode */
- MASK_CHANNEL = 0 /* A channel mode */
-};
-
-/**
* These fixed values can be used to proportionally compare module-defined prefixes to known values.
* For example, if your module queries a Channel, and is told that user 'joebloggs' has the prefix
* '$', and you dont know what $ means, then you can compare it to these three values to determine
@@ -85,6 +73,10 @@ enum ParamSpec
PARAM_ALWAYS
};
+class PrefixMode;
+class ListModeBase;
+class ParamModeBase;
+
/** Each mode is implemented by ONE ModeHandler class.
* You must derive ModeHandler and add the child class to
* the list of modes handled by the ircd, using
@@ -101,6 +93,22 @@ enum ParamSpec
*/
class CoreExport ModeHandler : public ServiceProvider
{
+ public:
+ typedef size_t Id;
+
+ enum Class
+ {
+ MC_PREFIX,
+ MC_LIST,
+ MC_PARAM,
+ MC_OTHER
+ };
+
+ private:
+ /** The opaque id of this mode assigned by the mode parser
+ */
+ Id modeid;
+
protected:
/**
* The mode parameter translation type
@@ -116,10 +124,6 @@ class CoreExport ModeHandler : public ServiceProvider
*/
char mode;
- /** Mode prefix, or 0
- */
- char prefix;
-
/**
* True if the mode requires oper status
* to set.
@@ -144,6 +148,10 @@ class CoreExport ModeHandler : public ServiceProvider
*/
ModeType m_type;
+ /** The object type of this mode handler
+ */
+ const Class type_id;
+
/** The prefix char needed on channel to use this mode,
* only checked for channel modes
*/
@@ -159,28 +167,34 @@ class CoreExport ModeHandler : public ServiceProvider
* @param modeletter The mode letter you wish to handle
* @param params Parameters taken by the mode
* @param type Type of the mode (MODETYPE_USER or MODETYPE_CHANNEL)
+ * @param mclass The object type of this mode handler, one of ModeHandler::Class
*/
- ModeHandler(Module* me, const std::string& name, char modeletter, ParamSpec params, ModeType type);
+ ModeHandler(Module* me, const std::string& name, char modeletter, ParamSpec params, ModeType type, Class mclass = MC_OTHER);
virtual CullResult cull();
virtual ~ModeHandler();
/**
* 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
- * value for this mode prefix.
+ * Check whether this mode is a prefix mode
+ * @return non-NULL if this mode is a prefix mode, NULL otherwise
*/
- inline char GetPrefix() const { return prefix; }
+ PrefixMode* IsPrefixMode();
+
/**
- * Get the 'value' of this modes prefix.
- * determines which to display when there are multiple.
- * The mode with the highest value is ranked first. See the
- * PrefixModeValue enum and Channel::GetPrefixValue() for
- * more information.
+ * Check whether this mode handler inherits from ListModeBase
+ * @return non-NULL if this mode handler inherits from ListModeBase, NULL otherwise
+ */
+ ListModeBase* IsListModeBase();
+
+ /**
+ * Check whether this mode handler inherits from ListModeBase
+ * @return non-NULL if this mode handler inherits from ParamModeBase, NULL otherwise
*/
- virtual unsigned int GetPrefixRank();
+ ParamModeBase* IsParameterMode();
+
/**
* Returns the mode's type
*/
@@ -206,6 +220,11 @@ class CoreExport ModeHandler : public ServiceProvider
*/
inline char GetModeChar() { return mode; }
+ /** Return the id of this mode which is used in User::modes and
+ * Channel::modes as the index to determine whether a mode is set.
+ */
+ Id GetId() const { return modeid; }
+
/** For user modes, return the current parameter, if any
*/
virtual std::string GetUserParameter(User* useor);
@@ -269,28 +288,102 @@ class CoreExport ModeHandler : public ServiceProvider
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; }
+
+ friend class ModeParser;
+};
+
+/**
+ * Prefix modes are channel modes that grant a specific rank to members having prefix mode set.
+ * They require a parameter when setting and unsetting; the parameter is always a member of the channel.
+ * A prefix mode may be set on any number of members on a channel, but for a given member a given prefix
+ * mode is either set or not set, in other words members cannot have the same prefix mode set more than once.
+ *
+ * A rank of a member is defined as the rank given by the 'strongest' prefix mode that member has.
+ * Other parts of the IRCd use this rank to determine whether a channel action is allowable for a user or not.
+ * The rank of a prefix mode is constant, i.e. the same rank value is given to all users having that prefix mode set.
+ *
+ * Note that it is possible that the same action requires a different rank on a different channel;
+ * for example changing the topic on a channel having +t set requires a rank that is >= than the rank of a halfop,
+ * but there is no such restriction when +t isn't set.
+ */
+class CoreExport PrefixMode : public ModeHandler
+{
+ protected:
+ /** The prefix character granted by this mode. '@' for op, '+' for voice, etc.
+ * If 0, this mode does not have a visible prefix character.
+ */
+ char prefix;
+
+ /** The prefix rank of this mode, used to compare prefix
+ * modes
+ */
+ unsigned int prefixrank;
+
+ public:
+ /**
+ * Constructor
+ * @param Creator The module creating this mode
+ * @param Name The user-friendly one word name of the prefix mode, e.g.: "op", "voice"
+ * @param ModeLetter The mode letter of this mode
+ */
+ PrefixMode(Module* Creator, const std::string& Name, char ModeLetter);
+
+ /**
+ * Handles setting and unsetting the prefix mode.
+ * Finds the given member of the given channel, if it's not found an error message is sent to 'source'
+ * and MODEACTION_DENY is returned. Otherwise the mode change is attempted.
+ * @param source Source of the mode change, an error message is sent to this user if the target is not found
+ * @param dest Unused
+ * @param channel The channel the mode change is happening on
+ * @param param The nickname or uuid of the target user
+ * @param adding True when the mode is being set, false when it is being unset
+ * @return MODEACTION_ALLOW if the change happened, MODEACTION_DENY if no change happened
+ * The latter occurs either when the member cannot be found or when the member already has this prefix set
+ * (when setting) or doesn't have this prefix set (when unsetting).
+ */
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& param, bool adding);
+
+ /**
+ * Removes this prefix mode from all users on the given channel
+ * @param chan The channel which the server wants to remove your mode from
+ * @param stack The mode stack to add the mode change to
+ */
+ void RemoveMode(Channel* chan, irc::modestacker& stack);
+
+ /**
+ * Mode prefix or 0. If this is defined, you should
+ * also implement GetPrefixRank() to return an integer
+ * value for this mode prefix.
+ */
+ char GetPrefix() const { return prefix; }
+
+ /**
+ * Get the 'value' of this modes prefix.
+ * determines which to display when there are multiple.
+ * The mode with the highest value is ranked first. See the
+ * PrefixModeValue enum and Channel::GetPrefixValue() for
+ * more information.
+ */
+ unsigned int GetPrefixRank() const { return prefixrank; }
};
/** A prebuilt mode handler which handles a simple user mode, e.g. no parameters, usable by any user, with no extra
@@ -303,7 +396,6 @@ class CoreExport SimpleUserModeHandler : public ModeHandler
public:
SimpleUserModeHandler(Module* Creator, const std::string& Name, char modeletter)
: ModeHandler(Creator, Name, modeletter, PARAM_NONE, MODETYPE_USER) {}
- virtual ~SimpleUserModeHandler() {}
virtual ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
};
@@ -317,20 +409,9 @@ class CoreExport SimpleChannelModeHandler : public ModeHandler
public:
SimpleChannelModeHandler(Module* Creator, const std::string& Name, char modeletter)
: ModeHandler(Creator, Name, modeletter, PARAM_NONE, MODETYPE_CHANNEL) {}
- virtual ~SimpleChannelModeHandler() {}
virtual ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
};
-class CoreExport ParamChannelModeHandler : public ModeHandler
-{
- public:
- ParamChannelModeHandler(Module* Creator, const std::string& Name, char modeletter)
- : ModeHandler(Creator, Name, modeletter, PARAM_SETONLY, MODETYPE_CHANNEL) {}
- virtual ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
- /** Validate the parameter - you may change the value to normalize it. Return true if it is valid. */
- virtual bool ParamValidate(std::string& parameter);
-};
-
/**
* The ModeWatcher class can be used to alter the behaviour of a mode implemented
* by the core or by another module. To use ModeWatcher, derive a class from it,
@@ -339,11 +420,12 @@ class CoreExport ParamChannelModeHandler : public ModeHandler
*/
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)
*/
@@ -354,17 +436,18 @@ class CoreExport ModeWatcher : public classbase
/**
* 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)
@@ -380,11 +463,10 @@ class CoreExport ModeWatcher : public classbase
* 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 &parameter, 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
@@ -393,12 +475,11 @@ class CoreExport ModeWatcher : public classbase
* @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 &parameter, 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,
@@ -407,18 +488,50 @@ typedef std::vector<ModeWatcher*>::iterator ModeWatchIter;
*/
class CoreExport ModeParser
{
+ public:
+ static const ModeHandler::Id MODEID_MAX = 64;
+
+ /** Type of the container that maps mode names to ModeHandlers
+ */
+ typedef TR1NS::unordered_map<std::string, ModeHandler*, irc::insensitive, irc::StrHashComp> ModeHandlerMap;
+
private:
+ /** Last item in the ModeType enum
+ */
+ static const unsigned int MODETYPE_LAST = 2;
+
/** Mode handlers for each mode, to access a handler subtract
* 65 from the ascii value of the mode letter.
* The upper bit of the value indicates if its a usermode
* 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.
+ ModeHandler* modehandlers[MODETYPE_LAST][128];
+
+ /** An array of mode handlers indexed by the mode id
+ */
+ ModeHandler* modehandlersbyid[MODETYPE_LAST][MODEID_MAX];
+
+ /** A map of mode handlers keyed by their name
+ */
+ ModeHandlerMap modehandlersbyname[MODETYPE_LAST];
+
+ /** Lists of mode handlers by type
+ */
+ struct
+ {
+ /** List of mode handlers that inherit from ListModeBase
+ */
+ std::vector<ListModeBase*> list;
+
+ /** List of mode handlers that inherit from PrefixMode
+ */
+ std::vector<PrefixMode*> prefix;
+ } mhlist;
+
+ /** 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.
*/
@@ -433,6 +546,26 @@ class CoreExport ModeParser
*/
ModeAction TryMode(User* user, User* targu, Channel* targc, bool adding, unsigned char mode, std::string &param, 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();
+
+ /** Allocates an unused id for the given mode type, throws a ModuleException if out of ids.
+ * @param mt The type of the mode to allocate the id for
+ * @return The id
+ */
+ ModeHandler::Id AllocateModeId(ModeType mt);
+
/** The string representing the last set of modes to be parsed.
* Use GetLastParse() to get this value, to be used for display purposes.
*/
@@ -444,17 +577,44 @@ class CoreExport ModeParser
unsigned int seq;
+ /** Cached mode list for use in 004 numeric
+ */
+ std::string Cached004ModeList;
+
public:
+ typedef std::vector<ListModeBase*> ListModeList;
+ typedef std::vector<PrefixMode*> PrefixModeList;
+
+ typedef unsigned int ModeProcessFlag;
+ enum ModeProcessFlags
+ {
+ /** If only this flag is specified, the mode change will be global
+ * and parameter modes will have their parameters explicitly set
+ * (not merged). This is the default.
+ */
+ MODE_NONE = 0,
+
+ /** If this flag is set then the parameters of non-listmodes will be
+ * merged according to their conflict resolution rules.
+ * Does not affect user modes, channel modes without a parameter and
+ * listmodes.
+ */
+ MODE_MERGE = 1,
+
+ /** If this flag is set then the mode change won't be handed over to
+ * the linking module to be sent to other servers, but will be processed
+ * locally and sent to local user(s) as usual.
+ */
+ MODE_LOCALONLY = 2
+ };
- /** The constructor initializes all the RFC basic modes by using ModeParserAddMode().
- */
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.
*
@@ -474,13 +634,15 @@ class CoreExport ModeParser
* 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.
- * @return True if the mode was successfully added.
+ * Throws a ModuleException if the mode cannot be added.
*/
- bool AddMode(ModeHandler* mh);
+ void AddMode(ModeHandler* mh);
+
/** Delete a mode from the mode parser.
* When a mode is deleted, the mode handler will be called
* for every user (if it is a user mode) or for every channel
@@ -496,9 +658,9 @@ class CoreExport ModeParser
* 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
@@ -510,12 +672,18 @@ class CoreExport ModeParser
/** Process a set of mode changes from a server or user.
* @param parameters The parameters of the mode change, in the format
* they would be from a MODE command.
- * @param user The user setting or removing the modes. When the modes are set
- * by a server, an 'uninitialized' User is used, where *user\::nick == NULL
- * and *user->server == NULL.
- * @param merge Should the mode parameters be merged?
+ * @param user The source of the mode change, can be a server user.
+ * @param flags Optional flags controlling how the mode change is processed,
+ * defaults to MODE_NONE.
+ */
+ void Process(const std::vector<std::string>& parameters, User* user, ModeProcessFlag flags = MODE_NONE);
+
+ /** Find the mode handler for a given mode name and type.
+ * @param modename The mode name to search for.
+ * @param mt Type of mode to search for, user or channel.
+ * @return A pointer to a ModeHandler class, or NULL of there isn't a handler for the given mode name.
*/
- void Process(const std::vector<std::string>& parameters, User *user, bool merge = false);
+ ModeHandler* FindMode(const std::string& modename, ModeType mt);
/** Find the mode handler for a given mode and type.
* @param modeletter mode letter to search for
@@ -524,27 +692,26 @@ class CoreExport ModeParser
*/
ModeHandler* FindMode(unsigned const char modeletter, ModeType mt);
+ /** Find the mode handler for the given prefix mode
+ * @param modeletter The mode letter to search for
+ * @return A pointer to the PrefixMode or NULL if the mode wasn't found or it isn't a prefix mode
+ */
+ PrefixMode* FindPrefixMode(unsigned char modeletter);
+
/** Find a mode handler by its prefix.
* If there is no mode handler with the given prefix, NULL will be returned.
* @param pfxletter The prefix to find, e.g. '@'
* @return The mode handler which handles this prefix, or NULL if there is none.
*/
- 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();
+ PrefixMode* FindPrefix(unsigned const char pfxletter);
- /** 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
@@ -552,14 +719,46 @@ class CoreExport ModeParser
* 3; Modes that only take a param when adding
* 4; Modes that dont take a param
*/
- std::string GiveModeList(ModeMasks m);
-
- static bool PrefixComparison(ModeHandler* one, ModeHandler* two);
+ std::string GiveModeList(ModeType mt);
/** This returns the PREFIX=(ohv)@%+ section of the 005 numeric, or
* just the "@%+" part if the parameter false
*/
std::string BuildPrefixes(bool lettersAndModes = true);
+
+ /** Get a list of all mode handlers that inherit from ListModeBase
+ * @return A list containing ListModeBase modes
+ */
+ const ListModeList& GetListModes() const { return mhlist.list; }
+
+ /** Get a list of all prefix modes
+ * @return A list containing all prefix modes
+ */
+ const PrefixModeList& GetPrefixModes() const { return mhlist.prefix; }
+
+ /** Get a mode name -> ModeHandler* map containing all modes of the given type
+ * @param mt Type of modes to return, MODETYPE_USER or MODETYPE_CHANNEL
+ * @return A map of mode handlers of the given type
+ */
+ const ModeHandlerMap& GetModes(ModeType mt) const { return modehandlersbyname[mt]; }
};
-#endif
+inline const std::string& ModeParser::GetModeListFor004Numeric()
+{
+ return Cached004ModeList;
+}
+
+inline PrefixMode* ModeHandler::IsPrefixMode()
+{
+ return (this->type_id == MC_PREFIX ? static_cast<PrefixMode*>(this) : NULL);
+}
+
+inline ListModeBase* ModeHandler::IsListModeBase()
+{
+ return (this->type_id == MC_LIST ? reinterpret_cast<ListModeBase*>(this) : NULL);
+}
+
+inline ParamModeBase* ModeHandler::IsParameterMode()
+{
+ return (this->type_id == MC_PARAM ? reinterpret_cast<ParamModeBase*>(this) : NULL);
+}
diff --git a/include/modes/cmode_b.h b/include/modes/cmode_b.h
deleted file mode 100644
index afd5cd13b..000000000
--- a/include/modes/cmode_b.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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 &parameter, 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);
-};
-
diff --git a/include/modes/cmode_l.h b/include/modes/cmode_l.h
deleted file mode 100644
index 3018a0d67..000000000
--- a/include/modes/cmode_l.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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);
-};
diff --git a/include/modes/cmode_v.h b/include/modes/cmode_v.h
deleted file mode 100644
index ab037f33f..000000000
--- a/include/modes/cmode_v.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 &parameter, bool adding);
- unsigned int GetPrefixRank();
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
-};
-
diff --git a/include/modes/simplemodes.h b/include/modes/simplemodes.h
deleted file mode 100644
index 661bba400..000000000
--- a/include/modes/simplemodes.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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')
- {
- }
-};
diff --git a/include/modes/umode_s.h b/include/modes/umode_s.h
deleted file mode 100644
index 8ac8fa31a..000000000
--- a/include/modes/umode_s.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 &parameter, bool adding);
- void OnParameterMissing(User* user, User* dest, Channel* channel);
- std::string GetUserParameter(User* user);
-};
diff --git a/include/modules.h b/include/modules.h
index c0d852b09..9c0b22b6c 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -23,8 +23,7 @@
*/
-#ifndef MODULES_H
-#define MODULES_H
+#pragma once
#include "dynamic.h"
#include "base.h"
@@ -35,7 +34,6 @@
#include <sstream>
#include "timer.h"
#include "mode.h"
-#include "dns.h"
/** Used to define a set of behavior bits for a module
*/
@@ -109,35 +107,33 @@ struct ModResult {
/** 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 7
+#define INSPIRCD_VERSION_API 1
/**
* This #define allows us to call a method in all
* loaded modules in a readable simple way, e.g.:
- * 'FOREACH_MOD(I_OnConnect,OnConnect(user));'
+ * 'FOREACH_MOD(OnConnect,(user));'
*/
#define FOREACH_MOD(y,x) do { \
- EventHandlerIter safei; \
- for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ) \
+ const IntModuleList& _handlers = ServerInstance->Modules->EventHandlers[I_ ## y]; \
+ for (IntModuleList::const_reverse_iterator _i = _handlers.rbegin(), _next; _i != _handlers.rend(); _i = _next) \
{ \
- safei = _i; \
- ++safei; \
+ _next = _i+1; \
try \
{ \
- (*_i)->x ; \
+ (*_i)->y x ; \
} \
catch (CoreException& modexcept) \
{ \
- ServerInstance->Logs->Log("MODULE",DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Exception caught: " + modexcept.GetReason()); \
} \
- _i = safei; \
} \
} while (0);
@@ -149,21 +145,19 @@ struct ModResult {
*/
#define DO_EACH_HOOK(n,v,args) \
do { \
- EventHandlerIter iter_ ## n = ServerInstance->Modules->EventHandlers[I_ ## n].begin(); \
- while (iter_ ## n != ServerInstance->Modules->EventHandlers[I_ ## n].end()) \
+ const IntModuleList& _handlers = ServerInstance->Modules->EventHandlers[I_ ## n]; \
+ for (IntModuleList::const_reverse_iterator _i = _handlers.rbegin(), _next; _i != _handlers.rend(); _i = _next) \
{ \
- Module* mod_ ## n = *iter_ ## n; \
- iter_ ## n ++; \
+ _next = _i+1; \
try \
{ \
- v = (mod_ ## n)->n args;
+ v = (*_i)->n args;
#define WHILE_EACH_HOOK(n) \
} \
catch (CoreException& except_ ## n) \
{ \
- ServerInstance->Logs->Log("MODULE",DEFAULT,"Exception caught: %s", (except_ ## n).GetReason()); \
- (void) mod_ ## n; /* catch mismatched pairs */ \
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Exception caught: " + (except_ ## n).GetReason()); \
} \
} \
} while(0)
@@ -212,41 +206,6 @@ class CoreExport Version
virtual ~Version() {}
};
-/** The Request class is a unicast message directed at a given module.
- * When this class is properly instantiated it may be sent to a module
- * using the Send() method, which will call the given module's OnRequest
- * method with this class as its parameter.
- */
-class CoreExport Request : public classbase
-{
- public:
- /** This should be a null-terminated string identifying the type of request,
- * all modules should define this and use it to determine the nature of the
- * request before they attempt to cast the Request in any way.
- */
- const char* const id;
- /** This is a pointer to the sender of the message, which can be used to
- * directly trigger events, or to create a reply.
- */
- ModuleRef source;
- /** The single destination of the Request
- */
- ModuleRef dest;
-
- /** Create a new Request
- * This is for the 'new' way of defining a subclass
- * of Request and defining it in a common header,
- * passing an object of your Request subclass through
- * as a Request* and using the ID string to determine
- * what to cast it back to and the other end.
- */
- Request(Module* src, Module* dst, const char* idstr);
- /** Send the Request.
- */
- void Send();
-};
-
-
/** The Event class is a unicast message directed at all modules.
* When the class is properly instantiated it may be sent to all modules
* using the Send() method, which will trigger the OnEvent method in
@@ -282,38 +241,6 @@ class CoreExport DataProvider : public ServiceProvider
: ServiceProvider(Creator, Name, SERVICE_DATA) {}
};
-class CoreExport dynamic_reference_base : public interfacebase
-{
- private:
- std::string name;
- protected:
- DataProvider* 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();
- static void reset_all();
-};
-
-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();
- return static_cast<T*>(value);
- }
-};
-
/** Priority types which can be used by Module::Prioritize()
*/
enum Priority { PRIORITY_FIRST, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER };
@@ -323,21 +250,21 @@ enum Priority { PRIORITY_FIRST, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }
enum Implementation
{
I_BEGIN,
- I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash,
+ I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart,
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_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_OnUserPostNick, I_OnPreMode, I_On005Numeric, I_OnKill, 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,
+ I_OnText, I_OnPassCompare, I_OnNamesListItem, I_OnNumeric,
I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnSetUserIP,
I_END
};
@@ -349,6 +276,11 @@ enum Implementation
*/
class CoreExport Module : public classbase, public usecountbase
{
+ /** Detach an event from this module
+ * @param i Event type to detach
+ */
+ void DetachEvent(Implementation i);
+
public:
/** File that this module was loaded from
*/
@@ -387,6 +319,13 @@ class CoreExport Module : public classbase, public usecountbase
{
}
+ /** This method is called when you should reload module specific configuration:
+ * on boot, on a /REHASH and on module load.
+ * @param status The current status, can be inspected for more information;
+ * also used for reporting configuration errors and warnings.
+ */
+ virtual void ReadConfig(ConfigStatus& status);
+
/** Returns the version number of a Module.
* The method should return a Version object with its version information assigned via
* Version::Version
@@ -477,14 +416,6 @@ class CoreExport Module : public classbase, public usecountbase
*/
virtual void OnModuleRehash(User* user, const std::string &parameter);
- /** Called on rehash.
- * This method is called after a rehash has completed. You should use it to reload any module
- * configuration from the main configuration file.
- * @param user The user that performed the rehash, if it was initiated by a user and that user
- * is still connected.
- */
- virtual void OnRehash(User* user);
-
/** Called whenever a snotice is about to be sent to a snomask.
* snomask and type may both be modified; the message may not.
* @param snomask The snomask the message is going to (e.g. 'A')
@@ -514,7 +445,7 @@ class CoreExport Module : public classbase, public usecountbase
* @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
@@ -611,30 +542,10 @@ class CoreExport Module : public classbase, public usecountbase
* @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
@@ -645,7 +556,7 @@ class CoreExport Module : public classbase, public usecountbase
*
* Set exceptions[user] = true to include, exceptions[user] = false to exclude
*/
- virtual void OnBuildNeighborList(User* source, UserChanList &include_c, std::map<User*,bool> &exceptions);
+ virtual void OnBuildNeighborList(User* source, IncludeChanList& include_c, std::map<User*, bool>& exceptions);
/** Called before any nickchange, local or remote. This can be used to implement Q-lines etc.
* Please note that although you can see remote nickchanges through this function, you should
@@ -668,25 +579,14 @@ class CoreExport Module : public classbase, public usecountbase
* @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
@@ -699,68 +599,46 @@ class CoreExport Module : public classbase, public usecountbase
virtual void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list);
/** Called after every MODE command 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. The text variable contains the remainder of the
- * mode string after the target, e.g. "+wsi" or "+ooo nick1 nick2 nick3".
+ * Either the usertarget or the chantarget variable contains the target of the modes,
+ * the actual target will have a non-NULL pointer.
+ * The modes vector contains the remainder of the mode string after the target,
+ * e.g.: "+wsi" or ["+ooo", "nick1", "nick2", "nick3"].
* @param user The user sending the MODEs
- * @param dest The target of the modes (User* or Channel*)
- * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
- * @param text The actual modes and their parameters if any
+ * @param usertarget The target user of the modes, NULL if the target is a channel
+ * @param chantarget The target channel of the modes, NULL if the target is a user
+ * @param modes The actual modes and their parameters if any
* @param translate The translation types of the mode parameters
*/
- virtual void OnMode(User* user, void* dest, int target_type, const std::vector<std::string> &text, const std::vector<TranslateType> &translate);
-
- /** Allows modules to alter or create server descriptions
- * Whenever a module requires a server description, for example for display in
- * WHOIS, this function is called in all modules. You may change or define the
- * description given in std::string &description. If you do, this description
- * will be shown in the WHOIS fields.
- * @param servername The servername being searched for
- * @param description Alterable server description for this server
- */
- virtual void OnGetServerDescription(const std::string &servername,std::string &description);
+ virtual void OnMode(User* user, User* usertarget, Channel* chantarget, const std::vector<std::string>& modes, const std::vector<TranslateType>& translate);
/** Allows modules to synchronize data which relates to users during a netburst.
* When this function is called, it will be called from the module which implements
- * the linking protocol. This currently is m_spanningtree.so. A pointer to this module
- * is given in Module* proto, so that you may call its methods such as ProtoSendMode
- * (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. Do not use this call to
- * synchronize data which you have stored using class Extensible -- There is a specialist
- * function OnSyncUserMetaData and OnSyncChannelMetaData for this!
+ * the linking protocol. This currently is m_spanningtree.so.
+ * This function will be called for every user visible on your side
+ * of the burst, allowing you to for example set modes, etc.
* @param user The user 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!
+ * @param server The target of the burst
*/
- virtual void OnSyncUser(User* user, Module* proto, void* opaque);
+ virtual void OnSyncUser(User* user, ProtocolServer& server);
/** Allows modules to synchronize data which relates to channels during a netburst.
* When this function is called, it will be called from the module which implements
- * the linking protocol. This currently is m_spanningtree.so. A pointer to this module
- * is given in Module* proto, so that you may call its methods such as ProtoSendMode
- * (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
+ * the linking protocol. This currently is m_spanningtree.so.
+ * This function will be called for every channel visible on your side of the burst,
+ * allowing you to for example set modes, etc.
*
* @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!
+ * @param server The target of the burst
*/
- virtual void OnSyncChannel(Channel* chan, Module* proto, void* opaque);
+ virtual void OnSyncChannel(Channel* chan, ProtocolServer& server);
- /* Allows modules to syncronize metadata not related to users or channels, over the network during a netburst.
- * Whenever the linking module wants to send out data, but doesnt know what the data
- * represents (e.g. it is Extensible metadata, added to a User or Channel by a module) then
- * this method is called. You should use the ProtoSendMetaData function after you've
- * correctly decided how the data should be represented, to send the metadata on its way if
- * if it belongs to your module.
- * @param proto A pointer to the module handling network protocol
- * @param opaque An opaque pointer set by the protocol module, should not be modified!
- * @param displayable If this value is true, the data is going to be displayed to a user,
- * and not sent across the network. Use this to determine wether or not to show sensitive data.
+ /** Allows modules to syncronize metadata not related to users or channels, over the network during a netburst.
+ * When the linking module has finished sending all data it wanted to send during a netburst, then
+ * this method is called. You should use the SendMetaData() function after you've
+ * correctly decided how the data should be represented, to send the data.
+ * @param server The target of the burst
*/
- virtual void OnSyncNetwork(Module* proto, void* opaque);
+ virtual void OnSyncNetwork(ProtocolServer& server);
/** Allows module data, sent via ProtoSendMetaData, to be decoded again by a receiving module.
* Please see src/modules/m_swhois.cpp for a working example of how to use this method call.
@@ -770,43 +648,6 @@ class CoreExport Module : public classbase, public usecountbase
*/
virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata);
- /** Implemented by modules which provide the ability to link servers.
- * These modules will implement this method, which allows transparent sending of servermodes
- * 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
- * @param modeline The modes and parameters to be sent
- * @param translate The translation types of the mode parameters
- */
- virtual void ProtoSendMode(void* opaque, TargetTypeFlags target_type, void* target, const std::vector<std::string> &modeline, const std::vector<TranslateType> &translate);
-
- /** Implemented by modules which provide the ability to link servers.
- * These modules will implement this method, which allows metadata (extra data added to
- * user and channel records using class Extensible, Extensible::Extend, etc) to be sent
- * to other servers on a netburst and decoded at the other end by the same module on a
- * different server.
- *
- * More documentation to follow soon. Please see src/modules/m_swhois.cpp for example of
- * how to use this function.
- * @param opaque An opaque pointer set by the protocol module, should not be modified!
- * @param target The Channel* or User* that metadata should be sent for
- * @param extname The extension name to send metadata for
- * @param extdata Encoded data for this extension name, which will be encoded at the oppsite end by an identical module using OnDecodeMetaData
- */
- 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
@@ -885,9 +726,9 @@ class CoreExport Module : public classbase, public usecountbase
/** 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 tokens 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,
@@ -904,14 +745,6 @@ class CoreExport Module : public classbase, public usecountbase
*/
virtual ModResult OnKill(User* source, User* dest, const std::string &reason);
- /** Called when an oper wants to disconnect a remote user via KILL
- * @param source The user sending the KILL
- * @param dest The user being killed
- * @param reason The kill reason
- * @param operreason The oper kill reason
- */
- virtual void OnRemoteKill(User* source, User* dest, const std::string &reason, const std::string &operreason);
-
/** Called whenever a module is loaded.
* mod will contain a pointer to the module, and string will contain its name,
* for example m_widgets.so. This function is primary for dependency checking,
@@ -976,7 +809,7 @@ class CoreExport Module : public classbase, public usecountbase
* @param result The return code given by the command handler, one of CMD_SUCCESS or CMD_FAILURE
* @param original_line The entire original line as passed to the parser from the user
*/
- virtual void OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, LocalUser *user, CmdResult result, const std::string &original_line);
+ virtual void OnPostCommand(Command* command, const std::vector<std::string>& parameters, LocalUser* user, CmdResult result, const std::string& original_line);
/** Called when a user is first connecting, prior to starting DNS lookups, checking initial
* connect class, or accepting any commands.
@@ -1020,15 +853,14 @@ class CoreExport Module : public classbase, public usecountbase
* Return 1 from this function to block the mode character from being processed entirely.
* @param user The user who is sending the mode
* @param chan The channel the mode is being sent to (or NULL if a usermode)
- * @param mode The mode character being set
+ * @param mh The mode handler for the mode being changed
* @param param The parameter for the mode or an empty string
* @param adding true of the mode is being added, false if it is being removed
- * @param pcnt The parameter count for the mode (0 or 1)
* @return ACR_DENY to deny the mode, ACR_DEFAULT to do standard mode checking, and ACR_ALLOW
* to skip all permission checking. Please note that for remote mode changes, your return value
* will be ignored!
*/
- virtual ModResult OnRawMode(User* user, Channel* chan, const char mode, const std::string &param, bool adding, int pcnt);
+ virtual ModResult OnRawMode(User* user, Channel* chan, ModeHandler* mh, const std::string& param, bool adding);
/** Called whenever a user joins a channel, to determine if key checks should go ahead or not.
* This method will always be called for each join, wether or not the channel is actually +k, and
@@ -1128,12 +960,6 @@ class CoreExport Module : public classbase, public usecountbase
*/
virtual void OnEvent(Event& event);
- /** Called whenever a Request class is sent to your module by another module.
- * The value of Request::id should be used to determine the type of request.
- * @param request The Request class being received
- */
- virtual void OnRequest(Request& request);
-
/** Called whenever a password check is to be made. Replaces the old OldOperCompare API.
* The password field (from the config file) is in 'password' and is to be compared against
* 'input'. This method allows for encryption of passwords (oper, connect:allow, die/restart, etc).
@@ -1162,30 +988,6 @@ class CoreExport Module : public classbase, public usecountbase
*/
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 OnHookIO(StreamSocket* user, ListenSocket* via);
-
/** Called when a port accepts a connection
* Return MOD_RES_ACCEPT if you have used the file descriptor.
* @param fd The file descriptor returned from accept()
@@ -1195,48 +997,6 @@ class CoreExport Module : public classbase, public usecountbase
*/
virtual ModResult OnAcceptConnection(int fd, ListenSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server);
- /** Called immediately after any connection is accepted. This is intended for raw socket
- * processing (e.g. modules which wrap the tcp connection within another library) and provides
- * no information relating to a user record as the connection has not been assigned yet.
- * There are no return values from this call as all modules get an opportunity if required to
- * process the connection.
- * @param sock The socket in question
- * @param client The client IP address and port
- * @param server The server IP address and port
- */
- virtual void OnStreamSocketAccept(StreamSocket* sock, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server);
-
- /**
- * Called when a hooked stream has data to write, or when the socket
- * engine returns it as writable
- * @param sock The socket in question
- * @param sendq Data to send to the socket
- * @return 1 if the sendq has been completely emptied, 0 if there is
- * still data to send, and -1 if there was an error
- */
- virtual int OnStreamSocketWrite(StreamSocket* sock, std::string& sendq);
-
- /** Called immediately before any socket is closed. When this event is called, shutdown()
- * has not yet been called on the socket.
- * @param sock The socket in question
- */
- virtual void OnStreamSocketClose(StreamSocket* sock);
-
- /** Called immediately upon connection of an outbound BufferedSocket which has been hooked
- * by a module.
- * @param sock The socket in question
- */
- virtual void OnStreamSocketConnect(StreamSocket* sock);
-
- /**
- * Called when the stream socket has data to read
- * @param sock The socket that is ready
- * @param recvq The receive queue that new data should be appended to
- * @return 1 if new data has been read, 0 if no new data is ready (but the
- * socket is still connected), -1 if there was an error or close
- */
- virtual int OnStreamSocketRead(StreamSocket* sock, std::string& recvq);
-
/** Called whenever a user sets away or returns from being away.
* The away message is available as a parameter, but should not be modified.
* At this stage, it has already been copied into the user record.
@@ -1273,10 +1033,12 @@ class CoreExport Module : public classbase, public usecountbase
*/
virtual ModResult OnSetConnectClass(LocalUser* user, ConnectClass* myclass);
+#ifdef INSPIRCD_ENABLE_TESTSUITE
/** Add test suite hooks here. These are used for testing functionality of a module
* via the --testsuite debugging parameter.
*/
virtual void OnRunTestSuite();
+#endif
/** Called for every item in a NAMES list, so that modules may reformat portions of it as they see fit.
* For example NAMESX, channel mode +u and +I, and UHNAMES. If the nick is set to an empty string by any
@@ -1290,9 +1052,10 @@ class CoreExport Module : public classbase, public usecountbase
* @param source The user running the /WHO query
* @param params The parameters to the /WHO query
* @param user The user that this line of the query is about
+ * @param memb The member shown in this line, NULL if no channel is in this line
* @param line The raw line to send; modifiable, if empty no line will be returned.
*/
- virtual void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line);
+ virtual void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, Membership* memb, std::string& line);
/** Called whenever a local user's IP is set for the first time, or when a local user's IP changes due to
* a module like m_cgiirc changing it.
@@ -1301,173 +1064,6 @@ class CoreExport Module : public classbase, public usecountbase
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.
- */
-class CoreExport FileReader : public classbase
-{
- /** The file contents
- */
- std::vector<std::string> fc;
-
- /** Content size in bytes
- */
- unsigned long contentsize;
-
- /** Calculate content size in bytes
- */
- void CalcSize();
-
- public:
- /** Default constructor.
- * This method does not load any file into memory, you must use the LoadFile method
- * after constructing the class this way.
- */
- FileReader();
-
- /** 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.
- */
- 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
- */
- std::string Contents();
-
- /** Returns the entire size of the file as std::string
- */
- unsigned long ContentSize();
-
- /** Returns true if the file exists
- * This function will return false if the file could not be opened.
- */
- bool Exists();
-
- /** 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();
-};
-
/** A list of modules
*/
typedef std::vector<Module*> IntModuleList;
@@ -1481,15 +1077,14 @@ typedef IntModuleList::iterator EventHandlerIter;
*/
class CoreExport ModuleManager
{
+ public:
+ typedef std::vector<ServiceProvider*> ServiceList;
+
private:
/** Holds a string describing the last module error to occur
*/
std::string LastModuleError;
- /** Total number of modules loaded into the ircd
- */
- int ModCount;
-
/** List of loaded modules and shared object/dll handles
* keyed by module name
*/
@@ -1503,7 +1098,18 @@ class CoreExport ModuleManager
/** Internal unload module hook */
bool CanUnload(Module*);
+
+ /** Loads all core modules (cmd_*)
+ */
+ void LoadCoreModules(std::map<std::string, ServiceList>& servicemap);
+
+ /** Calls the Prioritize() method in all loaded modules
+ * @return True if all went well, false if a dependency loop was detected
+ */
+ bool PrioritizeHooks();
+
public:
+ typedef std::map<std::string, Module*> ModuleMap;
/** Event handler hooks.
* This needs to be public to be used by FOREACH_MOD and friends.
@@ -1513,6 +1119,16 @@ class CoreExport ModuleManager
/** List of data services keyed by name */
std::multimap<std::string, ServiceProvider*> DataProviders;
+ /** A list of ServiceProviders waiting to be registered.
+ * Non-NULL when constructing a Module, NULL otherwise.
+ * When non-NULL ServiceProviders add themselves to this list on creation and the core
+ * automatically registers them (that is, call AddService()) after the Module is constructed,
+ * and before Module::init() is called.
+ * If a service is created after the construction of the Module (for example in init()) it
+ * has to be registered manually.
+ */
+ ServiceList* NewServices;
+
/** Simple, bog-standard, boring constructor.
*/
ModuleManager();
@@ -1585,6 +1201,11 @@ class CoreExport ModuleManager
*/
void DetachAll(Module* mod);
+ /** Attach all events to a module (used on module load)
+ * @param mod Module to attach to all events
+ */
+ void AttachAll(Module* mod);
+
/** Returns text describing the last module error
* @return The last error message to occur
*/
@@ -1616,14 +1237,6 @@ class CoreExport ModuleManager
void UnloadAll();
void DoSafeUnload(Module*);
- /** Get the total number of currently loaded modules
- * @return The number of loaded modules
- */
- int GetCount()
- {
- return this->ModCount;
- }
-
/** Find a module by name, and return a Module* to it.
* This is preferred over iterating the module lists yourself.
* @param name The module name to look up
@@ -1637,6 +1250,11 @@ class CoreExport ModuleManager
/** Unregister a service provided by a module */
void DelService(ServiceProvider&);
+ /** Register all services in a given ServiceList
+ * @param list The list containing the services to register
+ */
+ void AddServices(const ServiceList& list);
+
inline void AddServices(ServiceProvider** list, int count)
{
for(int i=0; i < count; i++)
@@ -1653,13 +1271,10 @@ class CoreExport ModuleManager
return static_cast<T*>(FindService(SERVICE_DATA, name));
}
- /** Return a list of all modules matching the given filter
- * @param filter This int is a bitmask of flags set in Module::Flags,
- * such as VF_VENDOR or VF_STATIC. If you wish to receive a list of
- * all modules with no filtering, set this to 0.
- * @return The list of module names
+ /** Get a map of all loaded modules keyed by their name
+ * @return A ModuleMap containing all loaded modules
*/
- const std::vector<std::string> GetAllModuleNames(int filter);
+ const ModuleMap& GetModules() const { return Modules; }
};
/** Do not mess with these functions unless you know the C preprocessor
@@ -1689,11 +1304,7 @@ struct AllModuleList {
};
#define MODULE_INIT(x) static Module* MK_ ## x() { return new x; } \
- static const AllModuleList PREP_ ## x(&MK_ ## x, MODNAMESTR);
-
-#define MODNAMESTR MODNAMESTR_FN_2(MODNAME)
-#define MODNAMESTR_FN_2(x) MODNAMESTR_FN_1(x)
-#define MODNAMESTR_FN_1(x) #x
+ static const AllModuleList PREP_ ## x(&MK_ ## x, MODNAME ".so");
#else
@@ -1726,11 +1337,9 @@ struct AllModuleList {
{ \
return new y; \
} \
- extern "C" const char inspircd_src_version[] = VERSION " r" REVISION;
+ extern "C" DllExport const char inspircd_src_version[] = VERSION " " REVISION;
#endif
#define COMMAND_INIT(c) MODULE_INIT(CommandModule<c>)
#endif
-
-#endif
diff --git a/include/modes/cmode_o.h b/include/modules/account.h
index c5f1764c1..c00b044e4 100644
--- a/include/modes/cmode_o.h
+++ b/include/modules/account.h
@@ -1,7 +1,7 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
- * Copyright (C) 2007 Dennis Friis <peavey@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
@@ -17,21 +17,25 @@
*/
-#include "mode.h"
-#include "channels.h"
+#pragma once
-class InspIRCd;
+#include <map>
+#include <string>
-/** Channel mode +o
- */
-class ModeChannelOp : public ModeHandler
+class AccountEvent : public Event
{
- private:
public:
- ModeChannelOp();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
- unsigned int GetPrefixRank();
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
+ 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"));
+}
diff --git a/include/modules/cap.h b/include/modules/cap.h
new file mode 100644
index 000000000..1b33e05bb
--- /dev/null
+++ b/include/modules/cap.h
@@ -0,0 +1,88 @@
+/*
+ * 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)
+ {
+ }
+
+ 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);
+ }
+ }
+};
diff --git a/include/modules/dns.h b/include/modules/dns.h
new file mode 100644
index 000000000..c76c53805
--- /dev/null
+++ b/include/modules/dns.h
@@ -0,0 +1,193 @@
+/*
+ * 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);
+ delete this;
+ return false;
+ }
+ };
+
+} // namespace DNS
diff --git a/include/modules/hash.h b/include/modules/hash.h
new file mode 100644
index 000000000..da04c45ba
--- /dev/null
+++ b/include/modules/hash.h
@@ -0,0 +1,58 @@
+/*
+ * 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);
+ }
+};
diff --git a/include/modules/httpd.h b/include/modules/httpd.h
new file mode 100644
index 000000000..86234d53f
--- /dev/null
+++ b/include/modules/httpd.h
@@ -0,0 +1,239 @@
+/*
+ * 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;
+ }
+};
+
+/** If you want to reply to HTTP requests, you must return a HTTPDocumentResponse to
+ * the httpd module via the HTTPdAPI.
+ * When you initialize this class you initialize it with all components required to
+ * form a valid HTTP response: the document data and a response code.
+ * You can add additional HTTP headers, if you want.
+ */
+class HTTPDocumentResponse
+{
+ public:
+ /** Module that generated this reply
+ */
+ Module* const module;
+
+ std::stringstream* document;
+ unsigned int responsecode;
+
+ /** Any extra headers to include with the defaults
+ */
+ HTTPHeaders headers;
+
+ HTTPRequest& src;
+
+ /** Initialize a HTTPDocumentResponse ready for sending to the httpd module.
+ * @param mod A pointer to the module who responded to the request
+ * @param req The request 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.
+ */
+ HTTPDocumentResponse(Module* mod, HTTPRequest& req, std::stringstream* doc, unsigned int response)
+ : module(mod), document(doc), responsecode(response), src(req)
+ {
+ }
+};
+
+class HTTPdAPIBase : public DataProvider
+{
+ public:
+ HTTPdAPIBase(Module* parent)
+ : DataProvider(parent, "m_httpd_api")
+ {
+ }
+
+ /** Answer an incoming HTTP request with the provided document
+ * @param response The response created by your module that will be sent to the client
+ */
+ virtual void SendResponse(HTTPDocumentResponse& response) = 0;
+};
+
+/** The API provided by the httpd module that allows other modules to respond to incoming
+ * HTTP requests
+ */
+class HTTPdAPI : public dynamic_reference<HTTPdAPIBase>
+{
+ public:
+ HTTPdAPI(Module* parent)
+ : dynamic_reference<HTTPdAPIBase>(parent, "m_httpd_api")
+ {
+ }
+};
diff --git a/include/modules/ldap.h b/include/modules/ldap.h
new file mode 100644
index 000000000..75ab16077
--- /dev/null
+++ b/include/modules/ldap.h
@@ -0,0 +1,199 @@
+/*
+ * 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
+
+typedef int LDAPQuery;
+
+class LDAPException : public ModuleException
+{
+ public:
+ LDAPException(const std::string& reason) : ModuleException(reason) { }
+
+ virtual ~LDAPException() throw() { }
+};
+
+struct LDAPModification
+{
+ enum LDAPOperation
+ {
+ LDAP_ADD,
+ LDAP_DEL,
+ LDAP_REPLACE
+ };
+
+ LDAPOperation op;
+ std::string name;
+ std::vector<std::string> values;
+};
+
+typedef std::vector<LDAPModification> LDAPMods;
+
+struct LDAPAttributes : public std::map<std::string, std::vector<std::string> >
+{
+ size_t size(const std::string& attr) const
+ {
+ const std::vector<std::string>& array = this->getArray(attr);
+ return array.size();
+ }
+
+ const std::vector<std::string> keys() const
+ {
+ std::vector<std::string> k;
+ for (const_iterator it = this->begin(), it_end = this->end(); it != it_end; ++it)
+ k.push_back(it->first);
+ return k;
+ }
+
+ const std::string& get(const std::string& attr) const
+ {
+ const std::vector<std::string>& array = this->getArray(attr);
+ if (array.empty())
+ throw LDAPException("Empty attribute " + attr + " in LDAPResult::get");
+ return array[0];
+ }
+
+ const std::vector<std::string>& getArray(const std::string& attr) const
+ {
+ const_iterator it = this->find(attr);
+ if (it == this->end())
+ throw LDAPException("Unknown attribute " + attr + " in LDAPResult::getArray");
+ return it->second;
+ }
+};
+
+struct LDAPResult
+{
+ std::vector<LDAPAttributes> messages;
+ std::string error;
+
+ enum QueryType
+ {
+ QUERY_UNKNOWN,
+ QUERY_BIND,
+ QUERY_SEARCH,
+ QUERY_ADD,
+ QUERY_DELETE,
+ QUERY_MODIFY,
+ QUERY_COMPARE
+ };
+
+ QueryType type;
+ LDAPQuery id;
+
+ LDAPResult()
+ : type(QUERY_UNKNOWN), id(-1)
+ {
+ }
+
+ size_t size() const
+ {
+ return this->messages.size();
+ }
+
+ bool empty() const
+ {
+ return this->messages.empty();
+ }
+
+ const LDAPAttributes& get(size_t sz) const
+ {
+ if (sz >= this->messages.size())
+ throw LDAPException("Index out of range");
+ return this->messages[sz];
+ }
+
+ const std::string& getError() const
+ {
+ return this->error;
+ }
+};
+
+class LDAPInterface
+{
+ public:
+ ModuleRef creator;
+
+ LDAPInterface(Module* m) : creator(m) { }
+ virtual ~LDAPInterface() { }
+
+ virtual void OnResult(const LDAPResult& r) = 0;
+ virtual void OnError(const LDAPResult& err) = 0;
+};
+
+class LDAPProvider : public DataProvider
+{
+ public:
+ LDAPProvider(Module* Creator, const std::string& Name)
+ : DataProvider(Creator, Name) { }
+
+ /** Attempt to bind to the LDAP server as a manager
+ * @param i The LDAPInterface the result is sent to
+ * @return The query ID
+ */
+ virtual LDAPQuery BindAsManager(LDAPInterface *i) = 0;
+
+ /** Bind to LDAP
+ * @param i The LDAPInterface the result is sent to
+ * @param who The binddn
+ * @param pass The password
+ * @return The query ID
+ */
+ virtual LDAPQuery Bind(LDAPInterface* i, const std::string& who, const std::string& pass) = 0;
+
+ /** Search ldap for the specified filter
+ * @param i The LDAPInterface the result is sent to
+ * @param base The base DN to search
+ * @param filter The filter to apply
+ * @return The query ID
+ */
+ virtual LDAPQuery Search(LDAPInterface* i, const std::string& base, const std::string& filter) = 0;
+
+ /** Add an entry to LDAP
+ * @param i The LDAPInterface the result is sent to
+ * @param dn The dn of the entry to add
+ * @param attributes The attributes
+ * @return The query ID
+ */
+ virtual LDAPQuery Add(LDAPInterface* i, const std::string& dn, LDAPMods& attributes) = 0;
+
+ /** Delete an entry from LDAP
+ * @param i The LDAPInterface the result is sent to
+ * @param dn The dn of the entry to delete
+ * @return The query ID
+ */
+ virtual LDAPQuery Del(LDAPInterface* i, const std::string& dn) = 0;
+
+ /** Modify an existing entry in LDAP
+ * @param i The LDAPInterface the result is sent to
+ * @param base The base DN to modify
+ * @param attributes The attributes to modify
+ * @return The query ID
+ */
+ virtual LDAPQuery Modify(LDAPInterface* i, const std::string& base, LDAPMods& attributes) = 0;
+
+ /** Compare an attribute in LDAP with our value
+ * @param i The LDAPInterface the result is sent to
+ * @param dn DN to use for comparing
+ * @param attr Attr of DN to compare with
+ * @param val value to compare attr of dn
+ * @return the query ID
+ */
+ virtual LDAPQuery Compare(LDAPInterface* i, const std::string& dn, const std::string& attr, const std::string& val) = 0;
+};
diff --git a/include/modules/regex.h b/include/modules/regex.h
new file mode 100644
index 000000000..5ef00cdd0
--- /dev/null
+++ b/include/modules/regex.h
@@ -0,0 +1,62 @@
+/*
+ * 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:
+ /** The uncompiled regex string. */
+ std::string 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;
+};
+
+class RegexException : public ModuleException
+{
+ public:
+ RegexException(const std::string& regex, const std::string& error)
+ : ModuleException("Error in regex '" + regex + "': " + error) { }
+
+ RegexException(const std::string& regex, const std::string& error, int offset)
+ : ModuleException("Error in regex '" + regex + "' at offset " + ConvToStr(offset) + ": " + error) { }
+};
diff --git a/include/modes/umode_o.h b/include/modules/sasl.h
index f9644a097..321711a68 100644
--- a/include/modes/umode_o.h
+++ b/include/modules/sasl.h
@@ -1,7 +1,7 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
- * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ * 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
@@ -17,15 +17,15 @@
*/
-#include "mode.h"
+#pragma once
-class InspIRCd;
-
-/** User mode +o
- */
-class ModeUserOperator : public ModeHandler
+class SASLFallback : public Event
{
public:
- ModeUserOperator();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
+ const parameterlist& params;
+ SASLFallback(Module* me, const parameterlist& p)
+ : Event(me, "sasl_fallback"), params(p)
+ {
+ Send();
+ }
};
diff --git a/include/modes/cmode_k.h b/include/modules/spanningtree.h
index 000667f72..99f4f9fc4 100644
--- a/include/modes/cmode_k.h
+++ b/include/modules/spanningtree.h
@@ -1,7 +1,7 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
- * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ * 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
@@ -17,17 +17,24 @@
*/
-#include "mode.h"
+#pragma once
-class InspIRCd;
+struct AddServerEvent : public Event
+{
+ const std::string servername;
+ AddServerEvent(Module* me, const std::string& name)
+ : Event(me, "new_server"), servername(name)
+ {
+ Send();
+ }
+};
-/** Channel mode +k
- */
-class ModeChannelKey : public ModeHandler
+struct DelServerEvent : public Event
{
- public:
- ModeChannelKey();
- ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding);
- void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
- void RemoveMode(User* user, irc::modestacker* stack = NULL);
+ const std::string servername;
+ DelServerEvent(Module* me, const std::string& name)
+ : Event(me, "lost_server"), servername(name)
+ {
+ Send();
+ }
};
diff --git a/include/modules/sql.h b/include/modules/sql.h
new file mode 100644
index 000000000..3f378d8b8
--- /dev/null
+++ b/include/modules/sql.h
@@ -0,0 +1,184 @@
+/*
+ * 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->GetName();
+ userinfo["uuid"] = user->uuid;
+ }
+};
diff --git a/include/modules/ssl.h b/include/modules/ssl.h
new file mode 100644
index 000000000..0f58e0b7b
--- /dev/null
+++ b/include/modules/ssl.h
@@ -0,0 +1,246 @@
+/*
+ * 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 <string>
+#include "iohook.h"
+
+/** 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();
+ }
+};
+
+class SSLIOHook : public IOHook
+{
+ protected:
+ /** Peer SSL certificate, set by the SSL module
+ */
+ reference<ssl_cert> certificate;
+
+ public:
+ SSLIOHook(IOHookProvider* hookprov)
+ : IOHook(hookprov)
+ {
+ }
+
+ /**
+ * Get the certificate sent by this peer
+ * @return The SSL certificate sent by the peer, NULL if no cert was sent
+ */
+ ssl_cert* GetCertificate() const
+ {
+ return certificate;
+ }
+
+ /**
+ * Get the fingerprint of the peer's certificate
+ * @return The fingerprint of the SSL client certificate sent by the peer,
+ * empty if no cert was sent
+ */
+ std::string GetFingerprint() const
+ {
+ ssl_cert* cert = GetCertificate();
+ if (cert)
+ return cert->GetFingerprint();
+ return "";
+ }
+};
+
+/** Helper functions for obtaining SSL client certificates and key fingerprints
+ * from StreamSockets
+ */
+class SSLClientCert
+{
+ public:
+ /**
+ * Get the client certificate from a socket
+ * @param sock The socket to get the certificate from, the socket does not have to use SSL
+ * @return The SSL client certificate information, NULL if the peer is not using SSL
+ */
+ static ssl_cert* GetCertificate(StreamSocket* sock)
+ {
+ IOHook* iohook = sock->GetIOHook();
+ if ((!iohook) || (iohook->prov->type != IOHookProvider::IOH_SSL))
+ return NULL;
+
+ SSLIOHook* ssliohook = static_cast<SSLIOHook*>(iohook);
+ return ssliohook->GetCertificate();
+ }
+
+ /**
+ * Get the fingerprint of a client certificate from a socket
+ * @param sock The socket to get the certificate fingerprint from, the
+ * socket does not have to use SSL
+ * @return The key fingerprint from the SSL certificate sent by the peer,
+ * empty if no cert was sent or the peer is not using SSL
+ */
+ static std::string GetFingerprint(StreamSocket* sock)
+ {
+ ssl_cert* cert = SSLClientCert::GetCertificate(sock);
+ if (cert)
+ return cert->GetFingerprint();
+ return "";
+ }
+};
+
+class UserCertificateAPIBase : public DataProvider
+{
+ public:
+ UserCertificateAPIBase(Module* parent)
+ : DataProvider(parent, "m_sslinfo_api")
+ {
+ }
+
+ /** Get the SSL certificate of a user
+ * @param user The user whose certificate to get, user may be remote
+ * @return The SSL certificate of the user or NULL if the user is not using SSL
+ */
+ virtual ssl_cert* GetCertificate(User* user) = 0;
+
+ /** Get the key fingerprint from a user's certificate
+ * @param user The user whose key fingerprint to get, user may be remote
+ * @return The key fingerprint from the user's SSL certificate or an empty string
+ * if the user is not using SSL or did not provide a client certificate
+ */
+ std::string GetFingerprint(User* user)
+ {
+ ssl_cert* cert = GetCertificate(user);
+ if (cert)
+ return cert->GetFingerprint();
+ return "";
+ }
+};
+
+/** API implemented by m_sslinfo that allows modules to retrive the SSL certificate
+ * information of local and remote users. It can also be used to find out whether a
+ * user is using SSL or not.
+ */
+class UserCertificateAPI : public dynamic_reference<UserCertificateAPIBase>
+{
+ public:
+ UserCertificateAPI(Module* parent)
+ : dynamic_reference<UserCertificateAPIBase>(parent, "m_sslinfo_api")
+ {
+ }
+};
diff --git a/include/numerics.h b/include/numerics.h
index 4fce4cb6d..2418730d2 100644
--- a/include/numerics.h
+++ b/include/numerics.h
@@ -18,13 +18,9 @@
*/
-#ifndef NUMERICS_H
-#define NUMERICS_H
+#pragma once
/*
- * This file is aimed providing a string that is easier to use than using the numeric
- * directly.
- *
* Module authors, please note!
* While you are free to use any numerics on this list, like the rest of the core, you
* *should not* be editing it!
@@ -44,76 +40,111 @@ enum Numerics
/*
* Reply range of numerics.
*/
- RPL_WELCOME = 1, // 2812, not 1459
- RPL_YOURHOSTIS = 2, // 2812, not 1459
- RPL_SERVERCREATED = 3, // 2812, not 1459
- RPL_SERVERVERSION = 4, // 2812, not 1459
- RPL_ISUPPORT = 5, // not RFC, extremely common though (defined as RPL_BOUNCE in 2812, widely ignored)
-
- RPL_MAP = 6, // unrealircd
- RPL_ENDMAP = 7, // unrealircd
- RPL_SNOMASKIS = 8, // unrealircd
-
- RPL_YOURUUID = 42, // taken from ircnet
-
- RPL_UMODEIS = 221,
- RPL_RULES = 232, // unrealircd
- RPL_ADMINME = 256,
- RPL_ADMINLOC1 = 257,
- RPL_ADMINLOC2 = 258,
- RPL_ADMINEMAIL = 259,
- RPL_MAPUSERS = 270, // insp-specific
-
- RPL_SYNTAX = 304, // insp-specific
-
- RPL_UNAWAY = 305,
- RPL_NOWAWAY = 306,
-
- RPL_RULESTART = 308, // unrealircd
- RPL_RULESEND = 309, // unrealircd
- RPL_CHANNELMODEIS = 324,
- RPL_CHANNELCREATED = 329, // ???
- RPL_NOTOPICSET = 331,
- RPL_TOPIC = 332,
- RPL_TOPICTIME = 333, // not RFC, extremely common though
-
- RPL_INVITING = 341,
- RPL_INVITELIST = 346, // insp-specific (stolen from ircu)
- RPL_ENDOFINVITELIST = 347, // insp-specific (stolen from ircu)
- RPL_VERSION = 351,
- RPL_NAMREPLY = 353,
- RPL_ENDOFNAMES = 366,
-
- RPL_INFO = 371,
- RPL_ENDOFINFO = 374,
- RPL_MOTD = 372,
- RPL_MOTDSTART = 375,
- RPL_ENDOFMOTD = 376,
-
- RPL_YOUAREOPER = 381,
- RPL_REHASHING = 382,
- RPL_TIME = 391,
- RPL_YOURDISPLAYEDHOST = 396, // from charybdis/etc, common convention
+ RPL_WELCOME = 1, // 2812, not 1459
+ RPL_YOURHOSTIS = 2, // 2812, not 1459
+ RPL_SERVERCREATED = 3, // 2812, not 1459
+ RPL_SERVERVERSION = 4, // 2812, not 1459
+ RPL_ISUPPORT = 5, // not RFC, extremely common though (defined as RPL_BOUNCE in 2812, widely ignored)
+
+ RPL_MAP = 6, // unrealircd
+ RPL_ENDMAP = 7, // unrealircd
+ RPL_SNOMASKIS = 8, // unrealircd
+ RPL_REDIR = 10,
+
+ RPL_YOURUUID = 42, // taken from ircnet
+
+ RPL_UMODEIS = 221,
+ RPL_RULES = 232, // unrealircd
+
+ RPL_LUSERCLIENT = 251,
+ RPL_LUSEROP = 252,
+ RPL_LUSERUNKNOWN = 253,
+ RPL_LUSERCHANNELS = 254,
+ RPL_LUSERME = 255,
+
+ RPL_ADMINME = 256,
+ RPL_ADMINLOC1 = 257,
+ RPL_ADMINLOC2 = 258,
+ RPL_ADMINEMAIL = 259,
+
+ RPL_LOCALUSERS = 265,
+ RPL_GLOBALUSERS = 266,
+
+ RPL_MAPUSERS = 270, // insp-specific
+
+ RPL_AWAY = 301,
+
+ RPL_SYNTAX = 304, // insp-specific
+
+ RPL_UNAWAY = 305,
+ RPL_NOWAWAY = 306,
+
+ RPL_RULESTART = 308, // unrealircd
+ RPL_RULESEND = 309, // unrealircd
+
+ RPL_WHOISSERVER = 312,
+ RPL_WHOWASUSER = 314,
+
+ RPL_ENDOFWHO = 315,
+ RPL_ENDOFWHOIS = 318,
+
+ RPL_LISTSTART = 321,
+ RPL_LIST = 322,
+ RPL_LISTEND = 323,
+
+ RPL_CHANNELMODEIS = 324,
+ RPL_CHANNELCREATED = 329, // ???
+ RPL_NOTOPICSET = 331,
+ RPL_TOPIC = 332,
+ RPL_TOPICTIME = 333, // not RFC, extremely common though
+
+ RPL_INVITING = 341,
+ RPL_INVITELIST = 346, // insp-specific (stolen from ircu)
+ RPL_ENDOFINVITELIST = 347, // insp-specific (stolen from ircu)
+ RPL_VERSION = 351,
+ RPL_NAMREPLY = 353,
+ RPL_LINKS = 364,
+ RPL_ENDOFLINKS = 365,
+ RPL_ENDOFNAMES = 366,
+ RPL_ENDOFWHOWAS = 369,
+
+ RPL_INFO = 371,
+ RPL_ENDOFINFO = 374,
+ RPL_MOTD = 372,
+ RPL_MOTDSTART = 375,
+ RPL_ENDOFMOTD = 376,
+
+ RPL_WHOWASIP = 379,
+
+ RPL_YOUAREOPER = 381,
+ RPL_REHASHING = 382,
+ RPL_TIME = 391,
+ RPL_YOURDISPLAYEDHOST = 396, // from charybdis/etc, common convention
/*
* Error range of numerics.
*/
- ERR_NOSUCHNICK = 401,
- ERR_NOSUCHSERVER = 402,
- ERR_NOSUCHCHANNEL = 403, // used to indicate an invalid channel name also, so don't rely on RFC text (don't do that anyway!)
- ERR_CANNOTSENDTOCHAN = 404,
- ERR_TOOMANYCHANNELS = 405,
- ERR_INVALIDCAPSUBCOMMAND = 410, // ratbox/charybdis(?)
- ERR_UNKNOWNCOMMAND = 421,
- ERR_NOMOTD = 422,
- ERR_NORULES = 434, // unrealircd
- ERR_USERNOTINCHANNEL = 441,
- ERR_NOTONCHANNEL = 442,
- ERR_USERONCHANNEL = 443,
- ERR_CANTCHANGENICK = 447, // unrealircd, probably
- ERR_NOTREGISTERED = 451,
- ERR_NEEDMOREPARAMS = 461,
- ERR_ALREADYREGISTERED = 462,
+ ERR_NOSUCHNICK = 401,
+ ERR_NOSUCHSERVER = 402,
+ ERR_NOSUCHCHANNEL = 403, // used to indicate an invalid channel name also, so don't rely on RFC text (don't do that anyway!)
+ ERR_CANNOTSENDTOCHAN = 404,
+ ERR_TOOMANYCHANNELS = 405,
+ ERR_WASNOSUCHNICK = 406,
+ ERR_INVALIDCAPSUBCOMMAND = 410, // ratbox/charybdis(?)
+ ERR_NOTEXTTOSEND = 412,
+ ERR_UNKNOWNCOMMAND = 421,
+ ERR_NOMOTD = 422,
+ ERR_ERRONEUSNICKNAME = 432,
+ ERR_NICKNAMEINUSE = 433,
+ ERR_NORULES = 434, // unrealircd
+ ERR_USERNOTINCHANNEL = 441,
+ ERR_NOTONCHANNEL = 442,
+ ERR_USERONCHANNEL = 443,
+ ERR_CANTCHANGENICK = 447, // unrealircd, probably
+ ERR_NOTREGISTERED = 451,
+ ERR_NEEDMOREPARAMS = 461,
+ ERR_ALREADYREGISTERED = 462,
+ ERR_UNKNOWNMODE = 472,
/*
* A quick side-rant about the next group of numerics..
@@ -131,31 +162,37 @@ enum Numerics
*
* -- A message from the IRC group for coder sanity, and w00t
*/
- ERR_BADCHANNELKEY = 475,
- ERR_INVITEONLYCHAN = 473,
- ERR_CHANNELISFULL = 471,
- ERR_BANNEDFROMCHAN = 474,
-
- ERR_NOPRIVILEGES = 481, // rfc, beware though, we use this for other things opers may not do also
- ERR_CHANOPRIVSNEEDED = 482, // rfc, beware though, we use this for other things like trying to kick a uline
-
- ERR_ALLMUSTSSL = 490, // unrealircd
- ERR_NOCTCPALLOWED = 492, // XXX: bzzzz. 1459 defines this as ERR_NOSERVICEHOST, research it more and perhaps change this! (ERR_CANNOTSENDTOCHAN?)
- // wtf, we also use this for m_noinvite. UGLY!
- ERR_DELAYREJOIN = 495, // insp-specific, XXX: we should use 'resource temporarily unavailable' from ircnet/ratbox or whatever
- ERR_UNKNOWNSNOMASK = 501, // insp-specific
- ERR_USERSDONTMATCH = 502,
- ERR_CANTJOINOPERSONLY = 520, // unrealircd, but crap to have so many numerics for cant join..
- ERR_CANTSENDTOUSER = 531, // ???
-
- RPL_COMMANDS = 702, // insp-specific
- RPL_COMMANDSEND = 703, // insp-specific
-
- ERR_WORDFILTERED = 936, // insp-specific, would be nice if we could get rid of this..
- ERR_CANTUNLOADMODULE = 972, // insp-specific
- RPL_UNLOADEDMODULE = 973, // insp-specific
- ERR_CANTLOADMODULE = 974, // insp-specific
- RPL_LOADEDMODULE = 975 // insp-specific
+ ERR_BADCHANNELKEY = 475,
+ ERR_INVITEONLYCHAN = 473,
+ ERR_CHANNELISFULL = 471,
+ ERR_BANNEDFROMCHAN = 474,
+
+ ERR_BANLISTFULL = 478,
+
+ ERR_NOPRIVILEGES = 481, // rfc, beware though, we use this for other things opers may not do also
+ ERR_CHANOPRIVSNEEDED = 482, // rfc, beware though, we use this for other things like trying to kick a uline
+
+ ERR_RESTRICTED = 484,
+
+ ERR_ALLMUSTSSL = 490, // unrealircd
+ ERR_NOOPERHOST = 491,
+ ERR_NOCTCPALLOWED = 492, // XXX: bzzzz. 1459 defines this as ERR_NOSERVICEHOST, research it more and perhaps change this! (ERR_CANNOTSENDTOCHAN?)
+ // wtf, we also use this for m_noinvite. UGLY!
+ ERR_DELAYREJOIN = 495, // insp-specific, XXX: we should use 'resource temporarily unavailable' from ircnet/ratbox or whatever
+ ERR_UNKNOWNSNOMASK = 501, // insp-specific
+ ERR_USERSDONTMATCH = 502,
+ ERR_CANTJOINOPERSONLY = 520, // unrealircd, but crap to have so many numerics for cant join..
+ ERR_CANTSENDTOUSER = 531, // ???
+
+ RPL_COMMANDS = 702, // insp-specific
+ RPL_COMMANDSEND = 703, // insp-specific
+
+ ERR_CHANOPEN = 713,
+ ERR_KNOCKONCHAN = 714,
+
+ ERR_WORDFILTERED = 936, // insp-specific, would be nice if we could get rid of this..
+ ERR_CANTUNLOADMODULE = 972, // insp-specific
+ RPL_UNLOADEDMODULE = 973, // insp-specific
+ ERR_CANTLOADMODULE = 974, // insp-specific
+ RPL_LOADEDMODULE = 975 // insp-specific
};
-
-#endif
diff --git a/include/parammode.h b/include/parammode.h
new file mode 100644
index 000000000..b0005262e
--- /dev/null
+++ b/include/parammode.h
@@ -0,0 +1,75 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2014 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/>.
+ */
+
+
+#pragma once
+
+class CoreExport ParamModeBase : public ModeHandler
+{
+ private:
+ virtual void OnUnsetInternal(User* source, Channel* chan) = 0;
+
+ public:
+ ParamModeBase(Module* Creator, const std::string& Name, char modeletter, ParamSpec ps)
+ : ModeHandler(Creator, Name, modeletter, ps, MODETYPE_CHANNEL, MC_PARAM) { }
+
+ ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string& param, bool adding) CXX11_OVERRIDE;
+
+ // Does nothing by default
+ void OnUnset(User* source, Channel* chan) { }
+ virtual ModeAction OnSet(User* source, Channel* chan, std::string& param) = 0;
+ virtual void GetParameter(Channel* chan, std::string& out) = 0;
+};
+
+/** Defines a parameter mode
+ * T = Child class
+ * ExtItemT = Type of the extension item used to store the parameter
+ *
+ * When unsetting the mode, the extension is automatically unset.
+ */
+template <typename T, typename ExtItemT>
+class ParamMode : public ParamModeBase
+{
+ public:
+ ExtItemT ext;
+
+ /**
+ * @param Creator Module handling this mode
+ * @param Name The internal name of this mode
+ * @param modeletter The mode letter of this mode
+ * @param ps The parameter type of this mode, one of ParamSpec
+ */
+ ParamMode(Module* Creator, const std::string& Name, char modeletter, ParamSpec ps = PARAM_SETONLY)
+ : ParamModeBase(Creator, Name, modeletter, ps)
+ , ext("parammode_" + Name, Creator)
+ {
+ }
+
+ void OnUnsetInternal(User* source, Channel* chan) CXX11_OVERRIDE
+ {
+ T* mh = static_cast<T*>(this);
+ mh->OnUnset(source, chan);
+ ext.unset(chan);
+ }
+
+ void GetParameter(Channel* chan, std::string& out) CXX11_OVERRIDE
+ {
+ T* mh = static_cast<T*>(this);
+ mh->SerializeParam(chan, ext.get(chan), out);
+ }
+};
diff --git a/include/protocol.h b/include/protocol.h
index aabb5b022..01eb145f1 100644
--- a/include/protocol.h
+++ b/include/protocol.h
@@ -18,8 +18,7 @@
*/
-#ifndef PROTOCOL_H
-#define PROTOCOL_H
+#pragma once
#include "hashcomp.h"
@@ -27,40 +26,77 @@ class User;
typedef std::vector<std::string> parameterlist;
-class ProtoServer
+class ProtocolServer
{
public:
- std::string servername;
- std::string parentname;
- std::string gecos;
- unsigned int usercount;
- unsigned int opercount;
- unsigned int latencyms;
+ /** Send metadata related to this server to the target server
+ * @param key The 'key' of the data
+ * @param data The string representation of the data
+ */
+ virtual void SendMetaData(const std::string& key, const std::string& data) = 0;
};
-typedef std::list<ProtoServer> ProtoServerList;
-
-class ProtocolInterface
+class CoreExport ProtocolInterface
{
public:
- ProtocolInterface() { }
+ typedef ProtocolServer Server;
+
+ class ServerInfo
+ {
+ public:
+ std::string servername;
+ std::string parentname;
+ std::string gecos;
+ unsigned int usercount;
+ unsigned int opercount;
+ unsigned int latencyms;
+ };
+
+ typedef std::vector<ServerInfo> ServerList;
+
virtual ~ProtocolInterface() { }
- /** Send an ENCAP message to one or more linked servers.
+ /** Send an ENCAP message to all servers matching a wildcard string.
* See the protocol documentation for the purpose of ENCAP.
- * @param encap This is a list of string parameters, the first of which must be a server ID or glob matching servernames.
- * The second must be a subcommand. All subsequent parameters are dependant on the subcommand.
+ * @param targetmask The target server mask (can contain wildcards)
+ * @param cmd The ENCAP subcommand
+ * @param params List of string parameters which are dependant on the subcommand
+ * @param source The source of the message (prefix), must be a local user or NULL which means use local server
+ * @return Always true if the target mask contains wildcards; otherwise true if the server name was found,
+ * and the message was sent, false if it was not found.
* ENCAP (should) be used instead of creating new protocol messages for easier third party application support.
- * @return True if the message was sent out (target exists)
*/
- virtual bool SendEncapsulatedData(const parameterlist &encap) { return false; }
+ virtual bool SendEncapsulatedData(const std::string& targetmask, const std::string& cmd, const parameterlist& params, User* source = NULL) { return false; }
+
+ /** Send an ENCAP message to all servers.
+ * See the protocol documentation for the purpose of ENCAP.
+ * @param cmd The ENCAP subcommand
+ * @param params List of string parameters which are dependant on the subcommand
+ * @param source The source of the message (prefix), must be a local user or a user behind 'omit'
+ * or NULL which is equivalent to the local server
+ * @param omit If non-NULL the message won't be sent in the direction of this server, useful for forwarding messages
+ */
+ virtual void BroadcastEncap(const std::string& cmd, const parameterlist& params, User* source = NULL, User* omit = NULL) { }
+
+ /** Send metadata for a channel to other linked servers.
+ * @param chan The channel to send metadata for
+ * @param key The 'key' of the data, e.g. "swhois" for swhois desc on a user
+ * @param data The string representation of the data
+ */
+ virtual void SendMetaData(Channel* chan, const std::string& key, const std::string& data) { }
- /** Send metadata for an object to other linked servers.
- * @param target The object to send metadata for.
+ /** Send metadata for a user to other linked servers.
+ * @param user The user to send metadata for
* @param key The 'key' of the data, e.g. "swhois" for swhois desc on a user
* @param data The string representation of the data
*/
- virtual void SendMetaData(Extensible* target, const std::string &key, const std::string &data) { }
+ virtual void SendMetaData(User* user, const std::string& key, const std::string& data) { }
+
+ /** Send metadata related to the server to other linked servers.
+ * @param key The 'key' of the data
+ * @param data The string representation of the data
+ */
+ virtual void SendMetaData(const std::string& key, const std::string& data) { }
/** Send a topic change for a channel
* @param channel The channel to change the topic for.
@@ -69,33 +105,19 @@ class ProtocolInterface
virtual void SendTopic(Channel* channel, std::string &topic) { }
/** Send mode changes for an object.
- * @param target The channel name or user to send mode changes for.
+ * @param source The source of the mode change
+ * @param usertarget The target user, NULL if the target is a channel
+ * @param chantarget The target channel, NULL if the target is a user
* @param modedata The mode changes to send.
* @param translate A list of translation types
*/
- virtual void SendMode(const std::string &target, const parameterlist &modedata, const std::vector<TranslateType> &translate) { }
-
- /** Convenience function, string wrapper around the above.
- */
- virtual void SendModeStr(const std::string &target, const std::string &modeline)
- {
- irc::spacesepstream x(modeline);
- parameterlist n;
- std::vector<TranslateType> types;
- std::string v;
- while (x.GetToken(v))
- {
- n.push_back(v);
- types.push_back(TR_TEXT);
- }
- SendMode(target, n, types);
- }
+ virtual void SendMode(User* source, User* usertarget, Channel* chantarget, const parameterlist& modedata, const std::vector<TranslateType>& translate) { }
/** Send a notice to users with a given snomask.
* @param snomask The snomask required for the message to be sent.
* @param text The message to send.
*/
- virtual void SendSNONotice(const std::string &snomask, const std::string &text) { }
+ virtual void SendSNONotice(char snomask, const std::string& text) { }
/** Send raw data to a remote client.
* @param target The user to push data to.
@@ -107,34 +129,39 @@ class ProtocolInterface
* @param target The channel to message.
* @param status The status character (e.g. %) required to recieve.
* @param text The message to send.
+ * @param type The message type (MSG_PRIVMSG or MSG_NOTICE)
*/
- virtual void SendChannelPrivmsg(Channel* target, char status, const std::string &text) { }
+ virtual void SendMessage(Channel* target, char status, const std::string& text, MessageType type = MSG_PRIVMSG) { }
- /** Send a notice to a channel.
- * @param target The channel to message.
- * @param status The status character (e.g. %) required to recieve.
+ /** Send a message to a user.
+ * @param target The user to message.
* @param text The message to send.
+ * @param type The message type (MSG_PRIVMSG or MSG_NOTICE)
*/
- virtual void SendChannelNotice(Channel* target, char status, const std::string &text) { }
+ virtual void SendMessage(User* target, const std::string& text, MessageType type = MSG_PRIVMSG) { }
- /** Send a message to a user.
- * @param target The user to message.
+ /** Send a notice to a channel.
+ * @param target The channel to message.
+ * @param status The status character (e.g. %) required to recieve.
* @param text The message to send.
*/
- virtual void SendUserPrivmsg(User* target, const std::string &text) { }
+ void SendChannelNotice(Channel* target, char status, const std::string &text)
+ {
+ SendMessage(target, status, text, MSG_NOTICE);
+ }
/** Send a notice to a user.
* @param target The user to message.
* @param text The message to send.
*/
- virtual void SendUserNotice(User* target, const std::string &text) { }
+ void SendUserNotice(User* target, const std::string &text)
+ {
+ SendMessage(target, text, MSG_NOTICE);
+ }
/** Fill a list of servers and information about them.
* @param sl The list of servers to fill.
* XXX: document me properly, this is shit.
*/
- virtual void GetServerList(ProtoServerList &sl) { }
+ virtual void GetServerList(ServerList& sl) { }
};
-
-#endif
-
diff --git a/include/server.h b/include/server.h
new file mode 100644
index 000000000..3d8854734
--- /dev/null
+++ b/include/server.h
@@ -0,0 +1,68 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2014 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/>.
+ */
+
+
+#pragma once
+
+class CoreExport Server : public classbase
+{
+ protected:
+ /** The name of this server
+ */
+ const std::string name;
+
+ /** The description of this server
+ */
+ const std::string description;
+
+ /** True if this server is ulined
+ */
+ bool uline;
+
+ /** True if this server is a silent uline, i.e. silent="true" in the uline block
+ */
+ bool silentuline;
+
+ public:
+ Server(const std::string& srvname, const std::string& srvdesc)
+ : name(srvname), description(srvdesc), uline(false), silentuline(false) { }
+
+ /**
+ * Returns the name of this server
+ * @return The name of this server, for example "irc.inspircd.org".
+ */
+ const std::string& GetName() const { return name; }
+
+ /** Returns the description (GECOS) of this server
+ * @return The description of this server
+ */
+ const std::string& GetDesc() const { return description; }
+
+ /**
+ * Checks whether this server is ulined
+ * @return True if this server is ulined, false otherwise.
+ */
+ bool IsULine() const { return uline; }
+
+ /**
+ * Checks whether this server is a silent uline
+ * Silent uline servers introduce, quit and oper up users without a snotice being generated.
+ * @return True if this server is a silent uline, false otherwise.
+ */
+ bool IsSilentULine() const { return silentuline; }
+};
diff --git a/include/snomasks.h b/include/snomasks.h
index 85ad26f71..df4faab47 100644
--- a/include/snomasks.h
+++ b/include/snomasks.h
@@ -20,31 +20,52 @@
*/
-#ifndef SNOMASKS_H
-#define SNOMASKS_H
+#pragma once
+class SnomaskManager;
class Snomask
{
- public:
+ /** Description of this snomask, e.g.: OPER, ANNOUNCEMENT, XLINE
+ */
std::string Description;
+
+ /** Information about the last sent message,
+ * used for sending "last message repeated X times" messages
+ */
std::string LastMessage;
- int Count;
- bool LastBlocked;
char LastLetter;
+ unsigned int Count;
+ /** Log and send a message to all opers who have the given snomask set
+ * @param letter The target users of this message
+ * @param desc The description of this snomask, will be prepended to the message
+ * @param msg The message to send
+ */
+ static void Send(char letter, const std::string& desc, const std::string& msg);
+
+ public:
/** Create a new Snomask
*/
- Snomask() : Count(0), LastBlocked(false), LastLetter(0)
- {
- }
+ Snomask();
/** Sends a message to all opers with this snomask.
+ * @param message The message to send
+ * @param remote If true the message will go to the uppercase variant of this snomask
*/
- void SendMessage(const std::string &message, char letter);
+ void SendMessage(const std::string& message, char letter);
/** Sends out the (last message repeated N times) message
*/
void Flush();
+
+ /** Returns the description of this snomask
+ * @param letter The letter of this snomask. If uppercase, the description of the remote
+ * variant of this snomask will be returned (i.e.: "REMOTE" will be prepended to the description).
+ * @return The description of this snomask
+ */
+ std::string GetDescription(char letter) const;
+
+ friend class SnomaskManager;
};
/** Snomask manager handles routing of SNOMASK (usermode +s) messages to opers.
@@ -53,9 +74,9 @@ class Snomask
*/
class CoreExport SnomaskManager
{
- public:
Snomask masks[26];
+ public:
/** Create a new SnomaskManager
*/
SnomaskManager();
@@ -95,7 +116,6 @@ class CoreExport SnomaskManager
*/
void WriteGlobalSno(char letter, const char* text, ...) CUSTOM_PRINTF(3, 4);
-
/** Called once per 5 seconds from the mainloop, this flushes any cached
* snotices. The way the caching works is as follows:
* Calls to WriteToSnoMask write to a cache, if the call is the same as it was
@@ -105,6 +125,12 @@ class CoreExport SnomaskManager
* is not particularly significant, in order to keep notices going out.
*/
void FlushSnotices();
-};
-#endif
+ /** Check whether a given character is an enabled (initialized) snomask.
+ * Valid snomask chars are lower- or uppercase letters and have a description.
+ * Snomasks are initialized with EnableSnomask().
+ * @param ch The character to check
+ * @return True if the given char is allowed to be set via +s.
+ */
+ bool IsSnomaskUsable(char ch) const;
+};
diff --git a/include/socket.h b/include/socket.h
index 5f6705124..c292b7010 100644
--- a/include/socket.h
+++ b/include/socket.h
@@ -22,8 +22,7 @@
*/
-#ifndef INSPIRCD_SOCKET_H
-#define INSPIRCD_SOCKET_H
+#pragma once
#ifndef _WIN32
@@ -110,9 +109,6 @@ namespace irc
*/
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
@@ -128,16 +124,10 @@ namespace irc
* @return true if the conversion was successful, false if unknown address family
*/
CoreExport bool satoap(const irc::sockets::sockaddrs& sa, std::string& addr, int &port);
-
- /** Convert a binary sockaddr to a user-readable string.
- * This means IPv6 addresses are written as [::1]:6667, and *:6668 is used for 0.0.0.0:6668
- * @param sa The structure to convert
- * @return The string; "<unknown>" if not a valid address
- */
- inline std::string satouser(const irc::sockets::sockaddrs& sa) { return sa.str(); }
}
}
+#include "iohook.h"
#include "socketengine.h"
/** This class handles incoming connections on client ports.
* It will create a new User for every valid connection
@@ -151,6 +141,12 @@ class CoreExport ListenSocket : public EventHandler
int bind_port;
/** Human-readable bind description */
std::string bind_desc;
+
+ /** The IOHook provider which handles connections on this socket,
+ * NULL if there is none.
+ */
+ dynamic_reference_nocheck<IOHookProvider> iohookprov;
+
/** Create a new listening socket
*/
ListenSocket(ConfigTag* tag, const irc::sockets::sockaddrs& bind_to);
@@ -164,7 +160,10 @@ class CoreExport ListenSocket : public EventHandler
/** Handles sockets internals crap of a connection, convenience wrapper really
*/
void AcceptInternal();
-};
-
-#endif
+ /** Inspects the bind block belonging to this socket to set the name of the IO hook
+ * provider which this socket will use for incoming connections.
+ * @return True if the IO hook provider was found or none was given, false otherwise.
+ */
+ bool ResetIOHookProvider();
+};
diff --git a/include/socketengine.h b/include/socketengine.h
index 37b7d6373..3a15e98c1 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -20,13 +20,12 @@
*/
-#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"
@@ -128,7 +127,7 @@ enum EventMask
/** 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.
@@ -137,7 +136,7 @@ enum EventMask
/** 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
@@ -166,6 +165,9 @@ class CoreExport EventHandler : public classbase
private:
/** Private state maintained by socket engine */
int event_mask;
+
+ void SetEventMask(int mask) { event_mask = mask; }
+
protected:
/** File descriptor.
* All events which can be handled must have a file descriptor. This
@@ -231,34 +233,79 @@ class CoreExport EventHandler : public classbase
*/
class CoreExport SocketEngine
{
+ public:
+ /** Socket engine statistics: count of various events, bandwidth usage
+ */
+ class Statistics
+ {
+ mutable size_t indata;
+ mutable size_t outdata;
+ mutable time_t lastempty;
+
+ /** Reset the byte counters and lastempty if there wasn't a reset in this second.
+ */
+ void CheckFlush() const;
+
+ public:
+ /** Constructor, initializes member vars except indata and outdata because those are set to 0
+ * in CheckFlush() the first time Update() or GetBandwidth() is called.
+ */
+ Statistics() : lastempty(0), TotalEvents(0), ReadEvents(0), WriteEvents(0), ErrorEvents(0) { }
+
+ /** Increase the counters for bytes sent/received in this second.
+ * @param len_in Bytes received, 0 if updating number of bytes written.
+ * @param len_out Bytes sent, 0 if updating number of bytes read.
+ */
+ void Update(size_t len_in, size_t len_out);
+
+ /** Get data transfer statistics.
+ * @param kbitspersec_in Filled with incoming traffic in this second in kbit/s.
+ * @param kbitspersec_out Filled with outgoing traffic in this second in kbit/s.
+ * @param kbitspersec_total Filled with total traffic in this second in kbit/s.
+ */
+ void CoreExport GetBandwidth(float& kbitpersec_in, float& kbitpersec_out, float& kbitpersec_total) const;
+
+ unsigned long TotalEvents;
+ unsigned long ReadEvents;
+ unsigned long WriteEvents;
+ unsigned long ErrorEvents;
+ };
+
+ private:
+ /** Reference table, contains all current handlers
+ **/
+ static std::vector<EventHandler*> ref;
+
protected:
/** Current number of descriptors in the engine
*/
- int CurrentSetSize;
- /** Reference table, contains all current handlers
- */
- EventHandler** ref;
+ static size_t CurrentSetSize;
/** List of handlers that want a trial read/write
*/
- std::set<int> trials;
+ static std::set<int> trials;
- int MAX_DESCRIPTORS;
+ static int MAX_DESCRIPTORS;
- size_t indata;
- size_t outdata;
- time_t lastempty;
+ /** Socket engine statistics: count of various events, bandwidth usage
+ */
+ static Statistics stats;
- void UpdateStats(size_t len_in, size_t len_out);
+ static void OnSetEvent(EventHandler* eh, int old_mask, int new_mask);
- virtual void OnSetEvent(EventHandler* eh, int old_mask, int new_mask) = 0;
- void SetEventMask(EventHandler* eh, int value);
-public:
+ /** Add an event handler to the base socket engine. AddFd(EventHandler*, int) should call this.
+ */
+ static bool AddFdRef(EventHandler* eh);
+
+ static void DelFdRef(EventHandler* eh);
- unsigned long TotalEvents;
- unsigned long ReadEvents;
- unsigned long WriteEvents;
- unsigned long ErrorEvents;
+ template <typename T>
+ static void ResizeDouble(std::vector<T>& vect)
+ {
+ if (SocketEngine::CurrentSetSize > vect.size())
+ vect.resize(vect.size() * 2);
+ }
+public:
/** Constructor.
* The constructor transparently initializes
* the socket engine which the ircd is using.
@@ -266,14 +313,16 @@ public:
* failure (for example, you try and enable
* epoll on a 2.4 linux kernel) then this
* function may bail back to the shell.
+ * @return void, but it is acceptable for this function to bail back to
+ * the shell or operating system on fatal error.
*/
- SocketEngine();
+ static void Init();
/** Destructor.
* The destructor transparently tidies up
* any resources used by the socket engine.
*/
- virtual ~SocketEngine();
+ static void Deinit();
/** Add an EventHandler object to the engine. Use AddFd to add a file
* descriptor to the engine and have the socket engine monitor it. You
@@ -282,7 +331,7 @@ public:
* @param eh An event handling object to add
* @param event_mask The initial event mask for the object
*/
- virtual bool AddFd(EventHandler* eh, int event_mask) = 0;
+ static bool AddFd(EventHandler* eh, int event_mask);
/** If you call this function and pass it an
* event handler, that event handler will
@@ -295,17 +344,17 @@ public:
* @param eh The event handler to change
* @param event_mask The changes to make to the wait state
*/
- void ChangeEventMask(EventHandler* eh, int event_mask);
+ static void ChangeEventMask(EventHandler* eh, int event_mask);
/** Returns the highest file descriptor you may store in the socket engine
* @return The maximum fd value
*/
- inline int GetMaxFds() const { return MAX_DESCRIPTORS; }
+ static int GetMaxFds() { return MAX_DESCRIPTORS; }
/** Returns the number of file descriptors being queried
* @return The set size
*/
- inline int GetUsedFds() const { return CurrentSetSize; }
+ static size_t GetUsedFds() { return CurrentSetSize; }
/** Delete an event handler from the engine.
* This function call deletes an EventHandler
@@ -315,21 +364,21 @@ public:
* required you must do this yourself.
* @param eh The event handler object to remove
*/
- virtual void DelFd(EventHandler* eh) = 0;
+ static void DelFd(EventHandler* eh);
/** Returns true if a file descriptor exists in
* the socket engine's list.
* @param fd The event handler to look for
* @return True if this fd has an event handler
*/
- virtual bool HasFd(int fd);
+ static bool HasFd(int fd);
/** Returns the EventHandler attached to a specific fd.
* If the fd isnt in the socketengine, returns NULL.
* @param fd The event handler to look for
* @return A pointer to the event handler, or NULL
*/
- virtual EventHandler* GetRef(int fd);
+ static EventHandler* GetRef(int fd);
/** Waits for events and dispatches them to handlers. Please note that
* this doesn't wait long, only a couple of milliseconds. It returns the
@@ -339,23 +388,17 @@ public:
* value.
* @return The number of events which have occured.
*/
- virtual int DispatchEvents() = 0;
+ static int DispatchEvents();
/** Dispatch trial reads and writes. This causes the actual socket I/O
* to happen when writes have been pre-buffered.
*/
- virtual void DispatchTrialWrites();
-
- /** Returns the socket engines name. This returns the name of the
- * engine for use in /VERSION responses.
- * @return The socket engine name
- */
- virtual std::string GetName() = 0;
+ static void DispatchTrialWrites();
/** Returns true if the file descriptors in the given event handler are
* within sensible ranges which can be handled by the socket engine.
*/
- virtual bool BoundsCheckFd(EventHandler* eh);
+ static bool BoundsCheckFd(EventHandler* eh);
/** Abstraction for BSD sockets accept(2).
* This function should emulate its namesake system call exactly.
@@ -364,21 +407,20 @@ public:
* @param addrlen The size of the sockaddr parameter.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
+ static int Accept(EventHandler* fd, sockaddr *addr, socklen_t *addrlen);
- /** Abstraction for BSD sockets close(2).
- * This function should emulate its namesake system call exactly.
- * @param fd This version of the call takes an EventHandler instead of a bare file descriptor.
- * @return This method should return exactly the same values as the system call it emulates.
+ /** Close the underlying fd of an event handler, remove it from the socket engine and set the fd to -1.
+ * @param eh The EventHandler to close.
+ * @return 0 on success, a negative value on error
*/
- int Close(EventHandler* fd);
+ static int Close(EventHandler* eh);
/** Abstraction for BSD sockets close(2).
* This function should emulate its namesake system call exactly.
* This function should emulate its namesake system call exactly.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Close(int fd);
+ static int Close(int fd);
/** Abstraction for BSD sockets send(2).
* This function should emulate its namesake system call exactly.
@@ -388,7 +430,7 @@ public:
* @param flags A flag value that controls the sending of the data.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Send(EventHandler* fd, const void *buf, size_t len, int flags);
+ static int Send(EventHandler* fd, const void *buf, size_t len, int flags);
/** Abstraction for BSD sockets recv(2).
* This function should emulate its namesake system call exactly.
@@ -398,7 +440,7 @@ public:
* @param flags A flag value that controls the reception of the data.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Recv(EventHandler* fd, void *buf, size_t len, int flags);
+ static int Recv(EventHandler* fd, void *buf, size_t len, int flags);
/** Abstraction for BSD sockets recvfrom(2).
* This function should emulate its namesake system call exactly.
@@ -410,7 +452,7 @@ public:
* @param fromlen The size of the from parameter.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
+ static int RecvFrom(EventHandler* fd, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen);
/** Abstraction for BSD sockets sendto(2).
* This function should emulate its namesake system call exactly.
@@ -418,11 +460,11 @@ public:
* @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.
*/
- int SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen);
+ static int SendTo(EventHandler* fd, const void *buf, size_t len, int flags, const sockaddr *to, socklen_t tolen);
/** Abstraction for BSD sockets connect(2).
* This function should emulate its namesake system call exactly.
@@ -431,19 +473,19 @@ public:
* @param addrlen The size of the sockaddr parameter.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen);
+ static int Connect(EventHandler* fd, const sockaddr *serv_addr, socklen_t addrlen);
/** Make a file descriptor blocking.
* @param fd a file descriptor to set to blocking mode
* @return 0 on success, -1 on failure, errno is set appropriately.
*/
- int Blocking(int fd);
+ static int Blocking(int fd);
/** Make a file descriptor nonblocking.
* @param fd A file descriptor to set to nonblocking mode
* @return 0 on success, -1 on failure, errno is set appropriately.
*/
- int NonBlocking(int fd);
+ static int NonBlocking(int fd);
/** Abstraction for BSD sockets shutdown(2).
* This function should emulate its namesake system call exactly.
@@ -451,29 +493,29 @@ public:
* @param how What part of the socket to shut down
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Shutdown(EventHandler* fd, int how);
+ static int Shutdown(EventHandler* fd, int how);
/** Abstraction for BSD sockets shutdown(2).
* This function should emulate its namesake system call exactly.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Shutdown(int fd, int how);
+ static int Shutdown(int fd, int how);
/** Abstraction for BSD sockets bind(2).
* This function should emulate its namesake system call exactly.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Bind(int fd, const irc::sockets::sockaddrs& addr);
+ static int Bind(int fd, const irc::sockets::sockaddrs& addr);
/** Abstraction for BSD sockets listen(2).
* This function should emulate its namesake system call exactly.
* @return This method should return exactly the same values as the system call it emulates.
*/
- int Listen(int sockfd, int backlog);
+ static int Listen(int sockfd, int backlog);
/** Set SO_REUSEADDR and SO_LINGER on this file descriptor
*/
- void SetReuse(int sockfd);
+ static void SetReuse(int sockfd);
/** This function is called immediately after fork().
* Some socket engines (notably kqueue) cannot have their
@@ -484,11 +526,11 @@ public:
* @return void, but it is acceptable for this function to bail back to
* the shell or operating system on fatal error.
*/
- virtual void RecoverFromFork();
+ static void RecoverFromFork();
- /** Get data transfer statistics, kilobits per second in and out and total.
+ /** Get data transfer and event statistics
*/
- void GetStats(float &kbitpersec_in, float &kbitpersec_out, float &kbitpersec_total);
+ static const Statistics& GetStats() { return stats; }
/** Should we ignore the error in errno?
* Checks EAGAIN and WSAEWOULDBLOCK
@@ -516,8 +558,3 @@ inline bool SocketEngine::IgnoreError()
return false;
}
-
-SocketEngine* CreateSocketEngine();
-
-#endif
-
diff --git a/include/stdalgo.h b/include/stdalgo.h
new file mode 100644
index 000000000..afbd763fb
--- /dev/null
+++ b/include/stdalgo.h
@@ -0,0 +1,97 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ * Copyright (C) 2014 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/>.
+ */
+
+
+#pragma once
+
+namespace stdalgo
+{
+ namespace vector
+ {
+ /**
+ * Erase a single element from a vector by overwriting it with a copy of the last element,
+ * which is then removed. This, in contrast to vector::erase(), does not result in all
+ * elements after the erased element being moved.
+ * @param vect Vector to remove the element from
+ * @param it Iterator to the element to remove
+ * @return Nothing, but all iterators, references and pointers to the erased element and the
+ * last element are invalidated
+ */
+ template <typename T>
+ inline void swaperase(typename std::vector<T>& vect, const typename std::vector<T>::iterator& it)
+ {
+ *it = vect.back();
+ vect.pop_back();
+ }
+
+ /**
+ * Find and if exists, erase a single element from a vector by overwriting it with a
+ * copy of the last element, which is then removed. This, in contrast to vector::erase(),
+ * does not result in all elements after the erased element being moved.
+ * If the given value occurs multiple times, the one with the lowest index is removed.
+ * Individual elements are compared to the given value using operator==().
+ * @param vect Vector to remove the element from
+ * @param val Value of the element to look for and remove
+ * @return True if the element was found and removed, false if it wasn't found.
+ * If true, all iterators, references and pointers pointing to either the first element that
+ * is equal to val or to the last element are invalidated.
+ */
+ template <typename T>
+ inline bool swaperase(typename std::vector<T>& vect, const T& val)
+ {
+ const typename std::vector<T>::iterator it = std::find(vect.begin(), vect.end(), val);
+ if (it != vect.end())
+ {
+ swaperase(vect, it);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Deleter that uses operator delete to delete the item
+ */
+ template <typename T>
+ struct defaultdeleter
+ {
+ void operator()(T* o)
+ {
+ delete o;
+ }
+ };
+
+ /**
+ * Deleter that adds the item to the cull list, that is, queues it for
+ * deletion at the end of the current mainloop iteration
+ */
+ struct culldeleter
+ {
+ void operator()(classbase* item);
+ };
+
+ /**
+ * Deletes all elements in a container using operator delete
+ * @param cont The container containing the elements to delete
+ */
+ template <template<typename, typename> class Cont, typename T, typename Alloc>
+ inline void delete_all(const Cont<T*, Alloc>& cont)
+ {
+ std::for_each(cont.begin(), cont.end(), defaultdeleter<T>());
+ }
+}
diff --git a/include/testsuite.h b/include/testsuite.h
index f91e508c9..c760513f8 100644
--- a/include/testsuite.h
+++ b/include/testsuite.h
@@ -16,12 +16,12 @@
*/
-#ifndef TESTSUITE_H
-#define TESTSUITE_H
+#pragma once
+
+#ifdef INSPIRCD_ENABLE_TESTSUITE
class TestSuite
{
- bool RealGenerateUIDTests();
public:
TestSuite();
~TestSuite();
diff --git a/include/threadengine.h b/include/threadengine.h
index 4bf5a48f3..39f150566 100644
--- a/include/threadengine.h
+++ b/include/threadengine.h
@@ -18,13 +18,12 @@
*/
-#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;
@@ -172,6 +171,3 @@ class CoreExport SocketThread : public Thread
*/
virtual void OnNotify() = 0;
};
-
-#endif
-
diff --git a/include/threadengines/threadengine_pthread.h b/include/threadengines/threadengine_pthread.h
index 5168ed238..253e8d223 100644
--- a/include/threadengines/threadengine_pthread.h
+++ b/include/threadengines/threadengine_pthread.h
@@ -18,8 +18,7 @@
*/
-#ifndef THREADENGINE_PTHREAD_H
-#define THREADENGINE_PTHREAD_H
+#pragma once
#include <pthread.h>
#include "typedefs.h"
@@ -153,6 +152,3 @@ class ThreadSignalData
public:
ThreadSignalSocket* sock;
};
-
-
-#endif
diff --git a/include/threadengines/threadengine_win32.h b/include/threadengines/threadengine_win32.h
index f068ac707..59848bd44 100644
--- a/include/threadengines/threadengine_win32.h
+++ b/include/threadengines/threadengine_win32.h
@@ -18,10 +18,9 @@
*/
-#ifndef THREADENGINE_WIN32_H
-#define THREADENGINE_WIN32_H
+#pragma once
-#include "inspircd_config.h"
+#include "config.h"
#include "base.h"
class Thread;
@@ -152,6 +151,3 @@ class ThreadSignalData
connFD = -1;
}
};
-
-#endif
-
diff --git a/include/timer.h b/include/timer.h
index 9bb7128b8..503fa82a2 100644
--- a/include/timer.h
+++ b/include/timer.h
@@ -19,8 +19,9 @@
*/
-#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
@@ -29,61 +30,71 @@
* 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 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.
+ * @param TIME The current time.
+ * @return True if the Timer object is still valid, false if it was destructed.
*/
- 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;
}
@@ -91,7 +102,7 @@ class CoreExport Timer
/** Returns the interval (number of seconds between ticks)
* of this timer object.
*/
- long GetSecs()
+ unsigned int GetInterval() const
{
return secs;
}
@@ -99,12 +110,6 @@ class CoreExport Timer
/** 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()
{
@@ -112,6 +117,7 @@ class CoreExport Timer
}
};
+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
@@ -119,17 +125,11 @@ class CoreExport Timer
*/
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
*/
@@ -140,15 +140,8 @@ class CoreExport TimerManager
*/
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
-
diff --git a/include/typedefs.h b/include/typedefs.h
index 06f704120..336084c55 100644
--- a/include/typedefs.h
+++ b/include/typedefs.h
@@ -19,81 +19,63 @@
*/
-#ifndef TYPEDEFS_H
-#define TYPEDEFS_H
+#pragma once
class BanCacheManager;
-class BanItem;
class BufferedSocket;
class Channel;
class Command;
-class ConfigReader;
+class ConfigStatus;
class ConfigTag;
-class DNSHeader;
-class DNSRequest;
class Extensible;
class FakeUser;
class InspIRCd;
class Invitation;
-class InviteBase;
class LocalUser;
class Membership;
class Module;
class OperInfo;
+class ProtocolServer;
class RemoteUser;
+class Server;
class ServerConfig;
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
*/
-typedef std::list<LocalUser*> LocalUserList;
+typedef intrusive_list<LocalUser> LocalUserList;
/** A list of failed port bindings, used for informational purposes on startup */
typedef std::vector<std::pair<std::string, std::string> > FailedPortList;
-/** Holds a complete list of all channels to which a user has been invited and has not yet joined, and the time at which they'll expire.
- */
-typedef std::vector<Invitation*> InviteList;
-
/** Holds a complete list of all allow and deny tags from the configuration file (connection classes)
*/
typedef std::vector<reference<ConnectClass> > ClassVector;
/** Typedef for the list of user-channel records for a user
*/
-typedef std::set<Channel*> UserChanList;
+typedef intrusive_list<Membership> UserChanList;
/** Shorthand for an iterator into a UserChanList
*/
typedef UserChanList::iterator UCListIter;
-/** Holds a complete ban list
- */
-typedef std::vector<BanItem> BanList;
-
-/** A list of custom modes parameters on a channel
+/** List of channels to consider when building the neighbor list of a user
*/
-typedef std::map<char,std::string> CustomModeList;
+typedef std::vector<Membership*> IncludeChanList;
/** A cached text file stored with its contents as lines
*/
@@ -120,7 +102,7 @@ typedef std::map<std::string, file_cache> ConfigFileCache;
/** 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;
@@ -159,7 +141,3 @@ typedef XLineContainer::iterator ContainerIter;
/** An interator in an XLineLookup
*/
typedef XLineLookup::iterator LookupIter;
-
-
-#endif
-
diff --git a/include/uid.h b/include/uid.h
index 17061bdee..772c8a716 100644
--- a/include/uid.h
+++ b/include/uid.h
@@ -16,12 +16,44 @@
* 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);
+};
diff --git a/include/usermanager.h b/include/usermanager.h
index ac8ae1cb3..a419916f2 100644
--- a/include/usermanager.h
+++ b/include/usermanager.h
@@ -17,42 +17,54 @@
*/
-#ifndef USERMANAGER_H
-#define USERMANAGER_H
+#pragma once
#include <list>
-/** A list of ip addresses cross referenced against clone counts */
-typedef std::map<irc::sockets::cidr_mask, unsigned int> clonemap;
-
class CoreExport UserManager
{
+ public:
+ struct CloneCounts
+ {
+ unsigned int global;
+ unsigned int local;
+ CloneCounts() : global(0), local(0) { }
+ };
+
+ /** Container that maps IP addresses to clone counts
+ */
+ typedef std::map<irc::sockets::cidr_mask, CloneCounts> CloneMap;
+
+ /** Sequence container in which each element is a User*
+ */
+ typedef std::vector<User*> OperList;
+
private:
- /** Map of local ip addresses for clone counting
+ /** Map of IP addresses for clone counting
+ */
+ CloneMap clonemap;
+
+ /** A CloneCounts that contains zero for both local and global
*/
- clonemap local_clones;
+ const CloneCounts zeroclonecounts;
+
public:
+ /** Constructor, initializes variables
+ */
UserManager();
- ~UserManager()
- {
- for (user_hash::iterator i = clientlist->begin();i != clientlist->end();i++)
- {
- delete i->second;
- }
- clientlist->clear();
- delete clientlist;
- delete uuidlist;
- }
+ /** Destructor, destroys all users in clientlist
+ */
+ ~UserManager();
/** Client list, a hash_map containing all clients, local and remote
*/
- user_hash* clientlist;
+ user_hash clientlist;
/** Client list stored by UUID. Contains all clients, and is updated
* automatically by the constructor and destructor of User.
*/
- user_hash* uuidlist;
+ user_hash uuidlist;
/** Local client list, a list containing only local clients
*/
@@ -60,21 +72,28 @@ class CoreExport UserManager
/** Oper list, a vector containing all local and remote opered users
*/
- std::list<User*> all_opers;
+ OperList all_opers;
/** Number of unregistered users online right now.
* (Unregistered means before USER/NICK/dns)
*/
unsigned int unregistered_count;
- /** Number of elements in local_users
+ /**
+ * Reset the already_sent IDs so we don't wrap it around and drop a message
+ * Also removes all expired invites
+ */
+ void GarbageCollect();
+
+ /** Perform background user events such as PING checks
*/
- unsigned int local_count;
+ void DoBackgroundUserStuff();
- /** Map of global ip addresses for clone counting
- * XXX - this should be private, but m_clones depends on it currently.
+ /** Returns true when all modules have done pre-registration checks on a user
+ * @param user The user to verify
+ * @return True if all modules have finished checking this user
*/
- clonemap global_clones;
+ bool AllModulesReportReady(LocalUser* user);
/** Add a client to the system.
* This will create a new User, insert it into the user_hash,
@@ -90,20 +109,15 @@ class CoreExport UserManager
/** Disconnect a user gracefully
* @param user The user to remove
* @param quitreason The quit reason to show to normal users
- * @param operreason The quit reason to show to opers
+ * @param operreason The quit reason to show to opers, can be NULL if same as quitreason
* @return Although this function has no return type, on exit the user provided will no longer exist.
*/
- void QuitUser(User *user, const std::string &quitreason, const char* operreason = "");
+ void QuitUser(User* user, const std::string& quitreason, const std::string* operreason = NULL);
- /** Add a user to the local clone map
+ /** Add a user to the clone map
* @param user The user to add
*/
- void AddLocalClone(User *user);
-
- /** Add a user to the global clone map
- * @param user The user to add
- */
- void AddGlobalClone(User *user);
+ void AddClone(User* user);
/** Remove all clone counts from the user, you should
* use this if you change the user's IP address
@@ -112,61 +126,52 @@ class CoreExport UserManager
*/
void RemoveCloneCounts(User *user);
- /** Return the number of global clones of this user
- * @param user The user to get a count for
- * @return The global clone count of this user
+ /** Return the number of local and global clones of this user
+ * @param user The user to get the clone counts for
+ * @return The clone counts of this user. The returned reference is volatile - you
+ * must assume that it becomes invalid as soon as you call any function other than
+ * your own.
*/
- unsigned long GlobalCloneCount(User *user);
+ const CloneCounts& GetCloneCounts(User* user) const;
- /** Return the number of local clones of this user
- * @param user The user to get a count for
- * @return The local clone count of this user
+ /** Return a map containg IP addresses and their clone counts
+ * @return The clone count map
*/
- unsigned long LocalCloneCount(User *user);
+ const CloneMap& GetCloneMap() const { return clonemap; }
- /** Return a count of users, unknown and known connections
- * @return The number of users
+ /** Return a count of all global users, unknown and known connections
+ * @return The number of users on the network, including local unregistered users
*/
- unsigned int UserCount();
+ unsigned int UserCount() const { return this->clientlist.size(); }
- /** Return a count of fully registered connections only
- * @return The number of registered users
+ /** Return a count of fully registered connections on the network
+ * @return The number of registered users on the network
*/
- unsigned int RegisteredUserCount();
+ unsigned int RegisteredUserCount() { return this->clientlist.size() - this->UnregisteredUserCount(); }
- /** Return a count of opered (umode +o) users only
- * @return The number of opers
+ /** Return a count of opered (umode +o) users on the network
+ * @return The number of opers on the network
*/
- unsigned int OperCount();
+ unsigned int OperCount() const { return this->all_opers.size(); }
- /** Return a count of unregistered (before NICK/USER) users only
- * @return The number of unregistered (unknown) connections
+ /** Return a count of local unregistered (before NICK/USER) users
+ * @return The number of local unregistered (unknown) connections
*/
- unsigned int UnregisteredUserCount();
+ unsigned int UnregisteredUserCount() const { return this->unregistered_count; }
- /** Return a count of local users on this server only
- * @return The number of local users
+ /** Return a count of local registered users
+ * @return The number of registered local users
*/
- unsigned int LocalUserCount();
-
-
+ unsigned int LocalUserCount() const { return (this->local_users.size() - this->UnregisteredUserCount()); }
-
- /** Number of users with a certain mode set on them
+ /** Get a hash map containing all users, keyed by their nickname
+ * @return A hash map mapping nicknames to User pointers
*/
- int ModeCount(const char mode);
+ user_hash& GetUsers() { return clientlist; }
/** Send a server notice to all local users
* @param text The text format string to send
* @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
diff --git a/include/users.h b/include/users.h
index 88abfbcd1..0f8154bef 100644
--- a/include/users.h
+++ b/include/users.h
@@ -22,12 +22,10 @@
*/
-#ifndef USERS_H
-#define USERS_H
+#pragma once
#include "socket.h"
#include "inspsocket.h"
-#include "dns.h"
#include "mode.h"
#include "membership.h"
@@ -42,19 +40,6 @@ enum ClassTypes {
CC_NAMED = 2
};
-/** RFC1459 channel modes
- */
-enum UserModes {
- /** +s: Server notice mask */
- UM_SNOMASK = 's' - 65,
- /** +w: WALLOPS */
- UM_WALLOPS = 'w' - 65,
- /** +i: Invisible */
- UM_INVISIBLE = 'i' - 65,
- /** +o: Operator */
- UM_OPERATOR = 'o' - 65
-};
-
/** Registration state of a user, e.g.
* have they sent USER, NICK, PASS yet?
*/
@@ -146,6 +131,10 @@ struct CoreExport ConnectClass : public refcountbase
*/
unsigned long limit;
+ /** If set to true, no user DNS lookups are to be performed
+ */
+ bool resolvehostnames;
+
/** Create a new connect class with no settings.
*/
ConnectClass(ConfigTag* tag, char type, const std::string& mask);
@@ -250,6 +239,14 @@ class CoreExport User : public Extensible
*/
std::string cachedip;
+ /** The user's mode list.
+ * Much love to the STL for giving us an easy to use bitset, saving us RAM.
+ * if (modes[modeid]) is set, then the mode is set.
+ * For example, to work out if mode +i is set, we check the field
+ * User::modes[invisiblemode->modeid] == true.
+ */
+ std::bitset<ModeParser::MODEID_MAX> modes;
+
public:
/** Hostname of connection.
@@ -267,10 +264,6 @@ class CoreExport User : public Extensible
*/
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.
@@ -302,18 +295,6 @@ class CoreExport User : public Extensible
*/
std::string fullname;
- /** The user's mode list.
- * NOT a null terminated string.
- * Also NOT an array.
- * Much love to the STL for giving us an easy to use bitset, saving us RAM.
- * if (modes[modeletter-65]) is set, then the mode is
- * set, for example, to work out if mode +s is set, we check the field
- * User::modes['s'-65] != 0.
- * The following RFC characters o, w, s, i have constants defined via an
- * enum, such as UM_SERVERNOTICE and UM_OPETATOR.
- */
- std::bitset<64> modes;
-
/** What snomasks are set on this user.
* This functions the same as the above modes.
*/
@@ -325,7 +306,7 @@ class CoreExport User : public Extensible
/** The server the user is connected to.
*/
- const std::string server;
+ Server* server;
/** The user's away message.
* If this string is empty, the user is not marked as away.
@@ -333,7 +314,7 @@ class CoreExport User : public Extensible
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;
@@ -347,16 +328,6 @@ class CoreExport User : public Extensible
*/
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;
-
/** If this is set to true, then all socket operations for the user
* are dropped into the bit-bucket.
* This value is set by QuitUser, and is not needed seperately from that call.
@@ -364,27 +335,13 @@ class CoreExport User : public Extensible
*/
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
*/
@@ -400,13 +357,7 @@ class CoreExport User : public Extensible
/** Constructor
* @throw CoreException if the UID allocated to the user already exists
*/
- 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);
+ User(const std::string& uid, Server* srv, int objtype);
/** Returns the full displayed host of the user
* This member function returns the hostname of the user as seen by other users
@@ -428,18 +379,17 @@ class CoreExport User : public Extensible
*/
void InvalidateCache();
- /** Create a displayable mode string for this users snomasks
- * @return The notice mask character sequence
+ /** 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
*/
- const char* FormatNoticeMasks();
+ bool IsAway() const { return (!awaymsg.empty()); }
- /** Process a snomask modifier string, e.g. +abc-de
- * @param sm A sequence of notice mask characters
- * @return The cleaned mode sequence which can be output,
- * e.g. in the above example if masks c and e are not
- * valid, this function will return +ab-d
+ /** 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
*/
- std::string ProcessNoticeMasks(const char *sm);
+ bool IsOper() const { return oper; }
/** Returns true if a notice mask is set
* @param sm A notice mask character to check
@@ -447,12 +397,6 @@ class CoreExport User : public Extensible
*/
bool IsNoticeMaskSet(unsigned char sm);
- /** Changed a specific notice mask value
- * @param sm The server notice mask to change
- * @param value An on/off value for this mask
- */
- void SetNoticeMask(unsigned char sm, bool value);
-
/** Create a displayable mode string for this users umodes
* @param showparameters The mode string
*/
@@ -463,12 +407,16 @@ class CoreExport User : public Extensible
* @return True if the mode is set
*/
bool IsModeSet(unsigned char m);
+ bool IsModeSet(ModeHandler* mh);
+ bool IsModeSet(ModeHandler& mh) { return IsModeSet(&mh); }
+ bool IsModeSet(UserModeReference& moderef);
/** Set a specific usermode to on or off
* @param m The user mode
* @param value On or off setting of the mode
*/
- void SetMode(unsigned char m, bool value);
+ void SetMode(ModeHandler* mh, bool value);
+ void SetMode(ModeHandler& mh, bool value) { SetMode(&mh, value); }
/** Returns true or false for if a user can execute a privilaged oper command.
* This is done by looking up their oper type from User::oper, then referencing
@@ -497,12 +445,6 @@ class CoreExport User : public Extensible
*/
virtual bool HasModePermission(unsigned char mode, ModeType type);
- /** Creates a wildcard host.
- * Takes a buffer to use and fills the given buffer with the host in the format *!*\@hostname
- * @return The wildcarded hostname in *!*\@host form
- */
- char* MakeWildHost();
-
/** Creates a usermask with real host.
* Takes a buffer to use and fills the given buffer with the hostmask in the format user\@host
* @return the usermask in the format user\@host
@@ -515,10 +457,6 @@ class CoreExport User : public Extensible
*/
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.
*/
@@ -531,7 +469,7 @@ class CoreExport User : public Extensible
* @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, time_t newts = 0) { return ChangeNick(newnick, true, newts); }
/** Oper down.
* This will clear the +o usermode and unset the user's oper type
@@ -563,6 +501,17 @@ class CoreExport User : public Extensible
*/
void WriteServ(const char* text, ...) CUSTOM_PRINTF(2, 3);
+ /** Sends a command to this user.
+ * @param command The command to be sent.
+ * @param text The message to send.
+ */
+ void WriteCommand(const char* command, const std::string& text);
+
+ /** Sends a server notice to this user.
+ * @param text The contents of the message to send.
+ */
+ void WriteNotice(const std::string& text) { this->WriteCommand("NOTICE", ":" + text); }
+
void WriteNumeric(unsigned int numeric, const char* text, ...) CUSTOM_PRINTF(3, 4);
void WriteNumeric(unsigned int numeric, const std::string &text);
@@ -580,19 +529,6 @@ class CoreExport User : public Extensible
*/
void WriteFrom(User *user, const char* text, ...) CUSTOM_PRINTF(3, 4);
- /** Write text to the user provided in the first parameter, appending CR/LF, and prepending THIS user's :nick!user\@host.
- * @param dest The user to route the message to
- * @param data A std::string to send to the user
- */
- void WriteTo(User *dest, const std::string &data);
-
- /** Write text to the user provided in the first parameter, appending CR/LF, and prepending THIS user's :nick!user\@host.
- * @param dest The user to route the message to
- * @param data The format string for text to send to the user
- * @param ... POD-type format arguments
- */
- void WriteTo(User *dest, const char *data, ...) CUSTOM_PRINTF(3, 4);
-
/** Write to all users that can see this user (including this user in the list if include_self is true), appending CR/LF
* @param line A std::string to send to the users
* @param include_self Should the message be sent back to the author?
@@ -605,12 +541,6 @@ class CoreExport User : public Extensible
*/
void WriteCommon(const char* text, ...) CUSTOM_PRINTF(2, 3);
- /** Write to all users that can see this user (not including this user in the list), appending CR/LF
- * @param text The format string for text to send to the users
- * @param ... POD-type format arguments
- */
- void WriteCommonExcept(const char* text, ...) CUSTOM_PRINTF(2, 3);
-
/** Write a quit message to all common users, as in User::WriteCommonExcept but with a specific
* quit message for opers only.
* @param normal_text Normal user quit message
@@ -619,10 +549,10 @@ class CoreExport User : public Extensible
void WriteCommonQuit(const std::string &normal_text, const std::string &oper_text);
/** Dump text to a user target, splitting it appropriately to fit
- * @param LinePrefix text to prefix each complete line with
- * @param TextStream the text to send to the user
+ * @param linePrefix text to prefix each complete line with
+ * @param textStream the text to send to the user
*/
- void SendText(const std::string &LinePrefix, std::stringstream &TextStream);
+ void SendText(const std::string& linePrefix, std::stringstream& textStream);
/** Write to the user, routing the line if the user is remote.
*/
@@ -638,32 +568,24 @@ class CoreExport User : public Extensible
*/
bool SharesChannelWith(User *other);
- /** Send fake quit/join messages for host or ident cycle.
- * Run this after the item in question has changed.
- * You should not need to use this function, call ChangeDisplayedHost instead
- *
- * @param quitline The entire QUIT line, including the source using the old value
- */
- void DoHostCycle(const std::string &quitline);
-
/** Change the displayed host of a user.
* ALWAYS use this function, rather than writing User::dhost directly,
* as this triggers module events allowing the change to be syncronized to
- * remote servers. This will also emulate a QUIT and rejoin (where configured)
- * before setting their host field.
+ * remote servers.
* @param host The new hostname to set
* @return True if the change succeeded, false if it didn't
+ * (a module vetoed the change).
*/
- bool ChangeDisplayedHost(const char* host);
+ bool ChangeDisplayedHost(const std::string& host);
/** Change the ident (username) of a user.
* ALWAYS use this function, rather than writing User::ident directly,
- * as this correctly causes the user to seem to quit (where configured)
- * before setting their ident field.
+ * as this triggers module events allowing the change to be syncronized to
+ * remote servers.
* @param newident The new ident to set
* @return True if the change succeeded, false if it didn't
*/
- bool ChangeIdent(const char* newident);
+ bool ChangeIdent(const std::string& newident);
/** Change a users realname field.
* ALWAYS use this function, rather than writing User::fullname directly,
@@ -672,49 +594,20 @@ class CoreExport User : public Extensible
* @param gecos The user's new realname
* @return True if the change succeeded, false if otherwise
*/
- bool ChangeName(const char* gecos);
+ bool ChangeName(const std::string& gecos);
/** Change a user's nick
* @param newnick The new nick
* @param force True if the change is being forced (should not be blocked by modes like +N)
* @return True if the change succeeded
*/
- bool ChangeNick(const std::string& newnick, bool force = false);
-
- /** Send a command to all local users from this user
- * The command given must be able to send text with the
- * first parameter as a servermask (e.g. $*), so basically
- * you should use PRIVMSG or NOTICE.
- * @param command the command to send
- * @param text The text format string to send
- * @param ... Format arguments
- */
- 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);
+ bool ChangeNick(const std::string& newnick, bool force = false, time_t newts = 0);
/** 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!
*/
void PurgeEmptyChannels();
- /** Get the connect class which this user belongs to. NULL for remote users.
- * @return A pointer to this user's connect class.
- */
- virtual ConnectClass* GetClass();
-
/** Default destructor
*/
virtual ~User();
@@ -739,7 +632,7 @@ class CoreExport UserIOHandler : public StreamSocket
typedef unsigned int already_sent_t;
-class CoreExport LocalUser : public User, public InviteBase
+class CoreExport LocalUser : public User, public InviteBase<LocalUser>, public intrusive_list_node<LocalUser>
{
public:
LocalUser(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server);
@@ -747,10 +640,6 @@ class CoreExport LocalUser : public User, public InviteBase
UserIOHandler eh;
- /** Position in UserManager::local_users
- */
- LocalUserList::iterator localuseriter;
-
/** Stats counter for bytes inbound
*/
unsigned int bytes_in;
@@ -777,11 +666,14 @@ class CoreExport LocalUser : public User, public InviteBase
*/
reference<ConnectClass> MyClass;
- ConnectClass* GetClass();
+ /** Get the connect class which this user belongs to.
+ * @return A pointer to this user's connect class.
+ */
+ ConnectClass* GetClass() const { return MyClass; }
/** Call this method to find the matching \<connect> for a user, and to check them against it.
*/
- void CheckClass();
+ void CheckClass(bool clone_count = true);
/** Server address and port that this user is connected to.
*/
@@ -792,10 +684,28 @@ class CoreExport LocalUser : public User, public InviteBase
*/
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
*/
@@ -804,15 +714,11 @@ class CoreExport LocalUser : public User, public InviteBase
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.
@@ -839,23 +745,18 @@ class CoreExport LocalUser : public User, public InviteBase
InviteList& GetInviteList();
/** Returns true if a user is invited to a channel.
- * @param channel A channel name to look up
+ * @param chan 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
+ * @param chan 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();
@@ -890,7 +791,7 @@ class CoreExport LocalUser : public User, public InviteBase
class CoreExport RemoteUser : public User
{
public:
- RemoteUser(const std::string& uid, const std::string& srv) : User(uid, srv, USERTYPE_REMOTE)
+ RemoteUser(const std::string& uid, Server* srv) : User(uid, srv, USERTYPE_REMOTE)
{
}
virtual void SendText(const std::string& line);
@@ -899,9 +800,15 @@ class CoreExport RemoteUser : public User
class CoreExport FakeUser : public User
{
public:
- FakeUser(const std::string &uid, const std::string& srv) : User(uid, srv, USERTYPE_SERVER)
+ FakeUser(const std::string& uid, Server* srv) : User(uid, srv, USERTYPE_SERVER)
+ {
+ nick = srv->GetName();
+ }
+
+ FakeUser(const std::string& uid, const std::string& sname, const std::string& sdesc)
+ : User(uid, new Server(sname, sdesc), USERTYPE_SERVER)
{
- nick = srv;
+ nick = sname;
}
virtual CullResult cull();
@@ -926,42 +833,20 @@ inline FakeUser* IS_SERVER(User* u)
{
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
+inline bool User::IsModeSet(ModeHandler* mh)
{
- 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);
+ return (modes[mh->GetId()]);
+}
- /** Called on failed lookup
- * @param e Error code
- * @param errormessage Error message string
- */
- void OnError(ResolverError e, const std::string &errormessage);
-};
+inline bool User::IsModeSet(UserModeReference& moderef)
+{
+ if (!moderef)
+ return false;
+ return IsModeSet(*moderef);
+}
-#endif
+inline void User::SetMode(ModeHandler* mh, bool value)
+{
+ modes[mh->GetId()] = value;
+}
diff --git a/include/xline.h b/include/xline.h
index 2a49d8b80..fe044d0f2 100644
--- a/include/xline.h
+++ b/include/xline.h
@@ -20,8 +20,7 @@
*/
-#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
@@ -101,16 +100,16 @@ class CoreExport XLine : public classbase
* 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.
*/
@@ -177,9 +176,7 @@ class CoreExport KLine : public XLine
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
virtual bool IsBurstable();
@@ -225,9 +222,7 @@ class CoreExport GLine : public XLine
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** Ident mask (ident part only)
*/
@@ -269,11 +264,9 @@ class CoreExport ELine : public XLine
virtual void Unset();
- virtual void DisplayExpiry();
-
virtual void OnAdd();
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** Ident mask (ident part only)
*/
@@ -314,9 +307,7 @@ class CoreExport ZLine : public XLine
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** IP mask (no ident part)
*/
@@ -351,9 +342,7 @@ class CoreExport QLine : public XLine
virtual void Apply(User* u);
- virtual void DisplayExpiry();
-
- virtual const char* Displayable();
+ virtual const std::string& Displayable();
/** Nickname mask
*/
@@ -536,5 +525,3 @@ class CoreExport XLineManager
*/
void InvokeStats(const std::string &type, int numeric, User* user, string_list &results);
};
-
-#endif