]> git.sur5r.net Git - minitube/blob - src/networkaccess.cpp
47d09df54ea9fafe7aa127021d7d26f7b0793b6c
[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 NetworkReply::NetworkReply(QNetworkReply *networkReply) : QObject(networkReply) {
10     this->networkReply = networkReply;
11 }
12
13 void NetworkReply::finished() {
14
15     QUrl redirection = networkReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
16     if (redirection.isValid()) {
17
18         // qDebug() << "Redirect!"; // << redirection;
19
20         QNetworkReply *redirectReply = The::http()->simpleGet(redirection, networkReply->operation());
21
22         setParent(redirectReply);
23         networkReply->deleteLater();
24         networkReply = redirectReply;
25
26         // when the request is finished we'll invoke the target method
27         connect(networkReply, SIGNAL(finished()), this, SLOT(finished()), Qt::AutoConnection);
28
29         return;
30     }
31
32
33     emit finished(networkReply);
34
35     // get the HTTP response body
36     QByteArray bytes = networkReply->readAll();
37
38     emit data(bytes);
39
40     // bye bye my reply
41     // this will also delete this NetworkReply as the QNetworkReply is its parent
42     networkReply->deleteLater();
43 }
44
45 void NetworkReply::requestError(QNetworkReply::NetworkError code) {
46     emit error(networkReply);
47 }
48
49 /* --- NetworkAccess --- */
50
51 NetworkAccess::NetworkAccess( QObject* parent) : QObject( parent ) {}
52
53 QNetworkReply* NetworkAccess::simpleGet(QUrl url, int operation) {
54
55     QNetworkAccessManager *manager = The::networkAccessManager();
56
57     QNetworkRequest request(url);
58     request.setRawHeader("User-Agent", Constants::USER_AGENT.toUtf8());
59     request.setRawHeader("Connection", "Keep-Alive");
60
61     QNetworkReply *networkReply;
62     switch (operation) {
63
64     case QNetworkAccessManager::GetOperation:
65         qDebug() << "GET" << url.toString();
66         networkReply = manager->get(request);
67         break;
68
69     case QNetworkAccessManager::HeadOperation:
70         qDebug() << "HEAD" << url.toString();
71         networkReply = manager->head(request);
72         break;
73
74     default:
75         qDebug() << "Unknown operation:" << operation;
76         return 0;
77
78     }
79
80     // error handling
81     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
82             this, SLOT(error(QNetworkReply::NetworkError)));
83
84     return networkReply;
85
86 }
87
88 NetworkReply* NetworkAccess::get(const QUrl url) {
89
90     QNetworkReply *networkReply = simpleGet(url);
91     NetworkReply *reply = new NetworkReply(networkReply);
92
93     // error signal
94     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
95             reply, SLOT(requestError(QNetworkReply::NetworkError)));
96
97     // when the request is finished we'll invoke the target method
98     connect(networkReply, SIGNAL(finished()), reply, SLOT(finished()), Qt::AutoConnection);
99
100     return reply;
101
102 }
103
104 NetworkReply* NetworkAccess::head(const QUrl url) {
105
106     QNetworkReply *networkReply = simpleGet(url, QNetworkAccessManager::HeadOperation);
107     NetworkReply *reply = new NetworkReply(networkReply);
108
109     // error signal
110     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
111             reply, SLOT(requestError(QNetworkReply::NetworkError)));
112
113     // when the request is finished we'll invoke the target method
114     connect(networkReply, SIGNAL(finished()), reply, SLOT(finished()), Qt::AutoConnection);
115
116     return reply;
117
118 }
119
120 /*** sync ***/
121
122
123 QNetworkReply* NetworkAccess::syncGet(QUrl url) {
124
125     working = true;
126
127     networkReply = simpleGet(url);
128     connect(networkReply, SIGNAL(metaDataChanged()),
129             this, SLOT(syncMetaDataChanged()), Qt::AutoConnection);
130     connect(networkReply, SIGNAL(finished()),
131             this, SLOT(syncFinished()), Qt::AutoConnection);
132     connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)),
133             this, SLOT(error(QNetworkReply::NetworkError)));
134
135     // A little trick to make this function blocking
136     while (working) {
137         // Do something else, maybe even network processing events
138         qApp->processEvents();
139     }
140
141     networkReply->deleteLater();
142     return networkReply;
143
144 }
145
146 void NetworkAccess::syncMetaDataChanged() {
147
148     QUrl redirection = networkReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
149     if (redirection.isValid()) {
150
151         qDebug() << "Redirect" << redirection;
152         networkReply->deleteLater();
153         syncGet(redirection);
154
155         /*
156         QNetworkAccessManager *manager = The::networkAccessManager();
157         networkReply->deleteLater();
158         networkReply = manager->get(QNetworkRequest(redirection));
159         connect(networkReply, SIGNAL(metaDataChanged()),
160                 this, SLOT(metaDataChanged()), Qt::AutoConnection);
161         connect(networkReply, SIGNAL(finished()),
162                 this, SLOT(finished()), Qt::AutoConnection);
163         */
164     }
165
166 }
167
168 void NetworkAccess::syncFinished() {
169     // got it!
170     working = false;
171 }
172
173 void NetworkAccess::error(QNetworkReply::NetworkError code) {
174     // get the QNetworkReply that sent the signal
175     QNetworkReply *networkReply = static_cast<QNetworkReply *>(sender());
176     if (!networkReply) {
177         qDebug() << "Cannot get sender";
178         return;
179     }
180
181     // Ignore HEADs
182     if (networkReply->operation() == QNetworkAccessManager::HeadOperation)
183         return;
184
185     // report the error in the status bar
186     QMainWindow* mainWindow = dynamic_cast<QMainWindow*>(qApp->topLevelWidgets().first());
187     if (mainWindow) mainWindow->statusBar()->showMessage(
188             tr("Network error: %1").arg(networkReply->errorString()));
189
190     qDebug() << "Network error:" << networkReply->errorString() << code;
191
192     networkReply->deleteLater();
193 }
194
195 QByteArray NetworkAccess::syncGetBytes(QUrl url) {
196     return syncGet(url)->readAll();
197 }
198
199 QString NetworkAccess::syncGetString(QUrl url) {
200     return QString::fromUtf8(syncGetBytes(url));
201 }