diff --git a/include/znc/Utils.h b/include/znc/Utils.h index 88a88ab6..e37dbff6 100644 --- a/include/znc/Utils.h +++ b/include/znc/Utils.h @@ -73,6 +73,9 @@ public: static void GenerateCert(FILE *pOut, const CString& sHost = ""); #endif /* HAVE_LIBSSL */ + static CString CTime(time_t t, const CString& sTZ); + static CString FormatTime(time_t t, const CString& sFormat, const CString& sTZ); + private: protected: }; diff --git a/modules/extra/listsockets.cpp b/modules/extra/listsockets.cpp index 625c6ccd..f7c1330f 100644 --- a/modules/extra/listsockets.cpp +++ b/modules/extra/listsockets.cpp @@ -155,7 +155,7 @@ public: CString GetCreatedTime(Csock* pSocket) { unsigned long long iStartTime = pSocket->GetStartTime(); time_t iTime = iStartTime / 1000; - return FormatTime("%Y-%m-%d %H:%M:%S", iTime); + return CUtils::FormatTime(iTime, "%Y-%m-%d %H:%M:%S", m_pUser->GetTimezone()); } CString GetLocalHost(Csock* pSocket, bool bShowHosts) { @@ -241,19 +241,6 @@ public: virtual ~CListSockets() { } - CString FormatTime(const CString& sFormat, time_t tm = 0) const { - char szTimestamp[1024]; - - if (tm == 0) { - tm = time(NULL); - } - - setenv("TZ", m_pUser->GetTimezone().c_str(), 1); - strftime(szTimestamp, sizeof(szTimestamp) / sizeof(char), - sFormat.c_str(), localtime(&tm)); - - return szTimestamp; - } }; MODULEDEFS(CListSockets, "List active sockets") diff --git a/modules/log.cpp b/modules/log.cpp index 73061484..793002d7 100644 --- a/modules/log.cpp +++ b/modules/log.cpp @@ -58,21 +58,15 @@ void CLogMod::PutLog(const CString& sLine, const CString& sWindow /*= "Status"*/ { CString sPath; time_t curtime; - tm* timeinfo; - char buffer[1024]; time(&curtime); - // Don't forget the user's timezone offset - setenv("TZ", m_pUser->GetTimezone().c_str(), 1); - timeinfo = localtime(&curtime); - // Generate file name - if (!strftime(buffer, sizeof(buffer), m_sLogPath.c_str(), timeinfo)) + sPath = CUtils::FormatTime(curtime, m_sLogPath, m_pUser->GetTimezone()); + if (sPath.empty()) { DEBUG("Could not format log path [" << sPath << "]"); return; } - sPath = buffer; // $WINDOW has to be handled last, since it can contain % sPath.Replace("$NETWORK", (m_pNetwork ? m_pNetwork->GetName() : "znc")); @@ -92,10 +86,7 @@ void CLogMod::PutLog(const CString& sLine, const CString& sWindow /*= "Status"*/ if (!CFile::Exists(sLogDir)) CDir::MakeDir(sLogDir); if (LogFile.Open(O_WRONLY | O_APPEND | O_CREAT)) { - snprintf(buffer, sizeof(buffer), "[%02d:%02d:%02d] ", - timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); - - LogFile.Write(buffer + sLine + "\n"); + LogFile.Write(CUtils::FormatTime(curtime, "[%H:%M:%S] ", m_pUser->GetTimezone()) + sLine + "\n"); } else DEBUG("Could not open log file [" << sPath << "]: " << strerror(errno)); } diff --git a/modules/simple_away.cpp b/modules/simple_away.cpp index a49447fc..a55048be 100644 --- a/modules/simple_away.cpp +++ b/modules/simple_away.cpp @@ -189,9 +189,7 @@ private: sReason = SIMPLE_AWAY_DEFAULT_REASON; time_t iTime = time(NULL); - setenv("TZ", m_pUser->GetTimezone().c_str(), 1); - CString sTime = ctime(&iTime); - sTime.Trim(); + CString sTime = CUtils::CTime(iTime, m_pUser->GetTimezone()); sReason.Replace("%s", sTime); return sReason; diff --git a/src/User.cpp b/src/User.cpp index e03460f3..71198a9b 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -61,7 +61,7 @@ CUser::CUser(const CString& sUserName) // set path that depends on the user name: m_sUserPath = CZNC::Get().GetUserPath() + "/" + m_sUserName; - m_sTimezone = "GMT"; + m_sTimezone = ""; m_fTimezoneOffset = 0; m_sNick = m_sCleanUserName; m_sIdent = m_sCleanUserName; @@ -500,16 +500,7 @@ CString CUser::ExpandString(const CString& sStr) const { } CString& CUser::ExpandString(const CString& sStr, CString& sRet) const { - time_t iUserTime = time(NULL); - setenv("TZ", m_sTimezone.c_str(), 1); - char *szTime = ctime(&iUserTime); - CString sTime; - - if (szTime) { - sTime = szTime; - // ctime() adds a trailing newline - sTime.Trim(); - } + CString sTime = CUtils::CTime(time(NULL), m_sTimezone); sRet = sStr; sRet.Replace("%user%", GetUserName()); @@ -537,27 +528,21 @@ CString CUser::AddTimestamp(const CString& sStr) const { } CString& CUser::AddTimestamp(const CString& sStr, CString& sRet) const { - char szTimestamp[1024]; - time_t tm; sRet = sStr; if (!GetTimestampFormat().empty() && (m_bAppendTimestamp || m_bPrependTimestamp)) { - time(&tm); - setenv("TZ", m_sTimezone.c_str(), 1); - size_t i = strftime(szTimestamp, sizeof(szTimestamp), GetTimestampFormat().c_str(), localtime(&tm)); - // If strftime returns 0, an error occured in format, or result is empty - // In both cases just don't prepend/append anything to our string - if (0 == i) { + CString sTimestamp = CUtils::FormatTime(time(NULL), GetTimestampFormat(), m_sTimezone); + if (sTimestamp.empty()) { return sRet; } if (m_bPrependTimestamp) { - sRet = szTimestamp; + sRet = sTimestamp; sRet += " " + sStr; } if (m_bAppendTimestamp) { sRet += " "; - sRet += szTimestamp; + sRet += sTimestamp; } } return sRet; diff --git a/src/Utils.cpp b/src/Utils.cpp index 70610c9c..69aa9d86 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -338,6 +338,60 @@ void CUtils::PrintStatus(bool bSuccess, const CString& sMessage) { fflush(stdout); } +CString CUtils::CTime(time_t t, const CString& sTZ) { + char s[30] = {}; // should have at least 26 bytes + if (sTZ.empty()) { + ctime_r(&t, s); + // ctime() adds a trailing newline + return CString(s).Trim_n(); + } + + // backup old value + char* oldTZ = getenv("TZ"); + if (oldTZ) oldTZ = strdup(oldTZ); + setenv("TZ", sTZ.c_str(), 1); + + ctime_r(&t, s); + + // restore old value + if (oldTZ) { + setenv("TZ", oldTZ, 1); + free(oldTZ); + } else { + unsetenv("TZ"); + } + + return CString(s).Trim_n(); +} + +CString CUtils::FormatTime(time_t t, const CString& sFormat, const CString& sTZ) { + char s[1024] = {}; + tm m; + if (sTZ.empty()) { + localtime_r(&t, &m); + strftime(s, sizeof(s), sFormat.c_str(), &m); + return s; + } + + // backup old value + char* oldTZ = getenv("TZ"); + if (oldTZ) oldTZ = strdup(oldTZ); + setenv("TZ", sTZ.c_str(), 1); + + localtime_r(&t, &m); + strftime(s, sizeof(s), sFormat.c_str(), &m); + + // restore old value + if (oldTZ) { + setenv("TZ", oldTZ, 1); + free(oldTZ); + } else { + unsetenv("TZ"); + } + + return s; +} + bool CTable::AddColumn(const CString& sName) { for (unsigned int a = 0; a < m_vsHeaders.size(); a++) { if (m_vsHeaders[a].Equals(sName)) {