Converting UTF-16 QByteArray to QString - qt

I have a QByteArray which contains bytes in UTF-16 format.
A Java program sends data to a QT program via socket using
//dos is DataOutPutStream
dos.writeChars("hello world");
On the receiver side in QT program I read the data from socket into QByteArray and I want to convert it to a QString. inspecting the data variable of QByteArray it has 0h0e0l0l0o0 0w0o0r0l0d
When I try to make a QString out of it like this
QString str(byteArray)
The resulting string is empty perhaps because it encounters a 0 byte at the start and ofcouse because the documentation of the constructor I am using says that it internally uses fromAscii and what I am passing is not ascii.
I guess i have to somehow use QString::fromUTF-16 but that requires a ushort* and I have a QbyteArray.
Please advise what is the best way to do it.
Thanks,

Get a pointer to the QByteArray.data() and cast it to ushort*

This would work, assuming your utf-16 data is of the same endianness or has the BOM (Byte Order Mark):
QByteArray utf16 = ....;
auto str = QString::fromUtf16(
reinterpret_cast<const ushort*>(utf16.constData()));

Related

Generate QByteArray format with Golang

I have an application on QT which reads from a file with text in a QByteArray format (the information belongs to a certificate stored in a file). Looks like this:
certificate="#ByteArray(0\x82\tF\x2\x1\x3\x30\x82\t\x10\x6\t*\x86H\x86\xf7\r\x1\a\x1\xa0\x82\t\x1\x4\x82\b\xfd\x30\x82\b\xf9\x30\x82\x3\xad\x6\t*\x86H\x86\xf7\r\x1\a\x1\xa0\x82\x3\x9e\x4\x82\x3\x9a\x30\x82\x3\x96\x30\x82\x3\x92\x6\v*\x86H\x86\xf7\r\x1\f\n\x1\x3\xa0\x82\x3+0\x82\x3'\x6\n*\x86H\x86\xf7\r\x1\t\x16\x1\xa0\x82\x3\x17\x4\x82\x3\x13\x30\x82\x3\xf\x30\x82\x1\xf7\xa0\x3\x2\x1\x2\x2\x1\x1\x30\r\x6\t*\x86H\x86\xf7\r\x1\x1\x5\x5\0\x30\x16\x31\x14\x30\x12\x6\x3U\x4\x3\f\vMumble User0\x1e\x17\r200130204841Z\x17\r400125204841Z0\x16\x31\x14\x30\x12\x6\x3U\x4\x3\f\vMumble User0\x82\x1\"0\r\x6\t*\x86H\x86\xf7\r\x1\x1\x1\x5\0\x3\x82\x1\xf\0\x30\x82\x1\n\x2\x82\x1\x1\0\xc6\x1d\x66\x8f\xc2\x31-N\xa1\xa0,\xf4\xb9\xc6\x80\x30)\xba\xf6\x17\x37\xec\x82\x1a\xf2s\xfc\xbc\x86\x93\x97\x83G\xccU(\vnr\t\xa8\x61\x12\b\x8f\xd6\x95T?\xc9\xe8\xe3v\x80%\xe3}\xe6,\x90\a\xe2\x18\xe0V\x80k\xee\x88&H <2G\x81\xec\xd6\xf1\xe9\xd0\xcat\x13\x9c?\x81\xcf\xaf\x14J\xc1X\xa5k\x9f\xf6P\xd9y\b\xa2\xe7\xaf\xa0l\xa0\xb4\xc7g\xc3*\xdd\x10\x16\xde\xe\xc3
Now I need generate the same format (QByteArray) using a GO application, but didn't find how generate this format.
Anyone can point me to some example or documentation on how create the same format of a QByteArray using another language (go)?
Thanks in advance.
QByteArray is just an array of bytes, in go that would just be []byte

How to convert byte*payload to an int?

I am programming ESP8266thing dev board using arduino.
I have a value stored in byte*payload. I want to convert that value and store it into an int variable. I tried different methods but non of them is working fine. Can anyone suggest me a good method ? Thank You!!
How you do this depends entirely upon how you represented the value when you transmitted it via MQTT.
If you transmitted it in binary - for instance, you published the integer as series of bytes - then you also need to know the byte order and the number of bytes. Most likely it's least-significant-byte first (so if the integer in hex were 0x1234 it would be transmitted as two bytes - 0x34 followed by 0x12) and 32 bits.
If you're transmitting binary between two identical computers running similar software then you'll probably be fine (as long as that never changes), but if the computers differ or the software differs, you're dealing with representations of your integer that will be dependent on the platform you're using. Even using different languages on the two ends might matter - Python might represent an integer one way and C another, even if they're running on identical processors.
So if you transmit in binary you should really choose a machine-independent representation.
If you did transmit in binary and made no attempt at a machine-independent representation, the code would be something like:
byte *payload;
int payload_length;
int result;
if(payload_length < sizeof(int)) {
HANDLE THIS ERROR
} else {
result = *(int *)payload;
}
That checks to make sure there are enough bytes to represent a binary integer, and then uses a cast to retrieve the integer from the payload.
If you transmitted in binary in a machine-independent format then you'd need to do whatever transformation is necessary for the receiving architecture.
I don't really recommend transmitting in binary unless you know what you're doing and have good reasons for it. Most applications today will be fine transmitting as text - which you could say is the machine-independent representation.
The most likely alternative to transmitting in binary is in text - which can be a machine independent format. If you're transmitting an integer as text, your code would look something like this:
byte *payload;
int payload_length;
char payload_string[payload_length + 1];
int result;
memcpy(payload_string, payload, payload_length);
payload_string[payload_length] = '\0';
result = atoi(payload_string);
This code uses a temporary buffer to copy the payload into. We need to treat the payload like a C string, and C strings have an extra byte on the end - '\0' - which indicates end-of-string. There's no space for this in the payload and an end-of-string indicator may or may not have been sent as part of the payload, so we'll guarantee there's one by copying the payload and then adding one.
After that it's simple to call atoi() to convert the string to an integer.
Don't know if you found an answer yet, but I had the exact same issue and eventually came up with this:
payload[length] = '\0'; // Add a NULL to the end of the char* to make it a string.
int aNumber = atoi((char *)payload);
Pretty simple in the end!

