Details
-
Bug
-
Resolution: Done
-
P0: Blocker
-
None
-
4.6.3, 4.7.3
-
None
-
Win 7 64 bits
Qt SDK 11 Release
Symbian^3 devices (N8, C7, E7)
-
b4028986a40406b077dfa14620a61ef718960a85, d65869a4a3bc76d2feecd039daa7f1e388e93433
Description
A basic Qt Quick application (see project NetworkIssue.zip enclosed) loading an image from network is systematically receiving the following message :
<< Error downloading http://www.lequipe.fr/Medias/Football/201104/650x475/les-quotidiens-espagnols-marca-et-as-ont-choisi-le-meme-titr.jpg - server replied:Forbidden >>
How to reproduce :
- Create a Qt Quick application using the wizard
- Edit main.qml so it looks like this :
import QtQuick 1.0 Rectangle { width: 360 height: 360 Text { text: "Touch to quit" anchors.centerIn: parent } Image{ id:newsImg width:100 height:80 source:"http://qt.nokia.com/logo.png" } MouseArea { anchors.fill: parent onClicked: { Qt.quit(); } } }
- Insert a sim card of the given operator in your Symbian^3 device
- Deactivate any wifi access point from your device to make sure you'll use operator IAP
- Build and run the application on a Symbian^3 device
- The image logo is not displayed
Solution :
The origin of the problem seems to be related to user agent filtering on operator network side : the default user agent used by http Qt stack is rejected by the network. The workaround solution consists in setting an explicit user agent (for instance the same user agent as the one used by Qt webkit). Here is how to fix it :
1- define a helper class which inherits QWebPage as followed :
class UserAgentProvider : public QWebPage { Q_OBJECT public: explicit UserAgentProvider(QWidget *parent = 0); QString getUserAgent() { return userAgentForUrl(QUrl("")); } };
2- define a custom factory class which inherits QDeclarativeNetworkAccessManagerFactory as followed :
class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory { public: explicit NetworkAccessManagerFactory(QString p_userAgent = ""); QNetworkAccessManager* create(QObject* parent) { CustomNetworkAccessManager* manager = new CustomNetworkAccessManager(__userAgent, parent); return manager; } private: QString __userAgent; };
3- define a custom network class which inherits QNetworkAccessManager as followed :
class CustomNetworkAccessManager : public QNetworkAccessManager { Q_OBJECT public: explicit CustomNetworkAccessManager(QString p_userAgent = "", QObject *parent = 0); protected: QNetworkReply *createRequest( Operation op, const QNetworkRequest &req, QIODevice * outgoingData=0 ) { QNetworkRequest new_req(req); new_req.setRawHeader("User-Agent", __userAgent.toAscii()); QNetworkReply *reply = QNetworkAccessManager::createRequest( op, new_req, outgoingData ); return reply; } private: QString __userAgent; };
4- modify main.cpp like this :
// Set custom NetworkAccessManagerFactory object in QDeclarative context UserAgentProvider p; QString userAgent = p.getUserAgent();
NetworkAccessManagerFactory factory(userAgent); viewer.engine()->setNetworkAccessManagerFactory(&factory);
Attached is a sample Qt project (NetworkOverload) which does the job.
Note :
The problem also occurs with pure Qt application (QML-less). The fix is slightly simple since subclassing QDeclarativeNetworkAccessManagerFactory is not required (step 2 and 4 can be removed).