mirror of
https://github.com/znc/znc.git
synced 2026-05-18 15:25:53 +02:00
+293
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2011 See the AUTHORS file for details.
|
||||
* Copyright (C) 2006-2007, CNU <bshalm@broadpark.no> (http://cnu.dieplz.net/znc)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "FileUtils.h"
|
||||
#include "User.h"
|
||||
#include "IRCNetwork.h"
|
||||
#include "Chan.h"
|
||||
#include "Server.h"
|
||||
|
||||
class CLogMod: public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CLogMod) {}
|
||||
|
||||
void PutLog(const CString& sLine, const CString& sWindow = "status");
|
||||
void PutLog(const CString& sLine, const CChan& Channel);
|
||||
void PutLog(const CString& sLine, const CNick& Nick);
|
||||
CString GetServer();
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sMessage);
|
||||
virtual void OnIRCConnected();
|
||||
virtual void OnIRCDisconnected();
|
||||
virtual EModRet OnBroadcast(CString& sMessage);
|
||||
|
||||
virtual void OnRawMode(const CNick& OpNick, CChan& Channel, const CString& sModes, const CString& sArgs);
|
||||
virtual void OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage);
|
||||
virtual void OnQuit(const CNick& Nick, const CString& sMessage, const vector<CChan*>& vChans);
|
||||
virtual void OnJoin(const CNick& Nick, CChan& Channel);
|
||||
virtual void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage);
|
||||
virtual void OnNick(const CNick& OldNick, const CString& sNewNick, const vector<CChan*>& vChans);
|
||||
virtual EModRet OnTopic(CNick& Nick, CChan& Channel, CString& sTopic);
|
||||
|
||||
/* notices */
|
||||
virtual EModRet OnUserNotice(CString& sTarget, CString& sMessage);
|
||||
virtual EModRet OnPrivNotice(CNick& Nick, CString& sMessage);
|
||||
virtual EModRet OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage);
|
||||
|
||||
/* actions */
|
||||
virtual EModRet OnUserAction(CString& sTarget, CString& sMessage);
|
||||
virtual EModRet OnPrivAction(CNick& Nick, CString& sMessage);
|
||||
virtual EModRet OnChanAction(CNick& Nick, CChan& Channel, CString& sMessage);
|
||||
|
||||
/* msgs */
|
||||
virtual EModRet OnUserMsg(CString& sTarget, CString& sMessage);
|
||||
virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage);
|
||||
virtual EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage);
|
||||
|
||||
private:
|
||||
CString m_sLogPath;
|
||||
};
|
||||
|
||||
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 (which is in hours and we want seconds)
|
||||
curtime += (time_t) (m_pUser->GetTimezoneOffset() * 60 * 60);
|
||||
timeinfo = localtime(&curtime);
|
||||
|
||||
// Generate file name
|
||||
if (!strftime(buffer, sizeof(buffer), m_sLogPath.c_str(), timeinfo))
|
||||
{
|
||||
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"));
|
||||
sPath.Replace("$WINDOW", sWindow.Replace_n("/", "?"));
|
||||
sPath.Replace("$USER", (m_pUser ? m_pUser->GetUserName() : "UNKNOWN"));
|
||||
|
||||
// Check if it's allowed to write in this specific path
|
||||
sPath = CDir::CheckPathPrefix(GetSavePath(), sPath);
|
||||
if (sPath.empty())
|
||||
{
|
||||
DEBUG("Invalid log path ["<<m_sLogPath<<"].");
|
||||
return;
|
||||
}
|
||||
|
||||
CFile LogFile(sPath);
|
||||
CString sLogDir = LogFile.GetDir();
|
||||
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");
|
||||
} else
|
||||
DEBUG("Could not open log file [" << sPath << "]: " << strerror(errno));
|
||||
}
|
||||
|
||||
void CLogMod::PutLog(const CString& sLine, const CChan& Channel)
|
||||
{
|
||||
PutLog(sLine, Channel.GetName());
|
||||
}
|
||||
|
||||
void CLogMod::PutLog(const CString& sLine, const CNick& Nick)
|
||||
{
|
||||
PutLog(sLine, Nick.GetNick());
|
||||
}
|
||||
|
||||
CString CLogMod::GetServer()
|
||||
{
|
||||
CServer* pServer = m_pNetwork->GetCurrentServer();
|
||||
CString sSSL;
|
||||
|
||||
if (!pServer)
|
||||
return "(no server)";
|
||||
|
||||
if (pServer->IsSSL())
|
||||
sSSL = "+";
|
||||
return pServer->GetName() + " " + sSSL + CString(pServer->GetPort());
|
||||
}
|
||||
|
||||
bool CLogMod::OnLoad(const CString& sArgs, CString& sMessage)
|
||||
{
|
||||
// Use load parameter as save path
|
||||
m_sLogPath = sArgs;
|
||||
|
||||
// Add default filename to path if it's a folder
|
||||
if (GetType() == CModInfo::UserModule) {
|
||||
if (m_sLogPath.Right(1) == "/" || m_sLogPath.find("$WINDOW") == string::npos || m_sLogPath.find("$NETWORK") == string::npos) {
|
||||
if (!m_sLogPath.empty()) {
|
||||
m_sLogPath += "/";
|
||||
}
|
||||
m_sLogPath += "$NETWORK_$WINDOW_%Y%m%d.log";
|
||||
}
|
||||
} else if (GetType() == CModInfo::NetworkModule) {
|
||||
if (m_sLogPath.Right(1) == "/" || m_sLogPath.find("$WINDOW") == string::npos) {
|
||||
if (!m_sLogPath.empty()) {
|
||||
m_sLogPath += "/";
|
||||
}
|
||||
m_sLogPath += "$WINDOW_%Y%m%d.log";
|
||||
}
|
||||
} else {
|
||||
if (m_sLogPath.Right(1) == "/" || m_sLogPath.find("$USER") == string::npos || m_sLogPath.find("$WINDOW") == string::npos || m_sLogPath.find("$NETWORK") == string::npos) {
|
||||
if (!m_sLogPath.empty()) {
|
||||
m_sLogPath += "/";
|
||||
}
|
||||
m_sLogPath += "$USER_$NETWORK_$WINDOW_%Y%m%d.log";
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it's allowed to write in this path in general
|
||||
m_sLogPath = CDir::CheckPathPrefix(GetSavePath(), m_sLogPath);
|
||||
if (m_sLogPath.empty())
|
||||
{
|
||||
sMessage = "Invalid log path ["+m_sLogPath+"].";
|
||||
return false;
|
||||
} else {
|
||||
sMessage = "Logging to ["+m_sLogPath+"].";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CLogMod::OnIRCConnected()
|
||||
{
|
||||
PutLog("Connected to IRC (" + GetServer() + ")");
|
||||
}
|
||||
|
||||
void CLogMod::OnIRCDisconnected()
|
||||
{
|
||||
PutLog("Disconnected from IRC (" + GetServer() + ")");
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnBroadcast(CString& sMessage)
|
||||
{
|
||||
PutLog("Broadcast: " + sMessage);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
void CLogMod::OnRawMode(const CNick& OpNick, CChan& Channel, const CString& sModes, const CString& sArgs)
|
||||
{
|
||||
PutLog("*** " + OpNick.GetNick() + " sets mode: " + sModes + " " + sArgs, Channel);
|
||||
}
|
||||
|
||||
void CLogMod::OnKick(const CNick& OpNick, const CString& sKickedNick, CChan& Channel, const CString& sMessage)
|
||||
{
|
||||
PutLog("*** " + sKickedNick + " was kicked by " + OpNick.GetNick() + " (" + sMessage + ")", Channel);
|
||||
}
|
||||
|
||||
void CLogMod::OnQuit(const CNick& Nick, const CString& sMessage, const vector<CChan*>& vChans)
|
||||
{
|
||||
for (std::vector<CChan*>::const_iterator pChan = vChans.begin(); pChan != vChans.end(); ++pChan)
|
||||
PutLog("*** Quits: " + Nick.GetNick() + " (" + Nick.GetIdent() + "@" + Nick.GetHost() + ") (" + sMessage + ")", **pChan);
|
||||
}
|
||||
|
||||
void CLogMod::OnJoin(const CNick& Nick, CChan& Channel)
|
||||
{
|
||||
PutLog("*** Joins: " + Nick.GetNick() + " (" + Nick.GetIdent() + "@" + Nick.GetHost() + ")", Channel);
|
||||
}
|
||||
|
||||
void CLogMod::OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage)
|
||||
{
|
||||
PutLog("*** Parts: " + Nick.GetNick() + " (" + Nick.GetIdent() + "@" + Nick.GetHost() + ") (" + sMessage + ")", Channel);
|
||||
}
|
||||
|
||||
void CLogMod::OnNick(const CNick& OldNick, const CString& sNewNick, const vector<CChan*>& vChans)
|
||||
{
|
||||
for (std::vector<CChan*>::const_iterator pChan = vChans.begin(); pChan != vChans.end(); ++pChan)
|
||||
PutLog("*** " + OldNick.GetNick() + " is now known as " + sNewNick, **pChan);
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnTopic(CNick& Nick, CChan& Channel, CString& sTopic)
|
||||
{
|
||||
PutLog("*** " + Nick.GetNick() + " changes topic to '" + sTopic + "'", Channel);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
/* notices */
|
||||
CModule::EModRet CLogMod::OnUserNotice(CString& sTarget, CString& sMessage)
|
||||
{
|
||||
if (m_pNetwork) {
|
||||
PutLog("-" + m_pNetwork->GetCurNick() + "- " + sMessage, sTarget);
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnPrivNotice(CNick& Nick, CString& sMessage)
|
||||
{
|
||||
PutLog("-" + Nick.GetNick() + "- " + sMessage, Nick);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnChanNotice(CNick& Nick, CChan& Channel, CString& sMessage)
|
||||
{
|
||||
PutLog("-" + Nick.GetNick() + "- " + sMessage, Channel);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
/* actions */
|
||||
CModule::EModRet CLogMod::OnUserAction(CString& sTarget, CString& sMessage)
|
||||
{
|
||||
if (m_pNetwork) {
|
||||
PutLog("* " + m_pNetwork->GetCurNick() + " " + sMessage, sTarget);
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnPrivAction(CNick& Nick, CString& sMessage)
|
||||
{
|
||||
PutLog("* " + Nick.GetNick() + " " + sMessage, Nick);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnChanAction(CNick& Nick, CChan& Channel, CString& sMessage)
|
||||
{
|
||||
PutLog("* " + Nick.GetNick() + " " + sMessage, Channel);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
/* msgs */
|
||||
CModule::EModRet CLogMod::OnUserMsg(CString& sTarget, CString& sMessage)
|
||||
{
|
||||
if (m_pNetwork) {
|
||||
PutLog("<" + m_pNetwork->GetCurNick() + "> " + sMessage, sTarget);
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnPrivMsg(CNick& Nick, CString& sMessage)
|
||||
{
|
||||
PutLog("<" + Nick.GetNick() + "> " + sMessage, Nick);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
CModule::EModRet CLogMod::OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage)
|
||||
{
|
||||
PutLog("<" + Nick.GetNick() + "> " + sMessage, Channel);
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
template<> void TModInfo<CLogMod>(CModInfo& Info) {
|
||||
Info.AddType(CModInfo::NetworkModule);
|
||||
Info.AddType(CModInfo::GlobalModule);
|
||||
}
|
||||
|
||||
MODULEDEFS(CLogMod, "Write IRC logs")
|
||||
Reference in New Issue
Block a user