]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Merge pull request #1106 from SaberUK/master+purge-pkg-path
authorAttila Molnar <attilamolnar@hush.com>
Mon, 16 Nov 2015 09:14:55 +0000 (10:14 +0100)
committerAttila Molnar <attilamolnar@hush.com>
Mon, 16 Nov 2015 09:14:55 +0000 (10:14 +0100)
Remove the PKG_CONFIG_PATH extension code from the build system.

23 files changed:
include/channels.h
include/configreader.h
include/membership.h
include/modules/invite.h [new file with mode: 0644]
include/usermanager.h
include/users.h
src/channels.cpp
src/configreader.cpp
src/coremods/core_channel/cmd_invite.cpp
src/coremods/core_channel/core_channel.cpp
src/coremods/core_channel/core_channel.h
src/coremods/core_channel/invite.cpp [new file with mode: 0644]
src/coremods/core_channel/invite.h [new file with mode: 0644]
src/coremods/core_info/cmd_info.cpp
src/inspircd.cpp
src/modules/extra/m_ssl_gnutls.cpp
src/modules/extra/m_ssl_openssl.cpp
src/modules/m_hostcycle.cpp
src/modules/m_override.cpp
src/modules/m_spanningtree/fjoin.cpp
src/modules/m_uninvite.cpp
src/usermanager.cpp
src/users.cpp

index 4d1d14c13ea5819a96e34fdb021b371442688cff..be84ac8009736510e031fa892a34c4cd51d1a6ed 100644 (file)
@@ -34,7 +34,7 @@
  * 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<Channel>
+class CoreExport Channel : public Extensible
 {
  public:
        /** A map of Memberships on a channel keyed by User pointers
index 57d7ab069741a1f68869183005b705a1a1ffabba..9b73dd3c630a095fdc5e3e59889a25e86fcff670 100644 (file)
@@ -495,10 +495,6 @@ class CoreExport ServerConfig
         */
        static std::string Escape(const std::string& str, bool xml = true);
 
-       /** If this value is true, invites will bypass more than just +i
-        */
-       bool InvBypassModes;
-
        /** If this value is true, snotices will not stack when repeats are sent
         */
        bool NoSnoticeStack;
index 11c142912ee60e6612980416c924bb514d08809c..05d6b3796fb1ac72e44a035117d927077b4878f0 100644 (file)
@@ -112,86 +112,3 @@ class CoreExport Membership : public Extensible, public insp::intrusive_list_nod
         */
        const char* GetAllPrefixChars() const;
 };
-
-template <typename T>
-class InviteBase
-{
- protected:
-       /** List of pending Invitations
-        */
-       insp::intrusive_list<Invitation, T> invites;
-
- public:
-       /** Remove and destruct all pending invitations this user or channel has.
-        * Must be called before the object is destroyed, also called when the TS of the channel is lowered.
-        */
-       void ClearInvites();
-
-       friend class Invitation;
-};
-
-/**
- * The Invitation class contains all data about a pending invitation.
- * Invitation objects are referenced from the user and the channel they belong to.
- */
-class CoreExport Invitation : public insp::intrusive_list_node<Invitation, Channel>, public insp::intrusive_list_node<Invitation, LocalUser>
-{
-       /** Constructs an Invitation, only called by Create()
-        * @param c Channel the user is invited to
-        * @param u User being invited
-        * @param timeout Expiration time for this Invitation
-        */
-       Invitation(Channel* c, LocalUser* u, time_t timeout) : user(u), chan(c), expiry(timeout) {}
-
- public:
-       /** User the invitation is for
-        */
-       LocalUser* const user;
-
-       /** Channel where the user is invited to
-        */
-       Channel* const chan;
-
-       /** Timestamp when this Invitation expires or 0 if it doesn't expire.
-        * Invitation::Create() can update this field; see that for more info.
-        */
-       time_t expiry;
-
-       /** Destructor
-        * Removes references to this Invitation from the associated user and channel.
-        */
-       ~Invitation();
-
-       /** Create or extend an Invitation.
-        * When a user is invited to join a channel either a new Invitation object is created or
-        * or the expiration timestamp is updated if there is already a pending Invitation for
-        * the given (user, channel) pair and the new expiration time is further than the current.
-        * @param c Target channel
-        * @param u Target user
-        * @param timeout Timestamp when the invite should expire, 0 for no expiration
-        */
-       static void Create(Channel* c, LocalUser* u, time_t timeout);
-
-       /** Finds the Invitation object for the given channel/user pair.
-        * @param c Target channel, can be NULL to remove expired entries
-        * @param u Target user, cannot be NULL
-        * @param check_expired Pass true to remove all expired invites found while searching, false
-        * to return with an Invitation even if it's expired
-        * @return Invitation object for the given (channel, user) pair if it exists, NULL otherwise
-        */
-       static Invitation* Find(Channel* c, LocalUser* u, bool check_expired = true);
-};
-
-typedef insp::intrusive_list<Invitation, LocalUser> InviteList;
-
-template<typename T>
-inline void InviteBase<T>::ClearInvites()
-{
-       for (typename insp::intrusive_list<Invitation, T>::iterator i = invites.begin(); i != invites.end(); )
-       {
-               Invitation* inv = *i;
-               // Destructing the Invitation invalidates the iterator, so move it now
-               ++i;
-               delete inv;
-       }
-}
diff --git a/include/modules/invite.h b/include/modules/invite.h
new file mode 100644 (file)
index 0000000..e53d520
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2012, 2015 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 Invite
+{
+       class APIBase;
+       class API;
+       class Invite;
+
+       typedef insp::intrusive_list<Invite, LocalUser> List;
+}
+
+class Invite::APIBase : public DataProvider
+{
+ public:
+       APIBase(Module* parent);
+
+       /** Create or extend an Invite.
+        * When a user is invited to join a channel either a new Invite object is created or
+        * or the expiration timestamp is updated if there is already a pending Invite for
+        * the given (user, channel) pair and the new expiration time is further than the current.
+        * @param user Target user
+        * @param chan Target channel
+        * @param timeout Timestamp when the invite should expire, 0 for no expiration
+        */
+       virtual void Create(LocalUser* user, Channel* chan, time_t timeout) = 0;
+
+       /** Retrieves the Invite object for the given (user, channel) pair
+        * @param user Target user
+        * @param chan Target channel
+        * @return Invite object for the given (channel, user) pair if it exists, NULL otherwise
+        */
+       virtual Invite* Find(LocalUser* user, Channel* chan) = 0;
+
+       /** Returns the list of channels a user has been invited to but has not yet joined.
+        * @param user User whose invite list to retrieve
+        * @return List of channels the user is invited to or NULL if the list is empty
+        */
+       virtual const List* GetList(LocalUser* user) = 0;
+
+       /** Check if a user is invited to a channel
+        * @param user User to check
+        * @param chan Channel to check
+        * @return True if the user is invited to the channel, false otherwise
+        */
+       bool IsInvited(LocalUser* user, Channel* chan) { return (Find(user, chan) != NULL); }
+
+       /** Removes an Invite if it exists
+        * @param user User whose invite to remove
+        * @param chan Channel to remove the invite to
+        * @return True if the user was invited to the channel and the invite was removed, false if the user wasn't invited
+        */
+       virtual bool Remove(LocalUser* user, Channel* chan) = 0;
+};
+
+class Invite::API : public dynamic_reference<APIBase>
+{
+ public:
+       API(Module* parent)
+               : dynamic_reference<APIBase>(parent, "core_channel_invite")
+       {
+       }
+};
+
+/**
+ * The Invite class contains all data about a pending invite.
+ * Invite objects are referenced from the user and the channel they belong to.
+ */
+class Invite::Invite : public insp::intrusive_list_node<Invite, LocalUser>, public insp::intrusive_list_node<Invite, Channel>
+{
+ public:
+       /** User the invite is for
+        */
+       LocalUser* const user;
+
+       /** Channel where the user is invited to
+        */
+       Channel* const chan;
+
+       /** Check whether the invite will expire or not
+        * @return True if the invite is timed, false if it doesn't expire
+        */
+       bool IsTimed() const { return (expiretimer != NULL); }
+
+       /** Serialize this object
+        * @param format Serialization format
+        * @param show_chans True to include channel in the output, false to include the nick/uuid
+        * @param out Output will be appended to this string
+        */
+       void Serialize(SerializeFormat format, bool show_chans, std::string& out);
+
+       friend class APIImpl;
+
+ private:
+       /** Timer handling expiration. If NULL this invite doesn't expire.
+        */
+       Timer* expiretimer;
+
+       /** Constructor, only available to the module providing the invite API (core_channel).
+        * To create Invites use InviteAPI::Create().
+        * @param user User being invited
+        * @param chan Channel the user is invited to
+        */
+       Invite(LocalUser* user, Channel* chan);
+
+       /** Destructor, only available to the module providing the invite API (core_channel).
+        * To remove Invites use InviteAPI::Remove().
+        */
+       ~Invite();
+};
index a67f90224d628839eda4c05a6f7feac53e08cd11..941569e8c02e7af1813ec95468fd7e924a3d36d8 100644 (file)
@@ -56,6 +56,11 @@ class CoreExport UserManager : public fakederef<UserManager>
         */
        LocalList local_users;
 
