QNetworkRequest and QUrl encoding c++ - c++

Im trying to connect to gmail and consume the atom file.
Im having problem with passwords that contain !#$%^&* chars.
pNetworkManager = new QNetworkAccessManager(this);
connect(pNetworkManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(result(QNetworkReply*)));
Settings settings;
settings.load();
QString url;
url.append("https://");
url.append(settings.getUserName());
url.append(":");
url.append(QUrl::toPercentEncoding(settings.getPassword()));
url.append("#mail.google.com/mail/feed/atom");
pNetworkManager->get(QNetworkRequest(QUrl(url.toUtf8())));
I get reply "Protocol "" is unknown"
Qt 4.8
How is this done properly

Why don't you construct a QUrl directly?
QUrl url("https://mail.google.com/mail/feed/atom");
url.setUserName(settings.getUserName());
url.setPassword(settings.getPassword());
pNetworkManager->get(QNetworkRequest(url));
It handles all the necessary encoding and QNetworkRequest takes it directly anyway. No need to mess with string encodings.

Related

QNetworkAccessManager and cookies

I'm trying to download a website (youtube) that opens after user passes the consent page (accepting cookies). So i create QNetworkRequest request and set RawHeader to ("COOKIE" , "CONSENT=YES+42"). It works fine, but only with the first attempt to download. With every next attempt i bounce against the consent page. The problem is somehow bypassed when each time i use deleteLater() on QNetworkAccessManager object. But the documentation claims "One QNetworkAccessManager instance should be enough for the whole Qt application" (also creating new instance of QNetworkAccessManager for each use eventually results with not receiving a replay and rise of processor use). So my question is how to "reset" QNetworkAccessManager so with each next use, it acts as with the first request.
My code looks like this:
Youtube::Youtube(QObject *parent) : QObject(parent)
{
manager = new QNetworkAccessManager(this);
}
void Youtube::makeRequest(QString indexCore){
QNetworkReply *reply;
QNetworkRequest request;
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotReadyRead(QNetworkReply*)));
request.setRawHeader("COOKIE" , "CONSENT=YES+42" ); //works
request.setUrl(QUrl("https://" + indexCore ));
reply = manager->get(request);
}
void Youtube::slotReadyRead(QNetworkReply *replay)
{
QByteArray dataTemp = replay->readAll();
website = dataTemp.toStdString();
replay->deleteLater();
}
OK.I just had to set and empty QNetworkCookieJar.

QUrl construction piece by piece

I tried to construct QUrl piece by piece:
QUrl url{"https://host.org/path"};
url.setScheme("http");
url.setPort(81);
url.setUserName("user");
url.setPassword("password");
url.setHost("server.com");
QUrlQuery urlQuery;
urlQuery.setQueryItems({{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}});
url.setQuery(urlQuery);
url.setFragment("fragment");
//url.setPath("dir/file.htm");
qDebug() << url;
Output (password is accidentally missed on the way):
QUrl("http://user#server.com:81/path?key1=value1&key2=value2&key3=value3#fragment")
First of all, if QUrl is default-constructed, then using setters I can't add anything into it at all.
In above code if I uncomment last but one line, then output became QUrl(""). That is QUrl::setPath clean up the whole internal representation of QUrl instance.
Are both mentioned behaviours normal? Or are they the bugs?
I use Qt 5.7.1.
It seems, that simple string concatenation is much less bug prone.
To answer at least some of your questions:
qDebug() << url; eats the password and that is a good thing. Why? Because qDebug and friends are often used to write log files and having password in log files or even on the console is bad, really bad. So the default is that qDebug eats the password. If you need it call qDebug() << url.toString(). You have been warned ;)
Why QUrl url("server.com"); url.setScheme("http"); results in http:server.com is because in QUrl url("server.com"); "server.com" is parsed and recognized as the path and not the host.
I am using 5.7.0 and using a default constructed QUrl with setters work fine:
QUrl url;
url.setScheme("http");
url.setHost("server.com");
qDebug() << url; // QUrl("http://server.com")
The reason why setPath makes the URL null is because it is ill-formed. The path must start with an slash. Use url.setPath("/dir/file.htm");.
Cheers and keep fighting!

