📄 qftp.cpp
字号:
clearData(); } else { callWriteData = true; } }}inline bool QFtpDTP::hasError() const{ return !err.isNull();}inline QString QFtpDTP::errorMessage() const{ return err;}inline void QFtpDTP::clearError(){ err.clear();}void QFtpDTP::abortConnection(){#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP::abortConnection, bytesAvailable == %lli", socket ? socket->bytesAvailable() : (qint64) 0);#endif callWriteData = false; clearData(); if (socket) socket->abort();}static void _q_fixupDateTime(QDateTime *dateTime){ // Adjust for future tolerance. const int futureTolerance = 86400; if (dateTime->secsTo(QDateTime::currentDateTime()) < -futureTolerance) { QDate d = dateTime->date(); d.setYMD(d.year() - 1, d.month(), d.day()); dateTime->setDate(d); }}static void _q_parseUnixDir(const QStringList &tokens, const QString &userName, QUrlInfo *info){ // Unix style, 7 + 1 entries // -rw-r--r-- 1 ftp ftp 17358091 Aug 10 2004 qt-x11-free-3.3.3.tar.gz // drwxr-xr-x 3 ftp ftp 4096 Apr 14 2000 compiled-examples // lrwxrwxrwx 1 ftp ftp 9 Oct 29 2005 qtscape -> qtmozilla if (tokens.size() != 8) return; char first = tokens.at(1).at(0).toLatin1(); if (first == 'd') { info->setDir(true); info->setFile(false); info->setSymLink(false); } else if (first == '-') { info->setDir(false); info->setFile(true); info->setSymLink(false); } else if (first == 'l') { info->setDir(true); info->setFile(false); info->setSymLink(true); } // Resolve filename QString name = tokens.at(7); if (info->isSymLink()) { int linkPos = name.indexOf(QLatin1String(" ->")); if (linkPos != -1) name.resize(linkPos); } info->setName(name); // Resolve owner & group info->setOwner(tokens.at(3)); info->setGroup(tokens.at(4)); // Resolve size info->setSize(tokens.at(5).toLongLong()); QStringList formats; formats << QLatin1String("MMM dd yyyy") << QLatin1String("MMM dd hh:mm") << QLatin1String("MMM d yyyy") << QLatin1String("MMM d hh:mm") << QLatin1String("MMM d yyyy") << QLatin1String("MMM dd yyyy"); QString dateString = tokens.at(6); dateString[0] = dateString[0].toUpper(); // Resolve the modification date by parsing all possible formats QDateTime dateTime; int n = 0;#ifndef QT_NO_DATESTRING do { dateTime = QDateTime::fromString(dateString, formats.at(n++)); } while (n < formats.size() && (!dateTime.isValid()));#endif if (n == 2 || n == 4) { // Guess the year. dateTime.setDate(QDate(QDate::currentDate().year(), dateTime.date().month(), dateTime.date().day())); _q_fixupDateTime(&dateTime); } if (dateTime.isValid()) info->setLastModified(dateTime); // Resolve permissions int permissions = 0; QString p = tokens.at(2); permissions |= (p[0] == QLatin1Char('r') ? QUrlInfo::ReadOwner : 0); permissions |= (p[1] == QLatin1Char('w') ? QUrlInfo::WriteOwner : 0); permissions |= (p[2] == QLatin1Char('x') ? QUrlInfo::ExeOwner : 0); permissions |= (p[3] == QLatin1Char('r') ? QUrlInfo::ReadGroup : 0); permissions |= (p[4] == QLatin1Char('w') ? QUrlInfo::WriteGroup : 0); permissions |= (p[5] == QLatin1Char('x') ? QUrlInfo::ExeGroup : 0); permissions |= (p[6] == QLatin1Char('r') ? QUrlInfo::ReadOther : 0); permissions |= (p[7] == QLatin1Char('w') ? QUrlInfo::WriteOther : 0); permissions |= (p[8] == QLatin1Char('x') ? QUrlInfo::ExeOther : 0); info->setPermissions(permissions); bool isOwner = info->owner() == userName; info->setReadable((permissions & QUrlInfo::ReadOther) || ((permissions & QUrlInfo::ReadOwner) && isOwner)); info->setWritable((permissions & QUrlInfo::WriteOther) || ((permissions & QUrlInfo::WriteOwner) && isOwner));}static void _q_parseDosDir(const QStringList &tokens, const QString &userName, QUrlInfo *info){ // DOS style, 3 + 1 entries // 01-16-02 11:14AM <DIR> epsgroup // 06-05-03 03:19PM 1973 readme.txt if (tokens.size() != 4) return; Q_UNUSED(userName); QString name = tokens.at(3); info->setName(name); info->setSymLink(name.toLower().endsWith(QLatin1String(".lnk"))); if (tokens.at(2) == QLatin1String("<DIR>")) { info->setFile(false); info->setDir(true); } else { info->setFile(true); info->setDir(false); info->setSize(tokens.at(2).toLongLong()); } // Note: We cannot use QFileInfo; permissions are for the server-side // machine, and QFileInfo's behavior depends on the local platform. int permissions = QUrlInfo::ReadOwner | QUrlInfo::WriteOwner | QUrlInfo::ReadGroup | QUrlInfo::WriteGroup | QUrlInfo::ReadOther | QUrlInfo::WriteOther; QString ext; int extIndex = name.lastIndexOf(QLatin1Char('.')); if (extIndex != -1) ext = name.mid(extIndex + 1); if (ext == QLatin1String("exe") || ext == QLatin1String("bat") || ext == QLatin1String("com")) permissions |= QUrlInfo::ExeOwner | QUrlInfo::ExeGroup | QUrlInfo::ExeOther; info->setPermissions(permissions); info->setReadable(true); info->setWritable(info->isFile()); QDateTime dateTime;#ifndef QT_NO_DATESTRING dateTime = QDateTime::fromString(tokens.at(1), QLatin1String("MM-dd-yy hh:mmAP")); if (dateTime.date().year() < 1971) { dateTime.setDate(QDate(dateTime.date().year() + 100, dateTime.date().month(), dateTime.date().day())); }#endif info->setLastModified(dateTime);}bool QFtpDTP::parseDir(const QByteArray &buffer, const QString &userName, QUrlInfo *info){ if (buffer.isEmpty()) return false; QString bufferStr = QString::fromLatin1(buffer).trimmed(); // Unix style FTP servers QRegExp unixPattern(QLatin1String("^([\\-dl])([a-zA-Z\\-]{9,9})\\s+\\d+\\s+(\\S*)\\s+" "(\\S*)\\s+(\\d+)\\s+(\\S+\\s+\\S+\\s+\\S+)\\s+(\\S.*)")); if (unixPattern.indexIn(bufferStr) == 0) { _q_parseUnixDir(unixPattern.capturedTexts(), userName, info); return true; } // DOS style FTP servers QRegExp dosPattern(QLatin1String("^(\\d\\d-\\d\\d-\\d\\d\\ \\ \\d\\d:\\d\\d[AP]M)\\s+" "(<DIR>|\\d+)\\s+(\\S.*)$")); if (dosPattern.indexIn(bufferStr) == 0) { _q_parseDosDir(dosPattern.capturedTexts(), userName, info); return true; } // Unsupported return false;}void QFtpDTP::socketConnected(){ bytesDone = 0;#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP::connectState(CsConnected)");#endif emit connectState(QFtpDTP::CsConnected);}void QFtpDTP::socketReadyRead(){ if (!socket) return; if (pi->currentCommand().isEmpty()) { socket->close();#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP::connectState(CsClosed)");#endif emit connectState(QFtpDTP::CsClosed); return; } if (pi->abortState == QFtpPI::AbortStarted) { // discard data socket->readAll(); return; } if (pi->currentCommand().startsWith(QLatin1String("LIST"))) { while (socket->canReadLine()) { QUrlInfo i; QByteArray line = socket->readLine();#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP read (list): '%s'", line.constData());#endif if (parseDir(line, QLatin1String(""), &i)) { emit listInfo(i); } else { // some FTP servers don't return a 550 if the file or directory // does not exist, but rather write a text to the data socket // -- try to catch these cases if (line.endsWith("No such file or directory\r\n")) err = QString::fromLatin1(line); } } } else { if (!is_ba && data.dev) { do { QByteArray ba; ba.resize(socket->bytesAvailable()); qint64 bytesRead = socket->read(ba.data(), ba.size()); if (bytesRead < 0) { // a read following a readyRead() signal will // never fail. return; } ba.resize(bytesRead); bytesDone += bytesRead;#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP read: %lli bytes (total %lli bytes)", bytesRead, bytesDone);#endif if (data.dev) // make sure it wasn't deleted in the slot data.dev->write(ba); emit dataTransferProgress(bytesDone, bytesTotal); // Need to loop; dataTransferProgress is often connected to // slots that update the GUI (e.g., progress bar values), and // if events are processed, more data may have arrived. } while (socket->bytesAvailable()); } else {#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP readyRead: %lli bytes available (total %lli bytes read)", bytesAvailable(), bytesDone);#endif emit dataTransferProgress(bytesDone+socket->bytesAvailable(), bytesTotal); emit readyRead(); } }}void QFtpDTP::socketError(QAbstractSocket::SocketError e){ if (e == QTcpSocket::HostNotFoundError) {#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP::connectState(CsHostNotFound)");#endif emit connectState(QFtpDTP::CsHostNotFound); } else if (e == QTcpSocket::ConnectionRefusedError) {#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP::connectState(CsConnectionRefused)");#endif emit connectState(QFtpDTP::CsConnectionRefused); }}void QFtpDTP::socketConnectionClosed(){ if (!is_ba && data.dev) { clearData(); } bytesFromSocket = socket->readAll();#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP::connectState(CsClosed)");#endif emit connectState(QFtpDTP::CsClosed);}void QFtpDTP::socketBytesWritten(qint64 bytes){ bytesDone += bytes;#if defined(QFTPDTP_DEBUG) qDebug("QFtpDTP::bytesWritten(%lli)", bytesDone);#endif emit dataTransferProgress(bytesDone, bytesTotal); if (callWriteData) writeData();}void QFtpDTP::setupSocket(){ socket = listener.nextPendingConnection(); socket->setObjectName(QLatin1String("QFtpDTP Active state socket")); connect(socket, SIGNAL(connected()), SLOT(socketConnected())); connect(socket, SIGNAL(readyRead()), SLOT(socketReadyRead())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError))); connect(socket, SIGNAL(disconnected()), SLOT(socketConnectionClosed())); connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); listener.close();}void QFtpDTP::clearData(){ is_ba = false; data.dev = 0;}/********************************************************************** * * QFtpPI implemenatation * *********************************************************************/QFtpPI::QFtpPI(QObject *parent) : QObject(parent), rawCommand(false), transferConnectionExtended(true), dtp(this), commandSocket(0), state(Begin), abortState(None), currentCmd(QString()), waitForDtpToConnect(false), waitForDtpToClose(false){ commandSocket.setObjectName(QLatin1String("QFtpPI_socket")); connect(&commandSocket, SIGNAL(hostFound()), SLOT(hostFound())); connect(&commandSocket, SIGNAL(connected()), SLOT(connected())); connect(&commandSocket, SIGNAL(disconnected()), SLOT(connectionClosed())); connect(&commandSocket, SIGNAL(readyRead()), SLOT(readyRead())); connect(&commandSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(error(QAbstractSocket::SocketError))); connect(&dtp, SIGNAL(connectState(int)), SLOT(dtpConnectState(int)));}void QFtpPI::connectToHost(const QString &host, quint16 port){ emit connectState(QFtp::HostLookup); commandSocket.connectToHost(host, port);}/* Sends the sequence of commands \a cmds to the FTP server. When the commands are all done the finished() signal is emitted. When an error occurs, the error() signal is emitted. If there are pending commands in the queue this functions returns false and the \a cmds are not added to the queue; otherwise it returns true.*/bool QFtpPI::sendCommands(const QStringList &cmds){ if (!pendingCommands.isEmpty()) return false; if (commandSocket.state() != QTcpSocket::ConnectedState || state!=Idle) { emit error(QFtp::NotConnected, QFtp::tr("Not connected")); return true; // there are no pending commands } pendingCommands = cmds; startNextCmd(); return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -