1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 09:32:12 +01:00

Merge pull request #755 from srazi/master

[FTP] Used a new method for list/download to support some FTP servers.
This commit is contained in:
David Rosca 2013-02-12 02:06:30 -08:00
commit be36811bc7
2 changed files with 77 additions and 34 deletions

View File

@ -66,9 +66,12 @@ QAuthenticator* FtpSchemeHandler::ftpAuthenticator(const QUrl &url)
FtpSchemeReply::FtpSchemeReply(const QNetworkRequest &request, QObject* parent) FtpSchemeReply::FtpSchemeReply(const QNetworkRequest &request, QObject* parent)
: QNetworkReply(parent) : QNetworkReply(parent)
, m_ftpLoginId(-1) , m_ftpLoginId(-1)
, m_ftpCdId(-1)
, m_port(21) , m_port(21)
, m_anonymousLoginChecked(false) , m_anonymousLoginChecked(false)
, m_request(request) , m_request(request)
, m_probablyFileForDownload("")
, m_isGoingToDownload(false)
{ {
m_ftp = new QFtp(this); m_ftp = new QFtp(this);
connect(m_ftp, SIGNAL(listInfo(QUrlInfo)), this, SLOT(processListInfo(QUrlInfo))); connect(m_ftp, SIGNAL(listInfo(QUrlInfo)), this, SLOT(processListInfo(QUrlInfo)));
@ -89,22 +92,7 @@ FtpSchemeReply::FtpSchemeReply(const QNetworkRequest &request, QObject* parent)
void FtpSchemeReply::processCommand(int id, bool err) void FtpSchemeReply::processCommand(int id, bool err)
{ {
if (err) { if (err) {
if (m_ftpLoginId == id) { ftpReplyErrorHandler(id);
if (!m_anonymousLoginChecked) {
m_anonymousLoginChecked = true;
FTP_AUTHENTICATOR(url())->setUser(QString());
FTP_AUTHENTICATOR(url())->setPassword(QString());
m_ftpLoginId = m_ftp->login();
return;
}
emit ftpAuthenticationRequierd(url(), FTP_AUTHENTICATOR(url()));
m_ftpLoginId = m_ftp->login(FTP_AUTHENTICATOR(url())->user(), FTP_AUTHENTICATOR(url())->password());
return;
}
setError(ContentNotFoundError, tr("Unknown command"));
emit error(ContentNotFoundError);
emit finished();
return; return;
} }
@ -119,11 +107,34 @@ void FtpSchemeReply::processCommand(int id, bool err)
break; break;
case QFtp::Login: case QFtp::Login:
m_ftp->list(url().path()); if (url().path() == "" || url().path() == "/") {
m_ftp->list();
}
else {
m_ftpCdId = m_ftp->cd(url().path());
}
break;
case QFtp::Cd:
m_ftp->list();
break; break;
case QFtp::List: case QFtp::List:
if (m_isGoingToDownload) {
foreach(const QUrlInfo & item, m_items) {
if (item.isFile() && item.name() == m_probablyFileForDownload) {
emit downloadRequest(m_request);
abort();
break;
}
}
m_probablyFileForDownload = "";
m_isGoingToDownload = false;
abort();
}
else {
loadPage(); loadPage();
}
break; break;
case QFtp::Get: case QFtp::Get:
@ -188,21 +199,6 @@ qint64 FtpSchemeReply::readData(char* data, qint64 maxSize)
void FtpSchemeReply::loadPage() void FtpSchemeReply::loadPage()
{ {
if (m_items.size() == 1 && m_items.at(0).isFile()) {
QUrlInfo item = m_items.at(0);
if (url().path() == url().resolved(QUrl(item.name())).path()) {
setHeader(QNetworkRequest::ContentLengthHeader, m_buffer.bytesAvailable());
// the following code can be used to open known contents
// and download unsupported contents, but there is some problem
// for example: it loads PDFs as text file!
// m_ftp->get(url().path());
emit downloadRequest(m_request);
abort();
return;
}
}
QWebSecurityOrigin::addLocalScheme("ftp"); QWebSecurityOrigin::addLocalScheme("ftp");
open(ReadOnly | Unbuffered); open(ReadOnly | Unbuffered);
QTextStream stream(&m_buffer); QTextStream stream(&m_buffer);
@ -278,8 +274,9 @@ QString FtpSchemeReply::loadDirectory()
} }
QString line = QLatin1String("<tr"); QString line = QLatin1String("<tr");
QUrl itemUrl = u.resolved(QUrl(item.name())); QUrl itemUrl = u.resolved(QUrl(QUrl::toPercentEncoding(item.name())));
QString itemPath = itemUrl.path(); QString itemPath = itemUrl.path();
if (itemPath.endsWith("/")) { if (itemPath.endsWith("/")) {
itemPath.remove(itemPath.size() - 1, 1); itemPath.remove(itemPath.size() - 1, 1);
} }
@ -315,6 +312,47 @@ QString FtpSchemeReply::loadDirectory()
return page; return page;
} }
void FtpSchemeReply::ftpReplyErrorHandler(int id)
{
if (m_ftpLoginId == id) {
if (!m_anonymousLoginChecked) {
m_anonymousLoginChecked = true;
FTP_AUTHENTICATOR(url())->setUser(QString());
FTP_AUTHENTICATOR(url())->setPassword(QString());
m_ftpLoginId = m_ftp->login();
return;
}
emit ftpAuthenticationRequierd(url(), FTP_AUTHENTICATOR(url()));
m_ftpLoginId = m_ftp->login(FTP_AUTHENTICATOR(url())->user(), FTP_AUTHENTICATOR(url())->password());
return;
}
else if (m_ftpCdId == id) {
if (m_isGoingToDownload) {
m_isGoingToDownload = false;
abort();
return;
}
QStringList sections = url().path().split("/", QString::SkipEmptyParts);
if (!sections.isEmpty()) {
m_probablyFileForDownload = sections.takeLast();
}
if (!m_probablyFileForDownload.isEmpty()) {
m_isGoingToDownload = true;
QString parentOfPath = "/"+sections.join("/")+"/";
m_ftpCdId = m_ftp->cd(parentOfPath);
}
else {
abort();
}
return;
}
else {
setError(ContentNotFoundError, tr("Unknown command"));
emit error(ContentNotFoundError);
emit finished();
}
}
FtpDownloader::FtpDownloader(QObject* parent) FtpDownloader::FtpDownloader(QObject* parent)
: QFtp(parent) : QFtp(parent)

View File

@ -72,13 +72,18 @@ private slots:
private: private:
void setContent(); void setContent();
void ftpReplyErrorHandler(int id);
QFtp* m_ftp; QFtp* m_ftp;
QList<QUrlInfo> m_items; QList<QUrlInfo> m_items;
int m_ftpLoginId; int m_ftpLoginId;
int m_ftpCdId;
int m_port; int m_port;
QBuffer m_buffer; QBuffer m_buffer;
bool m_anonymousLoginChecked; bool m_anonymousLoginChecked;
QNetworkRequest m_request; QNetworkRequest m_request;
QString m_probablyFileForDownload;
bool m_isGoingToDownload;
signals: signals:
void ftpAuthenticationRequierd(const QUrl &, QAuthenticator*); void ftpAuthenticationRequierd(const QUrl &, QAuthenticator*);