Q3FtpPI Class Reference

Inheritance diagram for Q3FtpPI:

Inheritance graph
[legend]
Collaboration diagram for Q3FtpPI:

Collaboration graph
[legend]
List of all members.

Detailed Description

Definition at line 145 of file q3ftp.cpp.

Signals

void connectState (int)
void finished (const QString &)
void error (int, const QString &)
void rawFtpReply (int, const QString &)

Public Member Functions

 Q3FtpPI (QObject *parent=0)
void connectToHost (const QString &host, Q_UINT16 port)
bool sendCommands (const QStringList &cmds)
bool sendCommand (const QString &cmd)
void clearPendingCommands ()
void abort ()
QString currentCommand () const

Public Attributes

bool rawCommand
Q3FtpDTP dtp

Private Types

enum  State
enum  AbortState

Private Slots

void hostFound ()
void connected ()
void connectionClosed ()
void delayedCloseFinished ()
void readyRead ()
void error (int)
void dtpConnectState (int)

Private Member Functions

bool processReply ()
bool startNextCmd ()

Private Attributes

Q3Socket commandSocket
QString replyText
signed char replyCode [3]
State state
AbortState abortState
QStringList pendingCommands
QString currentCmd
bool waitForDtpToConnect
bool waitForDtpToClose


Member Enumeration Documentation

enum Q3FtpPI::State [private]

Definition at line 187 of file q3ftp.cpp.

00187                {
00188   Begin,
00189   Idle,
00190   Waiting,
00191   Success,
00192   Failure
00193     };

enum Q3FtpPI::AbortState [private]

Definition at line 195 of file q3ftp.cpp.

00195                     {
00196   None,
00197   AbortStarted,
00198   WaitForAbortToFinish
00199     };


Constructor & Destructor Documentation

Q3FtpPI::Q3FtpPI ( QObject parent = 0  ) 

Definition at line 616 of file q3ftp.cpp.

References commandSocket, QObject::connect(), connected(), connectionClosed(), connectState(), delayedCloseFinished(), dtp, dtpConnectState(), error(), hostFound(), readyRead(), SIGNAL, and SLOT.

00616                                   :
00617     QObject( parent ),
00618     rawCommand(false),
00619     dtp( this ),
00620     commandSocket( 0, "Q3FtpPI_socket" ),
00621     state( Begin ), abortState( None ),
00622     currentCmd( QString() ),
00623     waitForDtpToConnect( false ),
00624     waitForDtpToClose( false )
00625 {
00626     connect( &commandSocket, SIGNAL(hostFound()),
00627       SLOT(hostFound()) );
00628     connect( &commandSocket, SIGNAL(connected()),
00629       SLOT(connected()) );
00630     connect( &commandSocket, SIGNAL(connectionClosed()),
00631       SLOT(connectionClosed()) );
00632     connect( &commandSocket, SIGNAL(delayedCloseFinished()),
00633       SLOT(delayedCloseFinished()) );
00634     connect( &commandSocket, SIGNAL(readyRead()),
00635       SLOT(readyRead()) );
00636     connect( &commandSocket, SIGNAL(error(int)),
00637       SLOT(error(int)) );
00638 
00639     connect( &dtp, SIGNAL(connectState(int)),
00640        SLOT(dtpConnectState(int)) );
00641 }

Here is the call graph for this function:


Member Function Documentation

void Q3FtpPI::connectToHost ( const QString host,
Q_UINT16  port 
)

Definition at line 643 of file q3ftp.cpp.

References commandSocket, connectState(), Q3Socket::connectToHost(), emit, and Q3Ftp::HostLookup.

00644 {
00645     emit connectState( Q3Ftp::HostLookup );
00646     commandSocket.connectToHost( host, port );
00647 }

Here is the call graph for this function:

bool Q3FtpPI::sendCommands ( const QStringList cmds  ) 

Definition at line 657 of file q3ftp.cpp.

