diff --git a/src/lib/downloads/downloadfilehelper.cpp b/src/lib/downloads/downloadfilehelper.cpp index 34000be48..79e03d60e 100644 --- a/src/lib/downloads/downloadfilehelper.cpp +++ b/src/lib/downloads/downloadfilehelper.cpp @@ -111,86 +111,6 @@ void DownloadFileHelper::handleUnsupportedContent(QNetworkReply* reply, const Do } } -// http://stackoverflow.com/questions/1031645/how-to-detect-utf-8-in-plain-c -static bool isUtf8(const char* string) -{ - if (!string) { - return 0; - } - - const unsigned char* bytes = (const unsigned char*)string; - while (*bytes) { - if ((// ASCII - bytes[0] == 0x09 || - bytes[0] == 0x0A || - bytes[0] == 0x0D || - (0x20 <= bytes[0] && bytes[0] <= 0x7F) - ) - ) { - bytes += 1; - continue; - } - - if ((// non-overlong 2-byte - (0xC2 <= bytes[0] && bytes[0] <= 0xDF) && - (0x80 <= bytes[1] && bytes[1] <= 0xBF) - ) - ) { - bytes += 2; - continue; - } - - if ((// excluding overlongs - bytes[0] == 0xE0 && - (0xA0 <= bytes[1] && bytes[1] <= 0xBF) && - (0x80 <= bytes[2] && bytes[2] <= 0xBF) - ) || - (// straight 3-byte - ((0xE1 <= bytes[0] && bytes[0] <= 0xEC) || - bytes[0] == 0xEE || - bytes[0] == 0xEF) && - (0x80 <= bytes[1] && bytes[1] <= 0xBF) && - (0x80 <= bytes[2] && bytes[2] <= 0xBF) - ) || - (// excluding surrogates - bytes[0] == 0xED && - (0x80 <= bytes[1] && bytes[1] <= 0x9F) && - (0x80 <= bytes[2] && bytes[2] <= 0xBF) - ) - ) { - bytes += 3; - continue; - } - - if ((// planes 1-3 - bytes[0] == 0xF0 && - (0x90 <= bytes[1] && bytes[1] <= 0xBF) && - (0x80 <= bytes[2] && bytes[2] <= 0xBF) && - (0x80 <= bytes[3] && bytes[3] <= 0xBF) - ) || - (// planes 4-15 - (0xF1 <= bytes[0] && bytes[0] <= 0xF3) && - (0x80 <= bytes[1] && bytes[1] <= 0xBF) && - (0x80 <= bytes[2] && bytes[2] <= 0xBF) && - (0x80 <= bytes[3] && bytes[3] <= 0xBF) - ) || - (// plane 16 - bytes[0] == 0xF4 && - (0x80 <= bytes[1] && bytes[1] <= 0x8F) && - (0x80 <= bytes[2] && bytes[2] <= 0xBF) && - (0x80 <= bytes[3] && bytes[3] <= 0xBF) - ) - ) { - bytes += 4; - continue; - } - - return false; - } - - return true; -} - QString DownloadFileHelper::parseContentDisposition(const QByteArray &header) { QString path; @@ -201,7 +121,7 @@ QString DownloadFileHelper::parseContentDisposition(const QByteArray &header) QString value; - if (isUtf8(header.constData())) { + if (QzTools::isUtf8(header.constData())) { value = QString::fromUtf8(header); } else { diff --git a/src/lib/network/schemehandlers/ftpschemehandler.cpp b/src/lib/network/schemehandlers/ftpschemehandler.cpp index a70709391..528fa8212 100644 --- a/src/lib/network/schemehandlers/ftpschemehandler.cpp +++ b/src/lib/network/schemehandlers/ftpschemehandler.cpp @@ -110,7 +110,7 @@ void FtpSchemeReply::processCommand(int id, bool err) m_ftp->list(); } else { - m_ftpCdId = m_ftp->cd(url().path()); + m_ftpCdId = m_ftp->cd(QString::fromLatin1(QByteArray::fromPercentEncoding(url().path().toUtf8()))); } break; @@ -122,6 +122,13 @@ void FtpSchemeReply::processCommand(int id, bool err) if (m_isGoingToDownload) { foreach(const QUrlInfo & item, m_items) { if (item.isFile() && item.name() == m_probablyFileForDownload) { + QByteArray decodedUrl = QByteArray::fromPercentEncoding(url().toString().toUtf8()); + if (QzTools::isUtf8(decodedUrl.constData())) { + m_request.setUrl(QUrl(QString::fromUtf8(decodedUrl))); + } + else { + m_request.setUrl(QUrl(QString::fromLatin1(decodedUrl))); + } emit downloadRequest(m_request); abort(); break; @@ -145,8 +152,13 @@ void FtpSchemeReply::processCommand(int id, bool err) } } -void FtpSchemeReply::processListInfo(const QUrlInfo &urlInfo) +void FtpSchemeReply::processListInfo(QUrlInfo urlInfo) { + QByteArray nameLatin1 = urlInfo.name().toLatin1(); + if (QzTools::isUtf8(nameLatin1.constData())) { + urlInfo.setName(QString::fromUtf8(nameLatin1)); + } + m_items.append(urlInfo); } @@ -247,7 +259,16 @@ QString FtpSchemeReply::loadDirectory() } QString page = sPage; - page.replace(QLatin1String("%TITLE%"), tr("Index for %1").arg(url().toString())); + + QByteArray titleByteArray = QByteArray::fromPercentEncoding(url().toString().toUtf8()); + QString title; + if (QzTools::isUtf8(titleByteArray.constData())) { + title = QString::fromUtf8(titleByteArray); + } + else { + title = QString::fromLatin1(titleByteArray); + } + page.replace(QLatin1String("%TITLE%"), tr("Index for %1").arg(title)); QString upDirDisplay = QLatin1String("none"); QString tBody; @@ -334,12 +355,18 @@ void FtpSchemeReply::ftpReplyErrorHandler(int id) } QStringList sections = url().path().split(QLatin1Char('/'), QString::SkipEmptyParts); if (!sections.isEmpty()) { - m_probablyFileForDownload = sections.takeLast(); + QByteArray lastSection = QByteArray::fromPercentEncoding(sections.takeLast().toUtf8()); + if (QzTools::isUtf8(lastSection.constData())) { + m_probablyFileForDownload = QString::fromUtf8(lastSection); + } + else { + m_probablyFileForDownload = QString::fromLatin1(lastSection); + } } if (!m_probablyFileForDownload.isEmpty()) { m_isGoingToDownload = true; QString parentOfPath = QString("/%1/").arg(sections.join(QLatin1String("/"))); - m_ftpCdId = m_ftp->cd(parentOfPath); + m_ftpCdId = m_ftp->cd(QString::fromLatin1(QByteArray::fromPercentEncoding(parentOfPath.toUtf8()))); } else { abort(); @@ -368,7 +395,7 @@ FtpDownloader::FtpDownloader(QObject* parent) void FtpDownloader::download(const QUrl &url, QIODevice* dev) { - m_url = url; + m_url = QUrl(QString::fromLatin1(QByteArray::fromPercentEncoding(url.toString().toUtf8()))); m_dev = dev; QString server = m_url.host(); if (server.isEmpty()) { diff --git a/src/lib/network/schemehandlers/ftpschemehandler.h b/src/lib/network/schemehandlers/ftpschemehandler.h index 30fb510d4..4b8ded1ff 100644 --- a/src/lib/network/schemehandlers/ftpschemehandler.h +++ b/src/lib/network/schemehandlers/ftpschemehandler.h @@ -65,7 +65,7 @@ protected: private slots: void processCommand(int id, bool err); - void processListInfo(const QUrlInfo &urlInfo); + void processListInfo(QUrlInfo urlInfo); void processData(); QString loadDirectory(); void loadPage(); diff --git a/src/lib/tools/qztools.cpp b/src/lib/tools/qztools.cpp index 434a75909..e0fd2b9bf 100644 --- a/src/lib/tools/qztools.cpp +++ b/src/lib/tools/qztools.cpp @@ -362,6 +362,86 @@ QIcon QzTools::iconFromFileName(const QString &fileName) return icon; } +// http://stackoverflow.com/questions/1031645/how-to-detect-utf-8-in-plain-c +bool QzTools::isUtf8(const char* string) +{ + if (!string) { + return 0; + } + + const unsigned char* bytes = (const unsigned char*)string; + while (*bytes) { + if ((// ASCII + bytes[0] == 0x09 || + bytes[0] == 0x0A || + bytes[0] == 0x0D || + (0x20 <= bytes[0] && bytes[0] <= 0x7F) + ) + ) { + bytes += 1; + continue; + } + + if ((// non-overlong 2-byte + (0xC2 <= bytes[0] && bytes[0] <= 0xDF) && + (0x80 <= bytes[1] && bytes[1] <= 0xBF) + ) + ) { + bytes += 2; + continue; + } + + if ((// excluding overlongs + bytes[0] == 0xE0 && + (0xA0 <= bytes[1] && bytes[1] <= 0xBF) && + (0x80 <= bytes[2] && bytes[2] <= 0xBF) + ) || + (// straight 3-byte + ((0xE1 <= bytes[0] && bytes[0] <= 0xEC) || + bytes[0] == 0xEE || + bytes[0] == 0xEF) && + (0x80 <= bytes[1] && bytes[1] <= 0xBF) && + (0x80 <= bytes[2] && bytes[2] <= 0xBF) + ) || + (// excluding surrogates + bytes[0] == 0xED && + (0x80 <= bytes[1] && bytes[1] <= 0x9F) && + (0x80 <= bytes[2] && bytes[2] <= 0xBF) + ) + ) { + bytes += 3; + continue; + } + + if ((// planes 1-3 + bytes[0] == 0xF0 && + (0x90 <= bytes[1] && bytes[1] <= 0xBF) && + (0x80 <= bytes[2] && bytes[2] <= 0xBF) && + (0x80 <= bytes[3] && bytes[3] <= 0xBF) + ) || + (// planes 4-15 + (0xF1 <= bytes[0] && bytes[0] <= 0xF3) && + (0x80 <= bytes[1] && bytes[1] <= 0xBF) && + (0x80 <= bytes[2] && bytes[2] <= 0xBF) && + (0x80 <= bytes[3] && bytes[3] <= 0xBF) + ) || + (// plane 16 + bytes[0] == 0xF4 && + (0x80 <= bytes[1] && bytes[1] <= 0x8F) && + (0x80 <= bytes[2] && bytes[2] <= 0xBF) && + (0x80 <= bytes[3] && bytes[3] <= 0xBF) + ) + ) { + bytes += 4; + continue; + } + + return false; + } + + return true; +} + // Qt5 migration help functions bool QzTools::isCertificateValid(const QSslCertificate &cert) { diff --git a/src/lib/tools/qztools.h b/src/lib/tools/qztools.h index fd3c07c87..46defb34f 100644 --- a/src/lib/tools/qztools.h +++ b/src/lib/tools/qztools.h @@ -57,6 +57,7 @@ QPixmap QT_QUPZILLA_EXPORT createPixmapForSite(const QIcon &icon, const QString QString QT_QUPZILLA_EXPORT applyDirectionToPage(QString &pageContents); QIcon QT_QUPZILLA_EXPORT iconFromFileName(const QString &fileName); +bool QT_QUPZILLA_EXPORT isUtf8(const char* string); QString QT_QUPZILLA_EXPORT buildSystem();