Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Move dcc file transfers to their own module

  • Loading branch information...
commit 16047eaf8156f8636e8bb8f0319367829292e0f9 1 parent 8f508cb
@kylef kylef authored
View
12 Client.cpp
@@ -369,18 +369,6 @@ void CClient::ReadLine(const CString& sData) {
sCTCP.RightChomp();
if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
- if (sCTCP.Equals("DCC RESUME ", false, 11)) {
- CString sFile = sCTCP.Token(2);
- unsigned short uResumePort = sCTCP.Token(3).ToUShort();
- unsigned long uResumeSize = sCTCP.Token(4).ToULong();
-
- if (m_pUser->ResumeFile(uResumePort, uResumeSize)) {
- PutClient(":" + sTarget + "!znc@znc.in PRIVMSG " + GetNick() + " :\001DCC ACCEPT " + sFile + " " + CString(uResumePort) + " " + CString(uResumeSize) + "\001");
- } else {
- PutStatus("DCC -> [" + GetNick() + "][" + sFile + "] Unable to find send to initiate resume.");
- }
- }
-
if (sTarget.Equals("status")) {
StatusCTCP(sCTCP);
} else {
View
103 ClientCommand.cpp
@@ -8,7 +8,6 @@
#include "Client.h"
#include "Chan.h"
-#include "DCCSock.h"
#include "FileUtils.h"
#include "IRCSock.h"
#include "Listener.h"
@@ -469,94 +468,6 @@ void CClient::UserCommand(CString& sLine) {
}
PutStatus(Table);
- } else if (sCommand.Equals("SEND")) {
- CString sToNick = sLine.Token(1);
- CString sFile = sLine.Token(2);
- CString sAllowedPath = m_pUser->GetDLPath();
- CString sAbsolutePath;
-
- if ((sToNick.empty()) || (sFile.empty())) {
- PutStatus("Usage: Send <nick> <file>");
- return;
- }
-
- sAbsolutePath = CDir::CheckPathPrefix(sAllowedPath, sFile);
-
- if (sAbsolutePath.empty()) {
- PutStatus("Illegal path.");
- return;
- }
-
- m_pUser->SendFile(sToNick, sFile);
- } else if (sCommand.Equals("GET")) {
- CString sFile = sLine.Token(1);
- CString sAllowedPath = m_pUser->GetDLPath();
- CString sAbsolutePath;
-
- if (sFile.empty()) {
- PutStatus("Usage: Get <file>");
- return;
- }
-
- sAbsolutePath = CDir::CheckPathPrefix(sAllowedPath, sFile);
-
- if (sAbsolutePath.empty()) {
- PutStatus("Illegal path.");
- return;
- }
-
- m_pUser->SendFile(GetNick(), sFile);
- } else if (sCommand.Equals("LISTDCCS")) {
- CSockManager& Manager = CZNC::Get().GetManager();
-
- CTable Table;
- Table.AddColumn("Type");
- Table.AddColumn("State");
- Table.AddColumn("Speed");
- Table.AddColumn("Nick");
- Table.AddColumn("IP");
- Table.AddColumn("File");
-
- for (unsigned int a = 0; a < Manager.size(); a++) {
- CString sSockName = Manager[a]->GetSockName();
-
- if (sSockName.TrimPrefix("DCC::")) {
- if (sSockName.Equals("SEND", false, 4)) {
- CDCCSock* pSock = (CDCCSock*) Manager[a];
-
- Table.AddRow();
- Table.SetCell("Type", "Sending");
- Table.SetCell("State", CString::ToPercent(pSock->GetProgress()));
- Table.SetCell("Speed", CString((int)(pSock->GetAvgWrite() / 1024.0)) + " KiB/s");
- Table.SetCell("Nick", pSock->GetRemoteNick());
- Table.SetCell("IP", pSock->GetRemoteIP());
- Table.SetCell("File", pSock->GetFileName());
- } else if (sSockName.Equals("GET", false, 3)) {
- CDCCSock* pSock = (CDCCSock*) Manager[a];
-
- Table.AddRow();
- Table.SetCell("Type", "Getting");
- Table.SetCell("State", CString::ToPercent(pSock->GetProgress()));
- Table.SetCell("Speed", CString((int)(pSock->GetAvgRead() / 1024.0)) + " KiB/s");
- Table.SetCell("Nick", pSock->GetRemoteNick());
- Table.SetCell("IP", pSock->GetRemoteIP());
- Table.SetCell("File", pSock->GetFileName());
- } else if (sSockName.Equals("LISTEN", false, 6)) {
- CDCCSock* pSock = (CDCCSock*) Manager[a];
-
- Table.AddRow();
- Table.SetCell("Type", "Sending");
- Table.SetCell("State", "Waiting");
- Table.SetCell("Nick", pSock->GetRemoteNick());
- Table.SetCell("IP", pSock->GetRemoteIP());
- Table.SetCell("File", pSock->GetFileName());
- }
- }
- }
-
- if (PutStatus(Table) == 0) {
- PutStatus("You have no active DCCs.");
- }
} else if (sCommand.Equals("LISTMODS") || sCommand.Equals("LISTMODULES")) {
if (m_pUser->IsAdmin()) {
CModules& GModules = CZNC::Get().GetModules();
@@ -1108,10 +1019,6 @@ void CClient::HelpUser() {
Table.SetCell("Description", "Print which version of ZNC this is");
Table.AddRow();
- Table.SetCell("Command", "ListDCCs");
- Table.SetCell("Description", "List all active DCCs");
-
- Table.AddRow();
Table.SetCell("Command", "ListMods");
Table.SetCell("Description", "List all loaded modules");
@@ -1224,16 +1131,6 @@ void CClient::HelpUser() {
Table.SetCell("Description", "Reconnect to IRC");
Table.AddRow();
- Table.SetCell("Command", "Send");
- Table.SetCell("Arguments", "<nick> <file>");
- Table.SetCell("Description", "Send a shell file to a nick on IRC");
-
- Table.AddRow();
- Table.SetCell("Command", "Get");
- Table.SetCell("Arguments", "<file>");
- Table.SetCell("Description", "Send a shell file to yourself");
-
- Table.AddRow();
Table.SetCell("Command", "Uptime");
Table.SetCell("Description", "Show for how long ZNC has been running");
View
249 DCCSock.cpp
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2004-2011 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 "DCCSock.h"
-#include "FileUtils.h"
-#include "User.h"
-#include "Utils.h"
-
-CDCCSock::CDCCSock(CUser* pUser, const CString& sRemoteNick, const CString& sLocalFile, const CString& sModuleName,
- unsigned long uFileSize, CFile* pFile) : CZNCSock() {
- m_sRemoteNick = sRemoteNick;
- m_uFileSize = uFileSize;
- m_uRemotePort = 0;
- m_uBytesSoFar = 0;
- m_pUser = pUser;
- m_pFile = pFile;
- m_sLocalFile = sLocalFile;
- m_sModuleName = sModuleName;
- m_bSend = true;
- m_bNoDelFile = false;
-
- m_pUser->AddDCCSock(this);
-}
-
-CDCCSock::CDCCSock(CUser* pUser, const CString& sRemoteNick, const CString& sRemoteIP, unsigned short uRemotePort,
- const CString& sLocalFile, unsigned long uFileSize, const CString& sModuleName) : CZNCSock() {
- m_sRemoteNick = sRemoteNick;
- m_sRemoteIP = sRemoteIP;
- m_uRemotePort = uRemotePort;
- m_uFileSize = uFileSize;
- m_uBytesSoFar = 0;
- m_pUser = pUser;
- m_pFile = NULL;
- m_sLocalFile = sLocalFile;
- m_sModuleName = sModuleName;
- m_bSend = false;
- m_bNoDelFile = false;
-
- m_pUser->AddDCCSock(this);
-}
-
-CDCCSock::~CDCCSock() {
- if ((m_pFile) && (!m_bNoDelFile)) {
- m_pFile->Close();
- delete m_pFile;
- }
-
- m_pUser->AddBytesRead(GetBytesRead());
- m_pUser->AddBytesWritten(GetBytesWritten());
-
- m_pUser->DelDCCSock(this);
-}
-
-void CDCCSock::ReadData(const char* data, size_t len) {
- if (!m_pFile) {
- DEBUG("File not open! closing get.");
- m_pUser->PutModule(m_sModuleName, ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - File not open!");
- Close();
- }
-
- // DCC specs says the receiving end sends the number of bytes it
- // received so far as a 4 byte integer in network byte order, so we need
- // uint32_t to do the job portably. This also means that the maximum
- // file that we can transfer is 4 GiB big (see OpenFile()).
- if (m_bSend) {
- m_sSendBuf.append(data, len);
-
- while (m_sSendBuf.size() >= 4) {
- uint32_t iRemoteSoFar;
- memcpy(&iRemoteSoFar, m_sSendBuf.data(), sizeof(iRemoteSoFar));
- iRemoteSoFar = ntohl(iRemoteSoFar);
-
- if ((iRemoteSoFar + 65536) >= m_uBytesSoFar) {
- SendPacket();
- }
-
- m_sSendBuf.erase(0, 4);
- }
- } else {
- m_pFile->Write(data, len);
- m_uBytesSoFar += len;
- uint32_t uSoFar = htonl(m_uBytesSoFar);
- Write((char*) &uSoFar, sizeof(uSoFar));
-
- if (m_uBytesSoFar >= m_uFileSize) {
- Close();
- }
- }
-}
-
-void CDCCSock::ConnectionRefused() {
- DEBUG(GetSockName() << " == ConnectionRefused()");
- m_pUser->PutModule(m_sModuleName, ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Connection Refused.");
-}
-
-void CDCCSock::Timeout() {
- DEBUG(GetSockName() << " == Timeout()");
- m_pUser->PutModule(m_sModuleName, ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Timed Out.");
-}
-
-void CDCCSock::SockError(int iErrno) {
- DEBUG(GetSockName() << " == SockError(" << iErrno << ")");
- m_pUser->PutModule(m_sModuleName, ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Socket Error [" + CString(iErrno) + "]");
-}
-
-void CDCCSock::Connected() {
- DEBUG(GetSockName() << " == Connected(" << GetRemoteIP() << ")");
- m_pUser->PutModule(m_sModuleName, ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Transfer Started.");
-
- if (m_bSend) {
- SendPacket();
- }
-
- SetTimeout(120);
-}
-
-void CDCCSock::Disconnected() {
- const CString sStart = ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - ";
-
- DEBUG(GetSockName() << " == Disconnected()");
-
- if (m_uBytesSoFar > m_uFileSize) {
- m_pUser->PutModule(m_sModuleName, sStart + "TooMuchData!");
- } else if (m_uBytesSoFar == m_uFileSize) {
- if (m_bSend) {
- m_pUser->PutModule(m_sModuleName, sStart + "Completed! - Sent [" + m_sLocalFile +
- "] at [" + CString((int) (GetAvgWrite() / 1024.0)) + " KiB/s ]");
- } else {
- m_pUser->PutModule(m_sModuleName, sStart + "Completed! - Saved to [" + m_sLocalFile +
- "] at [" + CString((int) (GetAvgRead() / 1024.0)) + " KiB/s ]");
- }
- } else {
- m_pUser->PutModule(m_sModuleName, sStart + "Incomplete!");
- }
-}
-
-void CDCCSock::SendPacket() {
- if (!m_pFile) {
- m_pUser->PutModule(m_sModuleName, ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - File closed prematurely.");
- Close();
- return;
- }
-
- if (GetInternalWriteBuffer().size() > 1024 * 1024) {
- // There is still enough data to be written, don't add more
- // stuff to that buffer.
- DEBUG("SendPacket(): Skipping send, buffer still full enough [" << GetInternalWriteBuffer().size() << "]["
- << m_sRemoteNick << "][" << m_sFileName << "]");
- return;
- }
-
- char szBuf[4096];
- int iLen = m_pFile->Read(szBuf, 4096);
-
- if (iLen < 0) {
- m_pUser->PutModule(m_sModuleName, ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Error reading from file.");
- Close();
- return;
- }
-
- if (iLen > 0) {
- Write(szBuf, iLen);
- m_uBytesSoFar += iLen;
- }
-}
-
-Csock* CDCCSock::GetSockObj(const CString& sHost, unsigned short uPort) {
- Close();
-
- CDCCSock* pSock = new CDCCSock(m_pUser, m_sRemoteNick, m_sLocalFile, m_sModuleName, m_uFileSize, m_pFile);
- pSock->SetSockName("DCC::SEND::" + m_sRemoteNick);
- pSock->SetTimeout(120);
- pSock->SetFileName(m_sFileName);
- pSock->SetFileOffset(m_uBytesSoFar);
- m_bNoDelFile = true;
-
- return pSock;
-}
-
-CFile* CDCCSock::OpenFile(bool bWrite) {
- if ((m_pFile) || (m_sLocalFile.empty())) {
- m_pUser->PutModule(m_sModuleName, ((bWrite) ? "DCC <- [" : "DCC -> [") + m_sRemoteNick + "][" + m_sLocalFile + "] - Unable to open file.");
- return NULL;
- }
-
- m_pFile = new CFile(m_sLocalFile);
-
- if (bWrite) {
- if (m_pFile->Exists()) {
- delete m_pFile;
- m_pFile = NULL;
- m_pUser->PutModule(m_sModuleName, "DCC <- [" + m_sRemoteNick + "] - File already exists [" + m_sLocalFile + "]");
- return NULL;
- }
-
- if (!m_pFile->Open(O_WRONLY | O_TRUNC | O_CREAT)) {
- delete m_pFile;
- m_pFile = NULL;
- m_pUser->PutModule(m_sModuleName, "DCC <- [" + m_sRemoteNick + "] - Could not open file [" + m_sLocalFile + "]");
- return NULL;
- }
- } else {
- if (!m_pFile->IsReg()) {
- delete m_pFile;
- m_pFile = NULL;
- m_pUser->PutModule(m_sModuleName, "DCC -> [" + m_sRemoteNick + "] - Not a file [" + m_sLocalFile + "]");
- return NULL;
- }
-
- if (!m_pFile->Open()) {
- delete m_pFile;
- m_pFile = NULL;
- m_pUser->PutModule(m_sModuleName, "DCC -> [" + m_sRemoteNick + "] - Could not open file [" + m_sLocalFile + "]");
- return NULL;
- }
-
- // The DCC specs only allow file transfers with files smaller
- // than 4GiB (see ReadData()).
- unsigned long long uFileSize = m_pFile->GetSize();
- if (uFileSize > (unsigned long long) 0xffffffff) {
- delete m_pFile;
- m_pFile = NULL;
- m_pUser->PutModule(m_sModuleName, "DCC -> [" + m_sRemoteNick + "] - File too large (>4 GiB) [" + m_sLocalFile + "]");
- return NULL;
- }
-
- m_uFileSize = (unsigned long) uFileSize;
- }
-
- m_sFileName = m_pFile->GetShortName();
-
- return m_pFile;
-}
-
-bool CDCCSock::Seek(unsigned int uPos) {
- if (m_pFile) {
- if (m_pFile->Seek(uPos)) {
- m_uBytesSoFar = uPos;
- return true;
- }
- }
-
- return false;
-}
View
72 DCCSock.h
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2004-2011 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.
- */
-
-#ifndef _DCCSOCK_H
-#define _DCCSOCK_H
-
-#include "zncconfig.h"
-#include "Socket.h"
-
-// Forward Declarations
-class CUser;
-class CFile;
-// !Forward Declarations
-
-class CDCCSock : public CZNCSock {
-public:
- CDCCSock(CUser* pUser, const CString& sRemoteNick, const CString& sLocalFile, const CString& sModuleName, unsigned long uFileSize = 0, CFile* pFile = NULL);
- CDCCSock(CUser* pUser, const CString& sRemoteNick, const CString& sRemoteIP, unsigned short uRemotePort, const CString& sLocalFile, unsigned long uFileSize, const CString& sModuleName);
- virtual ~CDCCSock();
-
- virtual void ReadData(const char* data, size_t len);
- virtual void ConnectionRefused();
- virtual void SockError(int iErrno);
- virtual void Timeout();
- virtual void Connected();
- virtual void Disconnected();
- void SendPacket();
- virtual Csock* GetSockObj(const CString& sHost, unsigned short uPort);
- CFile* OpenFile(bool bWrite = true);
- bool Seek(unsigned int uPos);
-
- // Setters
- void SetRemoteIP(const CString& s) { m_sRemoteIP = s; }
- void SetRemoteNick(const CString& s) { m_sRemoteNick = s; }
- void SetFileName(const CString& s) { m_sFileName = s; }
- void SetFileOffset(unsigned long u) { m_uBytesSoFar = u; }
- // !Setters
-
- // Getters
- unsigned short GetUserPort() const { return m_uRemotePort; }
- const CString& GetRemoteNick() const { return m_sRemoteNick; }
- const CString& GetFileName() const { return m_sFileName; }
- const CString& GetLocalFile() const { return m_sLocalFile; }
- const CString& GetModuleName() const { return m_sModuleName; }
- CFile* GetFile() { return m_pFile; }
- double GetProgress() const { return ((m_uFileSize) && (m_uBytesSoFar)) ? (double) (((double) m_uBytesSoFar / (double) m_uFileSize) *100.0) : 0; }
- //const CString& GetRemoteIP() const { return m_sRemoteIP; }
- // !Getters
-private:
-protected:
- CString m_sRemoteNick;
- CString m_sRemoteIP;
- CString m_sFileName;
- CString m_sLocalFile;
- CString m_sSendBuf;
- CString m_sModuleName;
- unsigned short m_uRemotePort;
- unsigned long m_uFileSize;
- unsigned long m_uBytesSoFar;
- bool m_bSend;
- bool m_bNoDelFile;
- CFile* m_pFile;
- CUser* m_pUser;
-};
-
-#endif // !_DCCSOCK_H
-
View
2  Makefile.in
@@ -29,7 +29,7 @@ INSTALL_SCRIPT := @INSTALL_SCRIPT@
INSTALL_DATA := @INSTALL_DATA@
LIB_SRCS := ZNCString.cpp Csocket.cpp znc.cpp User.cpp IRCSock.cpp Client.cpp \
- DCCSock.cpp Chan.cpp Nick.cpp Server.cpp Modules.cpp MD5.cpp Buffer.cpp Utils.cpp \
+ Chan.cpp Nick.cpp Server.cpp Modules.cpp MD5.cpp Buffer.cpp Utils.cpp \
FileUtils.cpp HTTPSock.cpp Template.cpp ClientCommand.cpp Socket.cpp SHA256.cpp \
WebModules.cpp Listener.cpp Config.cpp ZNCDebug.cpp
BIN_SRCS := main.cpp
View
74 User.cpp
@@ -9,7 +9,6 @@
#include "User.h"
#include "Chan.h"
#include "Config.h"
-#include "DCCSock.h"
#include "FileUtils.h"
#include "IRCSock.h"
#include "Server.h"
@@ -101,11 +100,6 @@ CUser::~CUser() {
delete m_vChans[b];
}
- // This will cause an endless loop if the destructor doesn't remove the
- // socket from this list / if the socket doesn't exist any more.
- while (!m_sDCCSocks.empty())
- CZNC::Get().GetManager().DelSockByAddr((CZNCSock*) *m_sDCCSocks.begin());
-
CZNC::Get().GetManager().DelCronByAddr(m_pUserTimer);
}
@@ -1327,74 +1321,6 @@ bool CUser::PutModNotice(const CString& sModule, const CString& sLine, CClient*
return (pClient == NULL);
}
-bool CUser::ResumeFile(unsigned short uPort, unsigned long uFileSize) {
- CSockManager& Manager = CZNC::Get().GetManager();
-
- for (unsigned int a = 0; a < Manager.size(); a++) {
- if (Manager[a]->GetSockName().Equals("DCC::LISTEN::", false, 13)) {
- CDCCSock* pSock = (CDCCSock*) Manager[a];
-
- if (pSock->GetLocalPort() == uPort) {
- if (pSock->Seek(uFileSize)) {
- PutModule(pSock->GetModuleName(), "DCC -> [" + pSock->GetRemoteNick() + "][" + pSock->GetFileName() + "] - Attempting to resume from file position [" + CString(uFileSize) + "]");
- return true;
- } else {
- return false;
- }
- }
- }
- }
-
- return false;
-}
-
-bool CUser::SendFile(const CString& sRemoteNick, const CString& sFileName, const CString& sModuleName) {
- CString sFullPath = CDir::ChangeDir(GetDLPath(), sFileName, CZNC::Get().GetHomePath());
- CDCCSock* pSock = new CDCCSock(this, sRemoteNick, sFullPath, sModuleName);
-
- CFile* pFile = pSock->OpenFile(false);
-
- if (!pFile) {
- delete pSock;
- return false;
- }
-
- unsigned short uPort = CZNC::Get().GetManager().ListenRand("DCC::LISTEN::" + sRemoteNick, GetLocalDCCIP(), false, SOMAXCONN, pSock, 120);
-
- if (GetNick().Equals(sRemoteNick)) {
- PutUser(":" + GetStatusPrefix() + "status!znc@znc.in PRIVMSG " + sRemoteNick + " :\001DCC SEND " + pFile->GetShortName() + " " + CString(CUtils::GetLongIP(GetLocalDCCIP())) + " "
- + CString(uPort) + " " + CString(pFile->GetSize()) + "\001");
- } else {
- PutIRC("PRIVMSG " + sRemoteNick + " :\001DCC SEND " + pFile->GetShortName() + " " + CString(CUtils::GetLongIP(GetLocalDCCIP())) + " "
- + CString(uPort) + " " + CString(pFile->GetSize()) + "\001");
- }
-
- PutModule(sModuleName, "DCC -> [" + sRemoteNick + "][" + pFile->GetShortName() + "] - Attempting Send.");
- return true;
-}
-
-bool CUser::GetFile(const CString& sRemoteNick, const CString& sRemoteIP, unsigned short uRemotePort, const CString& sFileName, unsigned long uFileSize, const CString& sModuleName) {
- if (CFile::Exists(sFileName)) {
- PutModule(sModuleName, "DCC <- [" + sRemoteNick + "][" + sFileName + "] - File already exists.");
- return false;
- }
-
- CDCCSock* pSock = new CDCCSock(this, sRemoteNick, sRemoteIP, uRemotePort, sFileName, uFileSize, sModuleName);
-
- if (!pSock->OpenFile()) {
- delete pSock;
- return false;
- }
-
- if (!CZNC::Get().GetManager().Connect(sRemoteIP, uRemotePort, "DCC::GET::" + sRemoteNick, 60, false, GetLocalDCCIP(), pSock)) {
- PutModule(sModuleName, "DCC <- [" + sRemoteNick + "][" + sFileName + "] - Unable to connect.");
- return false;
- }
-
- PutModule(sModuleName, "DCC <- [" + sRemoteNick + "][" + sFileName + "] - Attempting to connect to [" + sRemoteIP + "]");
- return true;
-}
-
CString CUser::GetCurNick() const {
const CIRCSock* pIRCSock = GetIRCSock();
View
5 User.h
@@ -26,7 +26,6 @@ class CFile;
class CIRCSock;
class CUserTimer;
class CServer;
-class CDCCSock;
class CUser {
public:
@@ -116,9 +115,6 @@ class CUser {
void IRCDisconnected();
void CheckIRCConnect();
- void AddDCCSock(CDCCSock* p) { m_sDCCSocks.insert(p); }
- void DelDCCSock(CDCCSock* p) { m_sDCCSocks.erase(p); }
-
CString ExpandString(const CString& sStr) const;
CString& ExpandString(const CString& sStr, CString& sRet) const;
@@ -271,7 +267,6 @@ class CUser {
vector<CServer*> m_vServers;
vector<CChan*> m_vChans;
vector<CClient*> m_vClients;
- set<CDCCSock*> m_sDCCSocks;
set<CString> m_ssAllowedHosts;
unsigned int m_uServerIdx; ///< Index in m_vServers of our current server + 1
unsigned int m_uBufferCount;
View
478 modules/extra/dcc.cpp
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2004-2011 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 "Chan.h"
+#include "User.h"
+#include "Modules.h"
+#include "FileUtils.h"
+
+class CDCCMod;
+
+class CDCCSock : public CSocket {
+public:
+ CDCCSock(CDCCMod* pMod, const CString& sRemoteNick, const CString& sLocalFile, unsigned long uFileSize = 0, CFile* pFile = NULL);
+ CDCCSock(CDCCMod* pMod, const CString& sRemoteNick, const CString& sRemoteIP, unsigned short uRemotePort, const CString& sLocalFile, unsigned long uFileSize);
+ virtual ~CDCCSock();
+
+ virtual void ReadData(const char* data, size_t len);
+ virtual void ConnectionRefused();
+ virtual void SockError(int iErrno);
+ virtual void Timeout();
+ virtual void Connected();
+ virtual void Disconnected();
+ void SendPacket();
+ virtual Csock* GetSockObj(const CString& sHost, unsigned short uPort);
+ CFile* OpenFile(bool bWrite = true);
+ bool Seek(unsigned int uPos);
+
+ // Setters
+ void SetRemoteIP(const CString& s) { m_sRemoteIP = s; }
+ void SetRemoteNick(const CString& s) { m_sRemoteNick = s; }
+ void SetFileName(const CString& s) { m_sFileName = s; }
+ void SetFileOffset(unsigned long u) { m_uBytesSoFar = u; }
+ // !Setters
+
+ // Getters
+ unsigned short GetUserPort() const { return m_uRemotePort; }
+ const CString& GetRemoteNick() const { return m_sRemoteNick; }
+ const CString& GetFileName() const { return m_sFileName; }
+ const CString& GetLocalFile() const { return m_sLocalFile; }
+ CFile* GetFile() { return m_pFile; }
+ double GetProgress() const { return ((m_uFileSize) && (m_uBytesSoFar)) ? (double) (((double) m_uBytesSoFar / (double) m_uFileSize) *100.0) : 0; }
+ bool IsSend() const { return m_bSend; }
+ //const CString& GetRemoteIP() const { return m_sRemoteIP; }
+ // !Getters
+private:
+protected:
+ CString m_sRemoteNick;
+ CString m_sRemoteIP;
+ CString m_sFileName;
+ CString m_sLocalFile;
+ CString m_sSendBuf;
+ unsigned short m_uRemotePort;
+ unsigned long m_uFileSize;
+ unsigned long m_uBytesSoFar;
+ bool m_bSend;
+ bool m_bNoDelFile;
+ CFile* m_pFile;
+ CDCCMod* m_pModule;
+};
+
+class CDCCMod : public CModule {
+public:
+ MODCONSTRUCTOR(CDCCMod) {
+ AddHelpCommand();
+ AddCommand("Send", static_cast<CModCommand::ModCmdFunc>(&CDCCMod::SendCommand),
+ "<nick> <file>");
+ AddCommand("Get", static_cast<CModCommand::ModCmdFunc>(&CDCCMod::GetCommand),
+ "<file>");
+ AddCommand("ListTransfers", static_cast<CModCommand::ModCmdFunc>(&CDCCMod::ListTransfersCommand));
+ }
+
+ virtual ~CDCCMod() {}
+
+#ifndef MOD_DCC_ALLOW_EVERYONE
+ virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
+ if (!m_pUser->IsAdmin()) {
+ sMessage = "You must be admin to use the DCC module";
+ return false;
+ }
+
+ return true;
+ }
+#endif
+
+ bool SendFile(const CString& sRemoteNick, const CString& sFileName) {
+ CString sFullPath = CDir::ChangeDir(m_pUser->GetDLPath(), sFileName, CZNC::Get().GetHomePath());
+ CDCCSock* pSock = new CDCCSock(this, sRemoteNick, sFullPath);
+
+ CFile* pFile = pSock->OpenFile(false);
+
+ if (!pFile) {
+ delete pSock;
+ return false;
+ }
+
+ unsigned short uPort = CZNC::Get().GetManager().ListenRand("DCC::LISTEN::" + sRemoteNick, m_pUser->GetLocalDCCIP(), false, SOMAXCONN, pSock, 120);
+
+ if (m_pUser->GetNick().Equals(sRemoteNick)) {
+ PutUser(":*dcc!znc@znc.in PRIVMSG " + sRemoteNick + " :\001DCC SEND " + pFile->GetShortName() + " " + CString(CUtils::GetLongIP(m_pUser->GetLocalDCCIP())) + " "
+ + CString(uPort) + " " + CString(pFile->GetSize()) + "\001");
+ } else {
+ PutIRC("PRIVMSG " + sRemoteNick + " :\001DCC SEND " + pFile->GetShortName() + " " + CString(CUtils::GetLongIP(m_pUser->GetLocalDCCIP())) + " "
+ + CString(uPort) + " " + CString(pFile->GetSize()) + "\001");
+ }
+
+ PutModule("DCC -> [" + sRemoteNick + "][" + pFile->GetShortName() + "] - Attempting Send.");
+ return true;
+ }
+
+ bool GetFile(const CString& sRemoteNick, const CString& sRemoteIP, unsigned short uRemotePort, const CString& sFileName, unsigned long uFileSize) {
+ if (CFile::Exists(sFileName)) {
+ PutModule("DCC <- [" + sRemoteNick + "][" + sFileName + "] - File already exists.");
+ return false;
+ }
+
+ CDCCSock* pSock = new CDCCSock(this, sRemoteNick, sRemoteIP, uRemotePort, sFileName, uFileSize);
+
+ if (!pSock->OpenFile()) {
+ delete pSock;
+ return false;
+ }
+
+ if (!CZNC::Get().GetManager().Connect(sRemoteIP, uRemotePort, "DCC::GET::" + sRemoteNick, 60, false, m_pUser->GetLocalDCCIP(), pSock)) {
+ PutModule("DCC <- [" + sRemoteNick + "][" + sFileName + "] - Unable to connect.");
+ return false;
+ }
+
+ PutModule("DCC <- [" + sRemoteNick + "][" + sFileName + "] - Attempting to connect to [" + sRemoteIP + "]");
+ return true;
+ }
+
+ void SendCommand(const CString& sLine) {
+ CString sToNick = sLine.Token(1);
+ CString sFile = sLine.Token(2);
+ CString sAllowedPath = m_pUser->GetDLPath();
+ CString sAbsolutePath;
+
+ if ((sToNick.empty()) || (sFile.empty())) {
+ PutModule("Usage: Send <nick> <file>");
+ return;
+ }
+
+ sAbsolutePath = CDir::CheckPathPrefix(sAllowedPath, sFile);
+
+ if (sAbsolutePath.empty()) {
+ PutStatus("Illegal path.");
+ return;
+ }
+
+ SendFile(sToNick, sFile);
+ }
+
+ void GetCommand(const CString& sLine) {
+ CString sFile = sLine.Token(1);
+ CString sAllowedPath = m_pUser->GetDLPath();
+ CString sAbsolutePath;
+
+ if (sFile.empty()) {
+ PutModule("Usage: Get <file>");
+ return;
+ }
+
+ sAbsolutePath = CDir::CheckPathPrefix(sAllowedPath, sFile);
+
+ if (sAbsolutePath.empty()) {
+ PutModule("Illegal path.");
+ return;
+ }
+
+ SendFile(m_pUser->GetNick(), sFile);
+ }
+
+ void ListTransfersCommand(const CString& sLine) {
+ CTable Table;
+ Table.AddColumn("Type");
+ Table.AddColumn("State");
+ Table.AddColumn("Speed");
+ Table.AddColumn("Nick");
+ Table.AddColumn("IP");
+ Table.AddColumn("File");
+
+ set<CSocket*>::const_iterator it;
+ for (it = BeginSockets(); it != EndSockets(); ++it) {
+ CDCCSock* pSock = (CDCCSock*) *it;
+
+ Table.AddRow();
+ Table.SetCell("Nick", pSock->GetRemoteNick());
+ Table.SetCell("IP", pSock->GetRemoteIP());
+ Table.SetCell("File", pSock->GetFileName());
+
+ if (pSock->IsSend()) {
+ Table.SetCell("Type", "Sending");
+ } else {
+ Table.SetCell("Type", "Getting");
+ }
+
+ if (pSock->GetType() == Csock::LISTENER) {
+ Table.SetCell("State", "Waiting");
+ } else {
+ Table.SetCell("State", CString::ToPercent(pSock->GetProgress()));
+ Table.SetCell("Speed", CString((int)(pSock->GetAvgRead() / 1024.0)) + " KiB/s");
+ }
+ }
+
+ if (PutModule(Table) == 0) {
+ PutModule("You have no active DCC transfers.");
+ }
+ }
+
+ virtual void OnModCTCP(const CString& sMessage) {
+ if (sMessage.Equals("DCC RESUME ", false, 11)) {
+ CString sFile = sMessage.Token(2);
+ unsigned short uResumePort = sMessage.Token(3).ToUShort();
+ unsigned long uResumeSize = sMessage.Token(4).ToULong();
+
+ set<CSocket*>::const_iterator it;
+ for (it = BeginSockets(); it != EndSockets(); ++it) {
+ CDCCSock* pSock = (CDCCSock*) *it;
+
+ if (pSock->GetLocalPort() == uResumePort) {
+ if (pSock->Seek(uResumeSize)) {
+ PutModule("DCC -> [" + pSock->GetRemoteNick() + "][" + pSock->GetFileName() + "] - Attempting to resume from file position [" + CString(uResumeSize) + "]");
+ PutUser(":*dcc!znc@znc.in PRIVMSG " + m_pUser->GetNick() + " :\001DCC ACCEPT " + sFile + " " + CString(uResumePort) + " " + CString(uResumeSize) + "\001");
+ } else {
+ PutModule("DCC -> [" + m_pUser->GetNick() + "][" + sFile + "] Unable to find send to initiate resume.");
+ }
+ }
+
+ }
+ } else if (sMessage.Equals("DCC SEND ", false, 9)) {
+ CString sLocalFile = CDir::CheckPathPrefix(m_pUser->GetDLPath(), sMessage.Token(2));
+ if (sLocalFile.empty()) {
+ PutModule("Bad DCC file: " + sMessage.Token(2));
+ }
+ unsigned long uLongIP = sMessage.Token(3).ToULong();
+ unsigned short uPort = sMessage.Token(4).ToUShort();
+ unsigned long uFileSize = sMessage.Token(5).ToULong();
+ GetFile(m_pUser->GetCurNick(), CUtils::GetIP(uLongIP), uPort, sLocalFile, uFileSize);
+ }
+ }
+};
+
+CDCCSock::CDCCSock(CDCCMod* pMod, const CString& sRemoteNick, const CString& sLocalFile,
+ unsigned long uFileSize, CFile* pFile) : CSocket(pMod) {
+ m_sRemoteNick = sRemoteNick;
+ m_uFileSize = uFileSize;
+ m_uRemotePort = 0;
+ m_uBytesSoFar = 0;
+ m_pModule = pMod;
+ m_pFile = pFile;
+ m_sLocalFile = sLocalFile;
+ m_bSend = true;
+ m_bNoDelFile = false;
+ SetMaxBufferThreshold(0);
+}
+
+CDCCSock::CDCCSock(CDCCMod* pMod, const CString& sRemoteNick, const CString& sRemoteIP, unsigned short uRemotePort,
+ const CString& sLocalFile, unsigned long uFileSize) : CSocket(pMod) {
+ m_sRemoteNick = sRemoteNick;
+ m_sRemoteIP = sRemoteIP;
+ m_uRemotePort = uRemotePort;
+ m_uFileSize = uFileSize;
+ m_uBytesSoFar = 0;
+ m_pModule = pMod;
+ m_pFile = NULL;
+ m_sLocalFile = sLocalFile;
+ m_bSend = false;
+ m_bNoDelFile = false;
+ SetMaxBufferThreshold(0);
+}
+
+CDCCSock::~CDCCSock() {
+ if ((m_pFile) && (!m_bNoDelFile)) {
+ m_pFile->Close();
+ delete m_pFile;
+ }
+}
+
+void CDCCSock::ReadData(const char* data, size_t len) {
+ if (!m_pFile) {
+ DEBUG("File not open! closing get.");
+ m_pModule->PutModule(((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - File not open!");
+ Close();
+ }
+
+ // DCC specs says the receiving end sends the number of bytes it
+ // received so far as a 4 byte integer in network byte order, so we need
+ // uint32_t to do the job portably. This also means that the maximum
+ // file that we can transfer is 4 GiB big (see OpenFile()).
+ if (m_bSend) {
+ m_sSendBuf.append(data, len);
+
+ while (m_sSendBuf.size() >= 4) {
+ uint32_t iRemoteSoFar;
+ memcpy(&iRemoteSoFar, m_sSendBuf.data(), sizeof(iRemoteSoFar));
+ iRemoteSoFar = ntohl(iRemoteSoFar);
+
+ if ((iRemoteSoFar + 65536) >= m_uBytesSoFar) {
+ SendPacket();
+ }
+
+ m_sSendBuf.erase(0, 4);
+ }
+ } else {
+ m_pFile->Write(data, len);
+ m_uBytesSoFar += len;
+ uint32_t uSoFar = htonl(m_uBytesSoFar);
+ Write((char*) &uSoFar, sizeof(uSoFar));
+
+ if (m_uBytesSoFar >= m_uFileSize) {
+ Close();
+ }
+ }
+}
+
+void CDCCSock::ConnectionRefused() {
+ DEBUG(GetSockName() << " == ConnectionRefused()");
+ m_pModule->PutModule(((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Connection Refused.");
+}
+
+void CDCCSock::Timeout() {
+ DEBUG(GetSockName() << " == Timeout()");
+ m_pModule->PutModule(((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Timed Out.");
+}
+
+void CDCCSock::SockError(int iErrno) {
+ DEBUG(GetSockName() << " == SockError(" << iErrno << ")");
+ m_pModule->PutModule(((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Socket Error [" + CString(iErrno) + "]");
+}
+
+void CDCCSock::Connected() {
+ DEBUG(GetSockName() << " == Connected(" << GetRemoteIP() << ")");
+ m_pModule->PutModule(((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Transfer Started.");
+
+ if (m_bSend) {
+ SendPacket();
+ }
+
+ SetTimeout(120);
+}
+
+void CDCCSock::Disconnected() {
+ const CString sStart = ((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - ";
+
+ DEBUG(GetSockName() << " == Disconnected()");
+
+ if (m_uBytesSoFar > m_uFileSize) {
+ m_pModule->PutModule(sStart + "TooMuchData!");
+ } else if (m_uBytesSoFar == m_uFileSize) {
+ if (m_bSend) {
+ m_pModule->PutModule(sStart + "Completed! - Sent [" + m_sLocalFile +
+ "] at [" + CString((int) (GetAvgWrite() / 1024.0)) + " KiB/s ]");
+ } else {
+ m_pModule->PutModule(sStart + "Completed! - Saved to [" + m_sLocalFile +
+ "] at [" + CString((int) (GetAvgRead() / 1024.0)) + " KiB/s ]");
+ }
+ } else {
+ m_pModule->PutModule(sStart + "Incomplete!");
+ }
+}
+
+void CDCCSock::SendPacket() {
+ if (!m_pFile) {
+ m_pModule->PutModule(((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - File closed prematurely.");
+ Close();
+ return;
+ }
+
+ if (GetInternalWriteBuffer().size() > 1024 * 1024) {
+ // There is still enough data to be written, don't add more
+ // stuff to that buffer.
+ DEBUG("SendPacket(): Skipping send, buffer still full enough [" << GetInternalWriteBuffer().size() << "]["
+ << m_sRemoteNick << "][" << m_sFileName << "]");
+ return;
+ }
+
+ char szBuf[4096];
+ int iLen = m_pFile->Read(szBuf, 4096);
+
+ if (iLen < 0) {
+ m_pModule->PutModule(((m_bSend) ? "DCC -> [" : "DCC <- [") + m_sRemoteNick + "][" + m_sFileName + "] - Error reading from file.");
+ Close();
+ return;
+ }
+
+ if (iLen > 0) {
+ Write(szBuf, iLen);
+ m_uBytesSoFar += iLen;
+ }
+}
+
+Csock* CDCCSock::GetSockObj(const CString& sHost, unsigned short uPort) {
+ Close();
+
+ CDCCSock* pSock = new CDCCSock(m_pModule, m_sRemoteNick, m_sLocalFile, m_uFileSize, m_pFile);
+ pSock->SetSockName("DCC::SEND::" + m_sRemoteNick);
+ pSock->SetTimeout(120);
+ pSock->SetFileName(m_sFileName);
+ pSock->SetFileOffset(m_uBytesSoFar);
+ m_bNoDelFile = true;
+
+ return pSock;
+}
+
+CFile* CDCCSock::OpenFile(bool bWrite) {
+ if ((m_pFile) || (m_sLocalFile.empty())) {
+ m_pModule->PutModule(((bWrite) ? "DCC <- [" : "DCC -> [") + m_sRemoteNick + "][" + m_sLocalFile + "] - Unable to open file.");
+ return NULL;
+ }
+
+ m_pFile = new CFile(m_sLocalFile);
+
+ if (bWrite) {
+ if (m_pFile->Exists()) {
+ delete m_pFile;
+ m_pFile = NULL;
+ m_pModule->PutModule("DCC <- [" + m_sRemoteNick + "] - File already exists [" + m_sLocalFile + "]");
+ return NULL;
+ }
+
+ if (!m_pFile->Open(O_WRONLY | O_TRUNC | O_CREAT)) {
+ delete m_pFile;
+ m_pFile = NULL;
+ m_pModule->PutModule("DCC <- [" + m_sRemoteNick + "] - Could not open file [" + m_sLocalFile + "]");
+ return NULL;
+ }
+ } else {
+ if (!m_pFile->IsReg()) {
+ delete m_pFile;
+ m_pFile = NULL;
+ m_pModule->PutModule("DCC -> [" + m_sRemoteNick + "] - Not a file [" + m_sLocalFile + "]");
+ return NULL;
+ }
+
+ if (!m_pFile->Open()) {
+ delete m_pFile;
+ m_pFile = NULL;
+ m_pModule->PutModule("DCC -> [" + m_sRemoteNick + "] - Could not open file [" + m_sLocalFile + "]");
+ return NULL;
+ }
+
+ // The DCC specs only allow file transfers with files smaller
+ // than 4GiB (see ReadData()).
+ unsigned long long uFileSize = m_pFile->GetSize();
+ if (uFileSize > (unsigned long long) 0xffffffff) {
+ delete m_pFile;
+ m_pFile = NULL;
+ m_pModule->PutModule("DCC -> [" + m_sRemoteNick + "] - File too large (>4 GiB) [" + m_sLocalFile + "]");
+ return NULL;
+ }
+
+ m_uFileSize = (unsigned long) uFileSize;
+ }
+
+ m_sFileName = m_pFile->GetShortName();
+
+ return m_pFile;
+}
+
+bool CDCCSock::Seek(unsigned int uPos) {
+ if (m_pFile) {
+ if (m_pFile->Seek(uPos)) {
+ m_uBytesSoFar = uPos;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+MODULEDEFS(CDCCMod, "This module allows you to transfer files to and from ZNC")
+
View
43 modules/extra/shell.cpp
@@ -85,54 +85,11 @@ class CShellMod : public CModule {
}
PutShell("znc$");
- } else if (sCommand.Equals("SEND")) {
- CString sToNick = sLine.Token(1);
- CString sFile = sLine.Token(2);
-
- if ((sToNick.empty()) || (sFile.empty())) {
- PutShell("usage: Send <nick> <file>");
- } else {
- sFile = CDir::ChangeDir(m_sPath, sFile, CZNC::Get().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 (sCommand.Equals("GET")) {
- CString sFile = sLine.Token(1);
-
- if (sFile.empty()) {
- PutShell("usage: Get <file>");
- } else {
- sFile = CDir::ChangeDir(m_sPath, sFile, CZNC::Get().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(sLine);
}
}
- virtual void OnModCTCP(const CString& sMessage) {
- if (sMessage.Equals("DCC SEND ", false, 9)) {
- CString sLocalFile = CDir::ChangeDir(m_sPath, sMessage.Token(2), CZNC::Get().GetHomePath());
- unsigned long uLongIP = sMessage.Token(3).ToULong();
- unsigned short uPort = sMessage.Token(4).ToUShort();
- unsigned long uFileSize = sMessage.Token(5).ToULong();
- m_pUser->GetFile(m_pUser->GetCurNick(), CUtils::GetIP(uLongIP), uPort, sLocalFile, uFileSize, GetModName());
- }
- }
-
void PutShell(const CString& sMsg) {
CString sPath = m_sPath.Replace_n(" ", "_");
CString sSource = ":" + GetModNick() + "!shell@" + sPath;
Please sign in to comment.
Something went wrong with that request. Please try again.