References commandSocket, Q3Socket::Connected, emit, error(), Idle, QList< T >::isEmpty(), Q3Ftp::NotConnected, pendingCommands, startNextCmd(), state, and Q3Socket::state().

Referenced by sendCommand().

00658 {
00659     if ( !pendingCommands.isEmpty() )
00660   return false;
00661 
00662     if ( commandSocket.state()!=Q3Socket::Connected || state!=Idle ) {
00663   emit error( Q3Ftp::NotConnected, QFtp::tr( "Not connected" ) );
00664   return true; // there are no pending commands
00665     }
00666 
00667     pendingCommands = cmds;
00668     startNextCmd();
00669     return true;
00670 }

Here is the call graph for this function:

bool Q3FtpPI::sendCommand ( const QString cmd  )  [inline]

Definition at line 155 of file q3ftp.cpp.

References sendCommands().

00156     { return sendCommands( QStringList( cmd ) ); }

Here is the call graph for this function:

void Q3FtpPI::clearPendingCommands (  ) 

Definition at line 672 of file q3ftp.cpp.

References Q3FtpDTP::abortConnection(), QString::clear(), QList< T >::clear(), currentCmd, dtp, Idle, pendingCommands, and state.

00673 {
00674     pendingCommands.clear();
00675     dtp.abortConnection();
00676     currentCmd.clear();
00677     state = Idle;
00678 }

Here is the call graph for this function:

void Q3FtpPI::abort (  ) 

Definition at line 680 of file q3ftp.cpp.

References Q3FtpDTP::abortConnection(), AbortStarted, abortState, QList< T >::clear(), commandSocket, currentCmd, dtp, None, pendingCommands, qDebug(), and QString::startsWith().

00681 {
00682     pendingCommands.clear();
00683 
00684     if ( abortState != None )
00685   // ABOR already sent
00686   return;
00687 
00688     abortState = AbortStarted;
00689 #if defined(Q3FTPPI_DEBUG)
00690     qDebug( "Q3FtpPI send: ABOR" );
00691 #endif
00692     commandSocket.writeBlock( "ABOR\r\n", 6 );
00693 
00694     if ( currentCmd.startsWith("STOR ") )
00695   dtp.abortConnection();
00696 }

Here is the call graph for this function:

QString Q3FtpPI::currentCommand (  )  const [inline]

Definition at line 161 of file q3ftp.cpp.

References currentCmd.

Referenced by Q3FtpDTP::socketReadyRead().

00162     { return currentCmd; }

void Q3FtpPI::connectState ( int   )  [signal]

Referenced by connected(), connectionClosed(), connectToHost(), delayedCloseFinished(), error(), hostFound(), processReply(), and Q3FtpPI().

void Q3FtpPI::finished ( const QString  )  [signal]

Referenced by processReply(), and startNextCmd().

void Q3FtpPI::error ( int  ,
const QString  
) [signal]

Referenced by dtpConnectState(), error(), processReply(), Q3FtpPI(), and sendCommands().

void Q3FtpPI::rawFtpReply ( int  ,
const QString  
) [signal]

Referenced by processReply().

void Q3FtpPI::hostFound (  )  [private, slot]

Definition at line 698 of file q3ftp.cpp.

References Q3Ftp::Connecting, connectState(), and emit.

Referenced by Q3FtpPI().

00699 {
00700     emit connectState( Q3Ftp::Connecting );
00701 }

void Q3FtpPI::connected (  )  [private, slot]

Definition at line 703 of file q3ftp.cpp.

References Begin, Q3Ftp::Connected, connectState(), emit, and state.

Referenced by Q3FtpPI().

00704 {
00705     state = Begin;
00706 #if defined(Q3FTPPI_DEBUG)
00707 //    qDebug( "Q3FtpPI state: %d [connected()]", state );
00708 #endif
00709     emit connectState( Q3Ftp::Connected );
00710 }

void Q3FtpPI::connectionClosed (  )  [private, slot]

Definition at line 712 of file q3ftp.cpp.