+       /** Last used already sent id, used when sending messages to neighbors to help determine whether the message has
+        * been sent to a particular user or not. See User::ForEachNeighbor() for more info.
+        */
+       already_sent_t already_sent_id;
+
  public:
        /** Constructor, initializes variables
         */
@@ -83,12 +88,6 @@ class CoreExport UserManager : public fakederef<UserManager>
         */
        unsigned int unregistered_count;
 
-       /**
-        * 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
         */
        void DoBackgroundUserStuff();
@@ -187,4 +186,9 @@ class CoreExport UserManager : public fakederef<UserManager>
         * @param ... The format arguments
         */
        void ServerNoticeAll(const char* text, ...) CUSTOM_PRINTF(2, 3);
+
+       /** Retrieves the next already sent id, guaranteed to be not equal to any user's already_sent field
+        * @return Next already_sent id
+        */
+       already_sent_t NextAlreadySentId();
 };
index fa8f610bc915c9c4b57af2f56573bf6e13bbbc0d..fa346a32968f2164a93aed14c447ef9ba25d7e42 100644 (file)
@@ -641,7 +641,7 @@ class CoreExport UserIOHandler : public StreamSocket
 
 typedef unsigned int already_sent_t;
 
-class CoreExport LocalUser : public User, public InviteBase<LocalUser>, public insp::intrusive_list_node<LocalUser>
+class CoreExport LocalUser : public User, public insp::intrusive_list_node<LocalUser>
 {
  public:
        LocalUser(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server);
@@ -720,7 +720,6 @@ class CoreExport LocalUser : public User, public InviteBase<LocalUser>, public i
         */
        unsigned int CommandFloodPenalty;
 
-       static already_sent_t already_sent_id;
        already_sent_t already_sent;
 
        /** Check if the user matches a G or K line, and disconnect them if they do.
@@ -748,27 +747,6 @@ class CoreExport LocalUser : public User, public InviteBase<LocalUser>, public i
        void Write(const std::string& text);
        void Write(const char*, ...) CUSTOM_PRINTF(2, 3);
 
-       /** Returns the list of channels this user has been invited to but has not yet joined.
-        * @return A list of channels the user is invited to
-        */
-       InviteList& GetInviteList();
-
-       /** Returns true if a user is invited to a channel.
-        * @param chan A channel to look up
-        * @return True if the user is invited to the given channel
-        */
-       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 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
-        */
-       bool RemoveInvite(Channel* chan);
-
-       void RemoveExpiredInvites();
-
        /** 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
         * this to their oper classes and checking the commands they can execute.
index f79b5b89f56c37e221e7aee01f24862d64f660cb..6e3bc5e04e4cbe6f21dcbb4104ed9af9e581c588 100644 (file)
@@ -90,7 +90,6 @@ void Channel::CheckDestroy()
 
        FOREACH_MOD(OnChannelDelete, (this));
        ServerInstance->chanlist.erase(iter);
-       ClearInvites();
        ServerInstance->GlobalCulls.AddItem(this);
 }
 
@@ -235,13 +234,10 @@ Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, co
                        if (MOD_RESULT == MOD_RES_PASSTHRU)
                        {
                                std::string ckey = chan->GetModeParameter(keymode);
-                               bool invited = user->IsInvited(chan);
-                               bool can_bypass = ServerInstance->Config->InvBypassModes && invited;
-
                                if (!ckey.empty())
                                {
                                        FIRST_MOD_RESULT(OnCheckKey, MOD_RESULT, (user, chan, key));
-                                       if (!MOD_RESULT.check((ckey == key) || can_bypass))
+                                       if (!MOD_RESULT.check(InspIRCd::TimingSafeCompare(ckey, key)))
                                        {
                                                // If no key provided, or key is not the right one, and can't bypass +k (not invited or option not enabled)
                                                user->WriteNumeric(ERR_BADCHANNELKEY, "%s :Cannot join channel (Incorrect channel key)", chan->name.c_str());
@@ -252,7 +248,7 @@ Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, co
                                if (chan->IsModeSet(inviteonlymode))
                                {
                                        FIRST_MOD_RESULT(OnCheckInvite, MOD_RESULT, (user, chan));
-                                       if (!MOD_RESULT.check(invited))
+                                       if (MOD_RESULT != MOD_RES_ALLOW)
                                        {
                                                user->WriteNumeric(ERR_INVITEONLYCHAN, "%s :Cannot join channel (Invite only)", chan->name.c_str());
                                                return NULL;
@@ -263,27 +259,18 @@ Channel* Channel::JoinUser(LocalUser* user, std::string cname, bool override, co
                                if (!limit.empty())
                                {
                                        FIRST_MOD_RESULT(OnCheckLimit, MOD_RESULT, (user, chan));
-                                       if (!MOD_RESULT.check((chan->GetUserCounter() < atol(limit.c_str()) || can_bypass)))
+                                       if (!MOD_RESULT.check((chan->GetUserCounter() < atol(limit.c_str()))))
                                        {
                                                user->WriteNumeric(ERR_CHANNELISFULL, "%s :Cannot join channel (Channel is full)", chan->name.c_str());
                                                return NULL;
                                        }
                                }
 
-                               if (chan->IsBanned(user) && !can_bypass)
+                               if (chan->IsBanned(user))
                                {
                                        user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s :Cannot join channel (You're banned)", chan->name.c_str());
                                        return NULL;
                                }
-
-                               /*
-                                * If the user has invites for this channel, remove them now
-                                * after a successful join so they don't build up.
-                                */
-                               if (invited)
-                               {
-                                       user->RemoveInvite(chan);
-                               }
                        }
                }
        }
