X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_httpd_stats.cpp;h=2b28c262802ff4f28c4973d87df0b7b21e745828;hb=d4a1ea70451abb333e71f9cff09b624db59531a0;hp=4b18eadc44803ca07dbd02e53f02741e3d72546d;hpb=e84858dc7f1efdfb76efc1e115e6999fd222af74;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_httpd_stats.cpp b/src/modules/m_httpd_stats.cpp index 4b18eadc4..2b28c2628 100644 --- a/src/modules/m_httpd_stats.cpp +++ b/src/modules/m_httpd_stats.cpp @@ -99,7 +99,7 @@ namespace Stats { return data << "" << ServerInstance->Config->ServerName << "" << Sanitize(ServerInstance->Config->ServerDesc) << "" - << Sanitize(ServerInstance->GetVersionString()) << ""; + << Sanitize(ServerInstance->GetVersionString(true)) << ""; } std::ostream& ISupport(std::ostream& data) @@ -124,6 +124,7 @@ namespace Stats data << "" << ServerInstance->Users->all_opers.size() << ""; data << "" << (SocketEngine::GetUsedFds()) << "" << SocketEngine::GetMaxFds() << ""; data << "" << ServerInstance->startup_time << ""; + data << "" << ServerInstance->Time() << ""; data << ISupport; return data << ""; @@ -201,6 +202,37 @@ namespace Stats return data << ""; } + std::ostream& DumpUser(std::ostream& data, User* u) + { + data << ""; + data << "" << u->nick << "" << u->uuid << "" + << u->GetRealHost() << "" << u->GetDisplayedHost() << "" + << Sanitize(u->GetRealName()) << "" << u->server->GetName() << "" + << u->signon << "" << u->age << ""; + + if (u->IsAway()) + data << "" << Sanitize(u->awaymsg) << "" << u->awaytime << ""; + + if (u->IsOper()) + data << "" << Sanitize(u->oper->name) << ""; + + data << "" << u->GetModeLetters().substr(1) << "" << Sanitize(u->ident) << ""; + + LocalUser* lu = IS_LOCAL(u); + if (lu) + data << "" << lu->GetServerPort() << "" + << lu->server_sa.str() << "" + << lu->GetClass()->GetName() << "" + << lu->idle_lastmsg << ""; + + data << "" << u->GetIPString() << ""; + + DumpMeta(data, u); + + data << ""; + return data; + } + std::ostream& Users(std::ostream& data) { data << ""; @@ -209,24 +241,10 @@ namespace Stats { User* u = i->second; - data << ""; - data << "" << u->nick << "" << u->uuid << "" - << u->GetRealHost() << "" << u->GetDisplayedHost() << "" - << Sanitize(u->GetRealName()) << "" << u->server->GetName() << ""; - if (u->IsAway()) - data << "" << Sanitize(u->awaymsg) << "" << u->awaytime << ""; - if (u->IsOper()) - data << "" << Sanitize(u->oper->name) << ""; - data << "" << u->GetModeLetters().substr(1) << "" << Sanitize(u->ident) << ""; - LocalUser* lu = IS_LOCAL(u); - if (lu) - data << "" << lu->GetServerPort() << "" - << lu->server_sa.str() << ""; - data << "" << u->GetIPString() << ""; - - DumpMeta(data, u); + if (u->registered != REG_ALL) + continue; - data << ""; + DumpUser(data, u); } return data << ""; } @@ -265,28 +283,145 @@ namespace Stats } return data << ""; } + + enum OrderBy + { + OB_NICK, + OB_LASTMSG, + + OB_NONE + }; + + struct UserSorter + { + OrderBy order; + bool desc; + + UserSorter(OrderBy Order, bool Desc = false) : order(Order), desc(Desc) {} + + template + inline bool Compare(const T& a, const T& b) + { + return desc ? a > b : a < b; + } + + bool operator()(User* u1, User* u2) + { + switch (order) { + case OB_LASTMSG: + return Compare(IS_LOCAL(u1)->idle_lastmsg, IS_LOCAL(u2)->idle_lastmsg); + break; + case OB_NICK: + return Compare(u1->nick, u2->nick); + break; + default: + case OB_NONE: + return false; + break; + } + } + }; + + std::ostream& ListUsers(std::ostream& data, const HTTPQueryParameters& params) + { + if (params.empty()) + return Users(data); + + data << ""; + + // Filters + size_t limit = params.getNum("limit"); + bool showunreg = params.getBool("showunreg"); + bool localonly = params.getBool("localonly"); + + // Minimum time since a user's last message + unsigned long min_idle = params.getDuration("minidle"); + time_t maxlastmsg = ServerInstance->Time() - min_idle; + + if (min_idle) + // We can only check idle times on local users + localonly = true; + + // Sorting + const std::string& sortmethod = params.getString("sortby"); + bool desc = params.getBool("desc", false); + + OrderBy orderby; + if (stdalgo::string::equalsci(sortmethod, "nick")) + orderby = OB_NICK; + else if (stdalgo::string::equalsci(sortmethod, "lastmsg")) + { + orderby = OB_LASTMSG; + // We can only check idle times on local users + localonly = true; + } + else + orderby = OB_NONE; + + typedef std::list NewUserList; + NewUserList user_list; + user_hash users = ServerInstance->Users->GetUsers(); + for (user_hash::iterator i = users.begin(); i != users.end(); ++i) + { + User* u = i->second; + if (!showunreg && u->registered != REG_ALL) + continue; + + LocalUser* lu = IS_LOCAL(u); + if (localonly && !lu) + continue; + + if (min_idle && lu->idle_lastmsg > maxlastmsg) + continue; + + user_list.push_back(u); + } + + UserSorter sorter(orderby, desc); + if (sorter.order != OB_NONE && !(!localonly && sorter.order == OB_LASTMSG)) + user_list.sort(sorter); + + size_t count = 0; + for (NewUserList::const_iterator i = user_list.begin(); i != user_list.end() && (!limit || count < limit); ++i, ++count) + DumpUser(data, *i); + + data << ""; + return data; + } } class ModuleHttpStats : public Module, public HTTPRequestEventListener { HTTPdAPI API; + bool enableparams; public: ModuleHttpStats() : HTTPRequestEventListener(this) , API(this) + , enableparams(false) { } + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE + { + ConfigTag* conf = ServerInstance->Config->ConfValue("httpstats"); + + // Parameterized queries may cause a performance issue + // Due to the sheer volume of data + // So default them to disabled + enableparams = conf->getBool("enableparams"); + } + ModResult HandleRequest(HTTPRequest* http) { - std::string uri = http->GetURI(); + std::string path = http->GetPath(); - if (uri != "/stats" && uri.substr(0, 7) != "/stats/") + if (path != "/stats" && path.substr(0, 7) != "/stats/") return MOD_RES_PASSTHRU; - if (uri[uri.size() - 1] == '/') - uri.erase(uri.size() - 1, 1); + if (path[path.size() - 1] == '/') + path.erase(path.size() - 1, 1); ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Handling httpd event"); @@ -294,20 +429,23 @@ class ModuleHttpStats : public Module, public HTTPRequestEventListener std::stringstream data; data << ""; - if (uri == "/stats") + if (path == "/stats") { data << Stats::ServerInfo << Stats::General << Stats::XLines << Stats::Modules << Stats::Channels << Stats::Users << Stats::Servers << Stats::Commands; } - else if (uri == "/stats/general") + else if (path == "/stats/general") { data << Stats::General; } - else if (uri == "/stats/users") + else if (path == "/stats/users") { - data << Stats::Users; + if (enableparams) + Stats::ListUsers(data, http->GetParsedURI().query_params); + else + data << Stats::Users; } else {