//
// 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 )
{
//tqDebug("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 , TQ_SIGNAL ( accepted ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_SLOT ( executeChat ( KviDccBox * , KviDccDescriptor * ) ) ) ;
connect ( box , TQ_SIGNAL ( rejected ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_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 , TQ_SIGNAL ( accepted ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_SLOT ( activeVoiceExecute ( KviDccBox * , KviDccDescriptor * ) ) ) ;
connect ( box , TQ_SIGNAL ( rejected ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_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 , TQ_SIGNAL ( accepted ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_SLOT ( activeCanvasExecute ( KviDccBox * , KviDccDescriptor * ) ) ) ;
connect ( box , TQ_SIGNAL ( rejected ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_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 , TQ_SIGNAL ( accepted ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_SLOT ( chooseSaveFileName ( KviDccBox * , KviDccDescriptor * ) ) ) ;
connect ( box , TQ_SIGNAL ( rejected ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_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 , TQ_SIGNAL ( renameSelected ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_SLOT ( renameDccSendFile ( KviDccBox * , KviDccDescriptor * ) ) ) ;
connect ( box , TQ_SIGNAL ( overwriteSelected ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_SLOT ( recvFileExecute ( KviDccBox * , KviDccDescriptor * ) ) ) ;
connect ( box , TQ_SIGNAL ( cancelSelected ( KviDccBox * , KviDccDescriptor * ) ) ,
this , TQ_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 )
{
//tqDebug("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 )
{
//tqDebug("FOUND");
// valid zero port resume request
if ( filePos < t - > m_uFileSize )
{
//tqDebug("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
}
}
}
//tqDebug("NOT A ZeRO PORT");
return KviDccFileTransfer : : handleResumeRequest ( filename , port , filePos ) ;
}
# include "m_broker.moc"