utilities/downloadmanager/src/downloadcore.cpp
changeset 16 3c88a81ff781
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utilities/downloadmanager/src/downloadcore.cpp	Fri Oct 15 17:30:59 2010 -0400
@@ -0,0 +1,370 @@
+/**
+   This file is part of CWRT package **
+
+   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). **
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU (Lesser) General Public License as 
+   published by the Free Software Foundation, version 2.1 of the License. 
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of 
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
+   (Lesser) General Public License for more details. You should have 
+   received a copy of the GNU (Lesser) General Public License along 
+   with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <qnetworkaccessmanager.h>
+#include <QNetworkReply>
+#include <QNetworkProxy>
+#include "downloadcore.h"
+
+// Http Headers
+#define RANGE_HEADER "Range"
+#define ETAG_HEADER "ETag"
+#define ECONTENT_DISPOSITION_HEADER "Content-Disposition"
+#define IF_MATCH_HEADER "If-Match"
+
+enum DownloadMethod
+{
+    Invalid,
+    FromURL,
+    FromReply
+};
+
+// private implementation class
+class DownloadCorePrivate
+{
+    DM_DECLARE_PUBLIC(DownloadCore);
+public:
+    DownloadCorePrivate();
+    ~DownloadCorePrivate();
+
+    // member variables
+    QString m_url; // url
+    QNetworkReply *m_reply;
+    QNetworkAccessManager *m_networkAccessManager;
+    // content type
+    QString m_contentType;
+    // ETag header value
+    QString m_entityTag;
+    // total size
+    qint64 m_sizeInHeader;
+    // Last error code
+    QNetworkReply::NetworkError m_lastError;
+    QString m_lastErrorString;
+    QNetworkProxy *m_proxy;  //not owned
+    DownloadMethod m_dlMethod; 
+    bool networkAccessManagerOwned;
+    QString m_fileNameFromContentDisposition;
+};
+
+DownloadCorePrivate::DownloadCorePrivate()
+{
+    m_url = "";
+    m_reply = 0;
+    m_networkAccessManager = 0;
+    m_contentType = "";
+    m_entityTag = "";
+    m_sizeInHeader = 0;
+    m_lastError = QNetworkReply::NoError;
+    m_lastErrorString = "";
+    m_proxy = 0;
+    m_dlMethod = Invalid;
+    networkAccessManagerOwned = false;
+    m_fileNameFromContentDisposition ="";
+}
+
+DownloadCorePrivate::~DownloadCorePrivate()
+{
+    if(m_reply)
+    {
+        m_reply->deleteLater();
+        m_reply = 0;
+    }
+    if(networkAccessManagerOwned && m_networkAccessManager)
+    {
+        m_networkAccessManager->disconnect();    
+        delete m_networkAccessManager;
+        m_networkAccessManager = 0;
+    }
+}       
+
+DownloadCore::DownloadCore(const QString& url)
+{
+    DM_INITIALIZE(DownloadCore);
+    priv->m_url = url;
+    priv->m_dlMethod = FromURL;
+
+    if(!priv->m_networkAccessManager)
+    {
+        priv->m_networkAccessManager = new QNetworkAccessManager(this);
+        priv->networkAccessManagerOwned = true;
+    }
+}
+
+DownloadCore::DownloadCore(QNetworkReply *reply)
+{
+    DM_INITIALIZE(DownloadCore);
+    priv->m_reply = reply;
+    priv->m_dlMethod = FromReply;
+
+    priv->m_networkAccessManager = (priv->m_reply)->manager();
+    priv->m_url = (priv->m_reply)->url().toString(QUrl::None);
+
+    QVariant header = (priv->m_reply)->header(QNetworkRequest::ContentLengthHeader);
+    if(header.isValid())
+    {
+        priv->m_sizeInHeader = header.toInt();
+    }
+    
+    header = (priv->m_reply)->header(QNetworkRequest::ContentTypeHeader);
+    if(header.isValid())
+    {
+        priv->m_contentType = header.toString();
+    }
+}
+
+DownloadCore::~DownloadCore()
+{
+    DM_UNINITIALIZE(DownloadCore);
+}
+
+int DownloadCore::doDownload(void)
+{
+    DM_PRIVATE(DownloadCore);
+    switch(priv->m_dlMethod)
+    {
+        case FromURL:
+        {
+            if((priv->m_url).length() <= 0 )
+            {
+                return -1;
+            }
+            if(priv->m_proxy)
+            {
+                priv->m_networkAccessManager->setProxy(*(priv->m_proxy));
+            }
+            
+            /* submit the HTTP request */
+            QNetworkRequest req(priv->m_url);
+            priv->m_reply = (priv->m_networkAccessManager)->get(req);
+
+            /* establish all HTTP listeners */
+            connect(priv->m_reply, SIGNAL(metaDataChanged()),                     this, SLOT(parseHeaders()));    
+            connect(priv->m_reply, SIGNAL(downloadProgress(qint64 , qint64 )),    this, SIGNAL(downloadProgress(qint64 , qint64 )));
+            connect(priv->m_reply, SIGNAL(finished()),                            this, SIGNAL(finished()));
+            connect(priv->m_reply, SIGNAL(error(QNetworkReply::NetworkError)),    this, SIGNAL(error(QNetworkReply::NetworkError)));
+            break;
+        }
+        case FromReply:
+        { 
+            if(!priv->m_reply)
+            {
+                return -1;
+            }
+            /* establish all HTTP listeners */
+            connect(priv->m_reply, SIGNAL(downloadProgress(qint64 , qint64 )),this, SIGNAL(downloadProgress(qint64 , qint64 )));
+            connect(priv->m_reply, SIGNAL(finished()),                        this, SIGNAL(finished()));
+            connect(priv->m_reply, SIGNAL(error(QNetworkReply::NetworkError)),this, SIGNAL(error(QNetworkReply::NetworkError)));            
+            break;
+        }
+        default:
+        {
+            return -1;// error
+        }
+    }
+    return 0; // successful
+}
+
+int DownloadCore::post(const QString& url, const QByteArray& data)
+{
+    DM_PRIVATE(DownloadCore);
+    QNetworkRequest req(url); 
+    // cancel the ongoing transaction if any
+    abort();
+    // post the data
+    priv->m_reply = priv->m_networkAccessManager->post(req, data);
+    if(priv->m_reply)
+    {
+        connect(priv->m_reply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64)));
+        return 0; // successful
+    }
+    else
+    {
+        return -1; // error
+    }
+}
+
+int DownloadCore::resumeDownload(qint64 startOffeset)
+{
+    DM_PRIVATE(DownloadCore);
+
+    QNetworkRequest req(priv->m_url);
+    // set the RANGE header
+    QString buf;
+    buf.sprintf("bytes=%ld-", (long int)startOffeset);
+    req.setRawHeader(RANGE_HEADER, buf.toAscii());
+    // set ETag header
+    if (!priv->m_entityTag.isEmpty())
+        req.setRawHeader(IF_MATCH_HEADER, (priv->m_entityTag).toAscii());
+
+    if(!priv->m_networkAccessManager)
+    {
+        priv->m_networkAccessManager = new QNetworkAccessManager(this);
+        priv->networkAccessManagerOwned = true;
+    }
+    if(priv->m_proxy)
+    {
+        priv->m_networkAccessManager->setProxy(*(priv->m_proxy));
+    }
+
+    /* submit the HTTP request */
+    priv->m_reply = (priv->m_networkAccessManager)->get(req);
+
+    /* establish all HTTP listeners */
+    connect(priv->m_reply, SIGNAL(metaDataChanged()),                     this, SLOT(parseHeaders()));
+    connect(priv->m_reply, SIGNAL(downloadProgress(qint64 , qint64 )),    this, SIGNAL(downloadProgress(qint64 , qint64 )));
+    connect(priv->m_reply, SIGNAL(finished()),                            this, SIGNAL(finished()));
+    connect(priv->m_reply, SIGNAL(error(QNetworkReply::NetworkError)),    this, SIGNAL(error(QNetworkReply::NetworkError)));
+    return 0; // successful
+}
+
+int DownloadCore::abort(void)
+{
+    DM_PRIVATE(DownloadCore);
+    if(priv->m_reply)
+    {
+        (priv->m_reply)->abort();
+        priv->m_reply->deleteLater();
+        priv->m_reply = 0;
+    }
+    return 0; // successful
+}
+
+QString& DownloadCore::url(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_url;
+}
+
+void DownloadCore::changeUrl(QString& url)
+{
+    DM_PRIVATE(DownloadCore);
+    priv->m_url = url;
+    priv->m_dlMethod = FromURL;
+}
+
+QNetworkReply* DownloadCore::reply(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_reply;
+}
+
+QNetworkAccessManager* DownloadCore::networkAccessManager(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_networkAccessManager;
+}
+
+QString& DownloadCore::contentType(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_contentType;
+}
+
+QString& DownloadCore::entityTag(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_entityTag;
+}
+
+void DownloadCore::setContentType(const QString& contentType)
+{
+    DM_PRIVATE(DownloadCore);
+    priv->m_contentType = contentType;
+    return;
+}
+
+void DownloadCore::setEntityTag(const QString& entityTag)
+{
+    DM_PRIVATE(DownloadCore);
+    priv->m_entityTag = entityTag;
+}
+
+qint64 DownloadCore::sizeInHeader(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_sizeInHeader;
+}
+
+QNetworkReply::NetworkError DownloadCore::lastError(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_lastError;
+}
+
+void DownloadCore::setLastError(QNetworkReply::NetworkError code)
+{
+    DM_PRIVATE(DownloadCore);
+    priv->m_lastError = code;
+}
+
+QString DownloadCore::lastErrorString(void)
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_lastErrorString;
+}
+
+void DownloadCore::setLastErrorString(const QString& errStr)
+{
+    DM_PRIVATE(DownloadCore);
+    priv->m_lastErrorString = errStr;
+}
+
+void DownloadCore::setProxy(QNetworkProxy *proxy)
+{
+    DM_PRIVATE(DownloadCore);
+    priv->m_proxy = proxy;
+}
+
+QNetworkProxy* DownloadCore::proxy()
+{
+    DM_PRIVATE(DownloadCore);
+    return priv->m_proxy;
+}
+
+QString DownloadCore::fileNameFromContentDispositionHeader()
+{
+     DM_PRIVATE(DownloadCore);
+     return priv->m_fileNameFromContentDisposition;
+}
+
+void DownloadCore::parseHeaders(void)
+{
+    DM_PRIVATE(DownloadCore);
+    QVariant lenHeader = (priv->m_reply)->header(QNetworkRequest::ContentLengthHeader);
+    if(lenHeader.isValid())
+    {
+        priv->m_sizeInHeader = lenHeader.toInt();
+    }                
+    priv->m_contentType = (priv->m_reply)->header(QNetworkRequest::ContentTypeHeader).toString();
+
+    // ETag
+    priv->m_entityTag = (priv->m_reply)->rawHeader(ETAG_HEADER);
+    
+    if (priv->m_reply->hasRawHeader(ECONTENT_DISPOSITION_HEADER)) {
+        const QString value = priv->m_reply->rawHeader(ECONTENT_DISPOSITION_HEADER);
+        const int pos = value.indexOf("filename=");
+        if (pos != -1) {
+            QString name = value.mid(pos + 9);
+            if (name.startsWith('"') && name.endsWith('"'))
+                name = name.mid(1, name.size() - 2);
+            priv->m_fileNameFromContentDisposition = name;
+        }
+    }
+    // emit the signal
+    emit metaDataChanged();
+    return;
+}
+