diff --git a/include/znc/WebModules.h b/include/znc/WebModules.h index a60c88f9..c445b4e4 100644 --- a/include/znc/WebModules.h +++ b/include/znc/WebModules.h @@ -49,8 +49,10 @@ public: const CString& GetId() const { return m_sId; } const CString& GetIP() const { return m_sIP; } CUser* GetUser() const { return m_pUser; } + time_t GetLastActive() const { return m_tmLastActive; } bool IsLoggedIn() const { return m_pUser != NULL; } bool IsAdmin() const; + void UpdateLastActive(); CUser* SetUser(CUser* p) { m_pUser = p; return m_pUser; } @@ -64,6 +66,7 @@ private: CUser* m_pUser; VCString m_vsErrorMsgs; VCString m_vsSuccessMsgs; + time_t m_tmLastActive; }; diff --git a/src/WebModules.cpp b/src/WebModules.cpp index 3f000f71..cf0aa484 100644 --- a/src/WebModules.cpp +++ b/src/WebModules.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include using std::pair; @@ -97,6 +98,11 @@ bool CZNCTagHandler::HandleTag(CTemplate& Tmpl, const CString& sName, const CStr CWebSession::CWebSession(const CString& sId, const CString& sIP) : m_sId(sId), m_sIP(sIP) { m_pUser = NULL; Sessions.m_mIPSessions.insert(make_pair(sIP, this)); + UpdateLastActive(); +} + +void CWebSession::UpdateLastActive() { + time(&m_tmLastActive); } bool CWebSession::IsAdmin() const { return IsLoggedIn() && m_pUser->IsAdmin(); } @@ -807,6 +813,10 @@ void CWebSock::PrintErrorPage(const CString& sMessage) { m_Template["Error"] = sMessage; } +static inline bool compareLastActive(const std::pair &first, const std::pair &second) { + return first.second->GetLastActive() < second.second->GetLastActive(); +} + CSmartPtr CWebSock::GetSession() { if (!m_spSession.IsNull()) { return m_spSession; @@ -818,13 +828,16 @@ CSmartPtr CWebSock::GetSession() { if (pSession != NULL) { // Refresh the timeout Sessions.m_mspSessions.AddItem((*pSession)->GetId(), *pSession); + (*pSession)->UpdateLastActive(); m_spSession = *pSession; DEBUG("Found existing session from cookie: [" + sCookieSessionId + "] IsLoggedIn(" + CString((*pSession)->IsLoggedIn() ? "true" : "false") + ")"); return *pSession; } if (Sessions.m_mIPSessions.count(GetRemoteIP()) > m_uiMaxSessions) { - mIPSessionsIterator it = Sessions.m_mIPSessions.find(GetRemoteIP()); + pair p = + Sessions.m_mIPSessions.equal_range(GetRemoteIP()); + mIPSessionsIterator it = std::min_element(p.first, p.second, compareLastActive); DEBUG("Remote IP: " << GetRemoteIP() << "; discarding session [" << it->second->GetId() << "]"); Sessions.m_mspSessions.RemItem(it->second->GetId()); }