Using QNetworkReply of a previous QNAM request as QHttpMultiPart body

In my application I need to post a large file which is available by HTTP location to another HTTP location without loading the whole file to memory.
I've already to tried to pass QNetworkReply received from the previous QNAM request instead of QFile, but no luck: the code compiles and starts downloading very_large_file.bin with no problems, but there does no POST request occurs:
QNetworkRequest request(QUrl("http://mylocation/very_large_file.bin"));
QNetworkReply *reply = nm.post(request, &multipart);
QHttpMultiPart multipart(QHttpMultiPart::FormDataType);
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader,
QVariant("application/octet-stream"));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"myfile\"; filename=\"test.bin\""));
filePart.setBodyDevice(reply); // working fine if I pass QFile instead of QNetworkReply
QNetworkRequest request(QUrl("http://myanotherlocation/post.php"));
QNetworkReply *reply = nm.post(request, &multipart);
By searching some info in Google I've found that the problem is that I'm trying to pass a sequential QIODevice while for some reasons QNAM is only working good with non-sequential QIODevice-s, so I need to implement a wrapper that converts QNetworkReply to something that QNAM would understand.
Does anybody can provide me with a minimal working example of that? It's necessary that very_large_file.bin will be transfered from mylocation to myanotherlocation chunk-by-chunk, rather from being fully loaded to memory.

Web service in blackberry 10

I am developing a BlackBerry 10 apps with Cascades (C++ programming language) right now. Can anyone tell me how do i make a call to web service in BlackBerry 10: Cascades? I'm just a beginner, so i don't really know anything. Thanks for your answer
void GetWeb::start(const QString &str)
{
QNetworkRequest request = QNetworkRequest();
request.setUrl(QUrl(str));
QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager(this);
connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
networkAccessManager->get(request);
}
void GetWeb::requestFinished(QNetworkReply* reply)
{
if (reply->error() == QNetworkReply::NoError)
{
emit complete(reply->readAll());
}
reply->deleteLater();
}
In this case I am emiting the resulting string as a signal, but you could also just use the reply->readAll() string directly if you wished...
There's a few moving parts to sending a network request using Qt. Here's the example Qt uses:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
So what you do is create a QNetworkAccessManager object, which handles the actual process of sending the request and processing the response. You then connect the signal that the manager emits when the QNetworkRequest has finished to a slot you've created called replyFinished which takes QNetworkReply * as a parameter, that might look like this:
void MyClass::replyFinished(QNetworkReply *serverResponse)
{
//do something with the response
}
You then use the managers get method to pass your QNetworkRequest, which you can create like it has been there, or separately. And that's about it, that's a minimal example that'll send a HTTP request to http://qt-project.org and return a response containing the data from the page, you can extend out from there to do things like get JSON or XML.
Example from: QtNetwork documentation

how can I create QUrl from encoded url

I have a QString which contains encoded URL, that means, the url as you would insert it to browser, for example:
QString string = "http://domain.tld/index.php?some%20encoded&another%20encoded";
When I create QUrl like
QUrl(string);
it randomly decides what should be encoded and what shouldn't, in this case it leave "?" and "&" decoded, but AGAIN encode the percent symbol. So the target php application receive "some%20encoded" instead of "some encoded".
This seems to be some feature of QT when it automatically attempt to parse "and fix" url. This feature can be disabled by calling
QUrl(string, QUrl::StrictMode);
which works perfectly in qt 5+ but in qt 4, despite it compiles, it has same behaviour as if I didn't provide StrictMode parameter. How can I create url from string I encoded myself and which needs no further encoding?
What's you are looking for is
QUrl QUrl::fromEncoded (const QByteArray &input ) [static]
QUrl doc