References Q3Socket::close(), commandSocket, connectState(), emit, and Q3Ftp::Unconnected.

Referenced by Q3FtpPI().

00713 {
00714     commandSocket.close();
00715     emit connectState( Q3Ftp::Unconnected );
00716 }

void Q3FtpPI::delayedCloseFinished (  )  [private, slot]

Definition at line 718 of file q3ftp.cpp.

References connectState(), emit, and Q3Ftp::Unconnected.

Referenced by Q3FtpPI().

00719 {
00720     emit connectState( Q3Ftp::Unconnected );
00721 }

void Q3FtpPI::readyRead (  )  [private, slot]

Definition at line 736 of file q3ftp.cpp.

References Q3Socket::canReadLine(), commandSocket, QUnicodeTables::digitValue(), QString::endsWith(), i, QString::isEmpty(), QString::left(), QString::length(), QString::mid(), processReply(), QIODevice::readLine(), replyCode, replyText, QString::truncate(), and waitForDtpToClose.

Referenced by dtpConnectState(), and Q3FtpPI().

00737 {
00738     if ( waitForDtpToClose )
00739   return;
00740 
00741     while ( commandSocket.canReadLine() ) {
00742   // read line with respect to line continuation
00743   QString line = commandSocket.readLine();
00744   if ( replyText.isEmpty() ) {
00745       if ( line.length() < 3 ) {
00746     // ### protocol error
00747     return;
00748       }
00749       const int lowerLimit[3] = {1,0,0};
00750       const int upperLimit[3] = {5,5,9};
00751       for ( int i=0; i<3; i++ ) {
00752     replyCode[i] = line[i].digitValue();
00753     if ( replyCode[i]<lowerLimit[i] || replyCode[i]>upperLimit[i] ) {
00754         // ### protocol error
00755         return;
00756     }
00757       }
00758   }
00759   QString endOfMultiLine;
00760   endOfMultiLine[0] = '0' + replyCode[0];
00761   endOfMultiLine[1] = '0' + replyCode[1];
00762   endOfMultiLine[2] = '0' + replyCode[2];
00763   endOfMultiLine[3] = ' ';
00764   QString lineCont( endOfMultiLine );
00765   lineCont[3] = '-';
00766   QString lineLeft4 = line.left(4);
00767 
00768   while ( lineLeft4 != endOfMultiLine ) {
00769       if ( lineLeft4 == lineCont )
00770     replyText += line.mid( 4 ); // strip 'xyz-'
00771       else
00772     replyText += line;
00773       if ( !commandSocket.canReadLine() )
00774     return;
00775       line = commandSocket.readLine();
00776       lineLeft4 = line.left(4);
00777   }
00778   replyText += line.mid( 4 ); // strip reply code 'xyz '
00779   if ( replyText.endsWith("\r\n") )
00780       replyText.truncate( replyText.length()-2 );
00781 
00782   if ( processReply() )
00783       replyText = "";
00784     }
00785 }

void Q3FtpPI::error ( int   )  [private, slot]

Definition at line 723 of file q3ftp.cpp.

References commandSocket, Q3Ftp::ConnectionRefused, connectState(), emit, Q3Socket::ErrConnectionRefused, Q3Socket::ErrHostNotFound, error(), Q3Ftp::HostNotFound, Q3Socket::peerName(), and Q3Ftp::Unconnected.

00724 {
00725     if ( e == Q3Socket::ErrHostNotFound ) {
00726   emit connectState( Q3Ftp::Unconnected );
00727   emit error( Q3Ftp::HostNotFound,
00728         QFtp::tr( "Host %1 not found" ).arg( commandSocket.peerName() ) );
00729     } else if ( e == Q3Socket::ErrConnectionRefused ) {
00730   emit connectState( Q3Ftp::Unconnected );
00731   emit error( Q3Ftp::ConnectionRefused,
00732         QFtp::tr( "Connection refused to host %1" ).arg( commandSocket.peerName() ) );
00733     }
00734 }

void Q3FtpPI::dtpConnectState ( int   )  [private, slot]

