/*************************************************************************** msnfiletransfersocket.cpp - description ------------------- begin : mer jui 31 2002 copyright : (C) 2002 by Olivier Goffart email : ogoffart @ kde.org ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include "msnfiletransfersocket.h" #include #include //qt #include // kde #include #include #include #include #include #include "kopetetransfermanager.h" #include "kopetecontact.h" #include "kopetemetacontact.h" #include "msnchatsession.h" #include "msnswitchboardsocket.h" #include "msnnotifysocket.h" #include "msnaccount.h" using namespace KNetwork; MSNFileTransferSocket::MSNFileTransferSocket(const TQString &handle, Kopete::Contact *c,bool incoming, TQObject* parent) : MSNSocket(parent) , MSNInvitation(incoming, MSNFileTransferSocket::applicationID() , i18n("File Transfer - MSN Plugin")) { m_handle=handle; m_kopeteTransfer=0l; m_file=0L; m_server=0L; m_contact=c; ready=true; TQObject::connect( this, TQT_SIGNAL( socketClosed() ), this, TQT_SLOT( slotSocketClosed() ) ); TQObject::connect( this, TQT_SIGNAL( blockRead( const TQByteArray & ) ), this, TQT_SLOT(slotReadBlock( const TQByteArray & ) ) ); } MSNFileTransferSocket::~MSNFileTransferSocket() { delete m_file; delete m_server; kdDebug(14140) << "MSNFileTransferSocket::~MSNFileTransferSocket" <open( IO_WriteOnly )) sendCommand( "TFR" ,NULL,false); else { kdDebug(14140) << "MSNFileTransferSocket::parseCommand: ERROR: unable to open file - disconnect " <close(); delete m_file; m_file=0L; delete m_server; m_server=0L; if(m_kopeteTransfer) { if( (m_downsize!=m_size || m_downsize==0 ) ) m_kopeteTransfer->slotError( KIO::ERR_UNKNOWN , i18n( "An unknown error occurred" ) ); else m_kopeteTransfer->slotComplete(); } emit done(this); } void MSNFileTransferSocket::slotReadBlock(const TQByteArray &block) { m_file->writeBlock( block.data(), block.size() ); // write to file m_downsize+=block.size(); if(m_kopeteTransfer) m_kopeteTransfer->slotProcessed(m_downsize); kdDebug(14140) << "MSNFileTransferSocket - " << m_downsize << " of " << m_size <<" done"<setAddress(TQString::number(port)); kdDebug(14140) << "MSNFileTransferSocket::listen: about to listen"<listen(1); kdDebug(14140) << "MSNFileTransferSocket::listen: result: "<< listenResult <slotError( KIO::ERR_UNKNOWN , i18n( "An unknown error occurred" ) ); emit done(this); } } void MSNFileTransferSocket::slotTimer() { if(onlinetqStatus() != Disconnected) return; kdDebug(14140) << "MSNFileTransferSocket::slotTimer: timeout "<< endl; if( m_kopeteTransfer) { m_kopeteTransfer->slotError( KIO::ERR_CONNECTION_BROKEN , i18n( "Connection timed out" ) ); } MSNChatSession* manager=dynamic_cast(m_contact->manager()); if(manager && manager->service()) manager->service()->sendCommand( "MSG" , "N", true, rejectMessage("TIMEOUT") ); emit done(this); } void MSNFileTransferSocket::abort() { if(m_incoming) { sendCommand( "CCL" , NULL ,false); } else { TQByteArray bytes(3); bytes[0]='\1'; bytes[1]='\0'; bytes[2]='\0'; sendBytes( bytes ); m_downsize=m_size; //we don't want to send data anymore; } //the timer wait one second, the time to send the CCL or the binary header //retarding the disconnection keep away from a crash. (in KIO::Job::emitResult when `delete this`) TQTimer::singleShot( 1000, this, TQT_SLOT(disconnect()) ); ready=false; } void MSNFileTransferSocket::setFile( const TQString &fn, long unsigned int fileSize ) { m_fileName=fn; if(!m_incoming) { if(m_file) { kdDebug(14140) << "MSNFileTransferSocket::setFileName: WARNING m_file already exists" << endl; delete m_file; } m_file = new TQFile( fn ); if(!m_file->open(IO_ReadOnly)) { //FIXME: abort transfer here kdDebug(14140) << "MSNFileTransferSocket::setFileName: WARNING unable to open the file" << endl; } //If the fileSize is 0 it was not given, we are to get it from the file if(fileSize == 0L) m_size = m_file->size(); else m_size = fileSize; } } void MSNFileTransferSocket::slotSendFile() { // kdDebug(14140) <<"MSNFileTransferSocket::slotSendFile()" <= m_size) { //the transfer seems to be finished. // if we are not already disconected in 30 seconds, do it. TQTimer::singleShot( 30000 , this, TQT_SLOT(disconnect() ) ); return; } if(ready) { char data[2046]; int bytesRead = m_file->readBlock( data, 2045 ); TQByteArray block(bytesRead+3); // char i1= (char)fmod( bytesRead, 256 ) ; // char i2= (char)floor( bytesRead / 256 ) ; // kdDebug(14140) << "MSNFileTransferSocket::slotSendFile: " << (int)i1 <<" + 256* "<< (int)i2 <<" = " << bytesRead <slotProcessed(m_downsize); kdDebug(14140) << "MSNFileTransferSocket::slotSendFile: " << m_downsize << " of " << m_size <<" done"<askIncomingTransfer( m_contact , filename, filesize, TQString(), TQString::number( cookie() ) ); TQObject::connect( Kopete::TransferManager::transferManager(), TQT_SIGNAL( accepted( Kopete::Transfer *, const TQString& ) ),this, TQT_SLOT( slotFileTransferAccepted( Kopete::Transfer *, const TQString& ) ) ); TQObject::connect( Kopete::TransferManager::transferManager(), TQT_SIGNAL( refused( const Kopete::FileTransferInfo & ) ), this, TQT_SLOT( slotFileTransferRefused( const Kopete::FileTransferInfo & ) ) ); } else if( msg.contains("Invitation-Command: ACCEPT") ) { if(incoming()) { rx=TQRegExp("IP-Address: ([0-9\\.]*)"); rx.search(msg); TQString ip_address = rx.cap(1); rx=TQRegExp("AuthCookie: ([0-9]*)"); rx.search(msg); TQString authcook = rx.cap(1); rx=TQRegExp("Port: ([0-9]*)"); rx.search(msg); TQString port = rx.cap(1); setAuthCookie(authcook); connect(ip_address, port.toUInt()); } else { unsigned long int auth = (rand()%(999999))+1; setAuthCookie(TQString::number(auth)); setKopeteTransfer(Kopete::TransferManager::transferManager()->addTransfer(m_contact, fileName(), size(), m_contact->metaContact() ? m_contact->metaContact()->displayName() : m_contact->contactId() , Kopete::FileTransferInfo::Outgoing)); MSNChatSession* manager=dynamic_cast(m_contact->manager()); if(manager && manager->service()) { MSNNotifySocket *notify=static_cast(manager->account())->notifySocket(); if(notify){ TQCString message=TQString( "MIME-Version: 1.0\r\n" "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n" "\r\n" "Invitation-Command: ACCEPT\r\n" "Invitation-Cookie: " + TQString::number(cookie()) + "\r\n" "IP-Address: " + notify->localIP() + "\r\n" "Port: 6891\r\n" "AuthCookie: "+TQString::number(auth)+"\r\n" "Launch-Application: FALSE\r\n" "Request-Data: IP-Address:\r\n\r\n").utf8(); manager->service()->sendCommand( "MSG" , "N", true, message ); } } listen(6891); } } else //CANCEL { MSNInvitation::parseInvitation(msg); if( m_kopeteTransfer) m_kopeteTransfer->slotError( KIO::ERR_ABORTED , i18n( "The remote user aborted" ) ); emit done(this); } } void MSNFileTransferSocket::slotFileTransferAccepted(Kopete::Transfer *trans, const TQString& fileName) { if(trans->info().internalId().toULong() != cookie()) return; if(!trans->info().contact()) return; setKopeteTransfer(trans); MSNChatSession* manager=dynamic_cast(m_contact->manager()); if(manager && manager->service()) { setFile(fileName); TQCString message=TQString( "MIME-Version: 1.0\r\n" "Content-Type: text/x-msmsgsinvite; charset=UTF-8\r\n" "\r\n" "Invitation-Command: ACCEPT\r\n" "Invitation-Cookie: " + TQString::number(cookie()) + "\r\n" "Launch-Application: FALSE\r\n" "Request-Data: IP-Address:\r\n" ).utf8(); manager->service()->sendCommand( "MSG" , "N", true, message ); TQTimer::singleShot( 3 * 60000, this, TQT_SLOT(slotTimer()) ); //if after 3 minutes the transfer has not begin, delete this } else { if( m_kopeteTransfer) m_kopeteTransfer->slotError( KIO::ERR_UNKNOWN , i18n( "An unknown error occurred" ) ); emit done(this); } } void MSNFileTransferSocket::slotFileTransferRefused(const Kopete::FileTransferInfo &info) { if(info.internalId().toULong() != cookie()) return; if(!info.contact()) return; MSNChatSession* manager=dynamic_cast(m_contact->manager()); if(manager && manager->service()) { manager->service()->sendCommand( "MSG" , "N", true, rejectMessage() ); } emit done(this); } void MSNFileTransferSocket::slotKopeteTransferDestroyed() { m_kopeteTransfer=0L; } #include "msnfiletransfersocket.moc"