-
Notifications
You must be signed in to change notification settings - Fork 211
Reliable binary data extraction from QR codes #64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
aec04b3
to
87a0b3c
Compare
87a0b3c
to
fca4ac5
Compare
@mchehab Hello! It's been two weeks since I submitted the PR. What are your thoughts? I completed the oneshot feature as well: #60, no breaking changes. These two features complement each other: raw oneshot mode makes it possible to pipe binary data to other programs with no intermediary processing. |
I would love to use this! |
FWIW I tested this by encoding and decoding a
|
@peter-moran Thanks, that is useful. I also made a test script when I created issue #55. Here's a simplified version of it that returns successfully when the binary data was successfully decoded: dd if=/dev/urandom bs=256 count=1 > test.bin
qrencode -8 -o test.png < test.bin
zbarimg --raw -Sbinary -Sdisable -Sqr.enable test.png | head -c -1 > test.dec
cmp test.bin test.dec I was unsure whether to commit this code. The test script requires either committing images to the repository or a dependency on |
77c93d9
to
1aaa353
Compare
Rebased on top of the latest master 9c6f6a1. Added a binary data decoding test. The temporary fix commit can be deleted if #60 is merged and 259a17a is amended with a @peter-moran Can you please verify that the test passes on your computer? |
Tests pass for me |
I tried the above, but got an error:
It seems that you need also to make sure that dbus will handle raw scans properly. Also, please add the testing scripting to test/Makefile.am.inc, in order for it to be called when |
Ah, please also add qr.binary to zbarcam-qt. It should be possible to fully set the ZBar options over there. |
@mchehab Thank you for your review.
Indeed. It appears ZBar is trying to transfer data via D-Bus using a string type. According to the D-Bus specification, NUL bytes cannot occur in the input:
D-Bus also supports byte and array types. After opening an array container for bytes, I believe I can use
The test I committed is part of
Would you like me to add more tests? It's possible to add the random data and
I added an entry to the struct settings_s {
QString name;
zbar::zbar_config_t ctrl;
bool is_bool;
};
static const struct settings_s settings[] = {
{ "binary", zbar::ZBAR_CFG_BINARY, true },
} I thought that'd cause the option to show up since the code loops over this structure. For example, the for (unsigned i = 0; i < SETTINGS_SIZE; i++) {
if (settings[i].is_bool) {
QCheckBox *button = new QCheckBox(settings[i].name, this);
layout->addWidget(button, i, 0, 1, 2, Qt::AlignTop | Qt::AlignLeft);
} else {
QLabel *label = new QLabel(settings[i].name);
layout->addWidget(label, i, 0, 1, 1, Qt::AlignTop | Qt::AlignLeft);
IntegerSetting *spin = new IntegerSetting(settings[i].name, value);
layout->addWidget(spin, i, 1, 1, 1, Qt::AlignTop | Qt::AlignLeft);
}
} When the dialog is accepted, it loops over all elements of the structure to apply the options: void accept() {
for (unsigned i = 0; i < SETTINGS_SIZE; i++)
zbar->set_config(sym, settings[i].ctrl, val[i]);
QDialog::accept();
}; |
Yeah, using a byte array will work for the raw mode. Yet, we should keep the strings on UTF-8 mode, in order to preserve backward compatibility. So, it sounds that it would need to use a different message for raw mode.
Yes. It seems that the current test didn't check handling the image via dBus. So, when I did a manual test, it failed. Also, as we'll need to add dBus raw output message using array of bytes, we'll need to change the dBus testing logic to test both UTF-8 and raw outputs.
Yeah, the code sounds right. Unfortunately, I could test it. I'm currently on a travel using a low-res monitor, not big enough to show all options. That reminds that we should likely add a scroll-bar for the options with low-res monitors. For the next changes, I'll double check it on a hi-res monitor. |
When decoders encounter binary data, they attempt to guess the encoding of the data and convert it to text. This destroys other types of data. The new boolean decoder configuration option ZBAR_CFG_BINARY suppresses this automatic character set conversion. The decoders that support it will output the raw binary data. Signed-off-by: Matheus Afonso Martins Moreira <[email protected]>
If a QR code doesn't specify the text encoding of binary data through Extended Channel Interpretation, ZBar tries to guess the encoding. This unconditional character set conversion makes it impossible to recover other types of binary data stored in the QR code. The QR decoder now supports the ZBAR_CFG_BINARY configuration option. If set, it will output the bytes without converting them to text. This allows access to the actual bytes encoded in a binary QR code. Closes: mchehab#55 Thanks: Martin von Wittich <[email protected]> Signed-off-by: Matheus Afonso Martins Moreira <[email protected]>
Check the correctness of binary data extracted from QR codes. This specific test can be run with: make check-images The binary QR code example is the qr-code.png file, QR encoded: qrencode --8bit --output examples/qr-code-binary.png < examples/qr-code.png Tested-by: Peter Moran <[email protected]> Signed-off-by: Matheus Afonso Martins Moreira <[email protected]>
1aaa353
to
fe07205
Compare
Now the image scanner outputs a byte array to D-Bus. It does this only if the user set the binary decoding option, so this should not conflict with existing users. I replaced the The code builds with D-Bus enabled and all tests pass, including the current D-Bus checkers. I don't know how to test the correctness of this output though. I get another type of error when I run
I know about |
Modified the D-Bus testing code: it now writes the
It seems the data is not being written to the bus. I'm not sure why yet but I suspect the problem is in the code that writes the array to the bus: dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT, "ay", &dict_val);
dbus_message_iter_append_fixed_array(&dict_val, DBUS_TYPE_BYTE, &value, value_length); Is there a problem with it? |
It looks sane to me.
No. If the data is not UTF-8 encoded, the best is to only output the raw message.
Based on your next patch, it seems that you already figured it out.
Ok. D-Bus is a new feat to ZBar. So, this code is new even to me ;-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modified the D-Bus testing code: it now writes the
BinaryData
to a separate file which the test script checksums. The non-binaryData
test passes and then times out while waiting for theBinaryData
message. The first invocation ofzbarimg
produces no error messages but the second prints the same error I got earlier:Name Release Error (Connection was disconnected before a reply was received)
It seems the data is not being written to the bus. I'm not sure why yet but I suspect the problem is in the code that writes the array to the bus:
dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT, "ay", &dict_val); dbus_message_iter_append_fixed_array(&dict_val, DBUS_TYPE_BYTE, &value, value_length);Is there a problem with it?
Didn't test, but in principle looks ok to me. What I do recommend you is to open two terminals. At the first one, you run just:
$ ./test/test_dbus
On the second one, parse different images, on raw and UTF-8 mode, for example running something like:
$ zbarimg/zbarimg examples/<image1>.png
$ zbarimg/zbarimg --raw examples/<image2>.png
...
This way, you can see what each different image (with or with and without --raw) will output.
You may add some additional prints at test_dbus.c,for example to double-check if the test_dbus will not be on some endless waiting loop.
test/test_dbus.c
Outdated
@@ -153,6 +154,11 @@ int main(int argc, char *argv[]) | |||
dbus_message_iter_recurse(&dict, &val); | |||
dbus_message_iter_get_basic(&val, &str); | |||
printf("Value = %s\n", str); | |||
} else if (strcmp(property, ZBAR_SIGNAL_BINARY_DATA) == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds hacky to test for a property here. I mean, the D-Bus listener should not rely on anything except on the received messages. See, the dbus testing code: it is possible to test if the received message is a string or not:
if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&dict))
The right way seems to have an else clause there for the bytearray type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is checking the type of the key. Strings are the only valid keys. The org.linuxtv.Zbar1.Code
signal is defined as a dictionary with string keys and variant values:
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{sv}", &dict);
The types of the values are currently not checked. I wrote my code following the pattern of the surrounding code. So currently the code checks the key and recurses into the variant value without checking its type. Before this patch, only string values were possible. I agree that it'd be wise to add some type checks.
Since the nature of the data can be distinguished by checking its type, do we need a new BinaryData
key? It should be possible to have Data
contain both strings and byte arrays and clients should be able to handle both types.
Decoding binary data with D-Bus enabled caused runtime errors because the decoded data was assumed to be valid UTF-8 text. Now the image scanner will output a byte array to the D-Bus system bus if the decoded symbol's decoder was configured for binary data decoding. Signed-off-by: Matheus Afonso Martins Moreira <[email protected]>
The D-Bus test program and script now reads and verifies binary data. Text and binary data are written to separate log files which must be specified by the test script. The checksums of these log files will be compared against the expected value. Signed-off-by: Matheus Afonso Martins Moreira <[email protected]>
4e25467
to
ca97621
Compare
Indeed, the problem was there. It's not possible to simply write the array into the variant. An array container must be opened and recursed into: dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT, "ay", &dict_val);
dbus_message_iter_open_container(&dict_val, DBUS_TYPE_ARRAY, "y", &array_val);
dbus_message_iter_append_fixed_array(&array_val, DBUS_TYPE_BYTE, &value, value_length); After updating the
Perhaps |
Currently, only the dictionary keys are validated. Dictionary values are variant and could benefit from type checking now that types other than string are being used.
@mchehab Hello! Have you had an opportunity to test the new D-Bus code? |
@matheusmoreira do you expect that this feature is fully available now? If you confirm I will give it a try here too :) |
@jerabaul29 Yes. I added a binary decoding option to the ZBar API and implemented support for it in the QR decoder. The I have added automated tests which use these new features to decode a QR code which contains a PNG file. They pass on my machine. Please clone my branch, build the project and run the tests. It'd be greatly appreciated if you could test the Qt GUI as well, I added the binary option to the GUI but I wasn't able to build it. |
@matheusmoreira I have some small problems here looks like (probably doing something stupid somewhere). It looks like I successfully compiled:
|
PS: I am on Ubuntu 18.04 if this is helpful to know. |
@jerabaul29 That's strange. I do not know why the Python tests are failing. It seems it didn't make it to the The tools use the |
Mmmh, I am probably doing something stupid somewhere, sorry for that, I am not used to build stuff... The tests failing to build:
|
I think I am just confused somewhere. I tried to compile locally by following the instructions here: https://github.com/mchehab/zbar/blob/master/INSTALL.md then following the Basic Installation section. This is where things fail (doing the tests). Then I simply try to launch the |
@jerabaul29 Every test command is outputting the same data. They all have the same checksum: /home/jrlab/Desktop/Git/zbar/zbarimg/zbarimg --nodbus --raw --oneshot -Sbinary '/home/jrlab/Desktop/Git/zbar/examples/qr-code-binary.png' |
(note that I have not run the |
|
I deeply apologize for my n00bness @matheusmoreira in the very likely case that I am doing something obviously wrong in the process for somebody with more experience but that I am missing... Any other way for your to share a 'built' version of the package that I can test, or some containerized version, or something in this kind? |
@jerabaul29 The following test should be working since I did not modify it in any way: /home/jrlab/Desktop/Git/zbar/zbarimg/zbarimg --nodbus '/home/jrlab/Desktop/Git/zbar/examples/code-93.png' Does it output anything? I built my copy of ZBar by executing Turns out |
Aah, I think that this is slightly different from the command I used to configure following what was in the
|
Ok, installing dbus-dev:
Lets me run your command for compilation without error. But when running
|
(@matheusmoreira @mchehab if you think I am polluting your push request thread let me know, and I can move / clean my posts to whatever location you think is better suited). |
Note: in the current state I cannot do anything:
Guess this means I am using the right binary? |
Seems to be some kind of linking issue. Looks like |
Hello, Btw, thanks for this patch. Need it for a project of mine. |
@matheusmoreira fails in the exact same way on the master branch. |
@joernheissler if I understand well the point with setting a LD_PRELOAD is to force the system to use a given .so object when executing the next command, right? Problem is, I do not see any .so after having run the make command (
while I guess I should see and set LD_PRELOAD to a .so present here, right? Possible I am completely wrong and lost, sorry. |
Looks like this issue is not specific to my pull request. The build system itself seems to be running into problems on your system. I don't understand autotools well enough to debug this issue. Perhaps there will be people who faced similar issues in a Ubuntu or Debian channel.
I remember seeing a hidden |
Applied. |
@matheusmoreira thank you so much for the feature,@jerabaul29 thank you for discussion on installation in ubuntu 18.04,I was having some of those issues on my ubuntu 20.04,now they're resolved and all checks/tests work. |
@ashwani-rathee You're welcome. Thank the original developers as well. It turns out the binary decoding capability was always there... I merely provided an API for it. If you managed to resolve the Ubuntu build issues, please provide details on how you did it. Could help future readers! |
Currently, ZBar tries to guess the character encoding of binary data streams stored in QR codes even though they might not be encoded text. This unconditional character set conversion makes it impossible to recover other types of binary data stored in the QR code. This is described in issue #55.
This pull request adds a new configuration option that instructs decoders not to convert binary data to text and adds support for it to the QR decoder. Now both
zbarimg
andzbarcam
produce the expected results when given the-Sqr.binary
option.