]> git.sur5r.net Git - minitube/blob - src/networkaccess.cpp
57f5637dccff1ddfccd10f571e27251a0a9d45ec
[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_7_2) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1";
16
17 NetworkReply::NetworkReply(QNetworkReply *networkReply) : QObject(networkReply) {
18     this->networkReply = networkReply;
19
20     // monitor downloadProgress to impl timeout
21     connect(networkReply, SIGNAL(downloadProgress(qint64,qint64)),
22             SLOT(downloadProgress(qint64,qint64)), Qt::UniqueConnection);
23
24     readTimeoutTimer = new QTimer(this);
25     readTimeoutTimer->setInterval(5000);
26     readTimeoutTimer->setSingleShot(true);
27     connect(readTimeoutTimer, SIGNAL(timeout()), SLOT(readTimeout()));
28     readTimeoutTimer->start();
29 }
30
31 void NetworkReply::finished() {
32     // qDebug() << "Finished" << networkReply->url();
33
34     QUrl redirection = networkReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
35     if (redirection.isValid()) {
36
37         // qDebug() << "Redirect!"; // << redirection;
38
39         QNetworkReply *redirectReply = The::http()->simpleGet(redirection, networkReply->operation());
40
41         setParent(redirectReply);
42         networkReply->deleteLater();
43         networkReply = redirectReply;
44
45         // when the request is finished we'll invoke the target method
46         connect(networkReply, SIGNAL(finished()), this, SLOT(finished()), Qt::UniqueConnection);
47
48         // monitor downloadProgress to impl timeout
49         connect(networkReply, SIGNAL(downloadProgress(qint64,qint64)),
50                 SLOT(downloadProgress(qint64,qint64)), Qt::UniqueConnection);
51         readTimeoutTimer->start();
52
53         // error signal
54         connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
55                 SLOT(requestError(QNetworkReply::NetworkError)), Qt::UniqueConnection);
56
57         connect(readTimeoutTimer, SIGNAL(timeout()), SLOT(readTimeout()), Qt::UniqueConnection);
58         readTimeoutTimer->start();
59
60         return;
61     }
62
63     emit data(networkReply->readAll());
64     emit finished(networkReply);
65
66 #ifndef QT_NO_DEBUG_OUTPUT
67     if (!networkReply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool()) {
68         qDebug() << networkReply->url().toEncoded();
69     }
70 #endif
71
72     // bye bye my reply
73     // this will also delete this NetworkReply as the QNetworkReply is its parent
74     networkReply->deleteLater();
75 }
76
77 void NetworkReply::requestError(QNetworkReply::NetworkError /* code */) {
78     emit error(networkReply);
79 }
80
81 void NetworkReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
82     // qDebug() << "Downloading" << bytesReceived << bytesTotal << networkReply->url();
83     if (bytesReceived > 0) {
84         readTimeoutTimer->stop();
85         disconnect(networkReply, SIGNAL(downloadProgress(qint64,qint64)),
86                    this, SLOT(downloadProgress(qint64,qint64)));
87     }
88 }
89
90 void NetworkReply::readTimeout() {
91     // qDebug() << "HTTP read timeout" << networkReply->url();
92     networkReply->disconnect();
93     networkReply->abort();
94
95     QNetworkReply *retryReply = The::http()->simpleGet(networkReply->url(), networkReply->operation());
96
97     setParent(retryReply);
98     networkReply->deleteLater();
99     networkReply = retryReply;
100
101     // when the request is finished we'll invoke the target method
102     connect(networkReply, SIGNAL(finished()), this, SLOT(finished()), Qt::UniqueConnection);
103
104     // monitor downloadProgress to impl timeout
105     connect(networkReply, SIGNAL(downloadProgress(qint64,qint64)),
106             SLOT(downloadProgress(qint64,qint64)), Qt::UniqueConnection);
107     readTimeoutTimer->start();
108
109     // error signal
110     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
111             SLOT(requestError(QNetworkReply::NetworkError)));
112
113     // emit error(networkReply);
114 }
115
116 /* --- NetworkAccess --- */
117
118 NetworkAccess::NetworkAccess( QObject* parent) : QObject( parent ) {}
119
120 QNetworkReply* NetworkAccess::manualGet(QNetworkRequest request, int operation) {
121
122     QNetworkAccessManager *manager = The::networkAccessManager();
123     // manager->setCookieJar(new QNetworkCookieJar());
124
125     QNetworkReply *networkReply;
126     switch (operation) {
127
128     case QNetworkAccessManager::GetOperation:
129         // qDebug() << "GET" << request.url().toEncoded();
130         networkReply = manager->get(request);
131         break;
132
133     case QNetworkAccessManager::HeadOperation:
134         // qDebug() << "HEAD" << request.url().toEncoded();
135         networkReply = manager->head(request);
136         break;
137
138     default:
139         qDebug() << "Unknown operation:" << operation;
140         return 0;
141
142     }
143
144     // error handling
145     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
146             this, SLOT(error(QNetworkReply::NetworkError)));
147
148     return networkReply;
149 }
150
151 QNetworkRequest NetworkAccess::buildRequest(QUrl url) {
152     QNetworkRequest request(url);
153     request.setRawHeader("User-Agent", USER_AGENT.toUtf8());
154     request.setRawHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
155     request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
156     request.setRawHeader("Accept-Language", "en-us,en;q=0.5");
157     request.setRawHeader("Connection", "Keep-Alive");
158     return request;
159 }
160
161 QNetworkReply* NetworkAccess::simpleGet(QUrl url, int operation) {
162     return manualGet(buildRequest(url), operation);
163 }
164
165 NetworkReply* NetworkAccess::get(const QUrl url) {
166
167     QNetworkReply *networkReply = simpleGet(url);
168     NetworkReply *reply = new NetworkReply(networkReply);
169
170     // error signal
171     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
172             reply, SLOT(requestError(QNetworkReply::NetworkError)));
173
174     // when the request is finished we'll invoke the target method
175     connect(networkReply, SIGNAL(finished()), reply, SLOT(finished()), Qt::UniqueConnection);
176
177     return reply;
178
179 }
180
181 NetworkReply* NetworkAccess::head(const QUrl url) {
182
183     QNetworkReply *networkReply = simpleGet(url, QNetworkAccessManager::HeadOperation);
184     NetworkReply *reply = new NetworkReply(networkReply);
185
186     // error signal
187     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
188             reply, SLOT(requestError(QNetworkReply::NetworkError)));
189
190     // when the request is finished we'll invoke the target method
191     connect(networkReply, SIGNAL(finished()), reply, SLOT(finished()), Qt::UniqueConnection);
192
193     return reply;
194
195 }
196
197 void NetworkAccess::error(QNetworkReply::NetworkError code) {
198     // get the QNetworkReply that sent the signal
199     QNetworkReply *networkReply = static_cast<QNetworkReply *>(sender());
200     if (!networkReply) {
201         qDebug() << "Cannot get sender";
202         return;
203     }
204
205     networkReply->deleteLater();
206
207     // Ignore HEADs
208     if (networkReply->operation() == QNetworkAccessManager::HeadOperation)
209         return;
210
211     // report the error in the status bar
212     QMainWindow* mainWindow = dynamic_cast<QMainWindow*>(qApp->topLevelWidgets().first());
213     if (mainWindow) mainWindow->statusBar()->showMessage(
214             tr("Network error: %1").arg(networkReply->errorString()));
215
216     qDebug() << "Network error:" << networkReply->errorString() << code;
217 }