Definition at line 974 of file q3ftp.cpp.

References Q3Ftp::ConnectionRefused, Q3FtpDTP::CsClosed, Q3FtpDTP::CsConnected, Q3FtpDTP::CsConnectionRefused, Q3FtpDTP::CsHostNotFound, emit, error(), processReply(), readyRead(), replyText, startNextCmd(), waitForDtpToClose, and waitForDtpToConnect.

Referenced by Q3FtpPI().

00975 {
00976     switch ( s ) {
00977   case Q3FtpDTP::CsClosed:
00978       if ( waitForDtpToClose ) {
00979     // there is an unprocessed reply
00980     if ( processReply() )
00981         replyText = "";
00982     else
00983         return;
00984       }
00985       waitForDtpToClose = false;
00986       readyRead();
00987       return;
00988   case Q3FtpDTP::CsConnected:
00989       waitForDtpToConnect = false;
00990       startNextCmd();
00991       return;
00992   case Q3FtpDTP::CsHostNotFound:
00993   case Q3FtpDTP::CsConnectionRefused:
00994       emit error( Q3Ftp::ConnectionRefused,
00995       QFtp::tr( "Connection refused for data connection" ) );
00996       startNextCmd();
00997       return;
00998   default:
00999       return;
01000     }
01001 }

bool Q3FtpPI::processReply (  )  [private]

Definition at line 793 of file q3ftp.cpp.

References AbortStarted, abortState, Begin, QRegExp::capturedTexts(), Q3FtpDTP::clearError(), commandSocket, connectState(), Q3FtpDTP::connectToHost(), QList< T >::count(), currentCmd, dtp, emit, error(), Q3FtpDTP::errorMessage(), Failure, finished(), QList< T >::first(), Q3FtpDTP::hasError(), Idle, Q3Socket::Idle, QString::length(), Q3Ftp::LoggedIn, None, Q3Socket::peerName(), pendingCommands, QList< T >::pop_front(), qDebug(), rawCommand, rawFtpReply(), replyCode, replyText, Q3FtpDTP::setBytesTotal(), Q3FtpDTP::socketState(), startNextCmd(), QString::startsWith(), state, Success, t, QString::toInt(), Q3Ftp::UnknownError, WaitForAbortToFinish, waitForDtpToClose, waitForDtpToConnect, Waiting, and Q3FtpDTP::writeData().

Referenced by dtpConnectState(), and readyRead().

