📄 q3ftp.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the Qt3Support module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qplatformdefs.h"#include "q3ftp.h"#ifndef QT_NO_NETWORKPROTOCOL_FTP#include "q3socket.h"#include "q3socketdevice.h"#include "qurlinfo.h"#include "q3urloperator.h"#include "qstringlist.h"#include "qregexp.h"#include "qtimer.h"#include "qfileinfo.h"#include "q3ptrdict.h"#include "q3cstring.h"#include "qcoreapplication.h"#include "qftp.h"#ifndef QT_NO_TEXTCODEC#include "qtextcodec.h"#endif//#define Q3FTPPI_DEBUG//#define Q3FTPDTP_DEBUGclass Q3FtpPI;class Q3FtpDTP : public QObject{ Q_OBJECTpublic: enum ConnectState { CsHostFound, CsConnected, CsClosed, CsHostNotFound, CsConnectionRefused }; Q3FtpDTP( Q3FtpPI *p, QObject *parent=0, const char *name=0 ); void setData( QByteArray * ); void setDevice( QIODevice * ); void writeData(); void setBytesTotal( int bytes ) { bytesTotal = bytes; bytesDone = 0; emit dataTransferProgress( bytesDone, bytesTotal ); } bool hasError() const; QString errorMessage() const; void clearError(); void connectToHost( const QString & host, Q_UINT16 port ) { socket.connectToHost( host, port ); } Q3Socket::State socketState() const { return socket.state(); } Q_ULONG bytesAvailable() const { return socket.bytesAvailable(); } Q_LONG readBlock( char *data, Q_ULONG maxlen ) { Q_LONG read = socket.readBlock( data, maxlen ); bytesDone += read; return read; } QByteArray readAll() { QByteArray tmp = socket.readAll(); bytesDone += tmp.size(); return tmp; } void abortConnection(); static bool parseDir( const QString &buffer, const QString &userName, QUrlInfo *info );signals: void listInfo( const QUrlInfo& ); void readyRead(); void dataTransferProgress( int, int ); void connectState( int );private slots: void socketConnected(); void socketReadyRead(); void socketError( int ); void socketConnectionClosed(); void socketBytesWritten( int );private: void clearData() { is_ba = false; data.dev = 0; } Q3Socket socket; Q3FtpPI *pi; QString err; int bytesDone; int bytesTotal; bool callWriteData; // If is_ba is true, ba is used; ba is never 0. // Otherwise dev is used; dev can be 0 or not. union { QByteArray *ba; QIODevice *dev; } data; bool is_ba;};class Q3FtpPI : public QObject{ Q_OBJECTpublic: Q3FtpPI( QObject *parent = 0 ); void connectToHost( const QString &host, Q_UINT16 port ); bool sendCommands( const QStringList &cmds ); bool sendCommand( const QString &cmd ) { return sendCommands( QStringList( cmd ) ); } void clearPendingCommands(); void abort(); QString currentCommand() const { return currentCmd; } bool rawCommand; Q3FtpDTP dtp; // the PI has a DTP which is not the design of RFC 959, but it // makes the design simpler this waysignals: void connectState( int ); void finished( const QString& ); void error( int, const QString& ); void rawFtpReply( int, const QString& );private slots: void hostFound(); void connected(); void connectionClosed(); void delayedCloseFinished(); void readyRead(); void error( int ); void dtpConnectState( int );private: // the states are modelled after the generalized state diagram of RFC 959, // page 58 enum State { Begin, Idle, Waiting, Success, Failure }; enum AbortState { None, AbortStarted, WaitForAbortToFinish }; bool processReply(); bool startNextCmd(); Q3Socket commandSocket; QString replyText; signed char replyCode[3]; State state; AbortState abortState; QStringList pendingCommands; QString currentCmd; bool waitForDtpToConnect; bool waitForDtpToClose;};/********************************************************************** * * Q3FtpCommand implemenatation * *********************************************************************/class Q3FtpCommand{public: Q3FtpCommand( Q3Ftp::Command cmd, QStringList raw ); Q3FtpCommand( Q3Ftp::Command cmd, QStringList raw, const QByteArray &ba ); Q3FtpCommand( Q3Ftp::Command cmd, QStringList raw, QIODevice *dev ); ~Q3FtpCommand(); int id; Q3Ftp::Command command; QStringList rawCmds; // If is_ba is true, ba is used; ba is never 0. // Otherwise dev is used; dev can be 0 or not. union { QByteArray *ba; QIODevice *dev; } data; bool is_ba; static int idCounter;};int Q3FtpCommand::idCounter = 0;Q3FtpCommand::Q3FtpCommand( Q3Ftp::Command cmd, QStringList raw ) : command(cmd), rawCmds(raw), is_ba(false){ id = ++idCounter; data.dev = 0;}Q3FtpCommand::Q3FtpCommand( Q3Ftp::Command cmd, QStringList raw, const QByteArray &ba ) : command(cmd), rawCmds(raw), is_ba(true){ id = ++idCounter; data.ba = new QByteArray( ba );}Q3FtpCommand::Q3FtpCommand( Q3Ftp::Command cmd, QStringList raw, QIODevice *dev ) : command(cmd), rawCmds(raw), is_ba(false){ id = ++idCounter; data.dev = dev;}Q3FtpCommand::~Q3FtpCommand(){ if ( is_ba ) delete data.ba;}/********************************************************************** * * Q3FtpDTP implemenatation * *********************************************************************/Q3FtpDTP::Q3FtpDTP( Q3FtpPI *p, QObject *parent, const char *name ) : QObject( parent, name ), socket( 0, "Q3FtpDTP_socket" ), pi( p ), callWriteData( false ){ clearData(); connect( &socket, SIGNAL(connected()), SLOT(socketConnected()) ); connect( &socket, SIGNAL(readyRead()), SLOT(socketReadyRead()) ); connect( &socket, SIGNAL(error(int)), SLOT(socketError(int)) ); connect( &socket, SIGNAL(connectionClosed()), SLOT(socketConnectionClosed()) ); connect( &socket, SIGNAL(bytesWritten(int)), SLOT(socketBytesWritten(int)) );}void Q3FtpDTP::setData( QByteArray *ba ){ is_ba = true; data.ba = ba;}void Q3FtpDTP::setDevice( QIODevice *dev ){ is_ba = false; data.dev = dev;}void Q3FtpDTP::writeData(){ if ( is_ba ) {#if defined(Q3FTPDTP_DEBUG) qDebug( "Q3FtpDTP::writeData: write %d bytes", data.ba->size() );#endif if ( data.ba->size() == 0 ) emit dataTransferProgress( 0, bytesTotal ); else socket.writeBlock( data.ba->data(), data.ba->size() ); socket.close(); clearData(); } else if ( data.dev ) { callWriteData = false; const int blockSize = 16*1024; char buf[blockSize]; while ( !data.dev->atEnd() && socket.bytesToWrite()==0 ) { Q_LONG read = data.dev->readBlock( buf, blockSize );#if defined(Q3FTPDTP_DEBUG) qDebug( "Q3FtpDTP::writeData: writeBlock() of size %d bytes", (int)read );#endif socket.writeBlock( buf, read ); if ( !data.dev ) return; // this can happen when a command is aborted } if ( data.dev->atEnd() ) { if ( bytesDone==0 && socket.bytesToWrite()==0 ) emit dataTransferProgress( 0, bytesTotal ); socket.close(); clearData(); } else { callWriteData = true; } }}inline bool Q3FtpDTP::hasError() const{ return !err.isNull();}inline QString Q3FtpDTP::errorMessage() const{ return err;}inline void Q3FtpDTP::clearError(){ err.clear();}void Q3FtpDTP::abortConnection(){#if defined(Q3FTPDTP_DEBUG) qDebug( "Q3FtpDTP::abortConnection" );#endif callWriteData = false; clearData(); socket.clearPendingData(); socket.close();}bool Q3FtpDTP::parseDir( const QString &buffer, const QString &userName, QUrlInfo *info ){ QStringList lst = QStringList::split( QLatin1String(" "), buffer ); if ( lst.count() < 9 ) return false; QString tmp; // permissions tmp = lst[ 0 ]; if ( tmp[ 0 ] == QChar( QLatin1Char('d') ) ) { info->setDir( true ); info->setFile( false ); info->setSymLink( false ); } else if ( tmp[ 0 ] == QChar( QLatin1Char('-') ) ) { info->setDir( false ); info->setFile( true ); info->setSymLink( false ); } else if ( tmp[ 0 ] == QChar( QLatin1Char('l') ) ) { info->setDir( true ); // #### todo info->setFile( false ); info->setSymLink( true ); } else { return false; } static int user = 0; static int group = 1; static int other = 2; static int readable = 0; static int writable = 1; static int executable = 2; bool perms[ 3 ][ 3 ]; perms[0][0] = (tmp[ 1 ] == QLatin1Char('r')); perms[0][1] = (tmp[ 2 ] == QLatin1Char('w')); perms[0][2] = (tmp[ 3 ] == QLatin1Char('x')); perms[1][0] = (tmp[ 4 ] == QLatin1Char('r')); perms[1][1] = (tmp[ 5 ] == QLatin1Char('w')); perms[1][2] = (tmp[ 6 ] == QLatin1Char('x')); perms[2][0] = (tmp[ 7 ] == QLatin1Char('r')); perms[2][1] = (tmp[ 8 ] == QLatin1Char('w')); perms[2][2] = (tmp[ 9 ] == QLatin1Char('x')); // owner tmp = lst[ 2 ]; info->setOwner( tmp ); // group tmp = lst[ 3 ]; info->setGroup( tmp ); // ### not correct info->setWritable( ( userName == info->owner() && perms[ user ][ writable ] ) || perms[ other ][ writable ] ); info->setReadable( ( userName == info->owner() && perms[ user ][ readable ] ) || perms[ other ][ readable ] ); int p = 0; if ( perms[ user ][ readable ] ) p |= QUrlInfo::ReadOwner; if ( perms[ user ][ writable ] ) p |= QUrlInfo::WriteOwner; if ( perms[ user ][ executable ] ) p |= QUrlInfo::ExeOwner; if ( perms[ group ][ readable ] ) p |= QUrlInfo::ReadGroup; if ( perms[ group ][ writable ] )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -