| 79 | } |
| 80 | |
| 81 | bool Upload::handleRedirect() |
| 82 | { |
| 83 | QUrl redirect = m_reply->header(QNetworkRequest::LocationHeader).toUrl(); |
| 84 | if (!redirect.isValid()) { |
| 85 | if (!m_reply->hasRawHeader("Location")) { |
| 86 | // no redirect -> it's fine to continue |
| 87 | return false; |
| 88 | } |
| 89 | // there is a Location header, but it's not correct. we need to apply some workarounds... |
| 90 | QByteArray redirectBA = m_reply->rawHeader("Location"); |
| 91 | if (redirectBA.size() == 0) { |
| 92 | // empty, yet present redirect header? WTF? |
| 93 | return false; |
| 94 | } |
| 95 | QString redirectStr = QString::fromUtf8(redirectBA); |
| 96 | |
| 97 | if (redirectStr.startsWith("//")) { |
| 98 | /* |
| 99 | * IF the URL begins with //, we need to insert the URL scheme. |
| 100 | * See: https://bugreports.qt.io/browse/QTBUG-41061 |
| 101 | * See: http://tools.ietf.org/html/rfc3986#section-4.2 |
| 102 | */ |
| 103 | redirectStr = m_reply->url().scheme() + ":" + redirectStr; |
| 104 | } else if (redirectStr.startsWith("/")) { |
| 105 | /* |
| 106 | * IF the URL begins with /, we need to process it as a relative URL |
| 107 | */ |
| 108 | auto url = m_reply->url(); |
| 109 | url.setPath(redirectStr, QUrl::TolerantMode); |
| 110 | redirectStr = url.toString(); |
| 111 | } |
| 112 | |
| 113 | /* |
| 114 | * Next, make sure the URL is parsed in tolerant mode. Qt doesn't parse the location header in tolerant mode, which causes issues. |
| 115 | * FIXME: report Qt bug for this |
| 116 | */ |
| 117 | redirect = QUrl(redirectStr, QUrl::TolerantMode); |
| 118 | if (!redirect.isValid()) { |
| 119 | qWarning() << "Failed to parse redirect URL:" << redirectStr; |
| 120 | downloadError(QNetworkReply::ProtocolFailure); |
| 121 | return false; |
| 122 | } |
| 123 | qDebug() << "Fixed location header:" << redirect; |
| 124 | } else { |
| 125 | qDebug() << "Location header:" << redirect; |
| 126 | } |
| 127 | |
| 128 | m_url = QUrl(redirect.toString()); |
| 129 | qDebug() << "Following redirect to " << m_url.toString(); |
| 130 | startAction(m_network); |
| 131 | return true; |
| 132 | } |
| 133 | |
| 134 | void Upload::downloadFinished() { |
| 135 | // handle HTTP redirection first |