Decode Shift-JIS and display to user interface using QT

I have a code to decode SHIFT-JIS using qt to user interface, here is my code:
QTextCodec *codec1 = QTextCodec::codecForName("Shift-JIS");
QByteArray encoded = "81ff";
QString current = codec->toUnicode(QByteArray::fromHex(encoded));
ui->hientai->setText(current);
And the result of my code is wrong. So please tell me what is the problem?
This is the output to UI

How to prevent decompression bomb attack in Qt

I am creating a client server application in Qt.
I serialize and deserialize some structures using my own algorithm, however in order to deserialize them, I need to load the QByteArray that contains the object into memory. In order to prevent some sort of hacker attacks that would cause the server go OOM, I set a fixed limit for a maximum size of the array that shouldn't, in normal situation be ever exceeded, so that if some "hacker" attempted to send for example array that contains 200GB of data, the server rejects it, instead of reading the data until it dies OOM.
Now the problem is that I implemented compression to the network protocol in order to speed it up. So I don't really know the size of uncompressed data, until I run qUncompress on the byte array I received from client. I am not sure if it's technically possible, but I think that someone in theory, could craft data that are so easy to compress that even if compressed version has few kb, uncompressed version could have gigabytes.
Is it possible? If so, is there any way to prevent this? For example run qUncompress in a way that it doesn't allow inflating over some specific size?
Maximum memory which qUncompress can allocate is 2147483632 bytes. It's a little more than 2GB. If the size of uncompressed data exceeds this limit, qUncompress return empty QByteArray.
Theoretical limit of compression factor for the deflate method is 1032:1. Gygabyte of zeroes can be compressed to 1 megabyte. It is impossible to compress gigabytes to few kb.
If you need more control over memory allocation, use zlib directly.
.pro file
LIBS += -lz
------------
#include "zlib.h"
...
QByteArray compressed = qCompress("Hello, World!");
//a four byte header contain the expected length (in bytes) of the uncompressed data
unsigned long len = (compressed[0] << 24) | (compressed[1] << 16) | (compressed[2] << 8) | (compressed[3]);
unsigned char *buffer = new unsigned char[len + 1];
int result = ::uncompress(buffer, &len, (const unsigned char*)compressed.constData() + 4, compressed.length() - 4);
QByteArray uncompressed;
if (result == Z_OK)
uncompressed = QByteArray((char*)buffer, len);
delete[] buffer;
qDebug() << uncompressed;
There is no way to do it with qUncompress, since it's a very simple API. However, there is a nice libary for Qt called Quazip. It gives you complete control over the compression and would allow you to e.g. abort once the decompression reaches the limit.

Displaying UTF-8 characters in a PlainTextEdit

I'm trying to display Chinese characters encoded in UTF-8 in a PlainTextEdit control, but it doesn't render them properly.
My data comes from a database and I know that the string I get in Qt is correct (the bytes are the same as in the database). Once I have the Chinese character in a QString, I tried various things to display it but always results in either question marks or random ASCII characters:
QString chineseChar = query.value(fieldNo).toString(); // get the character
ui->plainTextEdit->appendPlainText(chineseChar); // doesn't work
ui->plainTextEdit->appendPlainText(chineseChar.toUtf8()); // doesn't work
ui->plainTextEdit->appendPlainText(QString::fromUtf8(chineseChar.toAscii()); // doesn't work
Any suggestion on how to handle that?
"My data comes from a database and I know that the string I get in Qt is correct (the bytes are the same as in the database)."
How did you check that? Try with chineseChar.toUtf8().toHex().
Once your string data is in a QString, all UI elements accepting a QString will handle it correctly. Usually the error happens when converting from plain text data(const char*/QByteArray) to the QString.
The conversions here:
ui->plainTextEdit->appendPlainText(chineseChar.toUtf8()); // doesn't work
ui->plainTextEdit->appendPlainText(QString::fromUtf8(chineseChar.toAscii()); // doesn't work
convert the unicode string to a bytearray, and then implicitely back to a QString, as those methods expect a QString.
I suggest you define QT_NO_CAST_FROM_ASCII and QT_NO_CAST_TO_ASCII to avoid any unwanted QByteArray<->QString conversions.
If the string is wrong, the error usually happened before, when converting from QByteArray/const char* to QString, i.e. in query.value(fieldNo).toString(). Try with:
QString chineseChar = QString::fromUtf8( query.value(fieldNo).toByteArray() );
If that doesn't help, the problem is somewhere in QtSQL assuming the wrong encoding for the data it receives from the database.

Resources