]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/coremods/core_whowas.cpp
Move OnStats from the core to a cross-module event.
[user/henk/code/inspircd.git] / src / coremods / core_whowas.cpp
index d73fdf491bae833100a7ab53315a3fffe3cfbcb3..689340a8d79d84469aa13353b32eaa90bba096fa 100644 (file)
 
 #include "inspircd.h"
 #include "commands/cmd_whowas.h"
+#include "modules/stats.h"
+
+enum
+{
+       // From RFC 1459.
+       RPL_WHOWASUSER = 314,
+       RPL_ENDOFWHOWAS = 369,
+
+       // InspIRCd-specific.
+       RPL_WHOWASIP = 652
+};
 
 CommandWhowas::CommandWhowas( Module* parent)
        : Command(parent, "WHOWAS", 1)
@@ -35,39 +46,34 @@ CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, Use
        /* if whowas disabled in config */
        if (!manager.IsEnabled())
        {
-               user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :This command has been disabled.", name.c_str());
+               user->WriteNumeric(ERR_UNKNOWNCOMMAND, name, "This command has been disabled.");
                return CMD_FAILURE;
        }
 
        const WhoWas::Nick* const nick = manager.FindNick(parameters[0]);
        if (!nick)
        {
-               user->WriteNumeric(ERR_WASNOSUCHNICK, "%s :There was no such nickname", parameters[0].c_str());
+               user->WriteNumeric(ERR_WASNOSUCHNICK, parameters[0], "There was no such nickname");
        }
        else
        {
                const WhoWas::Nick::List& list = nick->entries;
-               if (!list.empty())
+               for (WhoWas::Nick::List::const_iterator i = list.begin(); i != list.end(); ++i)
                {
-                       for (WhoWas::Nick::List::const_iterator i = list.begin(); i != list.end(); ++i)
-                       {
-                               WhoWas::Entry* u = *i;
+                       WhoWas::Entry* u = *i;
 
-                               user->WriteNumeric(RPL_WHOWASUSER, "%s %s %s * :%s", parameters[0].c_str(),
-                                       u->ident.c_str(),u->dhost.c_str(),u->gecos.c_str());
+                       user->WriteNumeric(RPL_WHOWASUSER, parameters[0], u->ident, u->dhost, '*', u->gecos);
 
-                               if (user->HasPrivPermission("users/auspex"))
-                                       user->WriteNumeric(RPL_WHOWASIP, "%s :was connecting from *@%s",
-                                               parameters[0].c_str(), u->host.c_str());
+                       if (user->HasPrivPermission("users/auspex"))
+                               user->WriteNumeric(RPL_WHOWASIP, parameters[0], InspIRCd::Format("was connecting from *@%s", u->host.c_str()));
 
-                               std::string signon = InspIRCd::TimeString(u->signon);
-                               bool hide_server = (!ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"));
-                               user->WriteNumeric(RPL_WHOISSERVER, "%s %s :%s", parameters[0].c_str(), (hide_server ? ServerInstance->Config->HideWhoisServer.c_str() : u->server.c_str()), signon.c_str());
-                       }
+                       std::string signon = InspIRCd::TimeString(u->signon);
+                       bool hide_server = (!ServerInstance->Config->HideServer.empty() && !user->HasPrivPermission("servers/auspex"));
+                       user->WriteNumeric(RPL_WHOISSERVER, parameters[0], (hide_server ? ServerInstance->Config->HideServer : u->server), signon);
                }
        }
 
-       user->WriteNumeric(RPL_ENDOFWHOWAS, "%s :End of WHOWAS", parameters[0].c_str());
+       user->WriteNumeric(RPL_ENDOFWHOWAS, parameters[0], "End of WHOWAS");
        return CMD_SUCCESS;
 }
 
@@ -81,11 +87,7 @@ const WhoWas::Nick* WhoWas::Manager::FindNick(const std::string& nickname) const
        whowas_users::const_iterator it = whowas.find(nickname);
        if (it == whowas.end())
                return NULL;
-
-       const Nick* nick = it->second;
-       if (nick->entries.empty())
-               return NULL;
-       return nick;
+       return it->second;
 }
 
 WhoWas::Manager::Stats WhoWas::Manager::GetStats() const
@@ -124,10 +126,7 @@ void WhoWas::Manager::Add(User* user)
                if (whowas.size() > this->MaxGroups)
                {
                        // Too many nicks, remove the nick which was inserted the longest time ago from both the map and the fifo
-                       nick = whowas_fifo.front();
-                       whowas_fifo.pop_front();
-                       whowas.erase(nick->nick);
-                       delete nick;
+                       PurgeNick(whowas_fifo.front());
                }
        }
        else
