mirror of
https://github.com/znc/znc.git
synced 2026-08-10 10:52:59 +02:00
Initial revision
git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@2 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
CXXFLAGS="-Wall -D_GNU_SOURCE -DHAVE_LIBSSL -I.."
|
||||
LIBS="-lssl"
|
||||
|
||||
if test -z "$1"; then
|
||||
echo "Usage: $0 <module> [...]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for arg in "$@"
|
||||
do
|
||||
if test -d $arg; then
|
||||
(cd $arg && make || exit 1)
|
||||
elif test -f "$arg"; then
|
||||
FILE="$arg"
|
||||
MOD="${FILE%.cpp}"
|
||||
MOD="${MOD%.cc}"
|
||||
elif test -f "$arg.cpp"; then
|
||||
FILE="$arg.cpp"
|
||||
MOD="$arg"
|
||||
elif test -f "$arg.cc"; then
|
||||
FILE="$arg.cc"
|
||||
MOD="$arg"
|
||||
fi
|
||||
|
||||
rm -f "$MOD.so"
|
||||
|
||||
if test -n "$FILE"; then
|
||||
COMMAND="g++ $CXXFLAGS -c $FILE"
|
||||
echo $COMMAND
|
||||
$COMMAND || exit 1
|
||||
COMMAND="g++ $CXXFLAGS -shared -o $MOD.so $MOD.o $LIBS"
|
||||
echo $COMMAND
|
||||
$COMMAND || exit 1
|
||||
fi
|
||||
|
||||
if ! test -f "$MOD.so"; then
|
||||
echo "Failed to build $MOD.so!"
|
||||
exit 1
|
||||
else
|
||||
echo "Built $MOD.so"
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,269 @@
|
||||
#include "main.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
#include "Utils.h"
|
||||
#include "md5.h"
|
||||
#include <pwd.h>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
/*
|
||||
* Email Monitor / Retrieval
|
||||
* Author: imaginos <imaginos@imaginos.net>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.1 2004/08/24 00:08:52 prozacx
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
struct EmailST
|
||||
{
|
||||
string sFrom;
|
||||
string sSubject;
|
||||
string sUidl;
|
||||
u_int iSize;
|
||||
};
|
||||
|
||||
class CEmailJob : public CTimer
|
||||
{
|
||||
public:
|
||||
CEmailJob( CModule* pModule, unsigned int uInterval, unsigned int uCycles, const string& sLabel, const string& sDescription )
|
||||
: CTimer( pModule, uInterval, uCycles, sLabel, sDescription) {}
|
||||
|
||||
virtual ~CEmailJob() {}
|
||||
|
||||
protected:
|
||||
virtual void RunJob();
|
||||
};
|
||||
|
||||
class CEmail : public CModule
|
||||
{
|
||||
public:
|
||||
MODCONSTRUCTOR(CEmail)
|
||||
{
|
||||
m_iLastCheck = 0;
|
||||
m_bInitialized = false;
|
||||
}
|
||||
virtual ~CEmail()
|
||||
{
|
||||
vector<Csock*> vSocks = m_pManager->FindSocksByName( "EMAIL::" + m_pUser->GetUserName() );
|
||||
for( u_int a = 0; a < vSocks.size(); a++ )
|
||||
m_pManager->DelSockByAddr( vSocks[a] );
|
||||
}
|
||||
|
||||
virtual bool OnLoad(const string & sArgs) {
|
||||
m_sMailPath = sArgs;
|
||||
|
||||
StartParser();
|
||||
if ( m_pUser->IsUserAttached() )
|
||||
StartTimer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnUserAttached()
|
||||
{
|
||||
stringstream s;
|
||||
s << "You have " << m_ssUidls.size() << " emails.";
|
||||
PutModule( s.str() );
|
||||
StartTimer();
|
||||
}
|
||||
virtual void OnUserDetached()
|
||||
{
|
||||
RemTimer( "EMAIL::" + m_pUser->GetUserName() );
|
||||
}
|
||||
|
||||
void StartTimer()
|
||||
{
|
||||
if ( !FindTimer( "EMAIL::" + m_pUser->GetUserName() ) )
|
||||
{
|
||||
CEmailJob *p = new CEmailJob( this, 60, 0, "EmailMonitor", "Monitors email activity" );
|
||||
AddTimer( p );
|
||||
}
|
||||
}
|
||||
|
||||
virtual string GetDescription()
|
||||
{
|
||||
return ( "Monitors Email activity on local disk /var/mail/user" );
|
||||
}
|
||||
|
||||
virtual void OnModCommand( const string& sCommand );
|
||||
void StartParser();
|
||||
|
||||
void ParseEmails( const vector<EmailST> & vEmails )
|
||||
{
|
||||
if ( !m_bInitialized )
|
||||
{
|
||||
m_bInitialized = true;
|
||||
for( u_int a = 0; a < vEmails.size(); a++ )
|
||||
m_ssUidls.insert( vEmails[a].sUidl );
|
||||
|
||||
stringstream s;
|
||||
s << "You have " << vEmails.size() << " emails.";
|
||||
PutModule( s.str() );
|
||||
} else
|
||||
{
|
||||
set<string> ssUidls;
|
||||
|
||||
CTable Table;
|
||||
Table.AddColumn("From");
|
||||
Table.AddColumn("Size");
|
||||
Table.AddColumn("Subject");
|
||||
|
||||
for( u_int a = 0; a < vEmails.size(); a++ )
|
||||
{
|
||||
if ( m_ssUidls.find( vEmails[a].sUidl ) == m_ssUidls.end() )
|
||||
{
|
||||
//PutModule( "------------------- New Email -------------------" );
|
||||
Table.AddRow();
|
||||
Table.SetCell( "From", CUtils::Ellipsize( vEmails[a].sFrom, 32 ) );
|
||||
Table.SetCell( "Size", CUtils::ToString( vEmails[a].iSize ) );
|
||||
Table.SetCell( "Subject", CUtils::Ellipsize( vEmails[a].sSubject, 64 ) );
|
||||
}
|
||||
ssUidls.insert( vEmails[a].sUidl );
|
||||
}
|
||||
|
||||
m_ssUidls = ssUidls; // keep the list in synch
|
||||
|
||||
if (Table.size()) {
|
||||
unsigned int uTableIdx = 0;
|
||||
string sLine;
|
||||
while ( Table.GetLine( uTableIdx++, sLine ) ) {
|
||||
PutModule( sLine );
|
||||
}
|
||||
|
||||
stringstream s;
|
||||
s << "You have " << vEmails.size() << " emails.";
|
||||
PutModule( s.str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
string m_sMailPath;
|
||||
u_int m_iLastCheck;
|
||||
set<string> m_ssUidls;
|
||||
bool m_bInitialized;
|
||||
};
|
||||
|
||||
class CEmailFolder : public Csock
|
||||
{
|
||||
public:
|
||||
CEmailFolder( CEmail *pModule, const string & sMailbox ) : Csock()
|
||||
{
|
||||
m_pModule = pModule;
|
||||
m_sMailbox = sMailbox;
|
||||
EnableReadLine();
|
||||
}
|
||||
|
||||
virtual ~CEmailFolder()
|
||||
{
|
||||
if ( !m_sMailBuffer.empty() )
|
||||
ProcessMail(); // get the last one
|
||||
|
||||
if ( !m_vEmails.empty() )
|
||||
m_pModule->ParseEmails( m_vEmails );
|
||||
}
|
||||
|
||||
virtual void ReadLine( const CS_STRING & sLine )
|
||||
{
|
||||
if ( sLine.substr( 0, 5 ) == "From " )
|
||||
{
|
||||
if ( !m_sMailBuffer.empty() )
|
||||
{
|
||||
ProcessMail();
|
||||
m_sMailBuffer.clear();
|
||||
}
|
||||
}
|
||||
m_sMailBuffer += sLine;
|
||||
}
|
||||
|
||||
void ProcessMail()
|
||||
{
|
||||
EmailST tmp;
|
||||
tmp.sUidl = (char *)CMD5( m_sMailBuffer.substr( 0, 255 ) );
|
||||
string sLine;
|
||||
u_int iPos = 0;
|
||||
while( ::ReadLine( m_sMailBuffer, sLine, iPos ) )
|
||||
{
|
||||
CUtils::Trim( sLine );
|
||||
if ( sLine.empty() )
|
||||
break; // out of the headers
|
||||
|
||||
if ( strncasecmp( sLine.c_str(), "From: ", 6 ) == 0 )
|
||||
tmp.sFrom = sLine.substr( 6, string::npos );
|
||||
else if ( strncasecmp( sLine.c_str(), "Subject: ", 9 ) == 0 )
|
||||
tmp.sSubject = sLine.substr( 9, string::npos );
|
||||
|
||||
if ( ( !tmp.sFrom.empty() ) && ( !tmp.sSubject.empty() ) )
|
||||
break;
|
||||
}
|
||||
tmp.iSize = m_sMailBuffer.length();
|
||||
m_vEmails.push_back( tmp );
|
||||
}
|
||||
private:
|
||||
CEmail *m_pModule;
|
||||
string m_sMailbox;
|
||||
string m_sMailBuffer;
|
||||
vector<EmailST> m_vEmails;
|
||||
};
|
||||
|
||||
void CEmail::OnModCommand( const string& sCommand )
|
||||
{
|
||||
u_int iPos = sCommand.find( " " );
|
||||
string sCom, sArgs;
|
||||
if ( iPos == string::npos )
|
||||
sCom = sCommand;
|
||||
else
|
||||
{
|
||||
sCom = sCommand.substr( 0, iPos );
|
||||
sArgs = sCommand.substr( iPos + 1, string::npos );
|
||||
}
|
||||
|
||||
if ( sCom == "timers" )
|
||||
{
|
||||
ListTimers();
|
||||
} else
|
||||
PutModule( "Error, no such command [" + sCom + "]" );
|
||||
}
|
||||
|
||||
void CEmail::StartParser()
|
||||
{
|
||||
string sParserName = "EMAIL::" + m_pUser->GetUserName();
|
||||
|
||||
if ( m_pManager->FindSockByName( sParserName ) )
|
||||
return; // one at a time sucker
|
||||
|
||||
CFile cFile( m_sMailPath );
|
||||
if ( ( !cFile.Exists() ) || ( cFile.GetSize() == 0 ) )
|
||||
{
|
||||
m_bInitialized = true;
|
||||
return; // der
|
||||
}
|
||||
|
||||
if ( cFile.GetMTime() <= m_iLastCheck )
|
||||
return; // only check if modified
|
||||
|
||||
int iFD = open( m_sMailPath.c_str(), O_RDONLY );
|
||||
if ( iFD >= 0 )
|
||||
{
|
||||
m_iLastCheck = time( NULL );
|
||||
CEmailFolder *p = new CEmailFolder( this, m_sMailPath );
|
||||
p->SetRSock( iFD );
|
||||
p->SetWSock( iFD );
|
||||
m_pManager->AddSock( (Csock *)p, "EMAIL::" + m_pUser->GetUserName() );
|
||||
}
|
||||
}
|
||||
|
||||
void CEmailJob::RunJob()
|
||||
{
|
||||
CEmail *p = (CEmail *)m_pModule;
|
||||
p->StartParser();
|
||||
}
|
||||
MODULEDEFS(CEmail)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "main.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
|
||||
class CRawMod : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CRawMod) {}
|
||||
virtual ~CRawMod() {}
|
||||
|
||||
virtual string GetDescription() {
|
||||
return "View all of the raw traffic.";
|
||||
}
|
||||
|
||||
virtual bool OnRaw(string& sLine) {
|
||||
PutModule("IRC -> [" + sLine + "]");
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnUserRaw(string& sLine) {
|
||||
PutModule("YOU -> [" + sLine + "]");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
MODULEDEFS(CRawMod)
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
#include "main.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
|
||||
class CSampleTimer : public CTimer {
|
||||
public:
|
||||
|
||||
CSampleTimer(CModule* pModule, unsigned int uInterval, unsigned int uCycles, const string& sLabel, const string& sDescription) : CTimer(pModule, uInterval, uCycles, sLabel, sDescription) {}
|
||||
virtual ~CSampleTimer() {}
|
||||
|
||||
private:
|
||||
protected:
|
||||
virtual void RunJob() {
|
||||
m_pModule->PutModule("TEST!!!!");
|
||||
}
|
||||
};
|
||||
|
||||
class CSampleMod : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CSampleMod) {}
|
||||
|
||||
virtual bool OnLoad(const string& sArgs) {
|
||||
PutModule("I'm being loaded with the arguments: [" + sArgs + "]");
|
||||
//AddTimer(new CSampleTimer(this, 300, 0, "Sample", "Sample timer for sample things."));
|
||||
//AddTimer(new CSampleTimer(this, 5, 20, "Another", "Another sample timer."));
|
||||
//AddTimer(new CSampleTimer(this, 25000, 5, "Third", "A third sample timer."));
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~CSampleMod() {
|
||||
PutModule("I'm being unloaded!");
|
||||
}
|
||||
|
||||
virtual bool OnBoot() {
|
||||
// This is called when the app starts up (only modules that are loaded in the config will get this event)
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual string GetDescription() {
|
||||
return "To be used as a sample for writing modules.";
|
||||
}
|
||||
|
||||
virtual void OnIRCConnected() {
|
||||
PutModule("You got connected BoyOh.");
|
||||
}
|
||||
|
||||
virtual void OnIRCDisconnected() {
|
||||
PutModule("You got disconnected BoyOh.");
|
||||
}
|
||||
|
||||
virtual void OnOp(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) {
|
||||
PutModule(((bNoChange) ? "[0] " : "[1] [") + OpNick.GetNick() + "] opped [" + Nick.GetNick() + "] on [" + Channel.GetName() + "]");
|
||||
}
|
||||
|
||||
virtual void OnDeop(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) {
|
||||
PutModule(((bNoChange) ? "[0] " : "[1] [") + OpNick.GetNick() + "] deopped [" + Nick.GetNick() + "] on [" + Channel.GetName() + "]");
|
||||
}
|
||||
|
||||
virtual void OnVoice(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) {
|
||||
PutModule(((bNoChange) ? "[0] " : "[1] [") + OpNick.GetNick() + "] voiced [" + Nick.GetNick() + "] on [" + Channel.GetName() + "]");
|
||||
}
|
||||
|
||||
virtual void OnDevoice(const CNick& OpNick, const CNick& Nick, const CChan& Channel, bool bNoChange) {
|
||||
PutModule(((bNoChange) ? "[0] " : "[1] [") + OpNick.GetNick() + "] devoiced [" + Nick.GetNick() + "] on [" + Channel.GetName() + "]");
|
||||
}
|
||||
|
||||
virtual void OnRawMode(const CNick& OpNick, const CChan& Channel, const string& sModes, const string& sArgs) {
|
||||
PutModule("* " + OpNick.GetNick() + " sets mode: " + sModes + " " + sArgs + " (" + Channel.GetName() + ")");
|
||||
}
|
||||
|
||||
virtual bool OnRaw(string& sLine) {
|
||||
// PutModule("OnRaw() [" + sLine + "]");
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnUserRaw(string& sLine) {
|
||||
// PutModule("UserRaw() [" + sLine + "]");
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void OnKick(const CNick& OpNick, const string& sKickedNick, const CChan& Channel, const string& sMessage) {
|
||||
PutModule("[" + OpNick.GetNick() + "] kicked [" + sKickedNick + "] from [" + Channel.GetName() + "] with the msg [" + sMessage + "]");
|
||||
}
|
||||
|
||||
virtual void OnQuit(const CNick& Nick, const string& sMessage) {
|
||||
PutModule("* Quits: " + Nick.GetNick() + " (" + Nick.GetIdent() + "!" + Nick.GetHost() + ") (" + sMessage + ")");
|
||||
}
|
||||
|
||||
virtual void OnJoin(const CNick& Nick, const CChan& Channel) {
|
||||
PutModule("* Joins: " + Nick.GetNick() + " (" + Nick.GetIdent() + "!" + Nick.GetHost() + ")");
|
||||
}
|
||||
|
||||
virtual void OnPart(const CNick& Nick, const CChan& Channel) {
|
||||
PutModule("* Parts: " + Nick.GetNick() + " (" + Nick.GetIdent() + "!" + Nick.GetHost() + ")");
|
||||
}
|
||||
|
||||
virtual void OnNick(const CNick& OldNick, const string& sNewNick) {
|
||||
PutModule("* " + OldNick.GetNick() + " is now known as " + sNewNick);
|
||||
}
|
||||
|
||||
virtual bool OnUserCTCPReply(const CNick& Nick, string& sMessage) {
|
||||
PutModule("[" + Nick.GetNick() + "] userctcpreply [" + sMessage + "]");
|
||||
sMessage = "\037" + sMessage + "\037";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnCTCPReply(const CNick& Nick, string& sMessage) {
|
||||
PutModule("[" + Nick.GetNick() + "] ctcpreply [" + sMessage + "]");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnUserCTCP(const string& sTarget, string& sMessage) {
|
||||
PutModule("[" + sTarget + "] userctcp [" + sMessage + "]");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnPrivCTCP(const CNick& Nick, string& sMessage) {
|
||||
PutModule("[" + Nick.GetNick() + "] privctcp [" + sMessage + "]");
|
||||
sMessage = "\002" + sMessage + "\002";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnChanCTCP(const CNick& Nick, const CChan& Channel, string& sMessage) {
|
||||
PutModule("[" + Nick.GetNick() + "] chanctcp [" + sMessage + "] to [" + Channel.GetName() + "]");
|
||||
sMessage = "\00311,5 " + sMessage + " \003";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnUserNotice(const string& sTarget, string& sMessage) {
|
||||
PutModule("[" + sTarget + "] usernotice [" + sMessage + "]");
|
||||
sMessage = "\037" + sMessage + "\037";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnPrivNotice(const CNick& Nick, string& sMessage) {
|
||||
PutModule("[" + Nick.GetNick() + "] privnotice [" + sMessage + "]");
|
||||
sMessage = "\002" + sMessage + "\002";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnChanNotice(const CNick& Nick, const CChan& Channel, string& sMessage) {
|
||||
PutModule("[" + Nick.GetNick() + "] channotice [" + sMessage + "] to [" + Channel.GetName() + "]");
|
||||
sMessage = "\00311,5 " + sMessage + " \003";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnUserMsg(const string& sTarget, string& sMessage) {
|
||||
PutModule("[" + sTarget + "] usermsg [" + sMessage + "]");
|
||||
sMessage = "\0034" + sMessage + "\003";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnPrivMsg(const CNick& Nick, string& sMessage) {
|
||||
PutModule("[" + Nick.GetNick() + "] privmsg [" + sMessage + "]");
|
||||
sMessage = "\002" + sMessage + "\002";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnChanMsg(const CNick& Nick, const CChan& Channel, string& sMessage) {
|
||||
if (sMessage == "!ping") {
|
||||
PutIRC("PRIVMSG " + Channel.GetName() + " :PONG?");
|
||||
}
|
||||
|
||||
sMessage = "x " + sMessage + " x";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void OnModCommand(const string& sCommand) {
|
||||
if (strcasecmp(sCommand.c_str(), "TIMERS") == 0) {
|
||||
ListTimers();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool OnStatusCommand(const string& sCommand) {
|
||||
if (strcasecmp(sCommand.c_str(), "SAMPLE") == 0) {
|
||||
PutModule("Hi, I'm your friendly sample module.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
MODULEDEFS(CSampleMod)
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
#include "main.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
#include "Utils.h"
|
||||
#include <pwd.h>
|
||||
|
||||
#ifndef HAVE_LIBSSL
|
||||
#error This plugin only works with OpenSSL
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
#define CRYPT_VERIFICATION_TOKEN "::__:SAVEBUFF:__::"
|
||||
|
||||
/*
|
||||
* Buffer Saving thing, incase your shit goes out while your out
|
||||
* Author: imaginos <imaginos@imaginos.net>
|
||||
*
|
||||
* Its only as secure as your shell, the encryption only offers a slightly
|
||||
* better solution then plain text.
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.1 2004/08/24 00:08:52 prozacx
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
class CSaveBuff;
|
||||
|
||||
class CSaveBuffJob : public CTimer
|
||||
{
|
||||
public:
|
||||
CSaveBuffJob( CModule* pModule, unsigned int uInterval, unsigned int uCycles, const string& sLabel, const string& sDescription )
|
||||
: CTimer( pModule, uInterval, uCycles, sLabel, sDescription) {}
|
||||
|
||||
virtual ~CSaveBuffJob() {}
|
||||
|
||||
protected:
|
||||
virtual void RunJob();
|
||||
};
|
||||
|
||||
class CSaveBuff : public CModule
|
||||
{
|
||||
public:
|
||||
MODCONSTRUCTOR(CSaveBuff)
|
||||
{
|
||||
// m_sPassword = CBlowfish::MD5( "" );
|
||||
AddTimer( new CSaveBuffJob( this, 60, 0, "SaveBuff", "Saves the current buffer to disk every 1 minute" ) );
|
||||
}
|
||||
virtual ~CSaveBuff()
|
||||
{
|
||||
SaveBufferToDisk();
|
||||
}
|
||||
|
||||
virtual bool OnBoot()
|
||||
{
|
||||
if ( m_sPassword.empty() )
|
||||
{
|
||||
char *pTmp = getpass( "Enter Encryption Key for savebuff.so: " );
|
||||
|
||||
if ( pTmp )
|
||||
m_sPassword = CBlowfish::MD5( pTmp );
|
||||
|
||||
*pTmp = 0;
|
||||
}
|
||||
|
||||
const vector<CChan *>& vChans = m_pUser->GetChans();
|
||||
for( u_int a = 0; a < vChans.size(); a++ )
|
||||
{
|
||||
string sFile;
|
||||
string sPath = GetPath( vChans[a]->GetName() );
|
||||
|
||||
if ( ( sPath.empty() ) || ( !ReadFile( sPath, sFile ) ) )
|
||||
continue;
|
||||
if ( !sFile.empty() )
|
||||
{
|
||||
CBlowfish c( m_sPassword, BF_DECRYPT );
|
||||
sFile = c.Crypt( sFile );
|
||||
|
||||
if ( sFile.substr( 0, strlen( CRYPT_VERIFICATION_TOKEN ) ) != CRYPT_VERIFICATION_TOKEN )
|
||||
{
|
||||
// failed to decode :(
|
||||
cerr << "Unable to decode Encrypted file [" << sPath << "]" << endl;
|
||||
continue;
|
||||
}
|
||||
sFile.erase( 0, strlen( CRYPT_VERIFICATION_TOKEN ) );
|
||||
|
||||
string sLine;
|
||||
u_int iPos = 0;
|
||||
while( ReadLine( sFile, sLine, iPos ) )
|
||||
{
|
||||
CUtils::Trim( sLine );
|
||||
vChans[a]->AddBuffer( sLine );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
void SaveBufferToDisk()
|
||||
{
|
||||
if ( !m_sPassword.empty() )
|
||||
{
|
||||
const vector<CChan *>& vChans = m_pUser->GetChans();
|
||||
for( u_int a = 0; a < vChans.size(); a++ )
|
||||
{
|
||||
const vector<string> & vBuffer = vChans[a]->GetBuffer();
|
||||
if ( vBuffer.empty() )
|
||||
continue;
|
||||
|
||||
string sFile = CRYPT_VERIFICATION_TOKEN;
|
||||
|
||||
for( u_int b = 0; b < vBuffer.size(); b++ )
|
||||
sFile += vBuffer[b] + "\n";
|
||||
|
||||
CBlowfish c( m_sPassword, BF_ENCRYPT );
|
||||
sFile = c.Crypt( sFile );
|
||||
string sPath = GetPath( vChans[a]->GetName() );
|
||||
if ( !sPath.empty() )
|
||||
{
|
||||
WriteFile( sPath, sFile );
|
||||
chmod( sPath.c_str(), 0600 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual string GetDescription()
|
||||
{
|
||||
return ( "Stores channel buffers to disk, encrypted." );
|
||||
}
|
||||
|
||||
virtual void OnModCommand( const string& sCommand )
|
||||
{
|
||||
u_int iPos = sCommand.find( " " );
|
||||
string sCom, sArgs;
|
||||
if ( iPos == string::npos )
|
||||
sCom = sCommand;
|
||||
else
|
||||
{
|
||||
sCom = sCommand.substr( 0, iPos );
|
||||
sArgs = sCommand.substr( iPos + 1, string::npos );
|
||||
}
|
||||
|
||||
if ( strcasecmp( sCom.c_str(), "setpass" ) == 0 )
|
||||
{
|
||||
PutModule( "Password set to [" + sArgs + "]" );
|
||||
m_sPassword = CBlowfish::MD5( sArgs );
|
||||
|
||||
} else if ( strcasecmp( sCom.c_str(), "dumpbuff" ) == 0 )
|
||||
{
|
||||
string sChannel = GetPath( sArgs );
|
||||
string sFile;
|
||||
|
||||
if ( ( sChannel.empty() ) || ( !ReadFile( sChannel, sFile ) ) )
|
||||
{
|
||||
PutModule( "Unable to find buffer for that channel" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !sFile.empty() )
|
||||
{
|
||||
CBlowfish c( m_sPassword, BF_DECRYPT );
|
||||
sFile = c.Crypt( sFile );
|
||||
|
||||
if ( sFile.substr( 0, strlen( CRYPT_VERIFICATION_TOKEN ) ) != CRYPT_VERIFICATION_TOKEN )
|
||||
{
|
||||
// failed to decode :(
|
||||
PutModule( "Unable to decode Encrypted file [" + sChannel + "]" );
|
||||
return;
|
||||
}
|
||||
sFile.erase( 0, strlen( CRYPT_VERIFICATION_TOKEN ) );
|
||||
|
||||
string sLine;
|
||||
u_int iPos = 0;
|
||||
while( ReadLine( sFile, sLine, iPos ) )
|
||||
{
|
||||
CUtils::Trim( sLine );
|
||||
PutModule( "[" + sLine + "]" );
|
||||
}
|
||||
}
|
||||
} else if ( strcasecmp( sCom.c_str(), "save" ) == 0 )
|
||||
{
|
||||
SaveBufferToDisk();
|
||||
PutModule( "Done." );
|
||||
} else
|
||||
PutModule( "Unknown command [" + sCommand + "]" );
|
||||
}
|
||||
|
||||
string GetPath( const string & sChannel )
|
||||
{
|
||||
string sBuffer = m_pUser->GetUserName() + Lower( sChannel );
|
||||
string sRet = m_pUser->GetHomePath();
|
||||
sRet += "/.znc-savebuff-" + CBlowfish::MD5( sBuffer, true );
|
||||
return( sRet );
|
||||
}
|
||||
|
||||
private:
|
||||
string m_sPassword;
|
||||
};
|
||||
|
||||
|
||||
void CSaveBuffJob::RunJob()
|
||||
{
|
||||
CSaveBuff *p = (CSaveBuff *)m_pModule;
|
||||
p->SaveBufferToDisk();
|
||||
}
|
||||
|
||||
MODULEDEFS(CSaveBuff)
|
||||
|
||||
@@ -0,0 +1,462 @@
|
||||
#include "main.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
#include "Utils.h"
|
||||
#include "Csocket.h"
|
||||
#include "md5.h"
|
||||
#include <pwd.h>
|
||||
#include <sstream>
|
||||
|
||||
/*
|
||||
* Secure chat system
|
||||
* Author: imaginos <imaginos@imaginos.net>
|
||||
*
|
||||
* $Log$
|
||||
* Revision 1.1 2004/08/24 00:08:52 prozacx
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
class CSChat;
|
||||
|
||||
class CRemMarkerJob : public CTimer
|
||||
{
|
||||
public:
|
||||
CRemMarkerJob( CModule* pModule, unsigned int uInterval, unsigned int uCycles, const string& sLabel, const string& sDescription )
|
||||
: CTimer( pModule, uInterval, uCycles, sLabel, sDescription) {}
|
||||
|
||||
virtual ~CRemMarkerJob() {}
|
||||
void SetNick( const string & sNick )
|
||||
{
|
||||
m_sNick = sNick;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void RunJob();
|
||||
string m_sNick;
|
||||
};
|
||||
|
||||
class CSChatSock : public Csock
|
||||
{
|
||||
public:
|
||||
CSChatSock( CSChat *pMod ) : Csock()
|
||||
{
|
||||
m_pModule = pMod;
|
||||
}
|
||||
CSChatSock( int itimeout = 60 ) : Csock( itimeout )
|
||||
{
|
||||
m_pModule = NULL;
|
||||
EnableReadLine();
|
||||
}
|
||||
CSChatSock( const CS_STRING & sHost, int iPort, int iTimeout = 60 )
|
||||
: Csock( sHost, iPort, iTimeout )
|
||||
{
|
||||
m_pModule = NULL;
|
||||
EnableReadLine();
|
||||
}
|
||||
|
||||
virtual Csock *GetSockObj( const CS_STRING & sHostname, int iPort )
|
||||
{
|
||||
CSChatSock *p = new CSChatSock( sHostname, iPort );
|
||||
return( p );
|
||||
}
|
||||
|
||||
virtual bool ConnectionFrom( const CS_STRING & sHost, int iPort )
|
||||
{
|
||||
Close(); // close the listener after the first connection
|
||||
return( true );
|
||||
}
|
||||
|
||||
virtual void Connected();
|
||||
virtual bool CreatedChild( Csock *pSock )
|
||||
{
|
||||
CSChatSock *p = (CSChatSock *)pSock;
|
||||
p->SetModule( m_pModule );
|
||||
p->SetChatNick( m_sChatNick );
|
||||
p->SetSockName( GetSockName() + "::" + m_sChatNick );
|
||||
return( true );
|
||||
}
|
||||
|
||||
virtual void Timeout();
|
||||
|
||||
void SetModule( CSChat *p )
|
||||
{
|
||||
m_pModule = p;
|
||||
}
|
||||
void SetChatNick( const string & sNick )
|
||||
{
|
||||
m_sChatNick = sNick;
|
||||
}
|
||||
|
||||
const string & GetChatNick() const { return( m_sChatNick ); }
|
||||
|
||||
virtual void ReadLine( const CS_STRING & sLine );
|
||||
virtual void Disconnected();
|
||||
|
||||
virtual void AddLine( const string & sLine )
|
||||
{
|
||||
m_vBuffer.insert( m_vBuffer.begin(), sLine );
|
||||
if ( m_vBuffer.size() > 200 )
|
||||
m_vBuffer.pop_back();
|
||||
}
|
||||
|
||||
virtual void DumpBuffer()
|
||||
{
|
||||
for( vector<CS_STRING>::reverse_iterator it = m_vBuffer.rbegin(); it != m_vBuffer.rend(); it++ )
|
||||
ReadLine( *it );
|
||||
|
||||
m_vBuffer.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
CSChat *m_pModule;
|
||||
string m_sChatNick;
|
||||
vector<CS_STRING> m_vBuffer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CSChat : public CModule
|
||||
{
|
||||
public:
|
||||
MODCONSTRUCTOR(CSChat) {}
|
||||
virtual ~CSChat() { CleanSocks(); }
|
||||
|
||||
virtual bool OnLoad( const string & sArgs )
|
||||
{
|
||||
m_sPemFile = sArgs;
|
||||
|
||||
if ( m_sPemFile.empty() )
|
||||
{
|
||||
m_sPemFile = m_pUser->GetBinPath() + "/znc.pem";
|
||||
}
|
||||
|
||||
if (!CFile::Exists(m_sPemFile)) {
|
||||
PutModule("Unable to load pem file [" + m_sPemFile + "]");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void OnUserAttached()
|
||||
{
|
||||
string sName = "SCHAT::" + m_pUser->GetUserName();
|
||||
for( u_int a = 0; a < m_pManager->size(); a++ )
|
||||
{
|
||||
if ( ( strncmp( (*m_pManager)[a]->GetSockName().c_str(), sName.c_str(), sName.length() ) != 0 ) || ( (*m_pManager)[a]->GetType() == CSChatSock::LISTENER ) )
|
||||
continue;
|
||||
|
||||
CSChatSock *p = (CSChatSock *)(*m_pManager)[a];
|
||||
p->DumpBuffer();
|
||||
}
|
||||
}
|
||||
virtual void OnUserDetached() {}
|
||||
|
||||
void CleanSocks()
|
||||
{
|
||||
string sName = "SCHAT::" + m_pUser->GetUserName();
|
||||
for( u_int a= 0; a < m_pManager->size(); a++ )
|
||||
{
|
||||
if ( strncmp( (*m_pManager)[a]->GetSockName().c_str(), sName.c_str(), sName.length() ) == 0 )
|
||||
m_pManager->DelSock( a-- );
|
||||
}
|
||||
}
|
||||
|
||||
virtual string GetDescription()
|
||||
{
|
||||
return ( "Secure cross platform (:P) chat system" );
|
||||
}
|
||||
|
||||
virtual bool OnUserRaw( string & sLine )
|
||||
{
|
||||
if ( strncasecmp( sLine.c_str(), "schat ", 6 ) == 0 )
|
||||
{
|
||||
OnModCommand( "chat " + sLine.substr( 6, string::npos ) );
|
||||
return( true );
|
||||
|
||||
} else if ( strcasecmp( sLine.c_str(), "schat" ) == 0 )
|
||||
{
|
||||
PutModule( "SChat User Area ..." );
|
||||
OnModCommand( "help" );
|
||||
return( true );
|
||||
|
||||
}
|
||||
|
||||
return( false );
|
||||
}
|
||||
virtual void OnModCommand( const string& sCommand )
|
||||
{
|
||||
u_int iPos = sCommand.find( " " );
|
||||
string sCom, sArgs;
|
||||
if ( iPos == string::npos )
|
||||
sCom = sCommand;
|
||||
else
|
||||
{
|
||||
sCom = sCommand.substr( 0, iPos );
|
||||
sArgs = sCommand.substr( iPos + 1, string::npos );
|
||||
}
|
||||
|
||||
if ( ( strcasecmp( sCom.c_str(), "chat" ) == 0 ) && ( !sArgs.empty() ) )
|
||||
{
|
||||
string sSockName = "SCHAT::" + m_pUser->GetUserName();
|
||||
string sNick = "(s)" + sArgs;
|
||||
for( u_int a= 0; a < m_pManager->size(); a++ )
|
||||
{
|
||||
if ( strncmp( (*m_pManager)[a]->GetSockName().c_str(), sSockName.c_str(), sSockName.length() ) != 0 )
|
||||
continue;
|
||||
|
||||
CSChatSock *pSock = (CSChatSock *)(*m_pManager)[a];
|
||||
if ( strcasecmp( pSock->GetChatNick().c_str(), sNick.c_str() ) == 0 )
|
||||
{
|
||||
PutModule( "Already Connected to [" + sArgs + "]" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CSChatSock *pSock = new CSChatSock;
|
||||
pSock->SetCipher( "HIGH" );
|
||||
pSock->SetPemLocation( m_sPemFile );
|
||||
pSock->SetModule( this );
|
||||
pSock->SetChatNick( sNick );
|
||||
|
||||
u_short iPort = m_pManager->ListenRand( sSockName, m_pUser->GetLocalIP(), true, SOMAXCONN, pSock, 60 );
|
||||
|
||||
if ( iPort == 0 )
|
||||
{
|
||||
PutModule( "Failed to start chat!" );
|
||||
return;
|
||||
}
|
||||
|
||||
stringstream s;
|
||||
s << "PRIVMSG " << sArgs << " :\001";
|
||||
s << "DCC SCHAT chat ";
|
||||
s << CUtils::GetLongIP( m_pUser->GetLocalIP() );
|
||||
s << " " << iPort << "\001";
|
||||
|
||||
PutIRC( s.str() );
|
||||
|
||||
} else if ( strcasecmp( sCom.c_str(), "list" ) == 0 )
|
||||
{
|
||||
string sName = "SCHAT::" + m_pUser->GetUserName();
|
||||
CTable Table;
|
||||
Table.AddColumn( "Nick" );
|
||||
Table.AddColumn( "Created" );
|
||||
Table.AddColumn( "Host" );
|
||||
Table.AddColumn( "Port" );
|
||||
Table.AddColumn( "Status" );
|
||||
Table.AddColumn( "Cipher" );
|
||||
for( u_int a= 0; a < m_pManager->size(); a++ )
|
||||
{
|
||||
if ( strncmp( (*m_pManager)[a]->GetSockName().c_str(), sName.c_str(), sName.length() ) != 0 )
|
||||
continue;
|
||||
|
||||
Table.AddRow();
|
||||
|
||||
CSChatSock *pSock = (CSChatSock *)(*m_pManager)[a];
|
||||
Table.SetCell( "Nick", pSock->GetChatNick() );
|
||||
unsigned long long iStartTime = pSock->GetStartTime();
|
||||
time_t iTime = iStartTime / 1000;
|
||||
char *pTime = ctime( &iTime );
|
||||
if ( pTime )
|
||||
{
|
||||
string sTime = pTime;
|
||||
CUtils::Trim( sTime );
|
||||
Table.SetCell( "Created", sTime );
|
||||
}
|
||||
|
||||
if ( pSock->GetType() != CSChatSock::LISTENER )
|
||||
{
|
||||
Table.SetCell( "Status", "Established" );
|
||||
Table.SetCell( "Host", pSock->GetRemoteIP() );
|
||||
Table.SetCell( "Port", CUtils::ToString( pSock->GetRemotePort() ) );
|
||||
SSL_SESSION *pSession = pSock->GetSSLSession();
|
||||
if ( ( pSession ) && ( pSession->cipher ) && ( pSession->cipher->name ) )
|
||||
Table.SetCell( "Cipher", pSession->cipher->name );
|
||||
|
||||
} else
|
||||
{
|
||||
Table.SetCell( "Status", "Waiting" );
|
||||
Table.SetCell( "Port", CUtils::ToString( pSock->GetLocalPort() ) );
|
||||
}
|
||||
}
|
||||
if ( Table.size() )
|
||||
{
|
||||
unsigned int uTableIdx = 0;
|
||||
string sLine;
|
||||
while ( Table.GetLine( uTableIdx++, sLine ) )
|
||||
PutModule( sLine );
|
||||
} else
|
||||
PutModule( "No SDCCs currently in session" );
|
||||
|
||||
} else if ( strcasecmp( sCom.c_str(), "close" ) == 0 )
|
||||
{
|
||||
string sName = "SCHAT::" + m_pUser->GetUserName();
|
||||
for( u_int a= 0; a < m_pManager->size(); a++ )
|
||||
{
|
||||
if ( strncmp( (*m_pManager)[a]->GetSockName().c_str(), sName.c_str(), sName.length() ) != 0 )
|
||||
continue;
|
||||
|
||||
CSChatSock *pSock = (CSChatSock *)(*m_pManager)[a];
|
||||
if ( strncasecmp( sArgs.c_str(), "(s)", 3 ) != 0 )
|
||||
sArgs = "(s)" + sArgs;
|
||||
|
||||
if ( strcasecmp( sArgs.c_str(), pSock->GetChatNick().c_str() ) == 0 )
|
||||
{
|
||||
pSock->Close();
|
||||
return;
|
||||
}
|
||||
PutModule( "No Such Chat [" + sArgs + "]" );
|
||||
}
|
||||
|
||||
} else if ( strcasecmp( sCom.c_str(), "help" ) == 0 )
|
||||
{
|
||||
PutModule( "Commands are: " );
|
||||
PutModule( " help - This text." );
|
||||
PutModule( " chat <nick> - Chat a nick." );
|
||||
PutModule( " list - List current chats." );
|
||||
PutModule( " close <nick> - Close a chat to a nick." );
|
||||
PutModule( " timers - Shows related timers." );
|
||||
} else if ( strcasecmp( sCom.c_str(), "timers" ) == 0 )
|
||||
ListTimers();
|
||||
else
|
||||
PutModule( "Unknown command [" + sCom + "] [" + sArgs + "]" );
|
||||
}
|
||||
|
||||
virtual bool OnPrivCTCP( const CNick& Nick, string& sMessage )
|
||||
{
|
||||
if ( strncasecmp( sMessage.c_str(), "DCC SCHAT ", 10 ) == 0 )
|
||||
{
|
||||
// chat ip port
|
||||
unsigned long iIP = strtoul( CUtils::Token( sMessage, 3 ).c_str(), NULL, 10 );
|
||||
unsigned short iPort = strtoul( CUtils::Token( sMessage, 4 ).c_str(), NULL, 10 );
|
||||
|
||||
if ( ( iIP > 0 ) && ( iPort > 0 ) )
|
||||
{
|
||||
pair<u_long, u_short> pTmp;
|
||||
pTmp.first = iIP;
|
||||
pTmp.second = iPort;
|
||||
m_siiWaitingChats["(s)" + Nick.GetNick()] = pTmp;
|
||||
SendToUser( "(s)" + Nick.GetNick() + "!" + "(s)" + Nick.GetNick() + "@" + CUtils::GetIP( iIP ), "*** Incoming DCC SCHAT, Accept ? (yes/no)" );
|
||||
CRemMarkerJob *p = new CRemMarkerJob( this, 60, 1, "Remove (s)" + Nick.GetNick(), "Removes this nicks entry for waiting DCC." );
|
||||
p->SetNick( "(s)" + Nick.GetNick() );
|
||||
AddTimer( p );
|
||||
return( true );
|
||||
}
|
||||
}
|
||||
|
||||
return( false );
|
||||
}
|
||||
|
||||
void AcceptSDCC( const string & sNick, u_long iIP, u_short iPort )
|
||||
{
|
||||
CSChatSock *p = new CSChatSock( CUtils::GetIP( iIP ), iPort, 60 );
|
||||
p->SetModule( this );
|
||||
p->SetChatNick( sNick );
|
||||
string sSockName = "SCHAT::" + m_pUser->GetUserName() + "::" + sNick;
|
||||
m_pManager->Connect( CUtils::GetIP( iIP ), iPort, sSockName, 60, true, m_pUser->GetLocalIP(), p );
|
||||
RemTimer( "Remove " + sNick ); // delete any associated timer to this nick
|
||||
}
|
||||
virtual bool OnUserMsg( const string& sTarget, string& sMessage )
|
||||
{
|
||||
if ( strncmp( sTarget.c_str(), "(s)", 3 ) == 0 )
|
||||
{
|
||||
string sSockName = "SCHAT::" + m_pUser->GetUserName() + "::" + sTarget;
|
||||
CSChatSock *p = (CSChatSock *)m_pManager->FindSockByName( sSockName );
|
||||
if ( !p )
|
||||
{
|
||||
map< string,pair< u_long,u_short > >::iterator it = m_siiWaitingChats.find( sTarget );
|
||||
if ( it != m_siiWaitingChats.end() )
|
||||
{
|
||||
if ( strcasecmp( sMessage.c_str(), "yes" ) != 0 )
|
||||
SendToUser( sTarget + "!" + sTarget + "@" + CUtils::GetIP( it->second.first ), "Refusing to accept DCC SCHAT!" );
|
||||
else
|
||||
AcceptSDCC( sTarget, it->second.first, it->second.second );
|
||||
|
||||
m_siiWaitingChats.erase( it );
|
||||
return( true );
|
||||
}
|
||||
PutModule( "No such SCHAT to [" + sTarget + "]" );
|
||||
} else
|
||||
p->Write( sMessage + "\n" );
|
||||
|
||||
return( true );
|
||||
}
|
||||
return( false );
|
||||
}
|
||||
|
||||
virtual void RemoveMarker( const string & sNick )
|
||||
{
|
||||
map< string,pair< u_long,u_short > >::iterator it = m_siiWaitingChats.find( sNick );
|
||||
if ( it != m_siiWaitingChats.end() )
|
||||
m_siiWaitingChats.erase( it );
|
||||
}
|
||||
|
||||
void SendToUser( const string & sFrom, const string & sText )
|
||||
{
|
||||
//:*schat!znc@znc.com PRIVMSG Jim :
|
||||
string sSend = ":" + sFrom + " PRIVMSG " + m_pUser->GetCurNick() + " :" + sText;
|
||||
PutUser( sSend );
|
||||
}
|
||||
|
||||
bool IsAttached()
|
||||
{
|
||||
return( m_pUser->IsUserAttached() );
|
||||
}
|
||||
|
||||
private:
|
||||
map< string,pair< u_long,u_short > > m_siiWaitingChats;
|
||||
string m_sPemFile;
|
||||
};
|
||||
|
||||
|
||||
//////////////////// methods ////////////////
|
||||
|
||||
void CSChatSock::ReadLine( const CS_STRING & sLine )
|
||||
{
|
||||
if ( m_pModule )
|
||||
{
|
||||
string sText = sLine;
|
||||
CUtils::Trim( sText );
|
||||
if ( m_pModule->IsAttached() )
|
||||
m_pModule->SendToUser( m_sChatNick + "!" + m_sChatNick + "@" + GetRemoteIP(), sText );
|
||||
else
|
||||
AddLine( sText );
|
||||
}
|
||||
}
|
||||
|
||||
void CSChatSock::Disconnected()
|
||||
{
|
||||
if ( m_pModule )
|
||||
m_pModule->SendToUser( m_sChatNick + "!" + m_sChatNick + "@" + GetRemoteIP(), "*** Disconnected." );
|
||||
}
|
||||
|
||||
void CSChatSock::Connected()
|
||||
{
|
||||
SetTimeout( 0 );
|
||||
if ( m_pModule )
|
||||
m_pModule->SendToUser( m_sChatNick + "!" + m_sChatNick + "@" + GetRemoteIP(), "*** Connected." );
|
||||
}
|
||||
|
||||
void CSChatSock::Timeout()
|
||||
{
|
||||
if ( m_pModule )
|
||||
{
|
||||
if ( GetType() == LISTENER )
|
||||
m_pModule->PutModule( "Timeout while waiting for [" + m_sChatNick + "]" );
|
||||
else
|
||||
m_pModule->SendToUser( m_sChatNick + "!" + m_sChatNick + "@" + GetRemoteIP(), "*** Connection Timed out." );
|
||||
}
|
||||
}
|
||||
|
||||
void CRemMarkerJob::RunJob()
|
||||
{
|
||||
CSChat *p = (CSChat *)m_pModule;
|
||||
p->RemoveMarker( m_sNick );
|
||||
|
||||
// store buffer
|
||||
}
|
||||
MODULEDEFS(CSChat)
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
#ifndef _NO_CSOCKET_NS
|
||||
#define _NO_CSOCKET_NS
|
||||
#endif
|
||||
|
||||
#include "Csocket.h"
|
||||
#include "User.h"
|
||||
#include "Nick.h"
|
||||
#include "Modules.h"
|
||||
#include "Chan.h"
|
||||
#include "Utils.h"
|
||||
#include <sys/wait.h>
|
||||
|
||||
// Forward Declaration
|
||||
class CShellMod;
|
||||
|
||||
class CExecSock : public Csock {
|
||||
public:
|
||||
CExecSock(CShellMod* pShellMod, const string& sExec) : Csock() {
|
||||
EnableReadLine();
|
||||
m_pParent = pShellMod;
|
||||
int iReadFD, iWriteFD;
|
||||
m_iPid = popen2(iReadFD, iWriteFD, sExec);
|
||||
ConnectFD(iReadFD, iWriteFD, "0.0.0.0:0");
|
||||
}
|
||||
|
||||
virtual ~CExecSock() {
|
||||
close2(m_iPid, GetRSock(), GetWSock());
|
||||
SetRSock( -1 );
|
||||
SetWSock( -1 );
|
||||
}
|
||||
|
||||
// These next two function's bodies are at the bottom of the file since they reference CShellMod
|
||||
virtual void ReadLine(const string& sData);
|
||||
virtual void Disconnected();
|
||||
|
||||
CShellMod* m_pParent;
|
||||
int m_iPid;
|
||||
|
||||
int popen2(int & iReadFD, int & iWriteFD, const string & sCommand) {
|
||||
int rpipes[2] = { -1, -1 };
|
||||
int wpipes[2] = { -1, -1 };
|
||||
iReadFD = -1;
|
||||
iWriteFD = -1;
|
||||
|
||||
pipe(rpipes);
|
||||
pipe(wpipes);
|
||||
|
||||
int iPid = fork();
|
||||
|
||||
if (iPid == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iPid == 0) {
|
||||
close(wpipes[1]);
|
||||
close(rpipes[0]);
|
||||
dup2(wpipes[0], 0);
|
||||
dup2(rpipes[1], 1);
|
||||
dup2(rpipes[1], 2);
|
||||
close(wpipes[0]);
|
||||
close(rpipes[1]);
|
||||
system( sCommand.c_str() );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(wpipes[0]);
|
||||
close(rpipes[1]);
|
||||
|
||||
iWriteFD = wpipes[1];
|
||||
iReadFD = rpipes[0];
|
||||
|
||||
return iPid;
|
||||
}
|
||||
|
||||
void close2(int iPid, int iReadFD, int iWriteFD) {
|
||||
close( iReadFD );
|
||||
close( iWriteFD );
|
||||
u_int iNow = time( NULL );
|
||||
while( waitpid( iPid, NULL, WNOHANG ) == 0 )
|
||||
{
|
||||
if ( ( time( NULL ) - iNow ) > 5 )
|
||||
break; // giveup
|
||||
usleep( 100 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
class CShellMod : public CModule {
|
||||
public:
|
||||
MODCONSTRUCTOR(CShellMod) {
|
||||
m_sPath = pUser->GetHomePath();
|
||||
}
|
||||
|
||||
virtual ~CShellMod() {
|
||||
vector<Csock*> vSocks = m_pManager->FindSocksByName("SHELL");
|
||||
|
||||
for (unsigned int a = 0; a < vSocks.size(); a++) {
|
||||
m_pManager->DelSockByAddr(vSocks[a]);
|
||||
}
|
||||
}
|
||||
|
||||
virtual string GetDescription() {
|
||||
return "Gives shell access.";
|
||||
}
|
||||
|
||||
virtual void OnModCommand(const string& sCommand) {
|
||||
if ((strcasecmp(sCommand.c_str(), "cd") == 0) || (strncasecmp(sCommand.c_str(), "cd ", 3) == 0)) {
|
||||
string sPath = CUtils::ChangeDir(m_sPath, ((sCommand.length() == 2) ? m_pUser->GetHomePath() : sCommand.substr(3)), m_pUser->GetHomePath());
|
||||
CFile Dir(sPath);
|
||||
|
||||
if (Dir.IsDir()) {
|
||||
m_sPath = sPath;
|
||||
} else if (Dir.Exists()) {
|
||||
PutShell("cd: not a directory [" + sPath + "]");
|
||||
} else {
|
||||
PutShell("cd: no such directory [" + sPath + "]");
|
||||
}
|
||||
|
||||
PutShell("znc$");
|
||||
} else if (strcasecmp(CUtils::Token(sCommand, 0).c_str(), "SEND") == 0) {
|
||||
string sToNick = CUtils::Token(sCommand, 1);
|
||||
string sFile = CUtils::Token(sCommand, 2);
|
||||
|
||||
if ((sToNick.empty()) || (sFile.empty())) {
|
||||
PutShell("usage: Send <nick> <file>");
|
||||
} else {
|
||||
sFile = CUtils::ChangeDir(m_sPath, sFile, m_pUser->GetHomePath());
|
||||
|
||||
if (!CFile::Exists(sFile)) {
|
||||
PutShell("get: no such file [" + sFile + "]");
|
||||
} else if (!CFile::IsReg(sFile)) {
|
||||
PutShell("get: not a file [" + sFile + "]");
|
||||
} else {
|
||||
m_pUser->SendFile(sToNick, sFile, GetModName());
|
||||
}
|
||||
}
|
||||
} else if (strcasecmp(CUtils::Token(sCommand, 0).c_str(), "GET") == 0) {
|
||||
string sFile = CUtils::Token(sCommand, 1);
|
||||
|
||||
if (sFile.empty()) {
|
||||
PutShell("usage: Get <file>");
|
||||
} else {
|
||||
sFile = CUtils::ChangeDir(m_sPath, sFile, m_pUser->GetHomePath());
|
||||
|
||||
if (!CFile::Exists(sFile)) {
|
||||
PutShell("get: no such file [" + sFile + "]");
|
||||
} else if (!CFile::IsReg(sFile)) {
|
||||
PutShell("get: not a file [" + sFile + "]");
|
||||
} else {
|
||||
m_pUser->SendFile(m_pUser->GetCurNick(), sFile, GetModName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RunCommand(sCommand);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool OnStatusCommand(const string& sCommand) {
|
||||
if (strcasecmp(sCommand.c_str(), "SHELL") == 0) {
|
||||
PutShell("-- ZNC Shell Service --");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnDCCUserSend(const CNick& RemoteNick, unsigned long uLongIP, unsigned short uPort, const string& sFile, unsigned long uFileSize) {
|
||||
if (strcasecmp(RemoteNick.GetNick().c_str(), string(GetModNick()).c_str()) == 0) {
|
||||
string sLocalFile = CUtils::ChangeDir(m_sPath, sFile, m_pUser->GetHomePath());
|
||||
|
||||
m_pUser->GetFile(m_pUser->GetCurNick(), CUtils::GetIP(uLongIP), uPort, sLocalFile, uFileSize, GetModName());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PutShell(const string& sLine) {
|
||||
string sPath = m_sPath;
|
||||
|
||||
unsigned int a = sPath.find(' ');
|
||||
while (a != string::npos) {
|
||||
sPath.replace(a, 1, "_");
|
||||
a = sPath.find(' ');
|
||||
}
|
||||
|
||||
PutModule(sLine, m_pUser->GetCurNick(), sPath);
|
||||
}
|
||||
|
||||
void RunCommand(const string& sCommand) {
|
||||
m_pManager->AddSock((Csock*) new CExecSock(this, "cd " + m_sPath + " && " + sCommand), "SHELL");
|
||||
}
|
||||
private:
|
||||
string m_sPath;
|
||||
};
|
||||
|
||||
void CExecSock::ReadLine(const string& sData) {
|
||||
string sLine = sData;
|
||||
|
||||
while ((sLine.length()) && (sLine[sLine.length() -1] == '\r') || (sLine[sLine.length() -1] == '\n')) {
|
||||
sLine = sLine.substr(0, sLine.length() -1);
|
||||
}
|
||||
|
||||
unsigned int a = sLine.find('\t');
|
||||
while (a != string::npos) {
|
||||
sLine.replace(a, 1, " ");
|
||||
a = sLine.find('\t');
|
||||
}
|
||||
|
||||
m_pParent->PutShell(sLine);
|
||||
}
|
||||
|
||||
void CExecSock::Disconnected() {
|
||||
m_pParent->PutShell("znc$");
|
||||
}
|
||||
|
||||
MODULEDEFS(CShellMod)
|
||||
|
||||
Reference in New Issue
Block a user