00794 {
00795 #if defined(Q3FTPPI_DEBUG)
00796 //    qDebug( "Q3FtpPI state: %d [processReply() begin]", state );
00797     if ( replyText.length() < 400 )
00798   qDebug( "Q3FtpPI recv: %d %s", 100*replyCode[0]+10*replyCode[1]+replyCode[2], replyText.latin1() );
00799     else
00800   qDebug( "Q3FtpPI recv: %d (text skipped)", 100*replyCode[0]+10*replyCode[1]+replyCode[2] );
00801 #endif
00802 
00803     // process 226 replies ("Closing Data Connection") only when the data
00804     // connection is really closed to avoid short reads of the DTP
00805     if ( 100*replyCode[0]+10*replyCode[1]+replyCode[2] == 226 ) {
00806   if ( dtp.socketState() != Q3Socket::Idle ) {
00807       waitForDtpToClose = true;
00808       return false;
00809   }
00810     }
00811 
00812     switch ( abortState ) {
00813   case AbortStarted:
00814       abortState = WaitForAbortToFinish;
00815       break;
00816   case WaitForAbortToFinish:
00817       abortState = None;
00818       return true;
00819   default:
00820       break;
00821     }
00822 
00823     // get new state
00824     static const State table[5] = {
00825   /* 1yz   2yz      3yz   4yz      5yz */
00826   Waiting, Success, Idle, Failure, Failure
00827     };
00828     switch ( state ) {
00829   case Begin:
00830       if ( replyCode[0] == 1 ) {
00831     return true;
00832       } else if ( replyCode[0] == 2 ) {
00833     state = Idle;
00834     emit finished( QFtp::tr( "Connected to host %1" ).arg( commandSocket.peerName() ) );
00835     break;
00836       }
00837       // ### error handling
00838       return true;
00839   case Waiting:
00840       if ( replyCode[0]<0 || replyCode[0]>5 )
00841     state = Failure;
00842       else
00843 #if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
00844             {
00845                 // work around a crash on 64 bit gcc IRIX
00846                 State *t = (State *) table;
00847                 state = t[replyCode[0] - 1];
00848             }
00849 #else
00850             state = table[replyCode[0] - 1];
00851 #endif
00852       break;
00853   default:
00854       // ### spontaneous message
00855       return true;
00856     }
00857 #if defined(Q3FTPPI_DEBUG)
00858 //    qDebug( "Q3FtpPI state: %d [processReply() intermediate]", state );
00859 #endif
00860 
00861     // special actions on certain replies
00862     int replyCodeInt = 100*replyCode[0] + 10*replyCode[1] + replyCode[2];
00863     emit rawFtpReply( replyCodeInt, replyText );
00864     if ( rawCommand ) {
00865   rawCommand = false;
00866     } else if ( replyCodeInt == 227 ) {
00867   // 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)
00868         // rfc959 does not define this response precisely, and gives
00869         // both examples where the parenthesis are used, and where
00870         // they are missing. We need to scan for the address and host
00871         // info.
00872   QRegExp addrPortPattern("(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)");
00873   if (addrPortPattern.search(replyText) == -1) {
00874 #if defined(Q3FTPPI_DEBUG)
00875       qDebug( "Q3Ftp: bad 227 response -- address and port information missing" );
00876 #endif
00877       // ### error handling
00878   } else {
00879       QStringList lst = addrPortPattern.capturedTexts();
00880       QString host = lst[1] + "." + lst[2] + "." + lst[3] + "." + lst[4];
00881       Q_UINT16 port = ( lst[5].toUInt() << 8 ) + lst[6].toUInt();
00882       waitForDtpToConnect = true;
00883       dtp.connectToHost( host, port );
00884   }
00885     } else if ( replyCodeInt == 230 ) {
00886   if ( currentCmd.startsWith("USER ") && pendingCommands.count()>0 &&
00887     pendingCommands.first().startsWith("PASS ") ) {
00888       // no need to send the PASS -- we are already logged in
00889       pendingCommands.pop_front();
00890   }
00891   // 230 User logged in, proceed.
00892   emit connectState( Q3Ftp::LoggedIn );
00893     } else if ( replyCodeInt == 213 ) {
00894   // 213 File status.
00895   if ( currentCmd.startsWith("SIZE ") )
00896       dtp.setBytesTotal( replyText.simplifyWhiteSpace().toInt() );
00897     } else if ( replyCode[0]==1 && currentCmd.startsWith("STOR ") ) {
00898   dtp.writeData();
00899     }
00900 
00901     // react on new state
00902     switch ( state ) {
00903   case Begin:
00904       // ### should never happen
00905       break;
00906   case Success:
00907       // ### success handling
00908       state = Idle;
00909       // no break!
00910   case Idle:
00911       if ( dtp.hasError() ) {
00912     emit error( Q3Ftp::UnknownError, dtp.errorMessage() );
00913     dtp.clearError();
00914       }
00915       startNextCmd();
00916       break;
00917   case Waiting:
00918       // ### do nothing
00919       break;
00920   case Failure:
00921       emit error( Q3Ftp::UnknownError, replyText );
00922       state = Idle;
00923       startNextCmd();
00924       break;
00925     }
00926 #if defined(Q3FTPPI_DEBUG)
00927 //    qDebug( "Q3FtpPI state: %d [processReply() end]", state );
00928 #endif
00929     return true;
00930 }

Here is the call graph for this function:

bool Q3FtpPI::startNextCmd (  )  [private]

Definition at line 940 of file q3ftp.cpp.

