1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2009 InspIRCd Development Team
6 * See: http://wiki.inspircd.org/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
15 #include "commands/cmd_whowas.h"
17 WhoWasMaintainTimer * timer;
19 CommandWhowas::CommandWhowas(InspIRCd* Instance, Module* parent) : Command(Instance,parent, "WHOWAS", 0, 1, false, 2)
21 syntax = "<nick>{,<nick>}";
22 timer = new WhoWasMaintainTimer(Instance, 3600);
23 Instance->Timers->AddTimer(timer);
26 CmdResult CommandWhowas::Handle (const std::vector<std::string>& parameters, User* user)
28 /* if whowas disabled in config */
29 if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
31 user->WriteNumeric(421, "%s %s :This command has been disabled.",user->nick.c_str(),command.c_str());
35 whowas_users::iterator i = whowas.find(assign(parameters[0]));
37 if (i == whowas.end())
39 user->WriteNumeric(406, "%s %s :There was no such nickname",user->nick.c_str(),parameters[0].c_str());
40 user->WriteNumeric(369, "%s %s :End of WHOWAS",user->nick.c_str(),parameters[0].c_str());
45 whowas_set* grp = i->second;
48 for (whowas_set::iterator ux = grp->begin(); ux != grp->end(); ux++)
51 time_t rawtime = u->signon;
55 timeinfo = localtime(&rawtime);
57 strncpy(b,asctime(timeinfo),24);
60 user->WriteNumeric(314, "%s %s %s %s * :%s",user->nick.c_str(),parameters[0].c_str(),
61 u->ident.c_str(),u->dhost.c_str(),u->gecos.c_str());
63 if (user->HasPrivPermission("users/auspex"))
64 user->WriteNumeric(379, "%s %s :was connecting from *@%s",
65 user->nick.c_str(), parameters[0].c_str(), u->host.c_str());
67 if (*ServerInstance->Config->HideWhoisServer && !user->HasPrivPermission("servers/auspex"))
68 user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(),parameters[0].c_str(), ServerInstance->Config->HideWhoisServer, b);
70 user->WriteNumeric(312, "%s %s %s :%s",user->nick.c_str(),parameters[0].c_str(), u->server, b);
75 user->WriteNumeric(406, "%s %s :There was no such nickname",user->nick.c_str(),parameters[0].c_str());
76 user->WriteNumeric(369, "%s %s :End of WHOWAS",user->nick.c_str(),parameters[0].c_str());
81 user->WriteNumeric(369, "%s %s :End of WHOWAS",user->nick.c_str(),parameters[0].c_str());
85 CmdResult CommandWhowas::HandleInternal(const unsigned int id, const std::deque<classbase*> ¶meters)
90 AddToWhoWas(static_cast<User*>(parameters[0]));
94 GetStats(static_cast<Extensible*>(parameters[0]));
98 PruneWhoWas(ServerInstance->Time());
101 case WHOWAS_MAINTAIN:
102 MaintainWhoWas(ServerInstance->Time());
111 void CommandWhowas::GetStats(Extensible* ext)
114 int whowas_bytes = 0;
115 whowas_users_fifo::iterator iter;
116 for (iter = whowas_fifo.begin(); iter != whowas_fifo.end(); iter++)
118 whowas_set* n = (whowas_set*)whowas.find(iter->second)->second;
121 whowas_size += n->size();
122 whowas_bytes += (sizeof(whowas_set) + ( sizeof(WhoWasGroup) * n->size() ) );
125 stats.assign("Whowas(MAPSETS) " +ConvToStr(whowas_size)+" ("+ConvToStr(whowas_bytes)+" bytes)");
126 ext->Extend("stats", stats.c_str());
129 void CommandWhowas::AddToWhoWas(User* user)
131 /* if whowas disabled */
132 if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
137 whowas_users::iterator iter = whowas.find(irc::string(user->nick.c_str()));
139 if (iter == whowas.end())
141 whowas_set* n = new whowas_set;
142 WhoWasGroup *a = new WhoWasGroup(user);
144 whowas[user->nick.c_str()] = n;
145 whowas_fifo.push_back(std::make_pair(ServerInstance->Time(),user->nick.c_str()));
147 if ((int)(whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
149 whowas_users::iterator iter2 = whowas.find(whowas_fifo[0].second);
150 if (iter2 != whowas.end())
152 whowas_set* n2 = (whowas_set*)iter2->second;
156 while (n2->begin() != n2->end())
158 WhoWasGroup *a2 = *(n2->begin());
167 whowas_fifo.pop_front();
172 whowas_set* group = (whowas_set*)iter->second;
173 WhoWasGroup *a = new WhoWasGroup(user);
176 if ((int)(group->size()) > ServerInstance->Config->WhoWasGroupSize)
178 WhoWasGroup *a2 = (WhoWasGroup*)*(group->begin());
185 /* on rehash, refactor maps according to new conf values */
186 void CommandWhowas::PruneWhoWas(time_t t)
189 int groupsize = ServerInstance->Config->WhoWasGroupSize;
190 int maxgroups = ServerInstance->Config->WhoWasMaxGroups;
191 int maxkeep = ServerInstance->Config->WhoWasMaxKeep;
193 /* first cut the list to new size (maxgroups) and also prune entries that are timed out. */
194 whowas_users::iterator iter;
196 while ((fifosize = (int)whowas_fifo.size()) > 0)
198 if (fifosize > maxgroups || whowas_fifo[0].first < t - maxkeep)
200 iter = whowas.find(whowas_fifo[0].second);
202 /* hopefully redundant integrity check, but added while debugging r6216 */
203 if (iter == whowas.end())
205 /* this should never happen, if it does maps are corrupt */
206 ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (1)");
210 whowas_set* n = (whowas_set*)iter->second;
214 while (n->begin() != n->end())
216 WhoWasGroup *a = *(n->begin());
224 whowas_fifo.pop_front();
230 /* Then cut the whowas sets to new size (groupsize) */
231 fifosize = (int)whowas_fifo.size();
232 for (int i = 0; i < fifosize; i++)
234 iter = whowas.find(whowas_fifo[0].second);
235 /* hopefully redundant integrity check, but added while debugging r6216 */
236 if (iter == whowas.end())
238 /* this should never happen, if it does maps are corrupt */
239 ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (2)");
242 whowas_set* n = (whowas_set*)iter->second;
245 int nickcount = n->size();
246 while (n->begin() != n->end() && nickcount > groupsize)
248 WhoWasGroup *a = *(n->begin());
257 /* call maintain once an hour to remove expired nicks */
258 void CommandWhowas::MaintainWhoWas(time_t t)
260 for (whowas_users::iterator iter = whowas.begin(); iter != whowas.end(); iter++)
262 whowas_set* n = (whowas_set*)iter->second;
265 while ((n->begin() != n->end()) && ((*n->begin())->signon < t - ServerInstance->Config->WhoWasMaxKeep))
267 WhoWasGroup *a = *(n->begin());
269 n->erase(n->begin());
275 CommandWhowas::~CommandWhowas()
279 ServerInstance->Timers->DelTimer(timer);
282 whowas_users::iterator iter;
284 while ((fifosize = (int)whowas_fifo.size()) > 0)
286 iter = whowas.find(whowas_fifo[0].second);
288 /* hopefully redundant integrity check, but added while debugging r6216 */
289 if (iter == whowas.end())
291 /* this should never happen, if it does maps are corrupt */
292 ServerInstance->Logs->Log("WHOWAS",DEFAULT, "BUG: Whowas maps got corrupted! (3)");
296 whowas_set* n = (whowas_set*)iter->second;
300 while (n->begin() != n->end())
302 WhoWasGroup *a = *(n->begin());
310 whowas_fifo.pop_front();
314 WhoWasGroup::WhoWasGroup(User* user) : host(user->host), dhost(user->dhost), ident(user->ident),
315 server(user->server), gecos(user->fullname), signon(user->signon)
319 WhoWasGroup::~WhoWasGroup()
323 /* every hour, run this function which removes all entries older than Config->WhoWasMaxKeep */
324 void WhoWasMaintainTimer::Tick(time_t)
326 Command* whowas_command = ServerInstance->Parser->GetHandler("WHOWAS");
329 std::deque<classbase*> params;
330 whowas_command->HandleInternal(WHOWAS_MAINTAIN, params);
334 COMMAND_INIT(CommandWhowas)