]> git.sur5r.net Git - minitube/blob - src/networkaccess.cpp
Imported Upstream version 2.0
[minitube] / src / networkaccess.cpp
1 #include "networkaccess.h"
2 #include "constants.h"
3 #include <QtGui>
4
5 namespace The {
6 NetworkAccess* http();
7 }
8
9 /*
10 const QString USER_AGENT = QString(Constants::NAME)
11                            + " " + Constants::VERSION
12                            + " (" + Constants::WEBSITE + ")";
13 */
14
15 const QString USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11";
16
17 NetworkReply::NetworkReply(QNetworkReply *networkReply) :
18     QObject(networkReply),
19     networkReply(networkReply),
20     retryCount(0) {
21
22     setupReply();
23
24     readTimeoutTimer = new QTimer(this);
25     readTimeoutTimer->setInterval(10000);
26     readTimeoutTimer->setSingleShot(true);
27     connect(readTimeoutTimer, SIGNAL(timeout()), SLOT(readTimeout()), Qt::UniqueConnection);
28     readTimeoutTimer->start();
29 }
30
31 void NetworkReply::setupReply() {
32     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
33             SLOT(requestError(QNetworkReply::NetworkError)), Qt::UniqueConnection);
34     connect(networkReply, SIGNAL(finished()),
35             SLOT(finished()), Qt::UniqueConnection);
36     connect(networkReply, SIGNAL(downloadProgress(qint64,qint64)),
37             SLOT(downloadProgress(qint64,qint64)), Qt::UniqueConnection);
38 }
39
40 void NetworkReply::finished() {
41     QUrl redirection = networkReply->attribute(
42                 QNetworkRequest::RedirectionTargetAttribute).toUrl();
43     if (redirection.isValid()) {
44         if (networkReply->operation() == QNetworkAccessManager::GetOperation
45                 || networkReply->operation() == QNetworkAccessManager::HeadOperation) {
46             QNetworkReply *redirectReply =
47                     The::http()->request(redirection, networkReply->operation());
48             setParent(redirectReply);
49             networkReply->deleteLater();
50             networkReply = redirectReply;
51             setupReply();
52             readTimeoutTimer->start();
53             return;
54         } else qWarning() << "Redirection not supported" << networkReply->url().toEncoded();
55     }
56
57     if (receivers(SIGNAL(data(QByteArray))) > 0)
58         emit data(networkReply->readAll());
59     else if (receivers(SIGNAL(finished(QNetworkReply*))) > 0)
60         emit finished(networkReply);
61
62 #ifndef QT_NO_DEBUG_OUTPUT
63     if (!networkReply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool())
64         qDebug() << networkReply->url().toEncoded();
65 #endif
66
67     // bye bye my reply
68     // this will also delete this NetworkReply as the QNetworkReply is its parent
69     networkReply->deleteLater();
70 }
71
72 void NetworkReply::requestError(QNetworkReply::NetworkError code) {
73     qDebug() << networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()
74              << networkReply->errorString() << code;
75     emit error(networkReply);
76 }
77
78 void NetworkReply::downloadProgress(qint64 bytesReceived, qint64 /* bytesTotal */) {
79     // qDebug() << "Downloading" << bytesReceived << bytesTotal << networkReply->url();
80     if (bytesReceived > 0 && readTimeoutTimer->isActive()) {
81         readTimeoutTimer->stop();
82         disconnect(networkReply, SIGNAL(downloadProgress(qint64,qint64)),
83                    this, SLOT(downloadProgress(qint64,qint64)));
84     }
85 }
86
87 void NetworkReply::readTimeout() {
88     networkReply->disconnect();
89     networkReply->abort();
90     networkReply->deleteLater();
91
92     if (networkReply->operation() != QNetworkAccessManager::GetOperation
93             || networkReply->operation() != QNetworkAccessManager::HeadOperation) {
94         emit error(networkReply);
95         return;
96     }
97
98     if (retryCount > 3) {
99         emit error(networkReply);
100         return;
101     }
102     QNetworkReply *retryReply = The::http()->request(networkReply->url(), networkReply->operation());
103     setParent(retryReply);
104     networkReply = retryReply;
105     setupReply();
106     retryCount++;
107     readTimeoutTimer->start();
108 }
109
110 /* --- NetworkAccess --- */
111
112 NetworkAccess::NetworkAccess( QObject* parent) : QObject( parent ) {}
113
114 QNetworkRequest NetworkAccess::buildRequest(QUrl url) {
115     QNetworkRequest request(url);
116     request.setRawHeader("User-Agent", USER_AGENT.toUtf8());
117     request.setRawHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
118     request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
119     request.setRawHeader("Accept-Language", "en-us,en;q=0.5");
120     request.setRawHeader("Connection", "Keep-Alive");
121     return request;
122 }
123
124 QNetworkReply* NetworkAccess::request(QUrl url, int operation, const QByteArray& body) {
125     QNetworkAccessManager *manager = The::networkAccessManager();
126
127     QNetworkRequest request = buildRequest(url);
128
129     QNetworkReply *networkReply;
130     switch (operation) {
131
132     case QNetworkAccessManager::GetOperation:
133         networkReply = manager->get(request);
134         break;
135
136     case QNetworkAccessManager::HeadOperation:
137         networkReply = manager->head(request);
138         break;
139
140     case QNetworkAccessManager::PostOperation:
141         if (!body.isEmpty())
142             request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
143         networkReply = manager->post(request, body);
144         break;
145
146     default:
147         qWarning() << "Unknown operation:" << operation;
148         return 0;
149     }
150
151     return networkReply;
152 }
153
154 NetworkReply* NetworkAccess::get(const QUrl url) {
155     QNetworkReply *networkReply = request(url);
156     return new NetworkReply(networkReply);
157 }
158
159 NetworkReply* NetworkAccess::head(const QUrl url) {
160     QNetworkReply *networkReply = request(url, QNetworkAccessManager::HeadOperation);
161     return new NetworkReply(networkReply);
162 }
163
164 NetworkReply* NetworkAccess::post(const QUrl url, const QMap<QString, QString>& params) {
165     QByteArray body;
166     QMapIterator<QString, QString> i(params);
167     while (i.hasNext()) {
168         i.next();
169         body += QUrl::toPercentEncoding(i.key())
170                 + '='
171                 + QUrl::toPercentEncoding(i.value())
172                 + '&';
173     }
174     QNetworkReply *networkReply = request(url, QNetworkAccessManager::PostOperation, body);
175     return new NetworkReply(networkReply);
176 }