mirror of
https://github.com/znc/znc.git
synced 2026-08-08 18:03:22 +02:00
Import most of znc-extra
This imports all modules from znc-extra except modtcl under modules/extra. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1606 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
@@ -22,3 +22,4 @@ Sebastian Ramacher <sebastinas@users.sourceforge.net>
|
||||
cnu - master of destruction (security issues)
|
||||
Ingmar "KiNgMaR" Runge <mail@irsoft.de>
|
||||
Michael "Svedrin" Ziegler <diese-addy@funzt-halt.net>
|
||||
Robert Lacroix (http://www.robertlacroix.com)
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "Nick.h"
|
||||
#include "User.h"
|
||||
|
||||
class CAntiIdle;
|
||||
|
||||
class CAntiIdleJob : public CTimer
|
||||
{
|
||||
public:
|
||||
CAntiIdleJob(CModule* pModule, unsigned int uInterval, unsigned int uCycles, const CString& sLabel, const CString& sDescription)
|
||||
: CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
|
||||
virtual ~CAntiIdleJob() {}
|
||||
|
||||
protected:
|
||||
virtual void RunJob();
|
||||
};
|
||||
|
||||
class CAntiIdle : public CModule
|
||||
{
|
||||
public:
|
||||
MODCONSTRUCTOR(CAntiIdle) {
|
||||
SetInterval(30);
|
||||
}
|
||||
|
||||
virtual ~CAntiIdle() {}
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sErrorMsg)
|
||||
{
|
||||
if(!sArgs.Trim_n().empty())
|
||||
SetInterval(sArgs.ToInt());
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnModCommand( const CString& sCommand )
|
||||
{
|
||||
CString sCmdName = sCommand.Token(0).AsLower();
|
||||
if(sCmdName == "set")
|
||||
{
|
||||
CString sInterval = sCommand.Token(1, true);
|
||||
SetInterval(sInterval.ToInt());
|
||||
|
||||
if(m_uiInterval == 0)
|
||||
PutModule("AntiIdle is now turned off.");
|
||||
else
|
||||
PutModule("AntiIdle is now set to " + CString(m_uiInterval) + " seconds.");
|
||||
} else if(sCmdName == "off") {
|
||||
SetInterval(0);
|
||||
PutModule("AntiIdle is now turned off");
|
||||
} else if(sCmdName == "show") {
|
||||
if(m_uiInterval == 0)
|
||||
PutModule("AntiIdle is turned off.");
|
||||
else
|
||||
PutModule("AntiIdle is set to " + CString(m_uiInterval) + " seconds.");
|
||||
} else {
|
||||
PutModule("Commands: set, off, show");
|
||||
}
|
||||
}
|
||||
|
||||
virtual EModRet OnPrivMsg(CNick &Nick, CString &sMessage)
|
||||
{
|
||||
if(Nick.GetNick() == GetUser()->GetIRCNick().GetNick()
|
||||
&& sMessage == "\xAE")
|
||||
return HALTCORE;
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
private:
|
||||
void SetInterval(int i)
|
||||
{
|
||||
if(i < 0)
|
||||
return;
|
||||
|
||||
m_uiInterval = i;
|
||||
|
||||
RemTimer("AntiIdle");
|
||||
|
||||
if(m_uiInterval == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddTimer(new CAntiIdleJob(this, m_uiInterval, 0, "AntiIdle", "Periodically sends a msg to the user"));
|
||||
}
|
||||
|
||||
unsigned int m_uiInterval;
|
||||
};
|
||||
|
||||
//! This function sends a query with (r) back to the user
|
||||
void CAntiIdleJob::RunJob() {
|
||||
CString sNick = GetModule()->GetUser()->GetIRCNick().GetNick();
|
||||
GetModule()->PutIRC("PRIVMSG " + sNick + " :\xAE");
|
||||
}
|
||||
|
||||
MODULEDEFS(CAntiIdle, "Hides your real idle time")
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "Chan.h"
|
||||
#include "User.h"
|
||||
|
||||
class CAutoVoiceUser {
|
||||
public:
|
||||
CAutoVoiceUser() {}
|
||||
|
||||
CAutoVoiceUser(const CString& sLine) {
|
||||
FromString(sLine);
|
||||
}
|
||||
|
||||
CAutoVoiceUser(const CString& sUsername, const CString& sHostmask, const CString& sChannels) :
|
||||
m_sUsername(sUsername),
|
||||
m_sHostmask(sHostmask) {
|
||||
AddChans(sChannels);
|
||||
}
|
||||
|
||||
virtual ~CAutoVoiceUser() {}
|
||||
|
||||
const CString& GetUsername() const { return m_sUsername; }
|
||||
const CString& GetHostmask() const { return m_sHostmask; }
|
||||
|
||||
bool ChannelMatches(const CString& sChan) const {
|
||||
for (set<CString>::const_iterator it = m_ssChans.begin(); it != m_ssChans.end(); it++) {
|
||||
if (sChan.AsLower().WildCmp(*it)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HostMatches(const CString& sHostmask) {
|
||||
return sHostmask.WildCmp(m_sHostmask);
|
||||
}
|
||||
|
||||
CString GetChannels() const {
|
||||
CString sRet;
|
||||
|
||||
for (set<CString>::const_iterator it = m_ssChans.begin(); it != m_ssChans.end(); it++) {
|
||||
if (!sRet.empty()) {
|
||||
sRet += " ";
|
||||
}
|
||||
|
||||
sRet += *it;
|
||||
}
|
||||
|
||||
return sRet;
|
||||
}
|
||||
|
||||
void DelChans(const CString& sChans) {
|
||||
VCString vsChans;
|
||||
sChans.Split(" ", vsChans);
|
||||
|
||||
for (unsigned int a = 0; a < vsChans.size(); a++) {
|
||||
m_ssChans.erase(vsChans[a].AsLower());
|
||||
}
|
||||
}
|
||||
|
||||
void AddChans(const CString& sChans) {
|
||||
VCString vsChans;
|
||||
sChans.Split(" ", vsChans);
|
||||
|
||||
for (unsigned int a = 0; a < vsChans.size(); a++) {
|
||||
m_ssChans.insert(vsChans[a].AsLower());
|
||||
}
|
||||
}
|
||||
|
||||
CString ToString() const {
|
||||
CString sChans;
|
||||
|
||||
for (set<CString>::const_iterator it = m_ssChans.begin(); it != m_ssChans.end(); it++) {
|
||||
if (!sChans.empty()) {
|
||||
sChans += " ";
|
||||
}
|
||||
|
||||
sChans += *it;
|
||||
}
|
||||
|
||||
return m_sUsername + "\t" + m_sHostmask + "\t" + sChans;
|
||||
}
|
||||
|
||||
bool FromString(const CString& sLine) {
|
||||
m_sUsername = sLine.Token(0, false, "\t");
|
||||
m_sHostmask = sLine.Token(1, false, "\t");
|
||||
sLine.Token(2, false, "\t").Split(" ", m_ssChans);
|
||||
|
||||
return !m_sHostmask.empty();
|
||||
}
|
||||
private:
|
||||
protected:
|
||||
CString m_sUsername;
|
||||
CString m_sHostmask;
|
||||
set<CString> m_ssChans;
|
||||
};
|
||||
|
||||
class CAutoVoiceMod : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CAutoVoiceMod) {}
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
|
||||
// Load the chans from the command line
|
||||
unsigned int a = 0;
|
||||
CString sChan = sArgs.Token(a++);
|
||||
|
||||
while (!sChan.empty()) {
|
||||
CString sName = "Args";
|
||||
sName += CString(a);
|
||||
AddUser(sName, "*", sChan);
|
||||
|
||||
sChan = sArgs.Token(a++);
|
||||
}
|
||||
|
||||
// Load the saved users
|
||||
for (MCString::iterator it = BeginNV(); it != EndNV(); it++) {
|
||||
const CString& sLine = it->second;
|
||||
CAutoVoiceUser* pUser = new CAutoVoiceUser;
|
||||
|
||||
if (!pUser->FromString(sLine) || FindUser(pUser->GetUsername().AsLower())) {
|
||||
delete pUser;
|
||||
} else {
|
||||
m_msUsers[pUser->GetUsername().AsLower()] = pUser;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~CAutoVoiceMod() {
|
||||
for (map<CString, CAutoVoiceUser*>::iterator it = m_msUsers.begin(); it != m_msUsers.end(); it++) {
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
m_msUsers.clear();
|
||||
}
|
||||
|
||||
virtual void OnJoin(const CNick& Nick, CChan& Channel) {
|
||||
// If we have ops in this chan
|
||||
if (Channel.HasPerm(CChan::Op) || Channel.HasPerm(CChan::HalfOp)) {
|
||||
for (map<CString, CAutoVoiceUser*>::iterator it = m_msUsers.begin(); it != m_msUsers.end(); it++) {
|
||||
// and the nick who joined is a valid user
|
||||
if (it->second->HostMatches(Nick.GetHostMask()) && it->second->ChannelMatches(Channel.GetName())) {
|
||||
PutIRC("MODE " + Channel.GetName() + " +v " + Nick.GetNick());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnModCommand(const CString& sLine) {
|
||||
CString sCommand = sLine.Token(0).AsUpper();
|
||||
|
||||
if (sCommand.Equals("HELP")) {
|
||||
PutModule("Commands are: ListUsers, AddChans, DelChans, AddUser, DelUser");
|
||||
} else if (sCommand.Equals("ADDUSER") || sCommand.Equals("DELUSER")) {
|
||||
CString sUser = sLine.Token(1);
|
||||
CString sHost = sLine.Token(2);
|
||||
|
||||
if (sCommand.Equals("ADDUSER")) {
|
||||
if (sHost.empty()) {
|
||||
PutModule("Usage: " + sCommand + " <user> <hostmask> [channels]");
|
||||
} else {
|
||||
CAutoVoiceUser* pUser = AddUser(sUser, sHost, sLine.Token(3, true));
|
||||
|
||||
if (pUser) {
|
||||
SetNV(sUser, pUser->ToString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DelUser(sUser);
|
||||
DelNV(sUser);
|
||||
}
|
||||
} else if (sCommand.Equals("LISTUSERS")) {
|
||||
if (m_msUsers.empty()) {
|
||||
PutModule("There are no users defined");
|
||||
return;
|
||||
}
|
||||
|
||||
CTable Table;
|
||||
|
||||
Table.AddColumn("User");
|
||||
Table.AddColumn("Hostmask");
|
||||
Table.AddColumn("Channels");
|
||||
|
||||
for (map<CString, CAutoVoiceUser*>::iterator it = m_msUsers.begin(); it != m_msUsers.end(); it++) {
|
||||
Table.AddRow();
|
||||
Table.SetCell("User", it->second->GetUsername());
|
||||
Table.SetCell("Hostmask", it->second->GetHostmask());
|
||||
Table.SetCell("Channels", it->second->GetChannels());
|
||||
}
|
||||
|
||||
PutModule(Table);
|
||||
} else if (sCommand.Equals("ADDCHANS") || sCommand.Equals("DELCHANS")) {
|
||||
CString sUser = sLine.Token(1);
|
||||
CString sChans = sLine.Token(2, true);
|
||||
|
||||
if (sChans.empty()) {
|
||||
PutModule("Usage: " + sCommand + " <user> <channel> [channel] ...");
|
||||
return;
|
||||
}
|
||||
|
||||
CAutoVoiceUser* pUser = FindUser(sUser);
|
||||
|
||||
if (!pUser) {
|
||||
PutModule("No such user");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sCommand.Equals("ADDCHANS")) {
|
||||
pUser->AddChans(sChans);
|
||||
PutModule("Channel(s) added to user [" + pUser->GetUsername() + "]");
|
||||
} else {
|
||||
pUser->DelChans(sChans);
|
||||
PutModule("Channel(s) Removed from user [" + pUser->GetUsername() + "]");
|
||||
}
|
||||
|
||||
SetNV(pUser->GetUsername(), pUser->ToString());
|
||||
} else {
|
||||
PutModule("Unknown command, try HELP");
|
||||
}
|
||||
}
|
||||
|
||||
CAutoVoiceUser* FindUser(const CString& sUser) {
|
||||
map<CString, CAutoVoiceUser*>::iterator it = m_msUsers.find(sUser.AsLower());
|
||||
|
||||
return (it != m_msUsers.end()) ? it->second : NULL;
|
||||
}
|
||||
|
||||
CAutoVoiceUser* FindUserByHost(const CString& sHostmask, const CString& sChannel = "") {
|
||||
for (map<CString, CAutoVoiceUser*>::iterator it = m_msUsers.begin(); it != m_msUsers.end(); it++) {
|
||||
CAutoVoiceUser* pUser = it->second;
|
||||
|
||||
if (pUser->HostMatches(sHostmask) && (sChannel.empty() || pUser->ChannelMatches(sChannel))) {
|
||||
return pUser;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DelUser(const CString& sUser) {
|
||||
map<CString, CAutoVoiceUser*>::iterator it = m_msUsers.find(sUser.AsLower());
|
||||
|
||||
if (it == m_msUsers.end()) {
|
||||
PutModule("That user does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
delete it->second;
|
||||
m_msUsers.erase(it);
|
||||
PutModule("User [" + sUser + "] removed");
|
||||
}
|
||||
|
||||
CAutoVoiceUser* AddUser(const CString& sUser, const CString& sHost, const CString& sChans) {
|
||||
if (m_msUsers.find(sUser) != m_msUsers.end()) {
|
||||
PutModule("That user already exists");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CAutoVoiceUser* pUser = new CAutoVoiceUser(sUser, sHost, sChans);
|
||||
m_msUsers[sUser.AsLower()] = pUser;
|
||||
PutModule("User [" + sUser + "] added with hostmask [" + sHost + "]");
|
||||
return pUser;
|
||||
}
|
||||
|
||||
private:
|
||||
map<CString, CAutoVoiceUser*> m_msUsers;
|
||||
};
|
||||
|
||||
MODULEDEFS(CAutoVoiceMod, "Auto voice the good guys")
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "User.h"
|
||||
#include "IRCSock.h"
|
||||
#include "znc.h"
|
||||
|
||||
#define MESSAGE "Your account has been disabled. Contact your administrator."
|
||||
|
||||
class CBlockUser : public CGlobalModule {
|
||||
public:
|
||||
GLOBALMODCONSTRUCTOR(CBlockUser) {}
|
||||
|
||||
virtual ~CBlockUser() {}
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
|
||||
VCString vArgs;
|
||||
VCString::iterator it;
|
||||
MCString::iterator it2;
|
||||
|
||||
// Load saved settings
|
||||
for (it2 = BeginNV(); it2 != EndNV(); it2++) {
|
||||
// Ignore errors
|
||||
Block(it2->first);
|
||||
}
|
||||
|
||||
// Parse arguments, each argument is a user name to block
|
||||
sArgs.Split(" ", vArgs, false);
|
||||
|
||||
for (it = vArgs.begin(); it != vArgs.end(); it++) {
|
||||
if (!Block(*it)) {
|
||||
sMessage = "Could not block [" + *it + "]";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual EModRet OnLoginAttempt(CSmartPtr<CAuthBase> Auth) {
|
||||
if (IsBlocked(Auth->GetUsername())) {
|
||||
Auth->RefuseLogin(MESSAGE);
|
||||
return HALT;
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
void OnModCommand(const CString& sCommand) {
|
||||
CString sCmd = sCommand.Token(0);
|
||||
|
||||
if (sCmd.Equals("list")) {
|
||||
CTable Table;
|
||||
MCString::iterator it;
|
||||
|
||||
Table.AddColumn("Blocked user");
|
||||
|
||||
for (it = BeginNV(); it != EndNV(); it++) {
|
||||
Table.AddRow();
|
||||
Table.SetCell("Blocked user", it->first);
|
||||
}
|
||||
|
||||
if (PutModule(Table) == 0)
|
||||
PutModule("No users blocked");
|
||||
} else if (sCmd.Equals("block")) {
|
||||
CString sUser = sCommand.Token(1, true);
|
||||
|
||||
if (m_pUser->GetUserName().Equals(sUser)) {
|
||||
PutModule("You can't block yourself");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Block(sUser))
|
||||
PutModule("Blocked [" + sUser + "]");
|
||||
else
|
||||
PutModule("Could not block [" + sUser + "] (misspelled?)");
|
||||
} else if (sCmd.Equals("unblock")) {
|
||||
CString sUser = sCommand.Token(1, true);
|
||||
|
||||
if (DelNV(sUser))
|
||||
PutModule("Unblocked [" + sUser + "]");
|
||||
else
|
||||
PutModule("This user is not blocked");
|
||||
} else if (sCmd.Equals("help")) {
|
||||
PutModule("Commands: list, block [user], unblock [user]");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsBlocked(const CString& sUser) {
|
||||
MCString::iterator it;
|
||||
for (it = BeginNV(); it != EndNV(); it++) {
|
||||
if (sUser.Equals(it->first)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Block(const CString& sUser) {
|
||||
CUser *pUser = CZNC::Get().FindUser(sUser);
|
||||
|
||||
if (!pUser)
|
||||
return false;
|
||||
|
||||
// Disconnect all clients
|
||||
vector<CClient*>& vpClients = pUser->GetClients();
|
||||
vector<CClient*>::iterator it;
|
||||
for (it = vpClients.begin(); it != vpClients.end(); it++) {
|
||||
(*it)->PutStatusNotice(MESSAGE);
|
||||
(*it)->Close(Csock::CLT_AFTERWRITE);
|
||||
}
|
||||
|
||||
// Disconnect from IRC...
|
||||
CIRCSock *pIRCSock = pUser->GetIRCSock();
|
||||
if (pIRCSock) {
|
||||
pIRCSock->Quit();
|
||||
}
|
||||
|
||||
// ...and don't reconnect
|
||||
pUser->SetIRCConnectEnabled(false);
|
||||
|
||||
SetNV(pUser->GetUserName(), "");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
GLOBALMODULEDEFS(CBlockUser, "Block certain users from logging in")
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "main.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
#include "znc.h"
|
||||
|
||||
class CConnectThrottleMod : public CGlobalModule {
|
||||
public:
|
||||
GLOBALMODCONSTRUCTOR(CConnectThrottleMod) {}
|
||||
virtual ~CConnectThrottleMod() {}
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sMessage)
|
||||
{
|
||||
unsigned int timeout = sArgs.ToUInt();
|
||||
|
||||
if (sArgs.empty()) {
|
||||
timeout = 60; // 1 min
|
||||
} else if (timeout == 0 && sArgs != "0") {
|
||||
sMessage = "Invalid argument, must be a positive number "
|
||||
"which is the time one has to wait after failed login attempts";
|
||||
return false;
|
||||
}
|
||||
|
||||
// SetTTL() wants milliseconds
|
||||
m_Cache.SetTTL(timeout * 1000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnClientConnect(CClient* pClient, const CString& sHost, unsigned short uPort) {
|
||||
if (sHost.empty() || !m_Cache.HasItem(sHost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// refresh their ban
|
||||
m_Cache.AddItem(sHost);
|
||||
|
||||
pClient->PutClient("ERROR :Closing link [Please try again later - reconnecting too fast]");
|
||||
pClient->Close(Csock::CLT_AFTERWRITE);
|
||||
}
|
||||
|
||||
virtual void OnFailedLogin(const CString& sUsername, const CString& sRemoteIP) {
|
||||
m_Cache.AddItem(sRemoteIP);
|
||||
}
|
||||
|
||||
virtual EModRet OnLoginAttempt(CSmartPtr<CAuthBase> Auth) {
|
||||
// e.g. webadmin ends up here
|
||||
const CString &sRemoteIP = Auth->GetRemoteIP();
|
||||
|
||||
if (sRemoteIP.empty())
|
||||
return CONTINUE;
|
||||
|
||||
if (m_Cache.HasItem(sRemoteIP)) {
|
||||
// refresh their ban
|
||||
m_Cache.AddItem(sRemoteIP);
|
||||
|
||||
Auth->RefuseLogin("Please try again later - reconnecting too fast");
|
||||
return HALT;
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
private:
|
||||
TCacheMap<CString> m_Cache;
|
||||
};
|
||||
|
||||
GLOBALMODULEDEFS(CConnectThrottleMod, "Limit the number of login attempts a user can make per time")
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "Modules.h"
|
||||
#include "Chan.h"
|
||||
|
||||
class CCtcpFloodMod : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CCtcpFloodMod) {
|
||||
m_tLastCTCP = 0;
|
||||
m_iNumCTCP = 0;
|
||||
}
|
||||
|
||||
~CCtcpFloodMod() {
|
||||
}
|
||||
|
||||
void Save() {
|
||||
// We save the settings twice because the module arguments can
|
||||
// be more easily edited via webadmin, while the SetNV() stuff
|
||||
// survives e.g. /msg *status reloadmod ctcpflood.
|
||||
SetNV("secs", CString(m_iThresholdSecs));
|
||||
SetNV("msgs", CString(m_iThresholdMsgs));
|
||||
|
||||
SetArgs(CString(m_iThresholdMsgs) + " " + CString(m_iThresholdSecs));
|
||||
}
|
||||
|
||||
bool OnLoad(const CString& sArgs, CString& sMessage) {
|
||||
m_iThresholdMsgs = sArgs.Token(0).ToUInt();
|
||||
m_iThresholdSecs = sArgs.Token(1).ToUInt();
|
||||
|
||||
if (m_iThresholdMsgs == 0 || m_iThresholdSecs == 0) {
|
||||
m_iThresholdMsgs = GetNV("msgs").ToUInt();
|
||||
m_iThresholdSecs = GetNV("secs").ToUInt();
|
||||
}
|
||||
|
||||
if (m_iThresholdSecs == 0)
|
||||
m_iThresholdSecs = 2;
|
||||
if (m_iThresholdMsgs == 0)
|
||||
m_iThresholdMsgs = 4;
|
||||
|
||||
Save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EModRet Message(const CNick& Nick, const CString& sMessage) {
|
||||
// We never block /me, because it doesn't cause a reply
|
||||
if (sMessage.Token(0).Equals("ACTION"))
|
||||
return CONTINUE;
|
||||
|
||||
if (m_tLastCTCP + m_iThresholdSecs < time(NULL)) {
|
||||
m_tLastCTCP = time(NULL);
|
||||
m_iNumCTCP = 0;
|
||||
}
|
||||
|
||||
m_iNumCTCP++;
|
||||
|
||||
if (m_iNumCTCP < m_iThresholdMsgs)
|
||||
return CONTINUE;
|
||||
else if (m_iNumCTCP == m_iThresholdMsgs)
|
||||
PutModule("Limit reached by [" + Nick.GetHostMask() + "], blocking all CTCP");
|
||||
|
||||
// Reset the timeout so that we continue blocking messages
|
||||
m_tLastCTCP = time(NULL);
|
||||
|
||||
return HALT;
|
||||
}
|
||||
|
||||
EModRet OnPrivCTCP(CNick& Nick, CString& sMessage) {
|
||||
return Message(Nick, sMessage);
|
||||
}
|
||||
|
||||
EModRet OnChanCTCP(CNick& Nick, CChan& Channel, CString& sMessage) {
|
||||
return Message(Nick, sMessage);
|
||||
}
|
||||
|
||||
void OnModCommand(const CString& sCommand) {
|
||||
const CString& sCmd = sCommand.Token(0);
|
||||
const CString& sArg = sCommand.Token(1, true);
|
||||
|
||||
if (sCmd.Equals("secs") && !sArg.empty()) {
|
||||
m_iThresholdSecs = sArg.ToUInt();
|
||||
if (m_iThresholdSecs == 0)
|
||||
m_iThresholdSecs = 1;
|
||||
|
||||
PutModule("Set seconds limit to [" + CString(m_iThresholdSecs) + "]");
|
||||
Save();
|
||||
} else if (sCmd.Equals("lines") && !sArg.empty()) {
|
||||
m_iThresholdMsgs = sArg.ToUInt();
|
||||
if (m_iThresholdMsgs == 0)
|
||||
m_iThresholdMsgs = 2;
|
||||
|
||||
PutModule("Set lines limit to [" + CString(m_iThresholdMsgs) + "]");
|
||||
Save();
|
||||
} else if (sCmd.Equals("show")) {
|
||||
PutModule("Current limit is " + CString(m_iThresholdMsgs) + " CTCPs "
|
||||
"in " + CString(m_iThresholdSecs) + " secs");
|
||||
} else {
|
||||
PutModule("Commands: show, secs [limit], lines [limit]");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
time_t m_tLastCTCP;
|
||||
unsigned int m_iNumCTCP;
|
||||
|
||||
time_t m_iThresholdSecs;
|
||||
unsigned int m_iThresholdMsgs;
|
||||
};
|
||||
|
||||
MODULEDEFS(CCtcpFloodMod, "Don't forward CTCP floods to clients")
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "Modules.h"
|
||||
#include "User.h"
|
||||
#include "Chan.h"
|
||||
|
||||
class CKickClientOnIRCDisconnect: public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CKickClientOnIRCDisconnect) {}
|
||||
|
||||
void OnIRCDisconnected()
|
||||
{
|
||||
const vector<CChan*>& vChans = m_pUser->GetChans();
|
||||
|
||||
for(vector<CChan*>::const_iterator it = vChans.begin(); it != vChans.end(); it++)
|
||||
{
|
||||
PutUser(":ZNC!znc@znc.in KICK " + (*it)->GetName() + " " + m_pUser->GetIRCNick().GetNick()
|
||||
+ " :You have been disconnected from the IRC server");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULEDEFS(CKickClientOnIRCDisconnect, "Kicks the client from all channels when the connection to the IRC server is lost")
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* droproot.cpp
|
||||
*
|
||||
* Copyright (c) 2009 Vadtec (vadtec@vadtec.net)
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2004-2008 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "znc.h"
|
||||
#include "User.h"
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
class CDroproot : public CGlobalModule {
|
||||
|
||||
public:
|
||||
GLOBALMODCONSTRUCTOR(CDroproot) {
|
||||
}
|
||||
|
||||
virtual ~CDroproot() {
|
||||
}
|
||||
|
||||
uid_t GetUser(const CString& sUser, CString& sMessage) {
|
||||
uid_t ret = sUser.ToUInt();
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
struct passwd *pUser = getpwnam(sUser.c_str());
|
||||
|
||||
if (!pUser) {
|
||||
sMessage = "User [" + sUser + "] not found!";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pUser->pw_uid;
|
||||
}
|
||||
|
||||
gid_t GetGroup(const CString& sGroup, CString& sMessage) {
|
||||
gid_t ret = sGroup.ToUInt();
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
struct group *pGroup = getgrnam(sGroup.c_str());
|
||||
|
||||
if (!pGroup) {
|
||||
sMessage = "Group [" + sGroup + "] not found!";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pGroup->gr_gid;
|
||||
}
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
|
||||
CString sUser = sArgs.Token(0);
|
||||
CString sGroup = sArgs.Token(1, true);
|
||||
|
||||
if (sUser.empty() || sGroup.empty()) {
|
||||
sMessage = "Usage: LoadModule = Droproot <uid> <gid>";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_user = GetUser(sUser, sMessage);
|
||||
|
||||
if (m_user == 0) {
|
||||
sMessage
|
||||
= "Error: Cannot run as root, check your config file | Useage: LoadModule = Droproot <uid> <gid>";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_group = GetGroup(sGroup, sMessage);
|
||||
|
||||
if (m_group == 0) {
|
||||
sMessage
|
||||
= "Error: Cannot run as root, check your config file | Useage: LoadModule = Droproot <uid> <gid>";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool OnBoot() {
|
||||
int u, eu, g, eg, sg;
|
||||
|
||||
if ((geteuid() == 0) || (getuid() == 0) || (getegid() == 0) || (getgid()
|
||||
== 0)) {
|
||||
|
||||
CUtils::PrintAction("Dropping root permissions");
|
||||
|
||||
// Clear all the supplementary groups
|
||||
sg = setgroups(0, NULL);
|
||||
|
||||
if (sg < 0) {
|
||||
CUtils::PrintStatus(false,
|
||||
"Could not remove supplementary groups! ["
|
||||
+ CString(strerror(errno)) + "]");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the group (if we are root, this sets all three group IDs)
|
||||
g = setgid(m_group);
|
||||
eg = setegid(m_group);
|
||||
|
||||
if ((g < 0) || (eg < 0)) {
|
||||
CUtils::PrintStatus(false, "Could not switch group id! ["
|
||||
+ CString(strerror(errno)) + "]");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// and set the user (if we are root, this sets all three user IDs)
|
||||
u = setuid(m_user);
|
||||
eu = seteuid(m_user);
|
||||
|
||||
if ((u < 0) || (eu < 0)) {
|
||||
CUtils::PrintStatus(false, "Could not switch user id! ["
|
||||
+ CString(strerror(errno)) + "]");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CUtils::PrintStatus(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
uid_t m_user;
|
||||
gid_t m_group;
|
||||
};
|
||||
|
||||
GLOBALMODULEDEFS(CDroproot, "Allows ZNC to drop root privileges and run as an un-privileged user.")
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "User.h"
|
||||
#include "znc.h"
|
||||
|
||||
class CFOModule : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CFOModule) {}
|
||||
virtual ~CFOModule() {}
|
||||
|
||||
bool IsOnlineModNick(const CString& sNick) {
|
||||
const CString& sPrefix = m_pUser->GetStatusPrefix();
|
||||
if (!sNick.Equals(sPrefix, false, sPrefix.length()))
|
||||
return false;
|
||||
|
||||
CString sModNick = sNick.substr(sPrefix.length());
|
||||
if (!sModNick.Equals("status") &&
|
||||
!m_pUser->GetModules().FindModule(sModNick) &&
|
||||
!CZNC::Get().GetModules().FindModule(sModNick))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual EModRet OnUserRaw(CString& sLine) {
|
||||
//Handle ISON
|
||||
if (sLine.Token(0).Equals("ison")) {
|
||||
VCString vsNicks;
|
||||
VCString::const_iterator it;
|
||||
|
||||
// Get the list of nicks which are being asked for
|
||||
sLine.Token(1, true).TrimLeft_n(":").Split(" ", vsNicks, false);
|
||||
|
||||
CString sBNCNicks = "";
|
||||
for (it = vsNicks.begin(); it != vsNicks.end(); it++) {
|
||||
if (IsOnlineModNick(*it)) {
|
||||
sBNCNicks += " " + *it;
|
||||
}
|
||||
}
|
||||
// Remove the leading space
|
||||
sBNCNicks.LeftChomp();
|
||||
|
||||
// We let the server handle this request and then act on
|
||||
// the 303 response.
|
||||
m_ISONRequests.push_back(sBNCNicks);
|
||||
}
|
||||
|
||||
//Handle WHOIS
|
||||
if (sLine.Token(0).Equals("whois")) {
|
||||
CString sNick = sLine.Token(1);
|
||||
|
||||
if (IsOnlineModNick(sNick)) {
|
||||
PutUser(":znc.in 311 " + m_pUser->GetCurNick() + " " + sNick + " " + sNick + " znc.in * :" + sNick);
|
||||
PutUser(":znc.in 312 " + m_pUser->GetCurNick() + " " + sNick + " *.znc.in :Bouncer");
|
||||
PutUser(":znc.in 318 " + m_pUser->GetCurNick() + " " + sNick + " :End of /WHOIS list.");
|
||||
|
||||
return HALT;
|
||||
}
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
virtual EModRet OnRaw(CString& sLine) {
|
||||
//Handle 303 reply if m_Requests is not empty
|
||||
if (sLine.Token(1) == "303" && !m_ISONRequests.empty()) {
|
||||
VCString::iterator it = m_ISONRequests.begin();
|
||||
|
||||
sLine.Trim();
|
||||
|
||||
// Only append a space if this isn't an empty reply
|
||||
if (sLine.Right(1) != ":") {
|
||||
sLine += " ";
|
||||
}
|
||||
|
||||
//add BNC nicks to the reply
|
||||
sLine += *it;
|
||||
m_ISONRequests.erase(it);
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
private:
|
||||
VCString m_ISONRequests;
|
||||
};
|
||||
|
||||
MODULEDEFS(CFOModule, "Fakes online status of ZNC *-users.")
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "User.h"
|
||||
#include "znc.h"
|
||||
|
||||
using std::map;
|
||||
|
||||
class CLastSeenMod : public CGlobalModule {
|
||||
public:
|
||||
GLOBALMODCONSTRUCTOR(CLastSeenMod)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CLastSeenMod() {}
|
||||
|
||||
time_t GetTime(CUser *pUser)
|
||||
{
|
||||
return GetNV(pUser->GetUserName()).ToULong();
|
||||
}
|
||||
|
||||
void SetTime(CUser *pUser)
|
||||
{
|
||||
SetNV(pUser->GetUserName(), CString(time(NULL)));
|
||||
}
|
||||
|
||||
virtual void OnModCommand(const CString& sLine)
|
||||
{
|
||||
const CString sCommand = sLine.Token(0).AsLower();
|
||||
|
||||
if (!GetUser()->IsAdmin()) {
|
||||
PutModule("Access denied");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sCommand == "show") {
|
||||
char buf[1024];
|
||||
const map<CString, CUser*>& mUsers = CZNC::Get().GetUserMap();
|
||||
map<CString, CUser*>::const_iterator it;
|
||||
CTable Table;
|
||||
|
||||
Table.AddColumn("User");
|
||||
Table.AddColumn("Last Seen");
|
||||
|
||||
for (it = mUsers.begin(); it != mUsers.end(); it++) {
|
||||
CUser *pUser = it->second;
|
||||
time_t last = GetTime(pUser);
|
||||
|
||||
Table.AddRow();
|
||||
Table.SetCell("User", it->first);
|
||||
|
||||
if (last == 0)
|
||||
Table.SetCell("Last Seen", "never");
|
||||
else {
|
||||
strftime(buf, sizeof(buf), "%c", localtime(&last));
|
||||
Table.SetCell("Last Seen", buf);
|
||||
}
|
||||
}
|
||||
|
||||
PutModule(Table);
|
||||
} else {
|
||||
PutModule("This module only supports 'show'");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnClientLogin()
|
||||
{
|
||||
SetTime(GetUser());
|
||||
}
|
||||
|
||||
virtual void OnClientDisconnect()
|
||||
{
|
||||
SetTime(GetUser());
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
GLOBALMODULEDEFS(CLastSeenMod, "Collects data about when a user last logged in")
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "Modules.h"
|
||||
#include "User.h"
|
||||
#include "znc.h"
|
||||
#include <queue>
|
||||
|
||||
class CSocketSorter {
|
||||
public:
|
||||
CSocketSorter(Csock* p) {
|
||||
m_pSock = p;
|
||||
}
|
||||
bool operator<(const CSocketSorter& other) const {
|
||||
// The 'biggest' item is displayed first.
|
||||
// return false: this is first
|
||||
// return true: other is first
|
||||
|
||||
// Listeners go to the top
|
||||
if (m_pSock->GetType() != other.m_pSock->GetType()) {
|
||||
if (m_pSock->GetType() == Csock::LISTENER)
|
||||
return false;
|
||||
if (other.m_pSock->GetType() == Csock::LISTENER)
|
||||
return true;
|
||||
}
|
||||
const CString& sMyName = m_pSock->GetSockName();
|
||||
const CString& sMyName2 = sMyName.Token(1, true, "::");
|
||||
bool bMyEmpty = sMyName2.empty();
|
||||
const CString& sHisName = other.GetSock()->GetSockName();
|
||||
const CString& sHisName2 = sHisName.Token(1, true, "::");
|
||||
bool bHisEmpty = sHisName2.empty();
|
||||
|
||||
// Then sort by first token after "::"
|
||||
if (bMyEmpty && !bHisEmpty)
|
||||
return false;
|
||||
if (bHisEmpty && !bMyEmpty)
|
||||
return true;
|
||||
|
||||
if (!bMyEmpty && !bHisEmpty) {
|
||||
int c = sMyName2.StrCmp(sHisName2);
|
||||
if (c < 0)
|
||||
return false;
|
||||
if (c > 0)
|
||||
return true;
|
||||
}
|
||||
// and finally sort by the whole socket name
|
||||
return sMyName.StrCmp(sHisName) > 0;
|
||||
}
|
||||
Csock* GetSock() const { return m_pSock; }
|
||||
private:
|
||||
Csock* m_pSock;
|
||||
};
|
||||
|
||||
class CListSockets : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CListSockets) {}
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sMessage)
|
||||
{
|
||||
#ifndef MOD_LISTSOCKETS_ALLOW_EVERYONE
|
||||
if (!m_pUser->IsAdmin()) {
|
||||
sMessage = "You must be admin to use this module";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnModCommand(const CString& sLine) {
|
||||
CString sCommand = sLine.Token(0);
|
||||
CString sArg = sLine.Token(1, true);
|
||||
|
||||
if (sCommand.Equals("LIST")) {
|
||||
bool bShowHosts = true;
|
||||
if (sArg.Equals("-n")) {
|
||||
bShowHosts = false;
|
||||
}
|
||||
ShowSocks(bShowHosts);
|
||||
} else {
|
||||
PutModule("Use 'list' to view a list of active sockets");
|
||||
PutModule("Use 'list -n' if you want IP addresses to be displayed");
|
||||
}
|
||||
}
|
||||
|
||||
void ShowSocks(bool bShowHosts) {
|
||||
CSockManager& m = CZNC::Get().GetManager();
|
||||
if (!m.size()) {
|
||||
PutStatus("You have no open sockets.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::priority_queue<CSocketSorter> socks;
|
||||
|
||||
for (unsigned int a = 0; a < m.size(); a++) {
|
||||
socks.push(m[a]);
|
||||
}
|
||||
|
||||
CTable Table;
|
||||
Table.AddColumn("Name");
|
||||
Table.AddColumn("Created");
|
||||
Table.AddColumn("State");
|
||||
#ifdef HAVE_LIBSSL
|
||||
Table.AddColumn("SSL");
|
||||
#endif
|
||||
Table.AddColumn("Local");
|
||||
Table.AddColumn("Remote");
|
||||
|
||||
while (!socks.empty()) {
|
||||
Csock* pSocket = socks.top().GetSock();
|
||||
socks.pop();
|
||||
|
||||
Table.AddRow();
|
||||
|
||||
switch (pSocket->GetType()) {
|
||||
case Csock::LISTENER:
|
||||
Table.SetCell("State", "Listen");
|
||||
break;
|
||||
case Csock::INBOUND:
|
||||
Table.SetCell("State", "Inbound");
|
||||
break;
|
||||
case Csock::OUTBOUND:
|
||||
if (pSocket->IsConnected())
|
||||
Table.SetCell("State", "Outbound");
|
||||
else
|
||||
Table.SetCell("State", "Connecting");
|
||||
break;
|
||||
default:
|
||||
Table.SetCell("State", "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned long long iStartTime = pSocket->GetStartTime();
|
||||
time_t iTime = iStartTime / 1000;
|
||||
Table.SetCell("Created", FormatTime("%Y-%m-%d %H:%M:%S", iTime));
|
||||
|
||||
#ifdef HAVE_LIBSSL
|
||||
if (pSocket->GetSSL()) {
|
||||
Table.SetCell("SSL", "Yes");
|
||||
} else {
|
||||
Table.SetCell("SSL", "No");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Table.SetCell("Name", pSocket->GetSockName());
|
||||
CString sVHost;
|
||||
if (bShowHosts) {
|
||||
sVHost = pSocket->GetBindHost();
|
||||
}
|
||||
if (sVHost.empty()) {
|
||||
sVHost = pSocket->GetLocalIP();
|
||||
}
|
||||
Table.SetCell("Local", sVHost + " " + CString(pSocket->GetLocalPort()));
|
||||
|
||||
CString sHost;
|
||||
if (!bShowHosts) {
|
||||
sHost = pSocket->GetRemoteIP();
|
||||
}
|
||||
// While connecting, there might be no ip available
|
||||
if (sHost.empty()) {
|
||||
sHost = pSocket->GetHostName();
|
||||
}
|
||||
|
||||
u_short uPort;
|
||||
// While connecting, GetRemotePort() would return 0
|
||||
if (pSocket->GetType() == Csock::OUTBOUND) {
|
||||
uPort = pSocket->GetPort();
|
||||
} else {
|
||||
uPort = pSocket->GetRemotePort();
|
||||
}
|
||||
if (uPort != 0) {
|
||||
Table.SetCell("Remote", sHost + " " + CString(uPort));
|
||||
} else {
|
||||
Table.SetCell("Remote", sHost);
|
||||
}
|
||||
}
|
||||
|
||||
PutModule(Table);
|
||||
return;
|
||||
}
|
||||
|
||||
virtual ~CListSockets() {
|
||||
}
|
||||
|
||||
CString FormatTime(const CString& sFormat, time_t tm = 0) const {
|
||||
char szTimestamp[1024];
|
||||
|
||||
if (tm == 0) {
|
||||
tm = time(NULL);
|
||||
}
|
||||
|
||||
// offset is in hours
|
||||
tm += (time_t)(m_pUser->GetTimezoneOffset() * 60 * 60);
|
||||
strftime(szTimestamp, sizeof(szTimestamp) / sizeof(char),
|
||||
sFormat.c_str(), localtime(&tm));
|
||||
|
||||
return szTimestamp;
|
||||
}
|
||||
};
|
||||
|
||||
MODULEDEFS(CListSockets, "List active sockets")
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 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 "User.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 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);
|
||||
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);
|
||||
};
|
||||
|
||||
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: ~/.znc/users/<user>/moddata/log/WINDOW_YYYYMMDD.log */
|
||||
sPath = GetSavePath() + "/" + sWindow.Replace_n("/", "?") + "_";
|
||||
snprintf(buffer, sizeof(buffer), "%04d%02d%02d.log", timeinfo->tm_year + 1900,
|
||||
timeinfo->tm_mon + 1, timeinfo->tm_mday);
|
||||
sPath += buffer;
|
||||
|
||||
CFile LogFile(sPath);
|
||||
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_pUser->GetCurrentServer();
|
||||
CString sSSL;
|
||||
|
||||
if (!pServer)
|
||||
return "(no server)";
|
||||
|
||||
if (pServer->IsSSL())
|
||||
sSSL = "+";
|
||||
return pServer->GetName() + ":" + sSSL + CString(pServer->GetPort());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
PutLog("*** Parts: " + Nick.GetNick() + " (" + Nick.GetIdent() + "@" + Nick.GetHost() + ")", 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)
|
||||
{
|
||||
PutLog("-" + GetUser()->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)
|
||||
{
|
||||
PutLog("* " + GetUser()->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)
|
||||
{
|
||||
PutLog("<" + GetUser()->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;
|
||||
}
|
||||
|
||||
MODULEDEFS(CLogMod, "Write IRC logs")
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "Modules.h"
|
||||
#include "Client.h"
|
||||
|
||||
class CMotdFileMod : public CGlobalModule {
|
||||
public:
|
||||
GLOBALMODCONSTRUCTOR(CMotdFileMod) {}
|
||||
virtual ~CMotdFileMod() {}
|
||||
|
||||
virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
|
||||
if (sArgs.empty()) {
|
||||
sMessage = "Argument must be path to a MOTD file";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnClientLogin() {
|
||||
CString sFile = GetArgs();
|
||||
CString sBuffer;
|
||||
CFile cFile(sFile);
|
||||
if (!cFile.Open(O_RDONLY)) {
|
||||
m_pClient->PutStatusNotice("Could not open MOTD file");
|
||||
return;
|
||||
}
|
||||
while (cFile.ReadLine(sBuffer))
|
||||
m_pClient->PutStatusNotice(sBuffer);
|
||||
cFile.Close();
|
||||
}
|
||||
};
|
||||
|
||||
GLOBALMODULEDEFS(CMotdFileMod, "Send MOTD from a file")
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "main.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
#include "znc.h"
|
||||
|
||||
class CNotifyConnectMod : public CGlobalModule {
|
||||
public:
|
||||
GLOBALMODCONSTRUCTOR(CNotifyConnectMod) {}
|
||||
|
||||
virtual void OnClientLogin()
|
||||
{
|
||||
SendAdmins(m_pUser->GetUserName() + " attached");
|
||||
}
|
||||
|
||||
virtual void OnClientDisconnect()
|
||||
{
|
||||
SendAdmins(m_pUser->GetUserName() + " detached");
|
||||
}
|
||||
|
||||
private:
|
||||
void SendAdmins(const CString &msg)
|
||||
{
|
||||
CZNC::Get().Broadcast(msg, true, NULL, GetClient());
|
||||
}
|
||||
};
|
||||
|
||||
GLOBALMODULEDEFS(CNotifyConnectMod, "");
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 See the AUTHORS file for details.
|
||||
*
|
||||
* 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 "User.h"
|
||||
#include "znc.h"
|
||||
|
||||
class CSendRaw_Mod: public CGlobalModule {
|
||||
public:
|
||||
GLOBALMODCONSTRUCTOR(CSendRaw_Mod) {}
|
||||
|
||||
virtual ~CSendRaw_Mod() {
|
||||
}
|
||||
|
||||
virtual void OnModCommand(const CString& sLine) {
|
||||
CString sUser = sLine.Token(0);
|
||||
CString sSend = sLine.Token(1, true);
|
||||
CUser *pUser;
|
||||
|
||||
if (!m_pUser->IsAdmin()) {
|
||||
PutModule("You must have admin privileges to use this");
|
||||
return;
|
||||
}
|
||||
|
||||
pUser = CZNC::Get().FindUser(sUser);
|
||||
|
||||
if (!pUser) {
|
||||
PutModule("User not found");
|
||||
PutModule("The expected format is: <user> <line to send>");
|
||||
return;
|
||||
}
|
||||
|
||||
pUser->PutIRC(sSend);
|
||||
PutModule("done");
|
||||
}
|
||||
};
|
||||
|
||||
GLOBALMODULEDEFS(CSendRaw_Mod, "Let's you send some raw IRC lines as someone else");
|
||||
Reference in New Issue
Block a user