@@ -650,68 +637,3 @@ bool Membership::SetPrefix(PrefixMode* delta_mh, bool adding)
                modes.push_back(prefix);
        return adding;
 }
-
-void Invitation::Create(Channel* c, LocalUser* u, time_t timeout)
-{
-       if ((timeout != 0) && (ServerInstance->Time() >= timeout))
-               // Expired, don't bother
-               return;
-
-       ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Create chan=%s user=%s", c->name.c_str(), u->uuid.c_str());
-
-       Invitation* inv = Invitation::Find(c, u, false);
-       if (inv)
-       {
-                if ((inv->expiry == 0) || (inv->expiry > timeout))
-                       return;
-               inv->expiry = timeout;
-               ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Create changed expiry in existing invitation %p", (void*) inv);
-       }
-       else
-       {
-               inv = new Invitation(c, u, timeout);
-               c->invites.push_front(inv);
-               u->invites.push_front(inv);
-               ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Create created new invitation %p", (void*) inv);
-       }
-}
-
-Invitation* Invitation::Find(Channel* c, LocalUser* u, bool check_expired)
-{
-       ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Find chan=%s user=%s check_expired=%d", c ? c->name.c_str() : "NULL", u ? u->uuid.c_str() : "NULL", check_expired);
-
-       Invitation* result = NULL;
-       for (InviteList::iterator i = u->invites.begin(); i != u->invites.end(); )
-       {
-               Invitation* inv = *i;
-               ++i;
-
-               if ((check_expired) && (inv->expiry != 0) && (inv->expiry <= ServerInstance->Time()))
-               {
-                       /* Expired invite, remove it. */
-                       std::string expiration = InspIRCd::TimeString(inv->expiry);
-                       ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Find ecountered expired entry: %p expired %s", (void*) inv, expiration.c_str());
-                       delete inv;
-               }
-               else
-               {
-                       /* Is it what we're searching for? */
-                       if (inv->chan == c)
-                       {
-                               result = inv;
-                               break;
-                       }
-               }
-       }
-
-       ServerInstance->Logs->Log("INVITATION", LOG_DEBUG, "Invitation::Find result=%p", (void*) result);
-       return result;
-}
-
-Invitation::~Invitation()
-{
-       // Remove this entry from both lists
-       chan->invites.erase(this);
-       user->invites.erase(this);
-       ServerInstance->Logs->Log("INVITEBASE", LOG_DEBUG, "Invitation::~ %p", (void*) this);
-}
index 974e52abf137cd3488023463db85a88dcf6bd3b8..a81a1b646f8ea81cc911eae6f2ad2835e21b911f 100644 (file)
@@ -56,7 +56,7 @@ ServerConfig::ServerConfig()
        , NoSnoticeStack(false)
 {
        RawLog = HideBans = HideSplits = UndernetMsgPrefix = false;
-       WildcardIPv6 = InvBypassModes = true;
+       WildcardIPv6 = true;
        dns_timeout = 5;
        MaxTargets = 20;
        NetBufferSize = 10240;
@@ -427,7 +427,6 @@ void ServerConfig::Fill()
        Paths.Data = ConfValue("path")->getString("datadir", INSPIRCD_DATA_PATH);
        Paths.Log = ConfValue("path")->getString("logdir", INSPIRCD_LOG_PATH);
        Paths.Module = ConfValue("path")->getString("moduledir", INSPIRCD_MODULE_PATH);
-       InvBypassModes = options->getBool("invitebypassmodes", true);
        NoSnoticeStack = options->getBool("nosnoticestack", false);
 
        if (Network.find(' ') != std::string::npos)
index 7bf669b296837b469ea56072acf4209e34ad7589..96f56058256658177e52ed8c9f0fb68d7e9ab18c 100644 (file)
 
 #include "inspircd.h"
 #include "core_channel.h"
+#include "invite.h"
 
-CommandInvite::CommandInvite(Module* parent)
+CommandInvite::CommandInvite(Module* parent, Invite::APIImpl& invapiimpl)
        : Command(parent, "INVITE", 0, 0)
+       , invapi(invapiimpl)
 {
        Penalty = 4;
        syntax = "[<nick> <channel>]";
@@ -109,7 +111,7 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
 
                if (IS_LOCAL(u))
                {
-                       Invitation::Create(c, IS_LOCAL(u), timeout);
+                       invapi.Create(IS_LOCAL(u), c, timeout);
                        u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str());
                }
 
@@ -150,10 +152,11 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
        {
                // pinched from ircu - invite with not enough parameters shows channels
                // youve been invited to but haven't joined yet.
-               InviteList& il = IS_LOCAL(user)->GetInviteList();
-               for (InviteList::const_iterator i = il.begin(); i != il.end(); ++i)
+               const Invite::List* list = invapi.GetList(IS_LOCAL(user));
+               if (list)
                {
-                       user->WriteNumeric(RPL_INVITELIST, ":%s", (*i)->chan->name.c_str());
+                       for (Invite::List::const_iterator i = list->begin(); i != list->end(); ++i)
+                               user->WriteNumeric(RPL_INVITELIST, ":%s", (*i)->chan->name.c_str());
                }
                user->WriteNumeric(RPL_ENDOFINVITELIST, ":End of INVITE list");
        }
index 99ad74d3da009a90f87904f38d6c78b129c40fcb..aba4d97690ddb28d6270cc05357850b68e4300b3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2014-2015 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
 
 #include "inspircd.h"
 #include "core_channel.h"
+#include "invite.h"
 
 class CoreModChannel : public Module
 {
+       Invite::APIImpl invapi;
        CommandInvite cmdinvite;
        CommandJoin cmdjoin;
        CommandKick cmdkick;
        CommandNames cmdnames;
        CommandTopic cmdtopic;
 
+       ModResult IsInvited(User* user, Channel* chan)
+       {
+               LocalUser* localuser = IS_LOCAL(user);
+               if ((localuser) && (invapi.IsInvited(localuser, chan)))
+                       return MOD_RES_ALLOW;
+               return MOD_RES_PASSTHRU;
+       }
+
  public:
        CoreModChannel()
-               : cmdinvite(this), cmdjoin(this), cmdkick(this), cmdnames(this), cmdtopic(this)
+               : invapi(this)
+               , cmdinvite(this, invapi), cmdjoin(this), cmdkick(this), cmdnames(this), cmdtopic(this)
        {
        }
 
+       void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
+       {
+               ConfigTag* optionstag = ServerInstance->Config->ConfValue("options");
+               Implementation events[] = { I_OnCheckKey, I_OnCheckLimit, I_OnCheckChannelBan };
+               if (optionstag->getBool("invitebypassmodes", true))
+                       ServerInstance->Modules.Attach(events, this, sizeof(events)/sizeof(Implementation));
+               else
+               {
+                       for (unsigned int i = 0; i < sizeof(events)/sizeof(Implementation); i++)
+                               ServerInstance->Modules.Detach(events[i], this);
+               }
+       }
+
        void OnPostJoin(Membership* memb) CXX11_OVERRIDE
        {
                Channel* const chan = memb->chan;
                LocalUser* const localuser = IS_LOCAL(memb->user);
                if (localuser)
                {
+                       // Remove existing invite, if any
+                       invapi.Remove(localuser, chan);
+
                        if (chan->topicset)
                                Topic::ShowTopic(localuser, chan);
 
@@ -48,6 +75,41 @@ class CoreModChannel : public Module
                }
        }
 
+       ModResult OnCheckKey(User* user, Channel* chan, const std::string& keygiven) CXX11_OVERRIDE
+       {
+               // Hook only runs when being invited bypasses +bkl
+               return IsInvited(user, chan);
+       }
+
+       ModResult OnCheckChannelBan(User* user, Channel* chan) CXX11_OVERRIDE
+       {
+               // Hook only runs when being invited bypasses +bkl
+               return IsInvited(user, chan);
+       }
+
+       ModResult OnCheckLimit(User* user, Channel* chan) CXX11_OVERRIDE
+       {
+               // Hook only runs when being invited bypasses +bkl
+               return IsInvited(user, chan);
+       }
+
+       ModResult OnCheckInvite(User* user, Channel* chan) CXX11_OVERRIDE
+       {
+               // Hook always runs
+               return IsInvited(user, chan);
+       }
+
+       void OnUserDisconnect(LocalUser* user) CXX11_OVERRIDE
+       {
+               invapi.RemoveAll(user);
+       }
+
+       void OnChannelDelete(Channel* chan) CXX11_OVERRIDE
+       {
+               // Make sure the channel won't appear in invite lists from now on, don't wait for cull to unset the ext
+               invapi.RemoveAll(chan);
+       }
+
        void Prioritize() CXX11_OVERRIDE
        {
                ServerInstance->Modules.SetPriority(this, I_OnPostJoin, PRIORITY_FIRST);
index 755f876f6dd73953acdef6fcb22057817c7fd0c4..2a280052390006fe4615e546c171124ffae7e174 100644 (file)
@@ -26,14 +26,21 @@ namespace Topic
        void ShowTopic(LocalUser* user, Channel* chan);
 }
 
+namespace Invite
+{
+       class APIImpl;
+}
+
 /** Handle /INVITE.
  */
 class CommandInvite : public Command
 {
+       Invite::APIImpl& invapi;
+
  public:
        /** Constructor for invite.
         */
-       CommandInvite (Module* parent);
+       CommandInvite(Module* parent, Invite::APIImpl& invapiimpl);
 
        /** Handle command.
         * @param parameters The parameters to the command
diff --git a/src/coremods/core_channel/invite.cpp b/src/coremods/core_channel/invite.cpp
new file mode 100644 (file)
index 0000000..7ac662e
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2012, 2015 Attila Molnar <attilamolnar@hush.com>
+ *
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "inspircd.h"
+
+#include "invite.h"
+
+class InviteExpireTimer : public Timer
+{
+       Invite::Invite* const inv;
+
+       bool Tick(time_t currtime) CXX11_OVERRIDE;
+
+ public:
+       InviteExpireTimer(Invite::Invite* invite, time_t timeout);
+};
+
+static Invite::APIImpl* apiimpl;
+
+void RemoveInvite(Invite::Invite* inv, bool remove_user, bool remove_chan)
+{
+       apiimpl->Destruct(inv, remove_user, remove_chan);
+}
+
+void UnserializeInvite(LocalUser* user, const std::string& str)
+{
+       apiimpl->Unserialize(user, str);
+}
+
+Invite::APIBase::APIBase(Module* parent)
+       : DataProvider(parent, "core_channel_invite")
+{
+}
+
+Invite::APIImpl::APIImpl(Module* parent)
+       : APIBase(parent)
+       , userext(parent, "invite_user")
+       , chanext(parent, "invite_chan")
+{
+       apiimpl = this;
+}
+
+void Invite::APIImpl::Destruct(Invite* inv, bool remove_user, bool remove_chan)
+{
+       Store<LocalUser>* ustore = userext.get(inv->user);
+       if (ustore)
+       {
+               ustore->invites.erase(inv);
+               if ((remove_user) && (ustore->invites.empty()))
+                       userext.unset(inv->user);
+       }
+
+       Store<Channel>* cstore = chanext.get(inv->chan);
+       if (cstore)
+       {
+               cstore->invites.erase(inv);
+               if ((remove_chan) && (cstore->invites.empty()))
+                       chanext.unset(inv->chan);
+       }
+
+       delete inv;
+}
+
+bool Invite::APIImpl::Remove(LocalUser* user, Channel* chan)
+{
+       Invite* inv = Find(user, chan);
+       if (inv)
+       {
+               Destruct(inv);
+               return true;
+       }
+       return false;
+}
+
+void Invite::APIImpl::Create(LocalUser* user, Channel* chan, time_t timeout)
+{
+       if ((timeout != 0) && (ServerInstance->Time() >= timeout))
+               // Expired, don't bother
+               return;
+
+       ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): user=%s chan=%s timeout=%lu", user->uuid.c_str(), chan->name.c_str(), (unsigned long)timeout);
+
+       Invite* inv = Find(user, chan);
+       if (inv)
+       {
+               // We only ever extend invites, so nothing to do if the existing one is not timed
+               if (!inv->IsTimed())
+                       return;
+
+               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): changing expiration in %p", (void*) inv);
+               if (timeout == 0)
+               {
+                       // Convert timed invite to non-expiring
+                       delete inv->expiretimer;
+                       inv->expiretimer = NULL;
+               }
+               else if (inv->expiretimer->GetTrigger() >= ServerInstance->Time() + timeout)
+               {
+                       // New expiration time is further than the current, extend the expiration
+                       inv->expiretimer->SetInterval(timeout - ServerInstance->Time());
+               }
+       }
+       else
+       {
+               inv = new Invite(user, chan);
+               if (timeout)
+               {
+                       inv->expiretimer = new InviteExpireTimer(inv, timeout - ServerInstance->Time());
+                       ServerInstance->Timers.AddTimer(inv->expiretimer);
+               }
+
+               userext.get(user, true)->invites.push_front(inv);
+               chanext.get(chan, true)->invites.push_front(inv);
+               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::APIImpl::Create(): created new Invite %p", (void*) inv);
+       }
+}
+
+Invite::Invite* Invite::APIImpl::Find(LocalUser* user, Channel* chan)
+{
+       const List* list = APIImpl::GetList(user);
+       if (!list)
+               return NULL;
+
+       for (List::iterator i = list->begin(); i != list->end(); ++i)
+       {
+               Invite* inv = *i;
+               if (inv->chan == chan)
+                       return inv;
+       }
+
+       return NULL;
+}
+
+const Invite::List* Invite::APIImpl::GetList(LocalUser* user)
+{
+       Store<LocalUser>* list = userext.get(user);
+       if (list)
+               return &list->invites;
+       return NULL;
+}
+
+void Invite::APIImpl::Unserialize(LocalUser* user, const std::string& value)
+{
+       irc::spacesepstream ss(value);
+       for (std::string channame, exptime; (ss.GetToken(channame) && ss.GetToken(exptime)); )
+       {
+               Channel* chan = ServerInstance->FindChan(channame);
+               if (chan)
+                       Create(user, chan, ConvToInt(exptime));
+       }
+}
+
+Invite::Invite::Invite(LocalUser* u, Channel* c)
+       : user(u)
+       , chan(c)
+       , expiretimer(NULL)
+{
+}
+
+Invite::Invite::~Invite()
+{
+       delete expiretimer;
+       ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Invite::~ %p", (void*) this);
+}
+
+void Invite::Invite::Serialize(SerializeFormat format, bool show_chans, std::string& out)
+{
+       if (show_chans)
+               out.append(this->chan->name);
+       else
+               out.append((format == FORMAT_USER) ? user->nick : user->uuid);
+       out.push_back(' ');
+
+       if (expiretimer)
+               out.append(ConvToStr(expiretimer->GetTrigger()));
+       else
+               out.push_back('0');
+       out.push_back(' ');
+}
+
+InviteExpireTimer::InviteExpireTimer(Invite::Invite* invite, time_t timeout)
+       : Timer(timeout)
+       , inv(invite)
+{
+}
+
+bool InviteExpireTimer::Tick(time_t currtime)
+{
+       ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "InviteExpireTimer::Tick(): expired %p", (void*) inv);
+       apiimpl->Destruct(inv);
+       return false;
+}
diff --git a/src/coremods/core_channel/invite.h b/src/coremods/core_channel/invite.h
new file mode 100644 (file)
index 0000000..2a99ec2
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2015 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 "modules/invite.h"
+
+namespace Invite
+{
+       template<typename T>
+       struct Store
+       {
+               typedef insp::intrusive_list<Invite, T> List;
+
+               /** List of pending Invites
+                */
+               List invites;
+       };
+
+       template<typename T, ExtensionItem::ExtensibleType ExtType>
+       class ExtItem;
+
+       class APIImpl;
+}
+
+extern void RemoveInvite(Invite::Invite* inv, bool remove_user, bool remove_chan);
+extern void UnserializeInvite(LocalUser* user, const std::string& value);
+
+template<typename T, ExtensionItem::ExtensibleType ExtType>
+class Invite::ExtItem : public ExtensionItem
+{
+ public:
+       ExtItem(Module* owner, const char* extname)
+               : ExtensionItem(extname, ExtType, owner)
+       {
+       }
+
+       Store<T>* get(Extensible* ext, bool create = false)
+       {
+               Store<T>* store = static_cast<Store<T>*>(get_raw(ext));
+               if ((create) && (!store))
+               {
+                       store = new Store<T>;
+                       set_raw(ext, store);
+               }
+               return store;
+       }
+
+       void unset(Extensible* ext)
+       {
+               void* store = unset_raw(ext);
+               if (store)
+                       free(store);
+       }
+
+       void free(void* item) CXX11_OVERRIDE
+       {
+               Store<T>* store = static_cast<Store<T>*>(item);
+               for (typename Store<T>::List::iterator i = store->invites.begin(); i != store->invites.end(); )
+               {
+                       Invite* inv = *i;
+                       // Destructing the Invite invalidates the iterator, so move it now
+                       ++i;
+                       RemoveInvite(inv, (ExtType != ExtensionItem::EXT_USER), (ExtType == ExtensionItem::EXT_USER));
+               }
+
+               delete store;
+       }
+
+       std::string serialize(SerializeFormat format, const Extensible* container, void* item) const CXX11_OVERRIDE
+       {
+               if (format == FORMAT_NETWORK)
+                       return std::string();
+
+               std::string ret;
+               Store<T>* store = static_cast<Store<T>*>(item);
+               for (typename insp::intrusive_list<Invite, T>::iterator i = store->invites.begin(); i != store->invites.end(); ++i)
+               {
+                       Invite* inv = *i;
+                       inv->Serialize(format, (ExtType == ExtensionItem::EXT_USER), ret);
+               }
+               if (!ret.empty())
+                       ret.erase(ret.length()-1);
+               return ret;
+       }
+
+       void unserialize(SerializeFormat format, Extensible* container, const std::string& value) CXX11_OVERRIDE
+       {
+               if ((ExtType != ExtensionItem::EXT_CHANNEL) && (format != FORMAT_NETWORK))
+                       UnserializeInvite(static_cast<LocalUser*>(container), value);
+       }
+};
+
+class Invite::APIImpl : public APIBase
+{
+       ExtItem<LocalUser, ExtensionItem::EXT_USER> userext;
+       ExtItem<Channel, ExtensionItem::EXT_CHANNEL> chanext;
+
+ public:
+       APIImpl(Module* owner);
+
+       void Create(LocalUser* user, Channel* chan, time_t timeout) CXX11_OVERRIDE;
+       Invite* Find(LocalUser* user, Channel* chan) CXX11_OVERRIDE;
+       bool Remove(LocalUser* user, Channel* chan) CXX11_OVERRIDE;
+       const List* GetList(LocalUser* user) CXX11_OVERRIDE;
+
+       void RemoveAll(LocalUser* user) { userext.unset(user); }
+       void RemoveAll(Channel* chan) { chanext.unset(chan); }
+       void Destruct(Invite* inv, bool remove_chan = true, bool remove_user = true);
+       void Unserialize(LocalUser* user, const std::string& value);
+};
index 0d8c1a45a9a7d382e9d41a322f72f9ca34a78df7..8dad99453581684e212f2e9e17cef64aedbe4a30 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Copyright (C) 2011 Jackmcbarn <jackmcbarn@jackmcbarn.no-ip.org>
  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
- *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
+ *   Copyright (C) 2007-2015 Robin Burchell <robin+git@viroteck.net>
  *   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
  *
  * This file is part of InspIRCd.  InspIRCd is free software: you can
@@ -35,9 +35,10 @@ static const char* const lines[] = {
        "                 November 2002 - Present",
        " ",
        "\2Core Developers\2:",
-       "    Craig Edwards,          Brain,      <brain@inspircd.org>",
-       "    Craig McLure,           Craig,      <craig@inspircd.org>",
-       "    Robin Burchell,         w00t,       <w00t@inspircd.org>",
+       "    Attila Molnar,          Attila,     <attilamolnar@hush.com>",
+       "    Peter Powell,           SaberUK,    <petpow@saberuk.com>",
+       " ",
+       "\2Former Developers\2:",
        "    Oliver Lupton,          Om,         <om@inspircd.org>",
        "    John Brooks,            Special,    <special@inspircd.org>",
        "    Dennis Friis,           peavey,     <peavey@inspircd.org>",
@@ -45,14 +46,14 @@ static const char* const lines[] = {
        "    Uli Schlachter,         psychon,    <psychon@inspircd.org>",
        "    Matt Smith,             dz,         <dz@inspircd.org>",
        "    Daniel De Graaf,        danieldg,   <danieldg@inspircd.org>",
-       "                            jackmcbarn, <jackmcbarn@inspircd.org>",
-       "    Attila Molnar,          Attila,     <attilamolnar@hush.com>",
        " ",
-       "\2Regular Contributors\2:",
-       "    Adam           SaberUK",
+       "\2Founding Developers\2:",
+       "    Craig Edwards,          Brain,      <brain@inspircd.org>",
+       "    Craig McLure,           Craig,      <craig@inspircd.org>",
+       "    Robin Burchell,         w00t,       <w00t@inspircd.org>",
        " ",
-       "\2Other Contributors\2:",
-       "    ChrisTX        Shawn           Shutter",
+       "\2Active Contributors\2:",
+       "    Adam           Shutter",
        " ",
        "\2Former Contributors\2:",
        "   dmb             Zaba            skenmy         GreenReaper",
@@ -64,9 +65,10 @@ static const char* const lines[] = {
        "   Stskeeps        ThaPrince       BuildSmart     Thunderhacker",
        "   Skip            LeaChim         Majic          MacGyver",
        "   Namegduf        Ankit           Phoenix        Taros",
+       "   jackmcbarn      ChrisTX         Shawn",
        " ",
        "\2Thanks To\2:",
-       "   searchirc.com   irc-junkie.org  Brik           fraggeln",
+       "   Asmo            Brik            fraggeln",
        " ",
        " Best experienced with: \2An IRC client\2",
        NULL
index fce99f421ae2f39bf066cb87aa72b0f4ea7c5206..69aa2619ccc6f9a00c600dde581b5f3718fd2807 100644 (file)
@@ -367,12 +367,7 @@ InspIRCd::InspIRCd(int argc, char** argv) :
        }
 
        std::cout << con_green << "InspIRCd - Internet Relay Chat Daemon" << con_reset << ", compiled on " __DATE__ " at " __TIME__ << std::endl;
-       std::cout << con_green << "(C) InspIRCd Development Team." << con_reset << std::endl << std::endl;
-       std::cout << "Developers:" << std::endl;
-       std::cout << con_green << "\tBrain, FrostyCoolSlug, w00t, Om, Special, peavey" << std::endl;
-       std::cout << "\taquanight, psychon, dz, danieldg, jackmcbarn" << std::endl;
-       std::cout << "\tAttila" << con_reset << std::endl << std::endl;
-       std::cout << "Others:\t\t\t" << con_green << "See /INFO Output" << con_reset << std::endl;
+       std::cout << "For contributors & authors: " << con_green << "See /INFO Output" << con_reset << std::endl;
 
 #ifndef _WIN32
        if (!do_root)
@@ -664,10 +659,7 @@ void InspIRCd::Run()
                        OLDTIME = TIME.tv_sec;
 
                        if ((TIME.tv_sec % 3600) == 0)
-                       {
-                               Users->GarbageCollect();
                                FOREACH_MOD(OnGarbageCollect, ());
-                       }
 
                        Timers.TickTimers(TIME.tv_sec);
                        Users->DoBackgroundUserStuff();
index 962e80d28120797d02878aad80e018fcbb006c6a..716a736f87868f3304adfc7b79a8f697673fe5d2 100644 (file)
@@ -209,14 +209,6 @@ namespace GnuTLS
                        return dh;
                }
 
-               /** Generate */
-               static std::auto_ptr<DHParams> Generate(unsigned int bits)
-               {
-                       std::auto_ptr<DHParams> dh(new DHParams);
-                       ThrowOnError(gnutls_dh_params_generate2(dh->dh_params, bits), "Unable to generate DH params");
-                       return dh;
-               }
-
                ~DHParams()
                {
                        gnutls_dh_params_deinit(dh_params);
@@ -353,6 +345,40 @@ namespace GnuTLS
                {
                        gnutls_priority_set(sess, priority);
                }
+
+               static const char* GetDefault()
+               {
+                       return "NORMAL:%SERVER_PRECEDENCE:-VERS-SSL3.0";
+               }
+
+               static std::string RemoveUnknownTokens(const std::string& prio)
+               {
+                       std::string ret;
+                       irc::sepstream ss(prio, ':');
+                       for (std::string token; ss.GetToken(token); )
+                       {
+                               // Save current position so we can revert later if needed
+                               const std::string::size_type prevpos = ret.length();
+                               // Append next token
+                               if (!ret.empty())
+                                       ret.push_back(':');
+                               ret.append(token);
+
+                               gnutls_priority_t test;
+                               if (gnutls_priority_init(&test, ret.c_str(), NULL) < 0)
+                               {
+                                       // The new token broke the priority string, revert to the previously working one
+                                       ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Priority string token not recognized: \"%s\"", token.c_str());
+                                       ret.erase(prevpos);
+                               }
+                               else
+                               {
+                                       // Worked
+                                       gnutls_priority_deinit(test);
+                               }
+                       }
+                       return ret;
+               }
        };
 #else
        /** Dummy class, used when gnutls_priority_set() is not available
@@ -362,7 +388,7 @@ namespace GnuTLS
         public:
                Priority(const std::string& priorities)
                {
-                       if (priorities != "NORMAL")
+                       if (priorities != GetDefault())
                                throw Exception("You've set a non-default priority string, but GnuTLS lacks support for it");
                }
 
@@ -371,6 +397,17 @@ namespace GnuTLS
                        // Always set the default priorities
                        gnutls_set_default_priority(sess);
                }
+
+               static const char* GetDefault()
+               {
+                       return "NORMAL";
+               }
+
+               static std::string RemoveUnknownTokens(const std::string& prio)
+               {
+                       // We don't do anything here because only NORMAL is accepted
+                       return prio;
+               }
        };
 #endif
 
@@ -564,24 +601,40 @@ namespace GnuTLS
                        return ret;
                }
 
+               static std::string GetPrioStr(const std::string& profilename, ConfigTag* tag)
+               {
+                       // Use default priority string if this tag does not specify one
+                       std::string priostr = GnuTLS::Priority::GetDefault();
+                       bool found = tag->readString("priority", priostr);
+                       // If the prio string isn't set in the config don't be strict about the default one because it doesn't work on all versions of GnuTLS
+                       if (!tag->getBool("strictpriority", found))
+                       {
+                               std::string stripped = GnuTLS::Priority::RemoveUnknownTokens(priostr);
+                               if (stripped.empty())
+                               {
+                                       // Stripping failed, act as if a prio string wasn't set
+                                       stripped = GnuTLS::Priority::RemoveUnknownTokens(GnuTLS::Priority::GetDefault());
+                                       ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Priority string for profile \"%s\" contains unknown tokens and stripping it didn't yield a working one either, falling back to \"%s\"", profilename.c_str(), stripped.c_str());
+                               }
+                               else if ((found) && (stripped != priostr))
+                               {
+                                       // Prio string was set in the config and we ended up with something that works but different
+                                       ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Priority string for profile \"%s\" contains unknown tokens, stripped to \"%s\"", profilename.c_str(), stripped.c_str());
+                               }
+                               priostr.swap(stripped);
+                       }
+                       return priostr;
+               }
+
         public:
                static reference<Profile> Create(const std::string& profilename, ConfigTag* tag)
                {
                        std::string certstr = ReadFile(tag->getString("certfile", "cert.pem"));
                        std::string keystr = ReadFile(tag->getString("keyfile", "key.pem"));
 
-                       std::auto_ptr<DHParams> dh;
-                       int gendh = tag->getInt("gendh");
-                       if (gendh)
-                       {
-                               gendh = (gendh < 1024 ? 1024 : gendh);
-                               dh = DHParams::Generate(gendh);
-                       }
-                       else
-                               dh = DHParams::Import(ReadFile(tag->getString("dhfile", "dhparams.pem")));
+                       std::auto_ptr<DHParams> dh = DHParams::Import(ReadFile(tag->getString("dhfile", "dhparams.pem")));
 
-                       // Use default priority string if this tag does not specify one
-                       std::string priostr = tag->getString("priority", "NORMAL");
+                       std::string priostr = GetPrioStr(profilename, tag);
                        unsigned int mindh = tag->getInt("mindhbits", 1024);
                        std::string hashstr = tag->getString("hash", "md5");
 
index 7dd834e130e3fc6c9fcb404a38ff8d7575a8b9ad..c9ae14e11bad0b31547494d3b19cd9d3a052d199 100644 (file)
@@ -269,10 +269,10 @@ namespace OpenSSL
                        long setoptions = tag->getInt(ctxname + "setoptions");
                        long clearoptions = tag->getInt(ctxname + "clearoptions");
 #ifdef SSL_OP_NO_COMPRESSION
-                       if (!tag->getBool("compression", true))
+                       if (!tag->getBool("compression", false)) // Disable compression by default
                                setoptions |= SSL_OP_NO_COMPRESSION;
 #endif
-                       if (!tag->getBool("sslv3", true))
+                       if (!tag->getBool("sslv3", false)) // Disable SSLv3 by default
                                setoptions |= SSL_OP_NO_SSLv3;
                        if (!tag->getBool("tlsv1", true))
                                setoptions |= SSL_OP_NO_TLSv1;
@@ -363,6 +363,14 @@ namespace OpenSSL
                        return 1;
                }
 
+               static int destroy(BIO* bio)
+               {
+                       // XXX: Dummy function to avoid a memory leak in OpenSSL.
+                       // The memory leak happens in BIO_free() (bio_lib.c) when the destroy func of the BIO is NULL.
+                       // This is fixed in OpenSSL but some distros still ship the unpatched version hence we provide this workaround.
+                       return 1;
+               }
+
                static long ctrl(BIO* bio, int cmd, long num, void* ptr)
                {
                        if (cmd == BIO_CTRL_FLUSH)
@@ -385,7 +393,7 @@ static BIO_METHOD biomethods =
        NULL, // gets
        OpenSSL::BIOMethod::ctrl,
        OpenSSL::BIOMethod::create,
-       NULL, // destroy, NULL causes older OpenSSL to leak memory in BIO_free() (bio_lib.c)
+       OpenSSL::BIOMethod::destroy, // destroy, does nothing, see function body for more info
        NULL // callback_ctrl
 };
 
index e8a0abbf15800d1f6871483a2ad80e55c07a28b4..d4def647347e9e3fa0fbf4366cc85390661afa54 100644 (file)
@@ -29,8 +29,8 @@ class ModuleHostCycle : public Module
                // GetFullHost() returns the original data at the time this function is called
                const std::string quitline = ":" + user->GetFullHost() + " QUIT :" + quitmsg;
 
-               already_sent_t silent_id = ++LocalUser::already_sent_id;
-               already_sent_t seen_id = ++LocalUser::already_sent_id;
+               already_sent_t silent_id = ServerInstance->Users.NextAlreadySentId();
+               already_sent_t seen_id = ServerInstance->Users.NextAlreadySentId();
 
                IncludeChanList include_chans(user->chans.begin(), user->chans.end());
                std::map<User*,bool> exceptions;
index 69f4b3bca7c1bf876f880eeddf0c58572f056791..8bf1d30792f01a9a136d3caa3abc96f5581dc3de 100644 (file)
@@ -25,6 +25,7 @@
 
 
 #include "inspircd.h"
+#include "modules/invite.h"
 
 class ModuleOverride : public Module
 {
@@ -34,6 +35,7 @@ class ModuleOverride : public Module
        ChanModeReference inviteonly;
        ChanModeReference key;
        ChanModeReference limit;
+       Invite::API invapi;
 
        static bool IsOverride(unsigned int userlevel, const Modes::ChangeList::List& list)
        {
@@ -67,6 +69,7 @@ class ModuleOverride : public Module
                , inviteonly(this, "inviteonly")
                , key(this, "key")
                , limit(this, "limit")
+               , invapi(this)
        {
        }
 
@@ -177,7 +180,7 @@ class ModuleOverride : public Module
                        {
                                if (chan->IsModeSet(inviteonly) && (CanOverride(user,"INVITE")))
                                {
-                                       if (!user->IsInvited(chan))
+                                       if (!invapi->IsInvited(user, chan))
                                                return HandleJoinOverride(user, chan, keygiven, "invite-only", "+i");
                                        return MOD_RES_ALLOW;
                                }
index 687bf305e2c3b0380e5df78def76941bb7682f6b..0879e730a0551616533178ebfab4ce0ff798fc8b 100644 (file)
@@ -272,9 +272,6 @@ void CommandFJoin::LowerTS(Channel* chan, time_t TS, const std::string& newname)
        chan->name = newname;
        chan->age = TS;
 
-       // Remove all pending invites
-       chan->ClearInvites();
-
        // Clear all modes
        CommandFJoin::RemoveStatus(chan);
 
index 97ad841f12e37e09f4c2ae6619f5adb5387ed527..e92688d1ddfff17171c06c64b2ce5d54f8ad25c3 100644 (file)
 
 
 #include "inspircd.h"
+#include "modules/invite.h"
 
 /** Handle /UNINVITE
  */
 class CommandUninvite : public Command
 {
+       Invite::API invapi;
  public:
-       CommandUninvite(Module* Creator) : Command(Creator,"UNINVITE", 2)
+       CommandUninvite(Module* Creator)
+               : Command(Creator, "UNINVITE", 2)
+               , invapi(Creator)
        {
                syntax = "<nick> <channel>";
                TRANSLATE2(TR_NICK, TR_TEXT);
@@ -73,7 +77,7 @@ class CommandUninvite : public Command
                LocalUser* lu = IS_LOCAL(u);
                if (lu)
                {
-                       if (!lu->RemoveInvite(c))
+                       if (!invapi->Remove(lu, c))
                        {
                                user->SendText(":%s 505 %s %s %s :Is not invited to channel %s", user->server->GetName().c_str(), user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
                                return CMD_FAILURE;
index 7e92507ca77b5844f3db08f8b5cb1ffa1e5eb9d2..ba6bbf36bb8e6a96bd1a2a3c6bd82211df21bf9d 100644 (file)
@@ -49,7 +49,8 @@ namespace
 }
 
 UserManager::UserManager()
-       : unregistered_count(0)
+       : already_sent_id(0)
+       , unregistered_count(0)
 {
 }
 
@@ -278,17 +279,6 @@ void UserManager::ServerNoticeAll(const char* text, ...)
        }
 }
 
-void UserManager::GarbageCollect()
-{
-       // Reset the already_sent IDs so we don't wrap it around and drop a message
-       LocalUser::already_sent_id = 0;
-       for (LocalList::const_iterator i = local_users.begin(); i != local_users.end(); ++i)
-       {
-               (**i).already_sent = 0;
-               (**i).RemoveExpiredInvites();
-       }
-}
-
 /* this returns true when all modules are satisfied that the user should be allowed onto the irc server
  * (until this returns true, a user will block in the waiting state, waiting to connect up to the
  * registration timeout maximum seconds)
@@ -371,3 +361,18 @@ void UserManager::DoBackgroundUserStuff()
                }
        }
 }
+
+already_sent_t UserManager::NextAlreadySentId()
+{
+       if (++already_sent_id == 0)
+       {
+               // Wrapped around, reset the already_sent ids of all users
+               already_sent_id = 1;
+               for (LocalList::iterator i = local_users.begin(); i != local_users.end(); ++i)
+               {
+                       LocalUser* user = *i;
+                       user->already_sent = 0;
+               }
+       }
+       return already_sent_id;
+}
index d760c713f30803be77e026a8aab06b0c56c8a861..93fd8d06568b169f9e84138f09297a055bc92923 100644 (file)
@@ -26,8 +26,6 @@
 #include "inspircd.h"
 #include "xline.h"
 
-already_sent_t LocalUser::already_sent_id = 0;
-
 bool User::IsNoticeMaskSet(unsigned char sm)
 {
        if (!isalpha(sm))
@@ -139,28 +137,6 @@ const std::string& User::GetFullRealHost()
        return this->cached_fullrealhost;
 }
 
-InviteList& LocalUser::GetInviteList()
-{
-       RemoveExpiredInvites();
-       return invites;
-}
-
-bool LocalUser::RemoveInvite(Channel* chan)
-{
-       Invitation* inv = Invitation::Find(chan, this);
-       if (inv)
-       {
-               delete inv;
-               return true;
-       }
-       return false;
-}
-
-void LocalUser::RemoveExpiredInvites()
-{
-       Invitation::Find(NULL, this);
-}
-
 bool User::HasModePermission(unsigned char, ModeType)
 {
        return true;
@@ -328,7 +304,6 @@ CullResult User::cull()
 
 CullResult LocalUser::cull()
 {
-       ClearInvites();
        eh.cull();
        return User::cull();
 }
@@ -896,7 +871,7 @@ void User::ForEachNeighbor(ForEachNeighborHandler& handler, bool include_self)
        FOREACH_MOD(OnBuildNeighborList, (this, include_chans, exceptions));
 
        // Get next id, guaranteed to differ from the already_sent field of all users
-       const already_sent_t newid = ++LocalUser::already_sent_id;
+       const already_sent_t newid = ServerInstance->Users.NextAlreadySentId();
 
        // Handle exceptions first
        for (std::map<User*, bool>::const_iterator i = exceptions.begin(); i != exceptions.end(); ++i)