@@ -155,24 +154,13 @@ void WhoWas::Manager::Prune()
        {
                WhoWas::Nick* nick = whowas_fifo.front();
                if ((whowas_fifo.size() > this->MaxGroups) || (nick->addtime < min))
-               {
-                       /* hopefully redundant integrity check, but added while debugging r6216 */
-                       if (!whowas.erase(nick->nick))
-                       {
-                               /* this should never happen, if it does maps are corrupt */
-                               ServerInstance->Logs->Log("WHOWAS", LOG_DEFAULT, "BUG: Whowas maps got corrupted! (1)");
-                               return;
-                       }
-
-                       whowas_fifo.pop_front();
-                       delete nick;
-               }
+                       PurgeNick(nick);
                else
                        break;
        }
 
        /* Then cut the whowas sets to new size (groupsize) */
-       for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i)
+       for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); )
        {
                WhoWas::Nick::List& list = i->second->entries;
                while (list.size() > this->GroupSize)
@@ -180,6 +168,11 @@ void WhoWas::Manager::Prune()
                        delete list.front();
                        list.pop_front();
                }
+
+               if (list.empty())
+                       PurgeNick(i++);
+               else
+                       ++i;
        }
 }
 
@@ -187,7 +180,7 @@ void WhoWas::Manager::Prune()
 void WhoWas::Manager::Maintain()
 {
        time_t min = ServerInstance->Time() - this->MaxKeep;
-       for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); ++i)
+       for (whowas_users::iterator i = whowas.begin(); i != whowas.end(); )
        {
                WhoWas::Nick::List& list = i->second->entries;
                while (!list.empty() && list.front()->signon < min)
@@ -195,6 +188,11 @@ void WhoWas::Manager::Maintain()
                        delete list.front();
                        list.pop_front();
                }
+
+               if (list.empty())
+                       PurgeNick(i++);
+               else
+                       ++i;
        }
 }
 
@@ -223,9 +221,28 @@ void WhoWas::Manager::UpdateConfig(unsigned int NewGroupSize, unsigned int NewMa
        Prune();
 }
 
+void WhoWas::Manager::PurgeNick(whowas_users::iterator it)
+{
+       WhoWas::Nick* nick = it->second;
+       whowas_fifo.erase(nick);
+       whowas.erase(it);
+       delete nick;
+}
+
+void WhoWas::Manager::PurgeNick(WhoWas::Nick* nick)
+{
+       whowas_users::iterator it = whowas.find(nick->nick);
+       if (it == whowas.end())
+       {
+               ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "ERROR: Inconsistency detected in whowas database, please report");
+               return;
+       }
+       PurgeNick(it);
+}
+
 WhoWas::Entry::Entry(User* user)
-       : host(user->host)
-       , dhost(user->dhost)
+       : host(user->GetRealHost())
+       , dhost(user->GetDisplayedHost())
        , ident(user->ident)
        , server(user->server->GetName())
        , gecos(user->fullname)
@@ -244,30 +261,32 @@ WhoWas::Nick::~Nick()
        stdalgo::delete_all(entries);
 }
 
-class ModuleWhoWas : public Module
+class ModuleWhoWas : public Module, public Stats::EventListener
 {
        CommandWhowas cmd;
 
  public:
-       ModuleWhoWas() : cmd(this)
+       ModuleWhoWas()
+               : Stats::EventListener(this)
+               , cmd(this)
        {
        }
 
-       void OnGarbageCollect()
+       void OnGarbageCollect() CXX11_OVERRIDE
        {
                // Remove all entries older than MaxKeep
                cmd.manager.Maintain();
        }
 
-       void OnUserQuit(User* user, const std::string& message, const std::string& oper_message)
+       void OnUserQuit(User* user, const std::string& message, const std::string& oper_message) CXX11_OVERRIDE
        {
                cmd.manager.Add(user);
        }
 
-       ModResult OnStats(char symbol, User* user, string_list &results)
+       ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE
        {
-               if (symbol == 'z')
-                       results.push_back("249 "+user->nick+" :Whowas entries: "+ConvToStr(cmd.manager.GetStats().entrycount));
+               if (stats.GetSymbol() == 'z')
+                       stats.AddRow(249, "Whowas entries: "+ConvToStr(cmd.manager.GetStats().entrycount));
 
                return MOD_RES_PASSTHRU;
        }
@@ -282,7 +301,7 @@ class ModuleWhoWas : public Module
                cmd.manager.UpdateConfig(NewGroupSize, NewMaxGroups, NewMaxKeep);
        }
 
-       Version GetVersion()
+       Version GetVersion() CXX11_OVERRIDE
        {
                return Version("WHOWAS", VF_VENDOR);
        }