diff --git a/src/lib/network/schemehandlers/ftpschemehandler.cpp b/src/lib/network/schemehandlers/ftpschemehandler.cpp index 72bab518b..0f6b6ee82 100644 --- a/src/lib/network/schemehandlers/ftpschemehandler.cpp +++ b/src/lib/network/schemehandlers/ftpschemehandler.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -43,7 +42,7 @@ QNetworkReply* FtpSchemeHandler::createRequest(QNetworkAccessManager::Operation return 0; } - QNetworkReply* reply = new FtpSchemeReply(request); + QNetworkReply* reply = new FtpSchemeReply(request.url()); return reply; } @@ -63,14 +62,14 @@ QAuthenticator* FtpSchemeHandler::ftpAuthenticator(const QUrl &url) return m_ftpAuthenticatorsCache.value(key); } -FtpSchemeReply::FtpSchemeReply(const QNetworkRequest &request, QObject* parent) +FtpSchemeReply::FtpSchemeReply(const QUrl &url, QObject* parent) : QNetworkReply(parent) , m_ftpLoginId(-1) , m_ftpCdId(-1) , m_port(21) , m_anonymousLoginChecked(false) - , m_request(request) , m_isGoingToDownload(false) + , m_isContentTypeDetected(false) { m_ftp = new QFtp(this); connect(m_ftp, SIGNAL(listInfo(QUrlInfo)), this, SLOT(processListInfo(QUrlInfo))); @@ -78,14 +77,15 @@ FtpSchemeReply::FtpSchemeReply(const QNetworkRequest &request, QObject* parent) connect(m_ftp, SIGNAL(commandFinished(int,bool)), this, SLOT(processCommand(int,bool))); connect(m_ftp, SIGNAL(dataTransferProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64))); - m_buffer.open(QIODevice::ReadWrite); - - if (request.url().port() != -1) { - m_port = request.url().port(); + if (url.port() != -1) { + m_port = url.port(); } - setUrl(request.url()); - m_ftp->connectToHost(request.url().host(), m_port); + m_offset = 0; + setUrl(url); + m_ftp->connectToHost(url.host(), m_port); + + open(ReadOnly); } void FtpSchemeReply::processCommand(int id, bool err) @@ -126,19 +126,19 @@ void FtpSchemeReply::processCommand(int id, bool err) if (item.name() == m_probablyFileForDownload) { QByteArray decodedUrl = QByteArray::fromPercentEncoding(url().toString().toUtf8()); if (QzTools::isUtf8(decodedUrl.constData())) { - m_request.setUrl(QUrl(QString::fromUtf8(decodedUrl))); + setUrl(QUrl(QString::fromUtf8(decodedUrl))); } else { - m_request.setUrl(QUrl(QString::fromLatin1(decodedUrl))); + setUrl(QUrl(QString::fromLatin1(decodedUrl))); } - emit downloadRequest(m_request); - abort(); + + m_offset = 0; + m_ftp->get(url().path()); break; } } m_probablyFileForDownload.clear(); m_isGoingToDownload = false; - abort(); } else { loadPage(); @@ -166,22 +166,47 @@ void FtpSchemeReply::processListInfo(QUrlInfo urlInfo) void FtpSchemeReply::processData() { - open(ReadOnly | Unbuffered); - QTextStream stream(&m_buffer); - stream.setCodec("UTF-8"); + QByteArray data = m_ftp->readAll(); + + m_buffer += data; + + if (!m_isContentTypeDetected && !data.isEmpty()) { + data = m_buffer.size() < 1000 ? m_buffer : data; + data.truncate(1000); + data = data.simplified(); + m_contentSampleData += QString::fromUtf8(data).simplified(); + + if (m_contentSampleData.size() > 500) { + bool isContentText = true; + + for (int i = 0; i < m_contentSampleData.size(); ++i) { + if (!m_contentSampleData.at(i).isPrint()) { + isContentText = false; + break; + } + } - stream << m_ftp->readAll(); + //TODO: also request download for large text file - stream.flush(); - m_buffer.reset(); + m_contentSampleData.clear(); + m_isContentTypeDetected = true; - setHeader(QNetworkRequest::ContentLengthHeader, m_buffer.bytesAvailable()); + if (!isContentText) { + // request has unsupported content + m_buffer.clear(); + emit downloadRequest(QNetworkRequest(url())); + abort(); + return; + } + } + } + + setHeader(QNetworkRequest::ContentLengthHeader, QVariant(m_buffer.size())); emit metaDataChanged(); } void FtpSchemeReply::setContent() { - open(ReadOnly | Unbuffered); setHeader(QNetworkRequest::ContentLengthHeader, QVariant(m_buffer.size())); emit readyRead(); emit finished(); @@ -198,7 +223,7 @@ void FtpSchemeReply::abort() qint64 FtpSchemeReply::bytesAvailable() const { - return m_buffer.bytesAvailable() + QNetworkReply::bytesAvailable(); + return m_buffer.size() - m_offset + QNetworkReply::bytesAvailable(); } bool FtpSchemeReply::isSequential() const @@ -208,23 +233,28 @@ bool FtpSchemeReply::isSequential() const qint64 FtpSchemeReply::readData(char* data, qint64 maxSize) { - return m_buffer.read(data, maxSize); + if (m_offset < m_buffer.size()) { + qint64 size = qMin(maxSize, m_buffer.size() - m_offset); + memcpy(data, m_buffer.constData() + m_offset, size); + m_offset += size; + + return size; + } + else { + return -1; + } } void FtpSchemeReply::loadPage() { QWebSecurityOrigin::addLocalScheme("ftp"); open(ReadOnly | Unbuffered); - QTextStream stream(&m_buffer); - stream.setCodec("UTF-8"); - - stream << loadDirectory(); - stream.flush(); - m_buffer.reset(); + m_offset = 0; + m_buffer = loadDirectory().toUtf8(); setHeader(QNetworkRequest::ContentTypeHeader, QByteArray("text/html")); - setHeader(QNetworkRequest::ContentLengthHeader, m_buffer.bytesAvailable()); + setHeader(QNetworkRequest::ContentLengthHeader, m_buffer.size()); setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 200); setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, QByteArray("Ok")); emit metaDataChanged(); diff --git a/src/lib/network/schemehandlers/ftpschemehandler.h b/src/lib/network/schemehandlers/ftpschemehandler.h index ce62e7949..61df777a6 100644 --- a/src/lib/network/schemehandlers/ftpschemehandler.h +++ b/src/lib/network/schemehandlers/ftpschemehandler.h @@ -55,7 +55,7 @@ class QUPZILLA_EXPORT FtpSchemeReply : public QNetworkReply Q_OBJECT public: - FtpSchemeReply(const QNetworkRequest &request, QObject* parent = 0); + FtpSchemeReply(const QUrl &url, QObject* parent = 0); void abort(); qint64 bytesAvailable() const; bool isSequential() const; @@ -80,12 +80,15 @@ private: int m_ftpLoginId; int m_ftpCdId; int m_port; - QBuffer m_buffer; bool m_anonymousLoginChecked; - QNetworkRequest m_request; QString m_probablyFileForDownload; bool m_isGoingToDownload; + QByteArray m_buffer; + qint64 m_offset; + bool m_isContentTypeDetected; + QString m_contentSampleData; + signals: void ftpAuthenticationRequierd(const QUrl &, QAuthenticator*); void downloadRequest(const QNetworkRequest &); diff --git a/src/lib/webkit/webpage.cpp b/src/lib/webkit/webpage.cpp index 11bb26cbe..aac579d71 100644 --- a/src/lib/webkit/webpage.cpp +++ b/src/lib/webkit/webpage.cpp @@ -350,6 +350,12 @@ void WebPage::handleUnsupportedContent(QNetworkReply* reply) return; } + if (url.scheme() == QLatin1String("ftp")) { + DownloadManager* dManager = mApp->downloadManager(); + dManager->handleUnsupportedContent(reply, this); + return; + } + qDebug() << "WebPage::UnsupportedContent" << url << "ProtocolUnknowError"; desktopServicesOpen(url);