From c7ec9cc03a383a33315c9cc126ebbf73135a17cc Mon Sep 17 00:00:00 2001 From: Hartmut Goebel Date: Sat, 2 Mar 2019 11:00:53 +0100 Subject: [PATCH] gnunet-qr: Reimplement in C - yet only a proof of concept. Still to-do: * running gnunet-uri * Proper error handling * integration into build system (automake) Reimplementing in C was chosen since - official zbar python-bindings support python 2 only, - none of the other bindings available at PyPI supports the high-level "processor" interface which gnunet-qr uses - implementing bindings for zbar using ctypes required addin a lot of low-level error handling code, thus implementing in C seamed to be easier, - the programm is short, thus re-implementing is not such complicated, and - this allows to reduce the number of dependencies (here: another Python version), which should ease porting to other plattforms (zbar is a dependency anyway). --- src/util/gnunet-qr.c | 160 ++++++++++++++++++++++++++++++++++++++++++ src/util/gnunet-qr.in | 46 ------------ src/util/gnunet-qr.py | 110 ----------------------------- 3 files changed, 160 insertions(+), 156 deletions(-) create mode 100644 src/util/gnunet-qr.c delete mode 100755 src/util/gnunet-qr.in delete mode 100644 src/util/gnunet-qr.py diff --git a/src/util/gnunet-qr.c b/src/util/gnunet-qr.c new file mode 100644 index 000000000..c02212a51 --- /dev/null +++ b/src/util/gnunet-qr.c @@ -0,0 +1,160 @@ +/* + This file is part of GNUnet. + Copyright (C) 2013-2019 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later +*/ + +#include +#include +#include +#include + +static const char *usage_note = + "gnunet-qr\n" + "Scan a QR code using a video device and import\n" + "\n" + "Arguments mandatory for long options are also mandatory for short options.\n" + " -c, --config FILENAME use configuration file FILENAME\n" + " -d, --device DEVICE use device DEVICE\n" + " -s, --silent do not show preview windows\n" + " -h, --help print this help\n" + " -v, --verbose be verbose\n" + "Report bugs to gnunet-developers@gnu.org.\n" + "\n" + "GNUnet home page: https://gnunet.org/\n" + "General help using GNU software: https://www.gnu.org/gethelp/\n"; + +int main (int argc, char **argv) +{ + const char* configuration = NULL; + const char* device = "/dev/video0"; + static bool verbose = false; + static bool silent = false; + + static struct option long_options[] = { + {"verbose", no_argument, 0, 'v'}, + {"silent", no_argument, 0, 's'}, + {"help", no_argument, 0, 'h'}, + {"config", required_argument, 0, 'c'}, + {"device", required_argument, 0, 'd'}, + {0, 0, 0, 0} + }; + while (1) { + int opt; + opt = getopt_long (argc, argv, "c:hd:sv", + long_options, NULL); + if (opt == -1) + break; + + switch (opt) { + case 'h': + printf(usage_note); + return 0; + case 'c': + configuration = optarg; + break; + case 'd': + device = optarg; + break; + case 's': + silent = true; + break; + case 'v': + verbose = true; + break; + default: + printf(usage_note); + return 1; + } + } + + /* create a Processor */ + if (verbose == true) { + printf("Initializing\n"); + }; + zbar_processor_t *proc = zbar_processor_create(1); + + // FIXME: Wrap all this into a function which returns an error on + // failure. And here ensure the processor is destroyed at the end. + + /* configure the Processor */ + zbar_processor_parse_config(proc, "enable"); + + /* initialize the Processor */ + if (verbose == true) { + printf("Opening video device %s\n", device); + }; + // FIXME: error handling + zbar_processor_init(proc, device, 1); + + /* enable the preview window */ + zbar_processor_set_visible(proc, 1); + zbar_processor_set_active(proc, 1); + + /* keep scanning until user provides key/mouse input */ + //zbar_processor_user_wait(proc, -1); + + // read at least one barcode (or until window closed) + if (verbose == true) { + printf("Capturing\n"); + } + int n; + n = zbar_process_one(proc, -1); + if (verbose == true) { + printf("Got %i images\n", n); + }; + // FIXME: Error handling (n = -1) + + // hide the preview window + zbar_processor_set_active(proc, 0); + zbar_processor_set_visible(proc, 0); + + // extract results + int rc = 1; + + const zbar_symbol_set_t* symbols = zbar_processor_get_results(proc); + const zbar_symbol_t* symbol = zbar_symbol_set_first_symbol(symbols); + + if (symbol != NULL) { + const char* data = zbar_symbol_get_data(symbol); + if (verbose = true) { + zbar_symbol_type_t type = + printf("Found %s \"%s\"\n", + zbar_get_symbol_name(zbar_symbol_get_type(symbol)), data); + } + /* TODO + args = ["gnunet-uri", + // FIXME: "-c", configuration, + data]; + if (verbose = true) { + // TODO: print arguments: + printf("Running `%s %s %s %s`", *args, "", ""); // FIXME variable num args + }; + rc = popen("gnunet-uri", *args); + */ + if (rc != 0) { + printf("Failed to add URI %s\n", data); + } else { + printf("Added URI %s\n", data); + } + } + + /* clean up */ + zbar_processor_destroy(proc); + + return(rc); +} diff --git a/src/util/gnunet-qr.in b/src/util/gnunet-qr.in deleted file mode 100755 index ce7a19b69..000000000 --- a/src/util/gnunet-qr.in +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# -# From curl's buildconf, making this script subject to the -# curl license: https://curl.haxx.se/docs/copyright.html -# Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. -# Copyright (C) 2019 GNUnet e.V. - -# findtool works like which without relying on which (which is a problem -# for some limited shells. -findtool(){ - file="$1" - - if { echo "$file" | grep "/" >/dev/null 2>&1; } then - # when file is given with a path check it first - if test -f "$file"; then - echo "$file" - return - fi - fi - - old_IFS=$IFS; IFS=':' - for path in $PATH - do - IFS=$old_IFS - # echo "checks for $file in $path" >&2 - if test "$path" -a "$path" != '.' -a -f "$path/$file"; then - echo "$path/$file" - return - fi - done - IFS=$old_IFS -} - -# end curl licensed code -pythonize=`findtool python2.7 2>/dev/null` -if test ! -x "$pythonize"; then - pythonize=`findtool ${PYTHON2:-python2.7}` -fi - -if test -z "$pythonize"; then - echo "ERROR: python2.7 not found." - echo " You need python2.7 installed." - exit 1 -fi - -${pythonize} @PREFIX@/share/gnunet/gnunet-qr.py $@ diff --git a/src/util/gnunet-qr.py b/src/util/gnunet-qr.py deleted file mode 100644 index 0ee0b9507..000000000 --- a/src/util/gnunet-qr.py +++ /dev/null @@ -1,110 +0,0 @@ -import sys -import getopt -import subprocess -from sys import argv -try: - import zbar -except ImportError as e: - print('Cannot run gnunet-qr, please install the zbar module.') - print('For Debian, you can obtain it as "python-zbar".') - print('Upstream: http://zbar.sourceforge.net/') - sys.exit(1) - - -def help(): - print('gnunet-qr\n\ -Scan a QR code using a video device and import\n\ -Arguments mandatory for long options are also mandatory for short options.\n\ - -c, --config FILENAME use configuration file FILENAME\n\ - -d, --device DEVICE use device DEVICE\n\ - -s, --silent do not show preview windows\n\ - -h, --help print this help\n\ - -v, --verbose be verbose\n\ -Report bugs to gnunet-developers@gnu.org.\n\ -GNUnet home page: https://gnunet.org/\n\ -General help using GNU software: https://www.gnu.org/gethelp/') - - -if __name__ == '__main__': - configuration = '' - device = '/dev/video0' - url = '' - verbose = False - silent = False - # Parse arguments - try: - opts, args = getopt.gnu_getopt(sys.argv[1:], "c:hd:sv", ["config", "help", "device", "silent", "verbose"]) - except getopt.GetoptError as e: - help() - print(str(e)) - exit(1) - for o, a in opts: - if o in ("-h", "--help"): - help() - sys.exit(0) - elif o in ("-c", "--config"): - configuration = a - elif o in ("-d", "--device"): - device = a - elif o in ("-s", "--silent"): - silent = True - elif o in ("-v", "--verbose"): - verbose = True - if (True == verbose): - print('Initializing') - # create a Processor - proc = zbar.Processor() - - # configure the Processor - proc.parse_config('enable') - - # initialize the Processor - try: - if (True == verbose): - print('Opening video device ' + device) - proc.init(device) - except Exception as e: - print('Failed to open device ' + device) - exit(1) - - # enable the preview window - # if (True == silent): - # proc.visible = True - # else: - # proc.visible = False - - proc.visible = True - # read at least one barcode (or until window closed) - try: - if (True == verbose): - print('Capturing') - proc.process_one() - except Exception as e: - # Window was closed without finding code - exit(1) - - # hide the preview window - proc.visible = False - - # extract results - for symbol in proc.results: - # do something useful with results - if (True == verbose): - print('Found ', symbol.type, ' symbol ', '"%s"' % symbol.data) - args = list() - args.append("gnunet-uri") - if (configuration != ''): - args.append(str("-c " + str(configuration))) - args.append(str(symbol.data)) - cmd = '' - for a in args: - cmd += " " + str(a) - if (verbose): - print('Running `' + cmd +'`') - res = subprocess.call(args) - if (0 != res): - print('Failed to add URI ' + str(symbol.data)) - else: - print('Added URI ' + str(symbol.data)) - exit(res) - exit(1) -- 2.25.1