References QString::clear(), commandSocket, currentCmd, QByteArray::data(), emit, finished(), QList< T >::first(), QTextCodec::fromUnicode(), Idle, QList< T >::isEmpty(), QString::left(), len, QString::length(), pendingCommands, QList< T >::pop_front(), qDebug(), qt_ftp_filename_codec, replyText, state, waitForDtpToConnect, and Waiting.

Referenced by dtpConnectState(), processReply(), and sendCommands().

00941 {
00942     if ( waitForDtpToConnect )
00943   // don't process any new commands until we are connected
00944   return true;
00945 
00946 #if defined(Q3FTPPI_DEBUG)
00947     if ( state != Idle )
00948   qDebug( "Q3FtpPI startNextCmd: Internal error! Q3FtpPI called in non-Idle state %d", state );
00949 #endif
00950     if ( pendingCommands.isEmpty() ) {
00951   currentCmd.clear();
00952   emit finished( replyText );
00953   return false;
00954     }
00955     currentCmd = pendingCommands.first();
00956     pendingCommands.pop_front();
00957 #if defined(Q3FTPPI_DEBUG)
00958     qDebug( "Q3FtpPI send: %s", currentCmd.left( currentCmd.length()-2 ).latin1() );
00959 #endif
00960     state = Waiting;
00961 #ifndef QT_NO_TEXTCODEC
00962     if ( qt_ftp_filename_codec ) {
00963   int len;
00964   Q3CString enc = qt_ftp_filename_codec->fromUnicode(currentCmd,len);
00965   commandSocket.writeBlock( enc.data(), len );
00966     } else
00967 #endif
00968     {
00969   commandSocket.writeBlock( currentCmd.latin1(), currentCmd.length() );
00970     }
00971     return true;
00972 }

Here is the call graph for this function:


Member Data Documentation

bool Q3FtpPI::rawCommand

Definition at line 164 of file q3ftp.cpp.

Referenced by processReply().

Q3FtpDTP Q3FtpPI::dtp

Definition at line 166 of file q3ftp.cpp.

Referenced by abort(), clearPendingCommands(), processReply(), and Q3FtpPI().

Q3Socket Q3FtpPI::commandSocket [private]

Definition at line 204 of file q3ftp.cpp.

Referenced by abort(), connectionClosed(), connectToHost(), error(), processReply(), Q3FtpPI(), readyRead(), sendCommands(), and startNextCmd().

QString Q3FtpPI::replyText [private]

Definition at line 205 of file q3ftp.cpp.

Referenced by dtpConnectState(), processReply(), readyRead(), and startNextCmd().

signed char Q3FtpPI::replyCode[3] [private]

Definition at line 206 of file q3ftp.cpp.

Referenced by processReply(), and readyRead().

State Q3FtpPI::state [private]

Definition at line 207 of file q3ftp.cpp.

Referenced by clearPendingCommands(), connected(), processReply(), sendCommands(), and startNextCmd().

AbortState Q3FtpPI::abortState [private]

Definition at line 208 of file q3ftp.cpp.

Referenced by abort(), and processReply().

QStringList Q3FtpPI::pendingCommands [private]

Definition at line 209 of file q3ftp.cpp.

Referenced by abort(), clearPendingCommands(), processReply(), sendCommands(), and startNextCmd().

QString Q3FtpPI::currentCmd [private]

Definition at line 210 of file q3ftp.cpp.

Referenced by abort(), clearPendingCommands(), currentCommand(), processReply(), and startNextCmd().

bool Q3FtpPI::waitForDtpToConnect [private]

Definition at line 212 of file q3ftp.cpp.

Referenced by dtpConnectState(), processReply(), and startNextCmd().

bool Q3FtpPI::waitForDtpToClose [private]

Definition at line 213 of file q3ftp.cpp.

Referenced by dtpConnectState(), processReply(), and readyRead().


The documentation for this class was generated from the following file:
Generated on Thu Mar 15 15:57:17 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1