/*
* This file is part of the KFTPGrabber project
*
* Copyright ( C ) 2003 - 2004 by the KFTPGrabber developers
* Copyright ( C ) 2003 - 2004 Jernej Kos < kostko @ jweb - network . 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 option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* is provided AS IS , WITHOUT ANY WARRANTY ; without even the implied
* warranty of MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE , and
* NON - INFRINGEMENT . 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 Steet , Fifth Floor , Boston ,
* MA 02110 - 1301 , USA .
*
* In addition , as a special exception , the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file , and distribute linked combinations
* including the two .
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL . If you modify
* file ( s ) with this exception , you may extend this exception to your
* version of the file ( s ) , but you are not obligated to do so . If you
* do not wish to do so , delete this exception statement from your
* version . If you delete this exception statement from all source
* files in the program , then also delete it here .
*/
# include "kftptransferfile.h"
# include "widgets/systemtray.h"
# include "kftpsession.h"
# include "statistics.h"
# include "engine/thread.h"
# include "misc/kftpconfig.h"
# include <tdemessagebox.h>
# include <tdelocale.h>
# include <tdeio/renamedlg.h>
# include <kdiskfreesp.h>
# include <ntqtimer.h>
# include <ntqfileinfo.h>
using namespace KFTPEngine ;
using namespace KFTPSession ;
namespace KFTPQueue {
TransferFile : : TransferFile ( TQObject * parent )
: Transfer ( parent , Transfer : : File ) ,
m_updateTimer ( 0 ) ,
m_dfTimer ( 0 )
{
}
bool TransferFile : : assignSessions ( Session * source , Session * destination )
{
if ( ! Transfer : : assignSessions ( source , destination ) )
return false ;
// Connect signals
if ( m_srcConnection ) {
connect ( m_srcConnection - > getClient ( ) - > eventHandler ( ) , SIGNAL ( engineEvent ( KFTPEngine : : Event * ) ) , this , SLOT ( slotEngineEvent ( KFTPEngine : : Event * ) ) ) ;
connect ( m_srcConnection , SIGNAL ( aborting ( ) ) , this , SLOT ( slotSessionAborting ( ) ) ) ;
connect ( m_srcConnection , SIGNAL ( connectionLost ( KFTPSession : : Connection * ) ) , this , SLOT ( slotConnectionLost ( KFTPSession : : Connection * ) ) ) ;
}
if ( m_dstConnection ) {
connect ( m_dstConnection - > getClient ( ) - > eventHandler ( ) , SIGNAL ( engineEvent ( KFTPEngine : : Event * ) ) , this , SLOT ( slotEngineEvent ( KFTPEngine : : Event * ) ) ) ;
connect ( m_dstConnection , SIGNAL ( aborting ( ) ) , this , SLOT ( slotSessionAborting ( ) ) ) ;
connect ( m_dstConnection , SIGNAL ( connectionLost ( KFTPSession : : Connection * ) ) , this , SLOT ( slotConnectionLost ( KFTPSession : : Connection * ) ) ) ;
}
return true ;
}
void TransferFile : : execute ( )
{
// Failed transfers aren't allowed to be executed until they are readded to
// the queue and the Failed status is changed to Stopped.
if ( getStatus ( ) = = Failed )
return ;
// Assign sessions if they are missing
if ( ! connectionsReady ( ) & & ! assignSessions ( m_srcSession , m_dstSession ) )
return ;
if ( ( m_dstConnection & & ! m_dstConnection - > isConnected ( ) ) | | ( m_srcConnection & & ! m_srcConnection - > isConnected ( ) ) ) {
m_status = Connecting ;
return ;
}
// We are running now
m_status = Running ;
m_completed = 0 ;
m_resumed = 0 ;
// Init timer to follow the update
if ( ! m_updateTimer ) {
m_updateTimer = new TQTimer ( this ) ;
connect ( m_updateTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( slotTimerUpdate ( ) ) ) ;
m_updateTimer - > start ( 1000 ) ;
}
// Should we check for free space ?
if ( KFTPCore : : Config : : diskCheckSpace ( ) & & ! m_dfTimer ) {
m_dfTimer = new TQTimer ( this ) ;
connect ( m_dfTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( slotTimerDiskFree ( ) ) ) ;
m_dfTimer - > start ( KFTPCore : : Config : : diskCheckInterval ( ) * 1000 ) ;
}
emit transferStart ( m_id ) ;
switch ( m_transferType ) {
case Download : {
m_srcConnection - > getClient ( ) - > get ( m_sourceUrl , m_destUrl ) ;
break ;
}
case Upload : {
m_dstConnection - > getClient ( ) - > put ( m_sourceUrl , m_destUrl ) ;
break ;
}
case FXP : {
// Start the timer to extrapolate transfer rate
m_elapsedTime . start ( ) ;
m_srcConnection - > getClient ( ) - > siteToSite ( m_dstConnection - > getClient ( ) , m_sourceUrl , m_destUrl ) ;
break ;
}
}
}
void TransferFile : : slotConnectionLost ( KFTPSession : : Connection * connection )
{
if ( ! isRunning ( ) )
return ;
if ( m_status ! = Connecting ) {
// Semi-reset the current transfer
addCompleted ( - m_completed ) ;
m_resumed = 0 ;
m_completed = 0 ;
m_aborting = false ;
m_size = m_actualSize ;
setSpeed ( 0 ) ;
// Wait for the connection to come
m_status = Connecting ;
connection - > reconnect ( ) ;
} else
connection - > reconnect ( ) ;
}
void TransferFile : : slotEngineEvent ( KFTPEngine : : Event * event )
{
if ( ! isRunning ( ) )
return ;
switch ( event - > type ( ) ) {
case Event : : EventTransferComplete : {
// ***************************************************************************
// ************************ EventTransferComplete ****************************
// ***************************************************************************
// Calculate transfer rate for last transfer, and save to site's statistics
if ( getTransferType ( ) = = FXP ) {
if ( m_elapsedTime . elapsed ( ) > 10000 ) {
double speed = ( m_size - m_resumed ) / ( double ) m_elapsedTime . elapsed ( ) ;
Statistics : : self ( ) - > getSite ( m_sourceUrl ) - > setLastFxpSpeed ( speed * 1024 ) ;
}
}
// Update the completed size if the transfer was faster than the update timer
addCompleted ( m_size - m_completed ) ;
m_updateTimer - > stop ( ) ;
m_updateTimer - > TQObject : : disconnect ( ) ;
if ( m_openAfterTransfer & & m_transferType = = Download ) {
// Set status to stopped, so the view gets reloaded
m_status = Stopped ;
Manager : : self ( ) - > openAfterTransfer ( this ) ;
} else {
showTransCompleteBalloon ( ) ;
}
m_deleteMe = true ;
addActualSize ( - m_size ) ;
resetTransfer ( ) ;
emit transferComplete ( m_id ) ;
KFTPQueue : : Manager : : self ( ) - > doEmitUpdate ( ) ;
break ;
}
case Event : : EventResumeOffset : {
// ***************************************************************************
// ************************** EventResumeOffset ******************************
// ***************************************************************************
m_resumed = event - > getParameter ( 0 ) . asFileSize ( ) ;
addCompleted ( m_resumed ) ;
break ;
}
case Event : : EventError : {
// ***************************************************************************
// ****************************** EventError *********************************
// ***************************************************************************
ErrorCode error = event - > getParameter ( 0 ) . asErrorCode ( ) ;
switch ( error ) {
case ConnectFailed : {
FailedTransfer : : fail ( this , i18n ( " Connection to the server has failed. " ) ) ;
break ;
}
case LoginFailed : {
FailedTransfer : : fail ( this , i18n ( " Login to the server has failed " ) ) ;
break ;
}
case FileNotFound : {
FailedTransfer : : fail ( this , i18n ( " Source file cannot be found. " ) ) ;
break ;
}
case PermissionDenied : {
FailedTransfer : : fail ( this , i18n ( " Permission was denied. " ) ) ;
break ;
}
case FileOpenFailed : {
FailedTransfer : : fail ( this , i18n ( " Unable to open local file for read or write operations. " ) ) ;
break ;
}
case OperationFailed : {
FailedTransfer : : fail ( this , i18n ( " Transfer failed for some reason. " ) ) ;
break ;
}
default : break ;
}
break ;
}
case Event : : EventFileExists : {
// ***************************************************************************
// *************************** EventFileExists *******************************
// ***************************************************************************
DirectoryListing list = event - > getParameter ( 0 ) . asDirectoryListing ( ) ;
FileExistsWakeupEvent * event = Manager : : self ( ) - > fileExistsAction ( this , list . list ( ) ) ;
if ( event )
remoteConnection ( ) - > getClient ( ) - > wakeup ( event ) ;
break ;
}
default : break ;
}
}
void TransferFile : : wakeup ( KFTPEngine : : FileExistsWakeupEvent * event )
{
if ( event )
remoteConnection ( ) - > getClient ( ) - > wakeup ( event ) ;
}
void TransferFile : : slotTimerUpdate ( )
{
// Update the current stats
if ( ! m_srcSession & & ! m_dstSession ) {
m_updateTimer - > stop ( ) ;
m_updateTimer - > TQObject : : disconnect ( ) ;
return ;
}
if ( m_status = = Running ) {
// Get speed from connection, or use FXP extrapolation.
if ( getTransferType ( ) = = FXP ) {
double lastFxpSpeed = Statistics : : self ( ) - > getSite ( m_sourceUrl ) - > lastFxpSpeed ( ) ;
if ( lastFxpSpeed ! = 0.0 ) {
setSpeed ( lastFxpSpeed ) ;
if ( m_completed < m_size )
addCompleted ( getSpeed ( ) ) ;
}
} else {
if ( remoteConnection ( ) - > getClient ( ) - > socket ( ) - > getTransferBytes ( ) > m_completed - m_resumed )
addCompleted ( remoteConnection ( ) - > getClient ( ) - > socket ( ) - > getTransferBytes ( ) - ( m_completed - m_resumed ) ) ;
setSpeed ( remoteConnection ( ) - > getClient ( ) - > socket ( ) - > getTransferSpeed ( ) ) ;
}
}
update ( ) ;
}
void TransferFile : : slotTimerDiskFree ( )
{
// Check for disk usage
if ( KFTPCore : : Config : : diskCheckSpace ( ) ) {
KDiskFreeSp * df = KDiskFreeSp : : findUsageInfo ( ( getDestUrl ( ) . path ( ) ) ) ;
connect ( df , SIGNAL ( foundMountPoint ( const TQString & , unsigned long , unsigned long , unsigned long ) ) , this , SLOT ( slotDiskFree ( const TQString & , unsigned long , unsigned long , unsigned long ) ) ) ;
}
}
void TransferFile : : slotDiskFree ( const TQString & mountPoint , unsigned long , unsigned long , unsigned long kBAvail )
{
if ( KFTPCore : : Config : : diskCheckSpace ( ) ) {
// Is there enough free space ?
if ( kBAvail < ( unsigned long ) KFTPCore : : Config : : diskMinFreeSpace ( ) ) {
TQString transAbortStr = i18n ( " Transfer of the following files <b>has been aborted</b> because there is not enough free space left on '%1': " ) . arg ( mountPoint ) ;
transAbortStr + = " <br><i> " ;
transAbortStr + = getSourceUrl ( ) . fileName ( ) ;
transAbortStr + = " </i> " ;
KFTPWidgets : : SystemTray : : self ( ) - > showBalloon ( transAbortStr ) ;
// Abort the transfer
abort ( ) ;
}
}
}
void TransferFile : : resetTransfer ( )
{
// Unlock the sessions (they should be unlocked automaticly when the transferComplete signal
// is emitted, but when a transfer is a child transfer, the next transfer may need the session
// sooner). Also sessions should be unlocked when transfer aborts.
if ( getStatus ( ) ! = Waiting ) {
// Disconnect signals
if ( m_srcConnection ) {
m_srcConnection - > getClient ( ) - > eventHandler ( ) - > TQObject : : disconnect ( this , SLOT ( slotEngineEvent ( KFTPEngine : : Event * ) ) ) ;
m_srcConnection - > TQObject : : disconnect ( this , SLOT ( slotSessionAborting ( ) ) ) ;
m_srcConnection - > TQObject : : disconnect ( this , SLOT ( slotConnectionLost ( KFTPSession : : Connection * ) ) ) ;
m_srcConnection - > remove ( ) ;
}
if ( m_dstConnection ) {
m_dstConnection - > getClient ( ) - > eventHandler ( ) - > TQObject : : disconnect ( this , SLOT ( slotEngineEvent ( KFTPEngine : : Event * ) ) ) ;
m_dstConnection - > TQObject : : disconnect ( this , SLOT ( slotSessionAborting ( ) ) ) ;
m_dstConnection - > TQObject : : disconnect ( this , SLOT ( slotConnectionLost ( KFTPSession : : Connection * ) ) ) ;
m_dstConnection - > remove ( ) ;
}
}
Transfer : : resetTransfer ( ) ;
}
void TransferFile : : slotSessionAborting ( )
{
if ( ! m_aborting )
abort ( ) ;
}
void TransferFile : : abort ( )
{
if ( ! isRunning ( ) )
return ;
Transfer : : abort ( ) ;
if ( getStatus ( ) = = Waiting ) {
if ( m_srcSession )
m_srcSession - > TQObject : : disconnect ( this , SLOT ( slotConnectionAvailable ( ) ) ) ;
if ( m_dstSession )
m_dstSession - > TQObject : : disconnect ( this , SLOT ( slotConnectionAvailable ( ) ) ) ;
}
if ( m_updateTimer ) {
m_updateTimer - > stop ( ) ;
m_updateTimer - > TQObject : : disconnect ( ) ;
delete m_updateTimer ;
m_updateTimer = 0L ;
}
if ( m_dfTimer ) {
m_dfTimer - > stop ( ) ;
m_dfTimer - > TQObject : : disconnect ( ) ;
delete m_dfTimer ;
m_dfTimer = 0L ;
}
// Abort any transfers
if ( m_srcConnection )
m_srcConnection - > abort ( ) ;
if ( m_dstConnection )
m_dstConnection - > abort ( ) ;
// Update everything
resetTransfer ( ) ;
if ( ! hasParentTransfer ( ) )
update ( ) ;
if ( hasParentObject ( ) & & parentObject ( ) - > isAborting ( ) )
disconnect ( parent ( ) ) ;
}
}
# include "kftptransferfile.moc"