src/network/access/qnetworkaccesshttpbackend.cpp
changeset 30 5dc02b23752f
parent 23 89e065397ea6
child 33 3e2da88830cd
--- a/src/network/access/qnetworkaccesshttpbackend.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -213,6 +213,7 @@
     case QNetworkAccessManager::HeadOperation:
     case QNetworkAccessManager::PutOperation:
     case QNetworkAccessManager::DeleteOperation:
+    case QNetworkAccessManager::CustomOperation:
         break;
 
     default:
@@ -296,6 +297,7 @@
 #ifndef QT_NO_OPENSSL
     , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
 #endif
+    , resumeOffset(0)
 {
 }
 
@@ -344,6 +346,8 @@
 #endif
     connect(http, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
             SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)));
+    connect(http, SIGNAL(cacheCredentials(QHttpNetworkRequest,QAuthenticator*)),
+            SLOT(httpCacheCredentials(QHttpNetworkRequest,QAuthenticator*)));
     connect(http, SIGNAL(error(QNetworkReply::NetworkError,QString)),
             SLOT(httpError(QNetworkReply::NetworkError,QString)));
 #ifndef QT_NO_OPENSSL
@@ -480,10 +484,24 @@
         loadedFromCache = false;
 }
 
+static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio)
+{
+    switch (prio) {
+    case QNetworkRequest::LowPriority:
+        return QHttpNetworkRequest::LowPriority;
+    case QNetworkRequest::HighPriority:
+        return QHttpNetworkRequest::HighPriority;
+    case QNetworkRequest::NormalPriority:
+    default:
+        return QHttpNetworkRequest::NormalPriority;
+    }
+}
+
 void QNetworkAccessHttpBackend::postRequest()
 {
     bool loadedFromCache = false;
     QHttpNetworkRequest httpRequest;
+    httpRequest.setPriority(convert(request().priority()));
     switch (operation()) {
     case QNetworkAccessManager::GetOperation:
         httpRequest.setOperation(QHttpNetworkRequest::Get);
@@ -512,6 +530,14 @@
         httpRequest.setOperation(QHttpNetworkRequest::Delete);
         break;
 
+    case QNetworkAccessManager::CustomOperation:
+        invalidateCache(); // for safety reasons, we don't know what the operation does
+        httpRequest.setOperation(QHttpNetworkRequest::Custom);
+        httpRequest.setUploadByteDevice(createUploadByteDevice());
+        httpRequest.setCustomVerb(request().attribute(
+                QNetworkRequest::CustomVerbAttribute).toByteArray());
+        break;
+
     default:
         break;                  // can't happen
     }
@@ -519,6 +545,28 @@
     httpRequest.setUrl(url());
 
     QList<QByteArray> headers = request().rawHeaderList();
+    if (resumeOffset != 0) {
+        if (headers.contains("Range")) {
+            // Need to adjust resume offset for user specified range
+
+            headers.removeOne("Range");
+
+            // We've already verified that requestRange starts with "bytes=", see canResume.
+            QByteArray requestRange = request().rawHeader("Range").mid(6);
+
+            int index = requestRange.indexOf('-');
+
+            quint64 requestStartOffset = requestRange.left(index).toULongLong();
+            quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
+
+            requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
+                           '-' + QByteArray::number(requestEndOffset);
+
+            httpRequest.setHeaderField("Range", requestRange);
+        } else {
+            httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
+        }
+    }
     foreach (const QByteArray &header, headers)
         httpRequest.setHeaderField(header, request().rawHeader(header));
 
@@ -532,6 +580,11 @@
     if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
         httpRequest.setPipeliningAllowed(true);
 
+    if (static_cast<QNetworkRequest::LoadControl>
+        (request().attribute(QNetworkRequest::AuthenticationReuseAttribute,
+                             QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual)
+        httpRequest.setWithCredentials(false);
+
     httpReply = http->sendRequest(httpRequest);
     httpReply->setParent(this);
 #ifndef QT_NO_OPENSSL
@@ -815,6 +868,12 @@
     authenticationRequired(auth);
 }
 
+void QNetworkAccessHttpBackend::httpCacheCredentials(const QHttpNetworkRequest &,
+                                                 QAuthenticator *auth)
+{
+    cacheCredentials(auth);
+}
+
 void QNetworkAccessHttpBackend::httpError(QNetworkReply::NetworkError errorCode,
                                           const QString &errorString)
 {
@@ -1093,6 +1152,31 @@
     return metaData;
 }
 
+bool QNetworkAccessHttpBackend::canResume() const
+{
+    // Only GET operation supports resuming.
+    if (operation() != QNetworkAccessManager::GetOperation)
+        return false;
+
+    // Can only resume if server/resource supports Range header.
+    if (httpReply->headerField("Accept-Ranges", "none") == "none")
+        return false;
+
+    // We only support resuming for byte ranges.
+    if (request().hasRawHeader("Range")) {
+        QByteArray range = request().rawHeader("Range");
+        if (!range.startsWith("bytes="))
+            return false;
+    }
+
+    return true;
+}
+
+void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset)
+{
+    resumeOffset = offset;
+}
+
 QT_END_NAMESPACE
 
 #endif // QT_NO_HTTP