You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
899 lines
27 KiB
899 lines
27 KiB
//
|
|
// File : broker.cpp
|
|
// Creation date : Tue Sep 19 09 2000 10:21:54 by Szymon Stefanek
|
|
//
|
|
// This file is part of the KVirc irc client distribution
|
|
// Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot net)
|
|
//
|
|
// This program is FREE software. You can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your opinion) any later version.
|
|
//
|
|
// This program is distributed in the HOPE that it will be USEFUL,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
// See the GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, write to the Free Software Foundation,
|
|
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
//
|
|
|
|
#include "broker.h"
|
|
#include "dialogs.h"
|
|
#include "chat.h"
|
|
#include "send.h"
|
|
#ifdef COMPILE_DCC_CANVAS
|
|
#include "canvas.h"
|
|
#endif
|
|
#include "voice.h"
|
|
|
|
#include "kvi_app.h"
|
|
#include "kvi_frame.h"
|
|
#include "kvi_locale.h"
|
|
#include "kvi_options.h"
|
|
#include "kvi_console.h"
|
|
#include "kvi_fileutils.h"
|
|
#include "kvi_out.h"
|
|
#include "kvi_mediatype.h"
|
|
#include "kvi_ircconnection.h"
|
|
#include "kvi_sharedfiles.h"
|
|
|
|
// kvi_app.cpp
|
|
extern KVIRC_API KviMediaManager * g_pMediaManager;
|
|
extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
|
|
|
|
#include <tqfileinfo.h>
|
|
#include <tqstring.h>
|
|
|
|
//#warning "The broker might lookup the remote host name"
|
|
|
|
KviDccBroker::KviDccBroker()
|
|
: TQObject(0,"dcc_broker")
|
|
{
|
|
KviDccFileTransfer::init();
|
|
|
|
m_pBoxList = new KviPointerList<KviDccBox>;
|
|
m_pBoxList->setAutoDelete(false);
|
|
|
|
m_pDccWindowList = new KviPointerList<KviWindow>;
|
|
m_pDccWindowList->setAutoDelete(false);
|
|
|
|
m_pZeroPortTags = new KviPointerHashTable<TQString,KviDccZeroPortTag>(17);
|
|
m_pZeroPortTags->setAutoDelete(true);
|
|
}
|
|
|
|
KviDccBroker::~KviDccBroker()
|
|
{
|
|
delete m_pZeroPortTags;
|
|
while(m_pBoxList->first())delete m_pBoxList->first();
|
|
delete m_pBoxList;
|
|
m_pBoxList = 0;
|
|
while(m_pDccWindowList->first())delete m_pDccWindowList->first();
|
|
delete m_pDccWindowList;
|
|
KviDccFileTransfer::done();
|
|
}
|
|
|
|
|
|
KviDccZeroPortTag * KviDccBroker::addZeroPortTag()
|
|
{
|
|
static unsigned int g_uNextZeroPortTag = 0;
|
|
g_uNextZeroPortTag++;
|
|
KviDccZeroPortTag * t = new KviDccZeroPortTag;
|
|
t->m_tTimestamp = TQDateTime::currentDateTime();
|
|
t->m_szTag.setNum(g_uNextZeroPortTag);
|
|
//t->m_szTag.prepend("mIrc-zero-port-");
|
|
t->m_uResumePosition = 0;
|
|
// FIXME: we should clear this dict if it grows too high....
|
|
m_pZeroPortTags->insert(t->m_szTag,t);
|
|
return t;
|
|
}
|
|
|
|
KviDccZeroPortTag * KviDccBroker::findZeroPortTag(const TQString &szTag)
|
|
{
|
|
KviDccZeroPortTag * t = m_pZeroPortTags->find(szTag);
|
|
if(!t)return 0;
|
|
if(t->m_tTimestamp.secsTo(TQDateTime::currentDateTime()) > 180)
|
|
{
|
|
// too late man...
|
|
m_pZeroPortTags->remove(szTag);
|
|
return 0;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
void KviDccBroker::removeZeroPortTag(const TQString &szTag)
|
|
{
|
|
m_pZeroPortTags->remove(szTag);
|
|
}
|
|
|
|
unsigned int KviDccBroker::dccBoxCount()
|
|
{
|
|
return m_pBoxList->count();
|
|
}
|
|
|
|
void KviDccBroker::unregisterDccWindow(KviWindow *wnd)
|
|
{
|
|
m_pDccWindowList->removeRef(wnd);
|
|
}
|
|
|
|
void KviDccBroker::unregisterDccBox(KviDccBox * box)
|
|
{
|
|
//debug("Forgetting box %d",box);
|
|
m_pBoxList->removeRef(box);
|
|
}
|
|
|
|
|
|
void KviDccBroker::cancelDcc(KviDccDescriptor * dcc)
|
|
{
|
|
delete dcc;
|
|
dcc = 0;
|
|
}
|
|
|
|
void KviDccBroker::cancelDcc(KviDccBox *box,KviDccDescriptor * dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
delete dcc;
|
|
dcc = 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// RSEND
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void KviDccBroker::rsendManage(KviDccDescriptor * dcc)
|
|
{
|
|
// We need the filename...
|
|
TQFileInfo fi(dcc->szLocalFileName);
|
|
if(fi.exists())rsendExecute(0,dcc);
|
|
else rsendAskForFileName(dcc);
|
|
}
|
|
|
|
void KviDccBroker::rsendAskForFileName(KviDccDescriptor * dcc)
|
|
{
|
|
TQStringList filenames;
|
|
if(
|
|
KviFileDialog::askForOpenFileNames(filenames,
|
|
__tr2qs_ctx("Choose Files to Send - KVIrc","dcc"),"")
|
|
) {
|
|
if(filenames.count() > 0)
|
|
{
|
|
KviDccDescriptor * d;
|
|
KviDccDescriptor * templ = dcc;
|
|
TQStringList::Iterator it=filenames.begin();
|
|
while(it != filenames.end())
|
|
{
|
|
d = new KviDccDescriptor(*dcc);
|
|
d->szLocalFileName = *(it);
|
|
d->szLocalFileName.stripWhiteSpace();
|
|
++it;
|
|
if(d->szLocalFileName.isEmpty())
|
|
cancelDcc(d);
|
|
else
|
|
rsendExecute(d);
|
|
}
|
|
delete dcc;
|
|
}
|
|
} else {
|
|
cancelDcc(dcc);
|
|
}
|
|
}
|
|
|
|
void KviDccBroker::rsendExecute(KviDccDescriptor * dcc)
|
|
{
|
|
if(!g_pApp->windowExists(dcc->console()))
|
|
{
|
|
// No way...we NEED the right IRC context...
|
|
g_pApp->activeConsole()->output(KVI_OUT_DCCERROR,
|
|
__tr2qs_ctx("Can't send DCC %Q request to %Q: IRC connection has been terminated","dcc"),
|
|
&(dcc->szType),&(dcc->szNick));
|
|
delete dcc;
|
|
return;
|
|
}
|
|
|
|
// Ok...we need the file to exist
|
|
TQFileInfo fi(dcc->szLocalFileName);
|
|
if(!(fi.exists() && fi.isReadable() && (fi.isFile()) && (fi.size() > 0)))
|
|
{
|
|
dcc->console()->output(KVI_OUT_DCCERROR,__tr2qs_ctx("Can't open file %Q for reading","dcc"),
|
|
&(dcc->szLocalFileName));
|
|
delete dcc;
|
|
return;
|
|
}
|
|
|
|
dcc->szFileName = dcc->szLocalFileName;
|
|
dcc->szFileName = TQFileInfo(dcc->szFileName).fileName();
|
|
|
|
TQString fName = dcc->szFileName;
|
|
fName.replace(' ',"\\040"); // be cool :)
|
|
|
|
TQString szTag;
|
|
if(dcc->isZeroPortRequest())
|
|
{
|
|
// actually we tagged it as "nonempty" in /dcc.rsend --zero-port
|
|
// retag it with something more reasonable
|
|
KviDccZeroPortTag * t = addZeroPortTag();
|
|
t->m_uFileSize = fi.size();
|
|
dcc->setZeroPortRequestTag(t->m_szTag.latin1()); // latin1() should be ok here
|
|
szTag = t->m_szTag;
|
|
|
|
// DCC [ST]SEND <filename> <fakeipaddress> <zero-port> <filesize> <sessionid>
|
|
dcc->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s 127.0.0.1 0 %u %s%c",
|
|
dcc->console()->connection()->encodeText(dcc->szNick).data(),
|
|
0x01,
|
|
dcc->console()->connection()->encodeText(dcc->szType).data(),
|
|
dcc->console()->connection()->encodeText(fName).data(),
|
|
fi.size(),
|
|
dcc->console()->connection()->encodeText(szTag).data(),
|
|
0x01);
|
|
} else {
|
|
dcc->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %u%c",
|
|
dcc->console()->connection()->encodeText(dcc->szNick).data(),
|
|
0x01,
|
|
dcc->console()->connection()->encodeText(dcc->szType).data(),
|
|
dcc->console()->connection()->encodeText(fName).data(),
|
|
fi.size(),0x01);
|
|
szTag = dcc->szFileName;
|
|
}
|
|
|
|
// now add a file offer , so he we will accept it automatically
|
|
// 120 secs is a reasonable timeout
|
|
TQString szMask = dcc->szNick;
|
|
szMask += "!*@*";
|
|
|
|
g_pSharedFilesManager->addSharedFile(szTag,dcc->szLocalFileName,szMask,120);
|
|
|
|
delete dcc;
|
|
}
|
|
|
|
void KviDccBroker::rsendExecute(KviDccBox * box,KviDccDescriptor * dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
rsendExecute(dcc);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// DCC CHAT
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void KviDccBroker::handleChatRequest(KviDccDescriptor * dcc)
|
|
{
|
|
|
|
if(!dcc->bAutoAccept)
|
|
{
|
|
// FIXME: better message ? Secure Direct Client Connection...eventually
|
|
// need confirmation
|
|
TQString tmp = __tr2qs_ctx( \
|
|
"<b>%1 [%2@%3]</b> requests a " \
|
|
"<b>Direct Client Connection</b> in <b>%4</b> mode.<br>", \
|
|
"dcc").arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(dcc->szType);
|
|
|
|
#ifdef COMPILE_SSL_SUPPORT
|
|
if(dcc->bIsSSL)tmp += __tr2qs_ctx("The connection will be secured using SSL.<br>","dcc");
|
|
#endif
|
|
|
|
if(dcc->isZeroPortRequest())
|
|
{
|
|
tmp += __tr2qs_ctx( \
|
|
"You will be the passive side of the connection.<br>" \
|
|
,"dcc");
|
|
} else {
|
|
tmp += __tr2qs_ctx( \
|
|
"The connection target will be host <b>%1</b> on port <b>%2</b><br>" \
|
|
,"dcc").arg(dcc->szIp).arg(dcc->szPort);
|
|
}
|
|
|
|
|
|
TQString caption = __tr2qs_ctx("DCC %1 Request - KVIrc","dcc").arg(dcc->szType);
|
|
|
|
KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,caption);
|
|
|
|
m_pBoxList->append(box);
|
|
connect(box,TQT_SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(executeChat(KviDccBox *,KviDccDescriptor *)));
|
|
connect(box,TQT_SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
|
|
box->show();
|
|
} else {
|
|
// auto accept
|
|
executeChat(0,dcc);
|
|
}
|
|
}
|
|
|
|
void KviDccBroker::executeChat(KviDccBox *box,KviDccDescriptor * dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
|
|
if(!g_pApp->windowExists(dcc->console()))
|
|
{
|
|
// rebind to the first available console....
|
|
dcc->setConsole(g_pApp->activeConsole());
|
|
}
|
|
|
|
KviStr szSubProto = dcc->szType;
|
|
szSubProto.toLower();
|
|
|
|
TQString tmp = TQString("dcc: %1 %2@%3:%4").arg(szSubProto.ptr()).arg(dcc->szNick).arg(dcc->szIp).arg(dcc->szPort);
|
|
KviDccChat * chat = new KviDccChat(dcc->console()->frame(),dcc,tmp.utf8().data());
|
|
|
|
bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
|
|
(KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat) || \
|
|
(dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChatWhenAutoAccepted)));
|
|
|
|
dcc->console()->frame()->addWindow(chat,!bMinimized);
|
|
if(bMinimized)chat->minimize();
|
|
m_pDccWindowList->append(chat);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// ACTIVE VOICE
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void KviDccBroker::activeVoiceManage(KviDccDescriptor * dcc)
|
|
{
|
|
if(!dcc->bAutoAccept)
|
|
{
|
|
// need confirmation
|
|
TQString tmp = __tr2qs_ctx(
|
|
"<b>%1 [%2@%3]</b> requests a<br>" \
|
|
"<b>Direct Client Connection</b> in <b>VOICE</b> mode.<br>" \
|
|
"The connection target will be host <b>%4</b> on port <b>%5</b><br>" \
|
|
,"dcc" \
|
|
).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(dcc->szIp).arg(dcc->szPort);
|
|
|
|
KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,__tr2qs_ctx("DCC VOICE request","dcc"));
|
|
m_pBoxList->append(box);
|
|
connect(box,TQT_SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(activeVoiceExecute(KviDccBox *,KviDccDescriptor *)));
|
|
connect(box,TQT_SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
|
|
box->show();
|
|
} else {
|
|
// auto accept
|
|
activeVoiceExecute(0,dcc);
|
|
}
|
|
}
|
|
|
|
void KviDccBroker::activeVoiceExecute(KviDccBox *box,KviDccDescriptor * dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
|
|
if(!g_pApp->windowExists(dcc->console()))
|
|
{
|
|
// rebind to the first available console....
|
|
dcc->setConsole(g_pApp->activeConsole());
|
|
}
|
|
|
|
KviStr tmp(KviStr::Format,"dcc: voice %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
|
|
KviDccVoice * v = new KviDccVoice(dcc->console()->frame(),dcc,tmp.ptr());
|
|
|
|
bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
|
|
(KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccVoice) || \
|
|
(dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccVoiceWhenAutoAccepted)));
|
|
|
|
dcc->console()->frame()->addWindow(v,!bMinimized);
|
|
if(bMinimized)v->minimize();
|
|
|
|
m_pDccWindowList->append(v);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// PASSIVE VOICE
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void KviDccBroker::passiveVoiceExecute(KviDccDescriptor * dcc)
|
|
{
|
|
KviStr tmp(KviStr::Format,"dcc: voice %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
|
|
KviDccVoice * v = new KviDccVoice(dcc->console()->frame(),dcc,tmp.ptr());
|
|
//#warning "Create minimized dcc voice ?... or maybe it's too much ? :)"
|
|
bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat);
|
|
dcc->console()->frame()->addWindow(v,!bMinimized);
|
|
if(bMinimized)v->minimize();
|
|
m_pDccWindowList->append(v);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// ACTIVE CANVAS
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef COMPILE_DCC_CANVAS
|
|
|
|
void KviDccBroker::activeCanvasManage(KviDccDescriptor * dcc)
|
|
{
|
|
if(!dcc->bAutoAccept)
|
|
{
|
|
// need confirmation
|
|
TQString tmp = __tr2qs_ctx( \
|
|
"<b>%1 [%2@%3]</b> requests a<br>" \
|
|
"<b>Direct Client Connection</b> in <b>CANVAS</b> mode.<br>" \
|
|
"The connection target will be host <b>%4</b> on port <b>%5</b><br>" \
|
|
,"dcc" \
|
|
).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(dcc->szIp).arg(dcc->szPort);
|
|
|
|
KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,__tr2qs_ctx("DCC CANVAS request","dcc"));
|
|
m_pBoxList->append(box);
|
|
connect(box,TQT_SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(activeCanvasExecute(KviDccBox *,KviDccDescriptor *)));
|
|
connect(box,TQT_SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
|
|
box->show();
|
|
} else {
|
|
// auto accept
|
|
activeCanvasExecute(0,dcc);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void KviDccBroker::activeCanvasExecute(KviDccBox *box,KviDccDescriptor * dcc)
|
|
{
|
|
#ifdef COMPILE_DCC_CANVAS
|
|
if(box)box->forgetDescriptor();
|
|
|
|
if(!g_pApp->windowExists(dcc->console()))
|
|
{
|
|
// rebind to the first available console....
|
|
dcc->setConsole(g_pApp->activeConsole());
|
|
}
|
|
|
|
KviStr tmp(KviStr::Format,"dcc: canvas %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
|
|
KviDccCanvas * cnv = new KviDccCanvas(dcc->console()->frame(),dcc,tmp.ptr());
|
|
|
|
//#warning "This option should be dedicated to Dcc Canvas!....for now we are using the DccChat options"
|
|
bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
|
|
(KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat) || \
|
|
(dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChatWhenAutoAccepted)));
|
|
|
|
dcc->console()->frame()->addWindow(cnv,!bMinimized);
|
|
if(bMinimized)cnv->minimize();
|
|
|
|
m_pDccWindowList->append(cnv);
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// PASSIVE CANVAS
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#ifdef COMPILE_DCC_CANVAS
|
|
void KviDccBroker::passiveCanvasExecute(KviDccDescriptor * dcc)
|
|
{
|
|
KviStr tmp(KviStr::Format,"dcc: canvas %s@%s:%s",dcc->szNick.utf8().data(),dcc->szIp.utf8().data(),dcc->szPort.utf8().data());
|
|
KviDccCanvas * cnv = new KviDccCanvas(dcc->console()->frame(),dcc,tmp.ptr());
|
|
//#warning "This option should be dedicated to Dcc Canvas!....for now we are using the DccChat options"
|
|
bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccChat);
|
|
dcc->console()->frame()->addWindow(cnv,!bMinimized);
|
|
if(bMinimized)cnv->minimize();
|
|
m_pDccWindowList->append(cnv);
|
|
}
|
|
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// SEND
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void KviDccBroker::recvFileManage(KviDccDescriptor * dcc)
|
|
{
|
|
if(dcc->bIsIncomingAvatar)
|
|
{
|
|
bool bOk;
|
|
uint size = dcc->szFileSize.toUInt(&bOk);
|
|
if(bOk) {
|
|
if(size>=KVI_OPTION_UINT(KviOption_uintMaximumRequestedAvatarSize)) {
|
|
cancelDcc(0,dcc);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!dcc->bAutoAccept)
|
|
{
|
|
// need confirmation
|
|
TQString tmp;
|
|
|
|
if(dcc->bActive)
|
|
{
|
|
// Normal active send: we will be connecting
|
|
tmp = __tr2qs_ctx( \
|
|
"<b>%1 [%2@%3]</b> " \
|
|
"wants to send you the file " \
|
|
"'<b>%4</b>', " \
|
|
"<b>%5</b> large.<br>" \
|
|
"The connection target will be host <b>%6</b> on port <b>%7</b><br>" \
|
|
,"dcc" \
|
|
).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(
|
|
dcc->szFileName).arg(KviTQString::makeSizeReadable(dcc->szFileSize.toInt())).arg(
|
|
dcc->szIp).arg(dcc->szPort);
|
|
|
|
} else {
|
|
// passive: we will be listening!
|
|
tmp = __tr2qs_ctx( \
|
|
"<b>%1 [%2@%3]</b> "
|
|
"wants to send you the file " \
|
|
"'<b>%4</b>', " \
|
|
"<b>%5</b> large.<br>" \
|
|
"You will be the passive side of the connection.<br>" \
|
|
,"dcc" \
|
|
).arg(dcc->szNick).arg(dcc->szUser).arg(dcc->szHost).arg(
|
|
dcc->szFileName).arg(KviTQString::makeSizeReadable(dcc->szFileSize.toInt()));
|
|
}
|
|
|
|
if(dcc->bIsIncomingAvatar)
|
|
{
|
|
tmp += __tr2qs_ctx( \
|
|
"<center><b>Note:</b></center>" \
|
|
"The file appears to be an avatar that you have requested. " \
|
|
"You should not change its filename. " \
|
|
"Save it in a location where KVIrc can find it, such as " \
|
|
"the 'avatars', 'incoming', or 'pics' directories, " \
|
|
"your home directory, or the save directory for the incoming file type. " \
|
|
"The default save path will probably work. " \
|
|
"You can instruct KVIrc to accept incoming avatars automatically " \
|
|
"by setting the option <tt>boolAutoAcceptIncomingAvatars</tt> to true.<br>" \
|
|
,"dcc" \
|
|
);
|
|
}
|
|
|
|
//#warning "Maybe remove the pending avatar if rejected ?"
|
|
|
|
TQString title = __tr2qs_ctx("DCC %1 Request - KVIrc","dcc").arg(dcc->szType);
|
|
|
|
KviDccAcceptBox * box = new KviDccAcceptBox(this,dcc,tmp,title);
|
|
m_pBoxList->append(box);
|
|
connect(box,TQT_SIGNAL(accepted(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(chooseSaveFileName(KviDccBox *,KviDccDescriptor *)));
|
|
connect(box,TQT_SIGNAL(rejected(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
|
|
box->show();
|
|
} else {
|
|
// auto accept
|
|
|
|
if(_OUTPUT_VERBOSE)
|
|
{
|
|
dcc->console()->output(KVI_OUT_DCCMSG,__tr2qs_ctx("Auto-accepting DCC %Q request from %Q!%Q@%Q for file %Q","dcc"),
|
|
&(dcc->szType),&(dcc->szNick),&(dcc->szUser),
|
|
&(dcc->szHost),&(dcc->szFileName));
|
|
}
|
|
chooseSaveFileName(0,dcc);
|
|
}
|
|
}
|
|
|
|
void KviDccBroker::chooseSaveFileName(KviDccBox *box,KviDccDescriptor *dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
|
|
// Lookup the suggested save directory
|
|
|
|
dcc->szLocalFileName = "";
|
|
|
|
if(dcc->bIsIncomingAvatar)g_pApp->getLocalKvircDirectory(dcc->szLocalFileName,KviApp::Avatars);
|
|
else {
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolUseIncomingDccMediaTypeSavePath))
|
|
{
|
|
g_pMediaManager->lock();
|
|
if(KviMediaType * mt = g_pMediaManager->findMediaType(dcc->szFileName.utf8().data(),false))
|
|
{
|
|
if(mt->szSavePath.hasData())
|
|
{
|
|
if(KviFileUtils::directoryExists(mt->szSavePath.ptr()))dcc->szLocalFileName = mt->szSavePath;
|
|
else {
|
|
if(KviFileUtils::makeDir(mt->szSavePath.ptr()))dcc->szLocalFileName = mt->szSavePath;
|
|
}
|
|
if(KVI_OPTION_BOOL(KviOption_boolSortReceivedByDccFilesByNicks))
|
|
{
|
|
KviTQString::ensureLastCharIs(dcc->szLocalFileName,KVI_PATH_SEPARATOR_CHAR);
|
|
dcc->szLocalFileName.append(dcc->szNick);
|
|
KviFileUtils::adjustFilePath(dcc->szLocalFileName);
|
|
}
|
|
KviFileUtils::makeDir(dcc->szLocalFileName);
|
|
}
|
|
}
|
|
g_pMediaManager->unlock();
|
|
}
|
|
|
|
if(dcc->szLocalFileName.isEmpty())
|
|
{
|
|
g_pApp->getLocalKvircDirectory(dcc->szLocalFileName,KviApp::Incoming);
|
|
if(KVI_OPTION_BOOL(KviOption_boolSortReceivedByDccFilesByNicks))
|
|
{
|
|
KviTQString::ensureLastCharIs(dcc->szLocalFileName,KVI_PATH_SEPARATOR_CHAR);
|
|
dcc->szLocalFileName.append(dcc->szNick);
|
|
KviFileUtils::adjustFilePath(dcc->szLocalFileName);
|
|
KviFileUtils::makeDir(dcc->szLocalFileName);
|
|
}
|
|
}
|
|
}
|
|
KviFileUtils::adjustFilePath(dcc->szLocalFileName);
|
|
KviTQString::ensureLastCharIs(dcc->szLocalFileName,KVI_PATH_SEPARATOR_CHAR);
|
|
|
|
if(!(dcc->bAutoAccept))
|
|
{
|
|
dcc->szLocalFileName+=dcc->szFileName;
|
|
if(KviFileDialog::askForSaveFileName(dcc->szLocalFileName,
|
|
__tr2qs_ctx("Choose Files to Save - KVIrc","dcc"),dcc->szLocalFileName))
|
|
{
|
|
renameOverwriteResume(0,dcc);
|
|
} else {
|
|
cancelDcc(dcc);
|
|
}
|
|
} else {
|
|
// auto accept
|
|
// WE choose the filename
|
|
dcc->szLocalFileName.append(dcc->szFileName);
|
|
|
|
if(_OUTPUT_VERBOSE)
|
|
{
|
|
dcc->console()->output(KVI_OUT_DCCMSG,__tr2qs_ctx("Auto-saving DCC %Q file %Q as \r![!dbl]play $0\r%Q\r","dcc"),
|
|
&(dcc->szType),&(dcc->szFileName),&(dcc->szLocalFileName));
|
|
}
|
|
|
|
renameOverwriteResume(0,dcc);
|
|
}
|
|
}
|
|
|
|
void KviDccBroker::renameOverwriteResume(KviDccBox *box,KviDccDescriptor * dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
|
|
// Check if file exists
|
|
TQFileInfo fi(dcc->szLocalFileName);
|
|
if(fi.exists() && (fi.size() > 0)) // 0 byte files are senseless for us
|
|
{
|
|
dcc->szLocalFileSize.setNum(fi.size());
|
|
|
|
bool bOk;
|
|
int iRemoteSize = dcc->szFileSize.toInt(&bOk);
|
|
if(!bOk)iRemoteSize = -1;
|
|
|
|
// FIXME: Files downloaded succesfully shouldn't be resumed
|
|
// we should keep a db of downloaded files!
|
|
|
|
if(!dcc->bAutoAccept)
|
|
{
|
|
TQString tmp;
|
|
bool bDisableResume = false;
|
|
|
|
if((iRemoteSize > -1) || // remote size is unknown
|
|
(iRemoteSize > ((int)(fi.size())))) // or it is larger than the actual size on disk
|
|
{
|
|
tmp = __tr2qs_ctx( \
|
|
"The file '<b>%1</b>' already exists " \
|
|
"and is <b>%2</b> large.<br>" \
|
|
"Do you wish to<br>" \
|
|
"<b>overwrite</b> the existing file,<br> " \
|
|
"<b>auto-rename</b> the new file, or<br>" \
|
|
"<b>resume</b> an incomplete download?" \
|
|
,"dcc" \
|
|
).arg(dcc->szLocalFileName).arg(KviTQString::makeSizeReadable(fi.size()));
|
|
} else {
|
|
bDisableResume = true;
|
|
// the file on disk is larger or equal to the remote one
|
|
tmp = __tr2qs_ctx( \
|
|
"The file '<b>%1</b>' already exists" \
|
|
"and is larger than the offered one.<br>" \
|
|
"Do you wish to<br>" \
|
|
"<b>overwrite</b> the existing file, or<br> " \
|
|
"<b>auto-rename</b> the new file ?" \
|
|
,"dcc" \
|
|
).arg(dcc->szLocalFileName);
|
|
}
|
|
|
|
KviDccRenameBox * box = new KviDccRenameBox(this,dcc,tmp,bDisableResume);
|
|
m_pBoxList->append(box);
|
|
connect(box,TQT_SIGNAL(renameSelected(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(renameDccSendFile(KviDccBox *,KviDccDescriptor *)));
|
|
connect(box,TQT_SIGNAL(overwriteSelected(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(recvFileExecute(KviDccBox *,KviDccDescriptor *)));
|
|
connect(box,TQT_SIGNAL(cancelSelected(KviDccBox *,KviDccDescriptor *)),
|
|
this,TQT_SLOT(cancelDcc(KviDccBox *,KviDccDescriptor *)));
|
|
box->show();
|
|
return;
|
|
} else {
|
|
// auto resume ?
|
|
if(KVI_OPTION_BOOL(KviOption_boolAutoResumeDccSendWhenAutoAccepted) &&
|
|
(iRemoteSize > -1) && // only if the remote size is really known
|
|
(iRemoteSize > ((int)(fi.size()))) && // only if the remote size is larger than the local size
|
|
(!KviDccFileTransfer::nonFailedTransferWithLocalFileName(dcc->szLocalFileName.utf8().data()))) // only if there is no transfer with this local file name yet
|
|
{
|
|
// yep, auto resume...
|
|
dcc->bResume = true;
|
|
recvFileExecute(0,dcc);
|
|
} else {
|
|
// otherwise auto rename
|
|
renameDccSendFile(0,dcc);
|
|
}
|
|
return;
|
|
}
|
|
} else dcc->szLocalFileSize = "0";
|
|
|
|
// everything OK
|
|
recvFileExecute(0,dcc);
|
|
}
|
|
|
|
void KviDccBroker::renameDccSendFile(KviDccBox *box,KviDccDescriptor * dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
|
|
|
|
if(TQFileInfo(dcc->szLocalFileName).exists())
|
|
{
|
|
KviStr szOrig = dcc->szLocalFileName;
|
|
int i = 1;
|
|
do {
|
|
KviStr szNum;
|
|
szNum.setNum(i);
|
|
int idx = szOrig.findLastIdx('.');
|
|
if(idx != -1)
|
|
{
|
|
dcc->szLocalFileName = szOrig.left(idx);
|
|
dcc->szLocalFileName += ".";
|
|
dcc->szLocalFileName += szNum;
|
|
dcc->szLocalFileName += szOrig.right(szOrig.len() - idx);
|
|
} else {
|
|
dcc->szLocalFileName = szOrig;
|
|
dcc->szLocalFileName += ".";
|
|
dcc->szLocalFileName += szNum;
|
|
}
|
|
i++;
|
|
} while(TQFileInfo(dcc->szLocalFileName).exists());
|
|
|
|
if(_OUTPUT_VERBOSE)
|
|
{
|
|
dcc->console()->output(KVI_OUT_DCCMSG,__tr2qs_ctx("File %s exists, auto-renaming to %Q","dcc"),
|
|
szOrig.ptr(),&(dcc->szLocalFileName));
|
|
}
|
|
}
|
|
|
|
dcc->szLocalFileSize = "0"; // 0 for sure
|
|
|
|
recvFileExecute(0,dcc);
|
|
}
|
|
|
|
void KviDccBroker::recvFileExecute(KviDccBox *box,KviDccDescriptor * dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
|
|
if(!g_pApp->windowExists(dcc->console()))
|
|
{
|
|
// rebind to the first available console....
|
|
dcc->setConsole(g_pApp->activeConsole());
|
|
}
|
|
|
|
//KviDccSend * send = new KviDccSend(dcc->console()->frame(),dcc,tmp.ptr());
|
|
KviDccFileTransfer * send = new KviDccFileTransfer(dcc);
|
|
|
|
bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : \
|
|
(KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccSend) || \
|
|
(dcc->bAutoAccept && KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccSendWhenAutoAccepted)));
|
|
|
|
send->invokeTransferWindow(dcc->console(),bMinimized,bMinimized);
|
|
}
|
|
|
|
|
|
void KviDccBroker::sendFileManage(KviDccDescriptor * dcc)
|
|
{
|
|
TQStringList filenames;
|
|
if(
|
|
KviFileDialog::askForOpenFileNames(filenames,
|
|
__tr2qs_ctx("Choose Files to Send - KVIrc","dcc"),"")
|
|
) {
|
|
if(filenames.count() > 0)
|
|
{
|
|
KviDccDescriptor * d;
|
|
KviDccDescriptor * templ = dcc;
|
|
TQStringList::Iterator it=filenames.begin();
|
|
while(it != filenames.end())
|
|
{
|
|
d = new KviDccDescriptor(*dcc);
|
|
d->szLocalFileName = *(it);
|
|
d->szLocalFileName.stripWhiteSpace();
|
|
++it;
|
|
if(d->szLocalFileName.isEmpty())
|
|
cancelDcc(d);
|
|
else
|
|
sendFileExecute(0,d);
|
|
}
|
|
delete dcc;
|
|
}
|
|
} else {
|
|
cancelDcc(dcc);
|
|
}
|
|
}
|
|
|
|
void KviDccBroker::sendFileExecute(KviDccBox * box,KviDccDescriptor *dcc)
|
|
{
|
|
if(box)box->forgetDescriptor();
|
|
|
|
if(!g_pApp->windowExists(dcc->console()))
|
|
{
|
|
// rebind to the first available console....
|
|
dcc->setConsole(g_pApp->activeConsole());
|
|
}
|
|
|
|
TQFileInfo fi(dcc->szLocalFileName);
|
|
if(!(fi.exists() && fi.isReadable() && (fi.isFile()) && (fi.size() > 0)))
|
|
{
|
|
dcc->console()->output(KVI_OUT_DCCERROR,__tr2qs_ctx("Can't open file %Q for reading","dcc"),
|
|
&(dcc->szLocalFileName));
|
|
delete dcc;
|
|
return;
|
|
}
|
|
|
|
dcc->szFileName = dcc->szLocalFileName;
|
|
dcc->szFileName = TQFileInfo(dcc->szFileName).fileName();
|
|
|
|
dcc->szLocalFileSize.setNum(fi.size());
|
|
|
|
KviDccFileTransfer * send = new KviDccFileTransfer(dcc);
|
|
|
|
bool bMinimized = dcc->bOverrideMinimize ? dcc->bShowMinimized : KVI_OPTION_BOOL(KviOption_boolCreateMinimizedDccSend);
|
|
|
|
send->invokeTransferWindow(dcc->console(),bMinimized,bMinimized);
|
|
}
|
|
|
|
bool KviDccBroker::canUnload()
|
|
{
|
|
if(m_pBoxList)
|
|
{
|
|
if((m_pBoxList->count() != 0) ||
|
|
(m_pDccWindowList->count() != 0) ||
|
|
(KviDccFileTransfer::transferCount() != 0))return false;
|
|
} // else in the destructor anyway (going to die)
|
|
return true;
|
|
}
|
|
|
|
bool KviDccBroker::handleResumeAccepted(const char * filename,const char * port,const char * szZeroPortTag)
|
|
{
|
|
return KviDccFileTransfer::handleResumeAccepted(filename,port,szZeroPortTag);
|
|
}
|
|
|
|
bool KviDccBroker::handleResumeRequest(KviDccRequest * dcc,const char * filename,const char * port,unsigned int filePos,const char * szZeroPortTag)
|
|
{
|
|
//debug("HANDLE %s %s %u %s",filename,port,filePos,szZeroPortTag);
|
|
// the zeroPOrtTag is nonempty here only if port == 0
|
|
if(kvi_strEqualCI("0",port) && szZeroPortTag)
|
|
{
|
|
// zero port resume request (we have sent out a DCC SEND <filename> <fakeip> 0 <tag>
|
|
KviDccZeroPortTag * t = findZeroPortTag(TQString(szZeroPortTag));
|
|
if(t)
|
|
{
|
|
//debug("FOUND");
|
|
// valid zero port resume request
|
|
if(filePos < t->m_uFileSize)
|
|
{
|
|
//debug("VALID");
|
|
// ok!
|
|
t->m_uResumePosition = filePos;
|
|
|
|
KviStr szBuffy;
|
|
KviServerParser::encodeCtcpParameter(filename,szBuffy);
|
|
|
|
dcc->ctcpMsg->msg->console()->connection()->sendFmtData(
|
|
"PRIVMSG %s :%cDCC ACCEPT %s %s %u %s%c",
|
|
dcc->ctcpMsg->msg->console()->connection()->encodeText(dcc->ctcpMsg->pSource->nick()).data(),
|
|
0x01,
|
|
szBuffy.ptr(),
|
|
port,
|
|
filePos,
|
|
szZeroPortTag,
|
|
0x01);
|
|
|
|
return true;
|
|
} else {
|
|
return false; // invalid resume size
|
|
}
|
|
}
|
|
}
|
|
//debug("NOT A ZeRO PORT");
|
|
|
|
return KviDccFileTransfer::handleResumeRequest(filename,port,filePos);
|
|
}
|
|
|
|
|
|
#include "m_broker.moc"
|