how can I create QUrl from encoded url - c++

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

Related

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!

QMessageBox - url encoding/decoding

I created a QMessageBox with an html link:
QTMessageBox msgBox(Utility::UI::topLevelWidget());
msgBox.setText("Link");
msgBox.exec();
If I left click the link a new web browser tab opens. The problem is that the url http://www.example.cz/?url=www**%2525**www is opened instead of http://www.example.cz/?url=www**%25**www
How do I prevent such behavior?
UPDATE: If I right click the link, choose "Copy link" and paste it into the browser, the link is ok.
That's because % has the html encoding %25. So %25 -> %2525.
Why does Qt encode the links automatically?
In the QMessageBox, there is a QLabel. The label uses the Qt::TextFormat Qt::AutoText by default. Therefore, it detects in your text, that it is html encoded and generates the link.
The QLabel sends the signal linkActivated(const QString& link) or uses QDesktopServices::openUrl(), depending its the boolean openExternalLinks.
It seems, that the QMessageBox sets openExternalLinks to true.
Since the link will be used as input for a QUrl, it will be parsed. That's the reason for the double encoding.
It is possible, to modify the behavior of QDesktopServices::openUrl() by using its static method void QDesktopServices::setUrlHandler. I implemented and tested it for the desired behavior:
MyUrlHandler urlHandler;
QDesktopServices::setUrlHandler( "http", &urlHandler, "handleUrl" );
QMessageBox msgBox;
msgBox.setText( "Link" );
msgBox.show();
Using the class MyUrlHandler:
class MyUrlHandler : public QObject
{
Q_OBJECT
public:
MyUrlHandler(QObject* parent=0):QObject(parent){}
public slots:
void handleUrl(const QUrl &url)
{
QDesktopServices::openUrl( QUrl::fromEncoded( url.toString().toAscii() ) );
}
};
The trick is simple, I set the link address directly to the QUrl instance as already valid url.
But unfortunately, it modifies the behavior globally.

Saving the content of a QLineEdit object into a string variable (C++)

I've looked around the Qt Documentation, but within my project, I'd like to having most of the non-graphical 'more thinking' part of my program be on a seperate .cpp file.
Given that, I was wanting to take the text typed into a QLineEdit object and save it as a string after the user triggers the 'returnPressed' action, but when I type:
void MainWindow::on_lineEdit_returnPressed()
{
QMessageBox msgBox;
msgBox.setText("The entry has been modified.");
msgBox.exec();
//The line which should save the contents of the QLineEdit box:
string input = QLineEdit::text();
}
...Into the template provided by the Qt Creator IDE (with all necessary slots hopefully created) The compiler returns
In member function 'void MainWindow::on_lineEdit_returnPressed()'
cannot call member function 'QString...'
... and so on.
How should I rewrite my code to do this correctly?
You must choose how to store the string. Your main options are: array of chars, std::string from the standard library, and QString from Qt. If you need to use the string in a third party library then you might need to store it in an std::string or an array of chars, but if that's not the case then I suggest that you simply use QString as it is widely used throughout Qt, although you can convert a QString to std::string or array of chars.
You must actually retrieve the text. To do this you must call the text() function on the QLineEdit instance, not on the QLineEdit class itself. All widgets can be accessed through the ui pointer. Open the designer and check the name of the line edit, the default name is lineEdit, so try replacing the line
string input = QLineEdit::text();
with the line
QString input = ui->lineEdit->text();
How about that:
lineEdit->text().toStdString()
For Qt6 this is the best solution that I found
string input = ui->lineEdit->text().toStdString();
A more developed answer from 'alagner'

store input of line edit to string qt

I'm a beginner.I am making a simple gui program using qt in which you enter a url/website and that program will open that webpage in chrome.I used line edit in which user enters url and i used returnPressed() slot, but the problem is (it might sound stupid) that i don't know how to take the input by user and store it in a string so that i can pass that string as parameter to chrome.Is im asking something wrong.also tell me how can i save input to a txt file, i know how to do that in a console program.Is this process is same with others like text edit etc.
My mainwindow.cpp:
QString exeloc = "F:\\Users\\Amol-2\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe";
void MainWindow::on_site_returnPressed()
{
QString site;
getwchar(site);
QString space=" ";
QString result = exeloc + space + site;
QProcess::execute(result);
}
What im doing wrong.
thanks
You've got your approach slightly wrong, I can see where you're coming from though. It's actually a lot more simple than you're trying, Qt has a QDesktopServices class that allows you to interact with various system items, including open urls in the browser. There's documentation on it here.
QLineEdit has a text() function that will return a QString. So you can do something like this:
QString site = ui->site->text();
You don't have to use QProcess to open a web site in a browser. You can use QDesktopServices::openUrl static function.
Like this:
QString site = ui->site->text();
QUrl url(site);
QDesktopServices::openUrl(url);
Remember to include QDesktopServices and QUrl headers:
#include <QDesktopServices>
#include <QUrl>

QNetworkRequest and QUrl encoding 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.