PDA

View Full Version : Convert to html percent encoding



bull3t
30th October 2016, 15:39
Hi, I have what seems a simple issue but I was unable to solve.

I'm writing an application that login to an internet site. The problem is that the password contains a special character, À, but login fails. After a while I discovered that the problem is how qt converts the letter; instead of "%C0" as in every URL Encoded Characters Table, every qt method I used converts it in "%C3%80".

I tryed QByteArray::toPercentEncoding(), QUrl::toEncoded((FormattingOptions), Qurl::toString((FormattingOptions), without luck.

I'm using qt 5.7 on arch linux.

Thanks for your help.

ChrisW67
30th October 2016, 20:49
Your QString is a collection of Unicode character codes. The character 'À' is Unicode code point U+00C0. The UTF-8 encoding for that code point is two bytes 0xC3 0x80. I think you can see where your result is coming from. This behaviour is exactly as documented http://doc.qt.io/qt-5/qurl.html#toPercentEncoding

The original RFC talks about encoding the ASCII value of reserved characters: there is no ASCII code for 'À'. RFC 3986, in 2005, changed this to UTF-8, which explains the Qt behaviour.

Your server is expecting that the character has been encoded with a local eight bit encoding (probably Windows CP1252 (https://en.m.wikipedia.org/wiki/Windows-1252)) where that character would be a single byte 0xC0. It is possible the server triggers UTF-8 handling if the request has an Accept-Charset header listing utf-8, so that is worth a try. If not, you may have to manually encode the bytes out of QString:toLocal8Bit() to get the result your server expects.

bull3t
31st October 2016, 18:05
Thanks for tips. Unfortunately "Accept-Charset" has no effect on server. Also QString:toLocal8Bit() seems not working; here a small piece of code:


QString pass = "À";
QUrlQuery postData;
postData.addQueryItem( QLatin1String( "pass" ), pass.toLocal8Bit() );
qDebug() << postData.query( QUrl::EncodeUnicode );

output is "pass=c%C3%80"

EDIT 1:

postData.query( QUrl::PrettyDecoded ) returns

"pass=\xC0"

that's very close to "%C0"

EDIT 2:

The following code seems working:


QUrl(pass).toString(QUrl::PrettyDecoded).toLatin1( ).toPercentEncoding()