From f5f01f3ff143edd87b7e36f1b3540cbc5d42c51f Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 25 Feb 2014 12:12:30 +0100 Subject: build a shared library and rework parts of the code --- Makefile | 110 ++++++++++--------- config.def.h | 16 +-- cqrlogo.c | 324 ++++--------------------------------------------------- cqrlogo.h | 45 +++----- lib/.gitignore | 2 + lib/Makefile | 21 ++++ lib/libcqrlogo.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/libcqrlogo.h | 84 +++++++++++++++ 8 files changed, 496 insertions(+), 401 deletions(-) create mode 100644 lib/.gitignore create mode 100644 lib/Makefile create mode 100644 lib/libcqrlogo.c create mode 100644 lib/libcqrlogo.h diff --git a/Makefile b/Makefile index 9e29586..f46bef1 100644 --- a/Makefile +++ b/Makefile @@ -1,41 +1,46 @@ # cqrlogo - CGI QR-Code logo for web services -PREFIX := /usr -LIBDIR := $(PREFIX)/lib +# pathes +PREFIX := /usr APACHECONF := /etc/apache/conf/extra/ LIGHTTPDCONF := /etc/lighttpd/conf.d/ +# commands CC := gcc -MD := markdown -INSTALL := install CP := cp +FILE := file +GREP := grep +INSTALL := install +LN := ln +MD := markdown RM := rm -ZBARIMG := zbarimg SED := sed -GREP := grep -FILE := file +ZBARIMG := zbarimg +# flags CFLAGS += -O2 -Wall -Werror -CFLAGS += -liniparser -CFLAGS += $(shell pkg-config --cflags --libs libpng) -CFLAGS += $(shell pkg-config --cflags --libs zlib) -CFLAGS += $(shell pkg-config --cflags --libs libqrencode) +# calls to compiled binary files +CQRLOGO_CGI += LD_LIBRARY_PATH=lib/ ./cqrlogo.cgi +CQRLOGO_FCGI += LD_LIBRARY_PATH=lib/ ./cqrlogo.fcgi # this is just a fallback in case you do not use git but downloaded # a release tarball... VERSION := 0.4.0 -all: cqrlogo.cgi cqrlogo.fcgi README.html cqrlogo.png +all: libcqrlogo cqrlogo.cgi cqrlogo.fcgi README.html cqrlogo.png + +libcqrlogo: lib/libcqrlogo.c lib/libcqrlogo.h config.h version.h + $(MAKE) -C lib -cqrlogo.cgi: cqrlogo.c config.h version.h - $(CC) $(CFLAGS) $(LDFLAGS) -DHAVE_FCGI=0 -o cqrlogo.cgi cqrlogo.c +cqrlogo.cgi: libcqrlogo cqrlogo.c cqrlogo.h config.h version.h + $(CC) -lcqrlogo -Llib/ -Ilib/ $(LDFLAGS) -DHAVE_FCGI=0 -o cqrlogo.cgi cqrlogo.c -cqrlogo.fcgi: cqrlogo.c config.h version.h - $(CC) $(CFLAGS) -lfcgi $(LDFLAGS) -DHAVE_FCGI=1 -o cqrlogo.fcgi cqrlogo.c +cqrlogo.fcgi: libcqrlogo cqrlogo.c cqrlogo.h config.h version.h + $(CC) -lcqrlogo -Llib/ -Ilib/ -lfcgi $(LDFLAGS) -DHAVE_FCGI=1 -o cqrlogo.fcgi cqrlogo.c version.h: $(wildcard .git/HEAD .git/index .git/refs/tags/*) Makefile echo "#ifndef VERSION" > $@ echo "#define VERSION \"$(shell git describe --tags --long 2>/dev/null || echo ${VERSION})\"" >> $@ echo "#endif" >> $@ -config.h: +config.h: config.def.h $(CP) config.def.h config.h README.html: README.md @@ -43,21 +48,24 @@ README.html: README.md cqrlogo.png: cqrlogo.cgi SERVER_NAME="github.com" HTTP_REFERER="https://github.com/eworm-de/cqrlogo" \ - QUERY_STRING='scale=4' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > cqrlogo.png + QUERY_STRING='scale=4' \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > cqrlogo.png install: install-bin install-config install-doc -install-bin: cqrlogo.cgi cqrlogo.fcgi - $(INSTALL) -D -m0755 cqrlogo.cgi $(DESTDIR)$(LIBDIR)/cqrlogo/cqrlogo.cgi - $(INSTALL) -D -m0755 cqrlogo.fcgi $(DESTDIR)$(LIBDIR)/cqrlogo/cqrlogo.fcgi +install-bin: libcqrlogo lib/libcqrlogo.h cqrlogo.cgi cqrlogo.fcgi cqrlogo.conf + $(INSTALL) -D -m0755 lib/libcqrlogo.so.$(SOVERSION) $(DESTDIR)$(PREFIX)/lib/libcqrlogo.so.$(SOVERSION) + $(INSTALL) -D -m0755 lib/libcqrlogo.h $(DESTDIR)$(PREFIX)/include/libcqrlogo.h + $(LN) -sf libcqrlogo.so.$(SOVERSION) $(DESTDIR)$(PREFIX)/lib/libcqrlogo.so + $(INSTALL) -D -m0755 cqrlogo.cgi $(DESTDIR)$(PREFIX)/lib/cqrlogo/cqrlogo.cgi + $(INSTALL) -D -m0755 cqrlogo.fcgi $(DESTDIR)$(PREFIX)/lib/cqrlogo/cqrlogo.fcgi $(INSTALL) -D -m0644 cqrlogo.conf $(DESTDIR)/etc/cqrlogo.conf install-config: config/apache.conf config/lighttpd.conf $(INSTALL) -D -m0644 config/apache.conf $(DESTDIR)$(APACHECONF)/cqrlogo.conf $(INSTALL) -D -m0644 config/lighttpd.conf $(DESTDIR)$(LIGHTTPDCONF)/cqrlogo.conf -install-doc: README.html cqrlogo.png +install-doc: README.md README.html cqrlogo.png $(INSTALL) -D -m0644 README.md $(DESTDIR)$(PREFIX)/share/doc/cqrlogo/README.md $(INSTALL) -D -m0644 README.html $(DESTDIR)$(PREFIX)/share/doc/cqrlogo/README.html $(INSTALL) -D -m0644 cqrlogo.png $(DESTDIR)$(PREFIX)/share/doc/cqrlogo/cqrlogo.png @@ -67,184 +75,184 @@ check: $(RM) -f check.png SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > check.png + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=https://$(SERVER)/ HTTPS=on \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > check.png + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^https://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=0' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=4' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=20' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=0' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=2' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10&level=0' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10&level=2' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10&level=4' \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=eworm.net HTTP_REFERER=http://$(SERVER)/ \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | \ $(GREP) -e '^This QR Code has been stolen from http://eworm.net/!$$' SERVER_NAME=eworm.net HTTP_REFERER=https://$(SERVER)/ HTTPS=on \ - ./cqrlogo.cgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_CGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | \ $(GREP) -e '^This QR Code has been stolen from https://eworm.net/!$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > check.png + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=https://$(SERVER)/ HTTPS=on \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > check.png + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^https://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=0' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=4' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=20' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=0' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=2' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10&level=0' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10&level=2' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ QUERY_STRING='scale=2&border=10&level=4' \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | $(GREP) -e '^http://$(SERVER)/$$' SERVER_NAME=eworm.net HTTP_REFERER=http://$(SERVER)/ \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | \ $(GREP) -e '^This QR Code has been stolen from http://eworm.net/!$$' SERVER_NAME=eworm.net HTTP_REFERER=https://$(SERVER)/ HTTPS=on \ - ./cqrlogo.fcgi | $(SED) '1,/^$$/d' > \ + $(CQRLOGO_FCGI) | $(SED) '1,/^$$/d' > \ check.png $(FILE) check.png | $(GREP) 'PNG image data' $(ZBARIMG) --raw -q check.png | \ $(GREP) -e '^This QR Code has been stolen from https://eworm.net/!$$' clean: - $(RM) -f *.o *~ *.png README.html cqrlogo.cgi cqrlogo.fcgi version.h + $(RM) -f *.o *~ *.png README.html lib/libcqrlogo.so lib/libcqrlogo.so.* cqrlogo.cgi cqrlogo.fcgi version.h distclean: - $(RM) -f *.o *~ *.png README.html cqrlogo.cgi cqrlogo.fcgi version.h config.h + $(RM) -f *.o *~ *.png README.html lib/libcqrlogo.so lib/libcqrlogo.so.* cqrlogo.cgi cqrlogo.fcgi version.h config.h release: git archive --format=tar.xz --prefix=cqrlogo-$(VERSION)/ $(VERSION) > cqrlogo-$(VERSION).tar.xz diff --git a/config.def.h b/config.def.h index 1ac13c4..dc789d4 100644 --- a/config.def.h +++ b/config.def.h @@ -9,11 +9,11 @@ #define _CONFIG_H /* path to the config file */ -#define CONFIGFILE "/etc/cqrlogo.conf" +#define CONFIGFILE "/etc/cqrlogo.conf" /* whether or not defaults or settings from config may be overwritten * by query string */ -#define ALLOW_OVERWRITE 1 +#define ALLOW_OVERWRITE 1 /* pixels are scaled up by this factor */ #define QRCODE_SCALE 2 @@ -32,20 +32,10 @@ * QR_ECLEVEL_Q (about 25%) * QR_ECLEVEL_H (highest, about 30%) * image size raises with higher levels */ -#define QRCODE_LEVEL QR_ECLEVEL_L +#define QRCODE_LEVEL QR_ECLEVEL_L /* note that changing the level at runtime requies * a numeric value from 0 to 3 */ -/* if you really, really, really want to save some bytes... - * It is possible to disable text information in PNG file completly, though - * nobody will have an idea where you got this great software... - * So please do not. */ -#define PNG_ENABLE_TEXT 1 -/* do you want version information within the PNG file? */ -#define PNG_ENABLE_TEXT_VERSIONS 1 -/* add referer information to the PNG file? */ -#define PNG_ENABLE_TEXT_REFERER 1 - #endif /* _CONFIG_H */ // vim: set syntax=c: diff --git a/cqrlogo.c b/cqrlogo.c index 1681531..4b87371 100644 --- a/cqrlogo.c +++ b/cqrlogo.c @@ -5,285 +5,22 @@ * of the GNU General Public License, incorporated herein by reference. */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if HAVE_FCGI -#include -#endif - #include "config.h" #include "version.h" -/* define structs and functions */ #include "cqrlogo.h" -#define URLPATTERN "^[hH][tT][tT][pP][sS]\\?://%s/" -#define TEXTSTOLEN "This QR Code has been stolen from http%s://%s/!" - -#if defined PNG_TEXT_SUPPORTED && PNG_ENABLE_TEXT -/*** add_png_text ***/ -png_text * add_png_text(png_text *pngtext, unsigned int *textcount, char *key, char *text) { - pngtext = realloc(pngtext, ((*textcount) + 1) * sizeof(png_text)); - - pngtext[*textcount].compression = PNG_TEXT_COMPRESSION_zTXt; - pngtext[*textcount].key = key; - pngtext[*textcount].text = text; - - (*textcount)++; - return pngtext; -} -#endif - -#if HAVE_FCGI -/*** png_write_stdout ***/ -void png_write_stdout(png_structp png_ptr, png_bytep data, png_size_t length) { - if (length != fwrite(data, 1, length, png_get_io_ptr(png_ptr))) - png_error(png_ptr, "Write Error"); -} - -/*** png_flush_stdout ***/ -void png_flush_stdout(png_structp png_ptr) { - fflush(stdout); -} -#endif - -/*** generate_png ***/ -int generate_png (struct bitmap_t *bitmap, const char *uri) { - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - png_byte ** row_pointers = NULL; - unsigned int x, y; - uint8_t bit, byte; - - if ((png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) - return 1; - - if ((info_ptr = png_create_info_struct (png_ptr)) == NULL || - (setjmp (png_jmpbuf (png_ptr)))) { - png_destroy_write_struct (&png_ptr, &info_ptr); - return 1; - } - - png_set_IHDR (png_ptr, info_ptr, bitmap->width, bitmap->height, 1 /* depth */, - PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - /* use best compression */ - png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); - - /* use compression strategy filtered - * this way pngcrush can not optimize any more */ - png_set_compression_strategy(png_ptr, Z_FILTERED); - -#if defined PNG_TEXT_SUPPORTED && PNG_ENABLE_TEXT - unsigned int textcount = 0; - png_text *pngtext = NULL; - - pngtext = add_png_text(pngtext, &textcount, "comment", "QR-Code created by cqrlogo - https://github.com/eworm-de/cqrlogo"); -# if PNG_ENABLE_TEXT_REFERER - pngtext = add_png_text(pngtext, &textcount, "referer", (char *)uri); -# endif - -# if PNG_ENABLE_TEXT_VERSIONS -#if HAVE_FCGI -# define VERSIONSTR VERSION " (FastCGI) (" __DATE__ ", " __TIME__ ")" -#else -# define VERSIONSTR VERSION " (CGI) (" __DATE__ ", " __TIME__ ")" -#endif -# define LIBSSTR "libqrencode %s, libpng %s, zlib %s" - char *libsstr, *qrver = QRcode_APIVersionString(); - - libsstr = malloc(sizeof(LIBSSTR) + strlen(qrver) + strlen(png_libpng_ver) + strlen(zlib_version)); - sprintf(libsstr, LIBSSTR, qrver, png_libpng_ver, zlib_version); - - pngtext = add_png_text(pngtext, &textcount, "version", VERSIONSTR); - pngtext = add_png_text(pngtext, &textcount, "libs", libsstr); -# endif - - png_set_text(png_ptr, info_ptr, pngtext, textcount); - png_free (png_ptr, pngtext); -# if PNG_ENABLE_TEXT_VERSIONS - free(libsstr); -# endif -#endif - - row_pointers = png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); - for (y = 0; y < bitmap->height; ++y) { - /* we need to round up, need a complete byte for less than eight bits */ - row_pointers[y] = png_malloc (png_ptr, (sizeof(uint8_t) * bitmap->width + 7) / 8); - for (x = 0; x < bitmap->width; ++x) { - /* bit are written in reverse order! */ - bit = 7 - (x % 8); - byte = x / 8; - if (bitmap->pixel[y * bitmap->width + x]) - row_pointers[y][byte] |= 1 << (bit); - else - row_pointers[y][byte] &= ~(1 << (bit)); - } - } - -#if HAVE_FCGI - /* with fastcgi we can not just open stdout for writing... - * define a write function instead */ - png_set_write_fn(png_ptr, (png_voidp)stdout, png_write_stdout, png_flush_stdout); -#else - png_init_io (png_ptr, stdout); -#endif - - png_set_rows (png_ptr, info_ptr, row_pointers); - png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - for (y = 0; y < bitmap->height; ++y) - png_free (png_ptr, row_pointers[y]); - png_free (png_ptr, row_pointers); - png_destroy_write_struct(&png_ptr, &info_ptr); - - return 0; -} - -/*** bitmap_new ***/ -struct bitmap_t * bitmap_new(int width, int height) { - struct bitmap_t *bitmap; - - if ((bitmap = malloc(sizeof(struct bitmap_t))) == NULL) - return NULL; - - bitmap->width = width; - bitmap->height = height; - if ((bitmap->pixel = malloc(width * height * sizeof(uint8_t))) == NULL) { - free(bitmap); - return NULL; - } - - /* initialize with white */ - memset(bitmap->pixel, 0xff, width * height); - - return bitmap; -} - -/*** bitmap_free ***/ -void bitmap_free(struct bitmap_t * bitmap) { - free(bitmap->pixel); - free(bitmap); -} - -/*** encode_qrcode ***/ -struct bitmap_t * encode_qrcode (const char *text, unsigned int scale, - unsigned int border, unsigned int level) { - QRcode *qrcode; - struct bitmap_t *bitmap, *scaled; - int i, j, k, l; - unsigned char *data; - - qrcode = QRcode_encodeString8bit(text, 0, level); - - /* this happens if the string is too long - * possibly we have an URL (referer) that is too long, so the code - * automatically falls back to http_server (see main()) */ - if (qrcode == NULL) - return NULL; - - data = qrcode->data; - - /* wirte QR code to bitmap */ - if ((bitmap = bitmap_new(qrcode->width + border * 2, qrcode->width + border * 2)) == NULL) - return NULL; - for (i = border; i < qrcode->width + border; i++) - for (j = border; j < qrcode->width + border; j++) { - bitmap->pixel[i * (qrcode->width + border * 2) + j] = !(*data & 0x1) * 0xff; - data++; - } - - QRcode_free(qrcode); - - if (scale == 1) - return bitmap; - - /* scale bitmap */ - if ((scaled = bitmap_new(bitmap->width * scale, bitmap->height * scale)) == NULL) - return NULL; - for (i = 0; i < bitmap->height; i++) - for (j = 0; j < bitmap->width; j++) - for (k = 0; k < scale; k++) - for (l = 0; l < scale; l++) - scaled->pixel[i * bitmap->width * scale * scale + k * bitmap->width * scale + j * scale + l] = - bitmap->pixel[i * bitmap->width + j]; - - - bitmap_free(bitmap); - - return scaled; -} - -/*** get_query_value ***/ -unsigned int get_query_value(const char *query_string, const char *pattern, - unsigned int value, unsigned int min, unsigned int max) { - char *match = NULL, *newpattern = NULL; - unsigned int length; - int tmp = -1; - - newpattern = strdup(pattern); - - length = strlen(newpattern); - /* length is without null termination, allocacte 4 bytes so we - * have "=", "%u" and null termination */ - newpattern = realloc(newpattern, length + 4); - sprintf(newpattern + length, "="); - - if ((match = strstr(query_string, newpattern)) != NULL) { - sprintf(newpattern + length + 1, "%%u"); - - if ((sscanf(match, newpattern, &tmp)) > 0) - if (tmp >= min && tmp <= max) - value = tmp; - } - - free(newpattern); - - return value; -} - -/*** get_ini_value ***/ -unsigned int get_ini_value(dictionary * ini, uint8_t type, const char * section, const char * parameter, - unsigned int value, unsigned int min, unsigned int max) { - char * key; - unsigned int tmp; - - key = malloc(strlen(section) + strlen(parameter) + 2); - sprintf(key, "%s:%s", section, parameter); - - if (type) - tmp = iniparser_getint(ini, key, value); - else - tmp = iniparser_getboolean(ini, key, value); - - if (tmp >= min && tmp <= max) - value = tmp; - - free(key); - - return value; -} - /*** main ***/ int main(int argc, char **argv) { - dictionary * ini; const char * http_referer, * server_name, * query_string, * uri; char * uri_server_name, * uri_png, * pattern, * stolen; regex_t preg; regmatch_t pmatch[1]; - uint8_t https, overwrite; + uint8_t https; + struct png_t * png; struct bitmap_t * bitmap; - unsigned int scale, border, level; + struct cqrconf_t cqrconf; #if HAVE_FCGI /* loop for requests */ @@ -296,11 +33,12 @@ int main(int argc, char **argv) { stolen = NULL; https = 0; - overwrite = ALLOW_OVERWRITE; - scale = QRCODE_SCALE; - border = QRCODE_BORDER; - level = QRCODE_LEVEL; + /* these default values are defined in config.h */ + cqrconf.scale = QRCODE_SCALE; + cqrconf.border = QRCODE_BORDER; + cqrconf.level = QRCODE_LEVEL; + cqrconf.overwrite = ALLOW_OVERWRITE; /* check if we have environment variables from CGI */ if ((server_name = getenv("SERVER_NAME")) == NULL) { @@ -344,42 +82,14 @@ int main(int argc, char **argv) { uri = uri_server_name; } - /* parse config file */ - if ((ini = iniparser_load(CONFIGFILE)) == NULL) { - fprintf(stderr, "cannot parse file " CONFIGFILE ", continue anyway\n"); - /* continue anyway, there is nothing essential in the config file */ - } else { - scale = get_ini_value(ini, 1, "general", "scale", scale, 1, QRCODE_MAX_SCALE); - border = get_ini_value(ini, 1, "general", "border", border, 0, QRCODE_MAX_BORDER); - level = get_ini_value(ini, 1, "general", "level", level, QR_ECLEVEL_L, QR_ECLEVEL_H); - overwrite = get_ini_value(ini, 0, "general", "allow overwrite", overwrite, 0, 1); - - scale = get_ini_value(ini, 1, server_name, "scale", scale, 1, QRCODE_MAX_SCALE); - border = get_ini_value(ini, 1, server_name, "border", border, 0, QRCODE_MAX_BORDER); - level = get_ini_value(ini, 1, server_name, "level", level, QR_ECLEVEL_L, QR_ECLEVEL_H); - overwrite = get_ini_value(ini, 0, server_name, "allow overwrite", overwrite, 0, 1); - - /* done reading config file, free */ - iniparser_freedict(ini); - } - - /* get query string and read settings */ - if (overwrite && (query_string = getenv("QUERY_STRING")) != NULL) { - /* do we have a special scale? */ - scale = get_query_value(query_string, "scale", scale, 1, QRCODE_MAX_SCALE); - - /* width of the border? */ - border = get_query_value(query_string, "border", border, 0, QRCODE_MAX_BORDER); - - /* error correction level? */ - level = get_query_value(query_string, "level", level, QR_ECLEVEL_L, QR_ECLEVEL_H); - } + cqrconf_file(server_name, &cqrconf); + cqrconf_string(getenv("QUERY_STRING"), &cqrconf); /* encode the QR-Code */ - if ((bitmap = encode_qrcode(uri, scale, border, level)) == NULL) { + if ((bitmap = encode_qrcode(uri, cqrconf)) == NULL) { /* uri too long? retry with uri from server name */ uri = uri_server_name; - if ((bitmap = encode_qrcode(uri, scale, border, level)) == NULL) { + if ((bitmap = encode_qrcode(uri, cqrconf)) == NULL) { fprintf(stderr, "Could not generate QR-Code.\n"); return EXIT_FAILURE; } @@ -395,12 +105,15 @@ int main(int argc, char **argv) { uri = uri_png; } - /* print PNG data */ - if (generate_png(bitmap, uri)) { + /* generate PNG data */ + if ((png = generate_png(bitmap, CQR_COMMENT|CQR_REFERER|CQR_VERSION|CQR_LIBVERSION, uri)) == NULL) { fprintf(stderr, "Failed to generate PNG.\n"); return EXIT_FAILURE; } + /* write PNG data to stdout */ + fwrite(png->buffer, png->size, 1, stdout); + /* free memory we no longer need */ if (uri_server_name) free(uri_server_name); @@ -409,6 +122,9 @@ int main(int argc, char **argv) { if (uri_png) free(uri_png); bitmap_free(bitmap); + if (png->size > 0) + free(png->buffer); + free(png); #if HAVE_FCGI /* end of loop */ diff --git a/cqrlogo.h b/cqrlogo.h index d14050d..00795b9 100644 --- a/cqrlogo.h +++ b/cqrlogo.h @@ -8,45 +8,24 @@ #ifndef _CQRLOGO_H #define _CQRLOGO_H -/* a bitmap */ -struct bitmap_t { - unsigned int width; - unsigned int height; - uint8_t *pixel; -}; - -#if defined PNG_TEXT_SUPPORTED && PNG_ENABLE_TEXT -/*** add_png_text ***/ -png_text * add_png_text(png_text *pngtext, unsigned int *textcount, char *key, char *text); -#endif +#include +#include +#include +#include +#include +#include #if HAVE_FCGI -/*** png_write_stdout ***/ -void png_write_stdout(png_structp png_ptr, png_bytep data, png_size_t length); - -/*** png_flush_stdout ***/ -void png_flush_stdout(png_structp png_ptr); +#include #endif -/*** generate_png ***/ -int generate_png (struct bitmap_t *bitmap, const char *uri); - -/*** bitmap_new ***/ -struct bitmap_t * bitmap_new(int width, int height); -/*** bitmap_free ***/ -void bitmap_free(struct bitmap_t * bitmap); - -/*** encode_qrcode ***/ -struct bitmap_t * encode_qrcode (const char *text, unsigned int scale, - unsigned int border, unsigned int level); +#include -/*** get_query_value ***/ -unsigned int get_query_value(const char *query_string, const char *pattern, - unsigned int value, unsigned int min, unsigned int max); +#define URLPATTERN "^[hH][tT][tT][pP][sS]\\?://%s/" +#define TEXTSTOLEN "This QR Code has been stolen from http%s://%s/!" -/*** get_ini_value ***/ -unsigned int get_ini_value(dictionary * ini, uint8_t type, const char * section, const char * parameter, - unsigned int value, unsigned int min, unsigned int max); +/*** main ***/ +int main(int argc, char **argv); #endif /* _CQRLOGO_H */ diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..6842a0a --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,2 @@ +libcqrlogo.so +libcqrlogo.so.* diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..47f4db7 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,21 @@ +# cqrlogo - CGI QR-Code logo for web services + +CC := gcc +LN := ln +CFLAGS += -O2 -Wall -Werror +CFLAGS += -liniparser +CFLAGS += $(shell pkg-config --cflags --libs libpng) +CFLAGS += $(shell pkg-config --cflags --libs zlib) +CFLAGS += $(shell pkg-config --cflags --libs libqrencode) + +# library abi version +SOVERSION := 0 + +all: libcqrlogo + +libcqrlogo: libcqrlogo.c libcqrlogo.h ../config.h ../version.h + $(CC) $(CFLAGS) $(LDFLAGS) -shared -fPIC -Wl,-soname,libcqrlogo.so.$(SOVERSION) -o libcqrlogo.so.$(SOVERSION) libcqrlogo.c + $(LN) -sf libcqrlogo.so.$(SOVERSION) libcqrlogo.so + +clean: + $(RM) -f *.o *~ libcqrlogo.so libcqrlogo.so.* diff --git a/lib/libcqrlogo.c b/lib/libcqrlogo.c new file mode 100644 index 0000000..aca5cb5 --- /dev/null +++ b/lib/libcqrlogo.c @@ -0,0 +1,295 @@ +/* + * (C) 2013-2014 by Christian Hesse + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include "../config.h" +#include "../version.h" + +/* define structs and functions */ +#include "libcqrlogo.h" + +/*** png_write_stdout ***/ +void png_write_fn(png_structp png_ptr, png_bytep data, png_size_t length) { + struct png_t * png; + + png = (struct png_t *)png_get_io_ptr(png_ptr); + + png->buffer = realloc(png->buffer, png->size + length); + + memcpy(png->buffer + png->size, data, length); + + png->size += length; +} + +#if defined PNG_TEXT_SUPPORTED +/*** add_png_text ***/ +png_text * add_png_text(png_text *pngtext, unsigned int *textcount, char *key, char *text) { + pngtext = realloc(pngtext, ((*textcount) + 1) * sizeof(png_text)); + + pngtext[*textcount].compression = PNG_TEXT_COMPRESSION_zTXt; + pngtext[*textcount].key = key; + pngtext[*textcount].text = text; + + (*textcount)++; + return pngtext; +} +#endif + +/*** generate_png ***/ +struct png_t * generate_png (struct bitmap_t *bitmap, const uint8_t meta, const char *uri) { + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_byte ** row_pointers = NULL; + unsigned int x, y; + uint8_t bit, byte; + struct png_t * png; + + png = malloc(sizeof(struct png_t)); + png->buffer = NULL; + png->size = 0; + + if ((png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) + return NULL; + + if ((info_ptr = png_create_info_struct (png_ptr)) == NULL || + (setjmp (png_jmpbuf (png_ptr)))) { + png_destroy_write_struct (&png_ptr, &info_ptr); + return NULL; + } + + png_set_IHDR (png_ptr, info_ptr, bitmap->width, bitmap->height, 1 /* depth */, + PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + /* use best compression */ + png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + + /* use compression strategy filtered + * this way pngcrush can not optimize any more */ + png_set_compression_strategy(png_ptr, Z_FILTERED); + +#if defined PNG_TEXT_SUPPORTED + unsigned int textcount = 0; + png_text *pngtext = NULL; + char *libsstr = NULL, *qrver; + + if (meta & CQR_COMMENT) + pngtext = add_png_text(pngtext, &textcount, "comment", "QR-Code created by cqrlogo - https://github.com/eworm-de/cqrlogo"); + + if (meta & CQR_REFERER) + pngtext = add_png_text(pngtext, &textcount, "referer", (char *)uri); + + if (meta & CQR_VERSION) + pngtext = add_png_text(pngtext, &textcount, "version", VERSIONSTR); + + if (meta & CQR_LIBVERSION) { + qrver = QRcode_APIVersionString(); + + libsstr = malloc(sizeof(LIBSSTR) + strlen(qrver) + strlen(png_libpng_ver) + strlen(zlib_version)); + sprintf(libsstr, LIBSSTR, qrver, png_libpng_ver, zlib_version); + + pngtext = add_png_text(pngtext, &textcount, "libs", libsstr); + } + + png_set_text(png_ptr, info_ptr, pngtext, textcount); + png_free (png_ptr, pngtext); + if (libsstr) + free(libsstr); +#endif + + row_pointers = png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); + for (y = 0; y < bitmap->height; ++y) { + /* we need to round up, need a complete byte for less than eight bits */ + row_pointers[y] = png_malloc (png_ptr, (sizeof(uint8_t) * bitmap->width + 7) / 8); + for (x = 0; x < bitmap->width; ++x) { + /* bit are written in reverse order! */ + bit = 7 - (x % 8); + byte = x / 8; + if (bitmap->pixel[y * bitmap->width + x]) + row_pointers[y][byte] |= 1 << (bit); + else + row_pointers[y][byte] &= ~(1 << (bit)); + } + } + + /* with FastCGI we can not just open stdout for writing... + * define a write function instead */ + png_set_write_fn(png_ptr, png, png_write_fn, NULL); + + png_set_rows (png_ptr, info_ptr, row_pointers); + png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + + for (y = 0; y < bitmap->height; ++y) + png_free (png_ptr, row_pointers[y]); + png_free (png_ptr, row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + + return png; +} + +/*** bitmap_new ***/ +struct bitmap_t * bitmap_new(int width, int height) { + struct bitmap_t *bitmap; + + if ((bitmap = malloc(sizeof(struct bitmap_t))) == NULL) + return NULL; + + bitmap->width = width; + bitmap->height = height; + if ((bitmap->pixel = malloc(width * height * sizeof(uint8_t))) == NULL) { + free(bitmap); + return NULL; + } + + /* initialize with white */ + memset(bitmap->pixel, 0xff, width * height); + + return bitmap; +} + +/*** bitmap_free ***/ +void bitmap_free(struct bitmap_t * bitmap) { + free(bitmap->pixel); + free(bitmap); +} + +/*** encode_qrcode ***/ +struct bitmap_t * encode_qrcode (const char *text, const struct cqrconf_t cqrconf) { + QRcode *qrcode; + struct bitmap_t *bitmap, *scaled; + int i, j, k, l; + unsigned char *data; + + qrcode = QRcode_encodeString8bit(text, 0, cqrconf.level); + + /* this happens if the string is too long + * possibly we have an URL (referer) that is too long, so the code + * automatically falls back to http_server (see main()) */ + if (qrcode == NULL) + return NULL; + + data = qrcode->data; + + /* wirte QR code to bitmap */ + if ((bitmap = bitmap_new(qrcode->width + cqrconf.border * 2, qrcode->width + cqrconf.border * 2)) == NULL) + return NULL; + for (i = cqrconf.border; i < qrcode->width + cqrconf.border; i++) + for (j = cqrconf.border; j < qrcode->width + cqrconf.border; j++) { + bitmap->pixel[i * (qrcode->width + cqrconf.border * 2) + j] = !(*data & 0x1) * 0xff; + data++; + } + + QRcode_free(qrcode); + + if (cqrconf.scale == 1) + return bitmap; + + /* cqrconf.scale bitmap */ + if ((scaled = bitmap_new(bitmap->width * cqrconf.scale, bitmap->height * cqrconf.scale)) == NULL) + return NULL; + for (i = 0; i < bitmap->height; i++) + for (j = 0; j < bitmap->width; j++) + for (k = 0; k < cqrconf.scale; k++) + for (l = 0; l < cqrconf.scale; l++) + scaled->pixel[i * bitmap->width * cqrconf.scale * cqrconf.scale + k * bitmap->width * cqrconf.scale + j * cqrconf.scale + l] = + bitmap->pixel[i * bitmap->width + j]; + + + bitmap_free(bitmap); + + return scaled; +} + +/*** get_query_value ***/ +unsigned int get_query_value(const char *query_string, const char *pattern, + unsigned int value, unsigned int min, unsigned int max) { + char *match = NULL, *newpattern = NULL; + unsigned int length; + int tmp = -1; + + newpattern = strdup(pattern); + + length = strlen(newpattern); + /* length is without null termination, allocacte 4 bytes so we + * have "=", "%u" and null termination */ + newpattern = realloc(newpattern, length + 4); + sprintf(newpattern + length, "="); + + if ((match = strstr(query_string, newpattern)) != NULL) { + sprintf(newpattern + length + 1, "%%u"); + + if ((sscanf(match, newpattern, &tmp)) > 0) + if (tmp >= min && tmp <= max) + value = tmp; + } + + free(newpattern); + + return value; +} + +/*** get_ini_value ***/ +unsigned int get_ini_value(dictionary * ini, uint8_t type, const char * section, const char * parameter, + unsigned int value, unsigned int min, unsigned int max) { + char * key; + unsigned int tmp; + + key = malloc(strlen(section) + strlen(parameter) + 2); + sprintf(key, "%s:%s", section, parameter); + + if (type) + tmp = iniparser_getint(ini, key, value); + else + tmp = iniparser_getboolean(ini, key, value); + + if (tmp >= min && tmp <= max) + value = tmp; + + free(key); + + return value; +} + +/*** cqrconf_file ***/ +void cqrconf_file(const char * server_name, struct cqrconf_t * cqrconf) { + dictionary * ini; + + /* parse config file */ + if ((ini = iniparser_load(CONFIGFILE)) == NULL) { + fprintf(stderr, "cannot parse file " CONFIGFILE ", continue anyway\n"); + return; + } + + cqrconf->scale = get_ini_value(ini, 1, "general", "scale", cqrconf->scale, 1, QRCODE_MAX_SCALE); + cqrconf->border = get_ini_value(ini, 1, "general", "border", cqrconf->border, 0, QRCODE_MAX_BORDER); + cqrconf->level = get_ini_value(ini, 1, "general", "level", cqrconf->level, QR_ECLEVEL_L, QR_ECLEVEL_H); + cqrconf->overwrite = get_ini_value(ini, 0, "general", "allow overwrite", cqrconf->overwrite, false, true); + + cqrconf->scale = get_ini_value(ini, 1, server_name, "scale", cqrconf->scale, 1, QRCODE_MAX_SCALE); + cqrconf->border = get_ini_value(ini, 1, server_name, "border", cqrconf->border, 0, QRCODE_MAX_BORDER); + cqrconf->level = get_ini_value(ini, 1, server_name, "level", cqrconf->level, QR_ECLEVEL_L, QR_ECLEVEL_H); + cqrconf->overwrite = get_ini_value(ini, 0, server_name, "allow overwrite", cqrconf->overwrite, false, true); + + /* done reading config file, free */ + iniparser_freedict(ini); +} + +/*** cqrconf_string ***/ +void cqrconf_string(const char * query_string, struct cqrconf_t * cqrconf) { + if (cqrconf->overwrite == false) + return; + + if (query_string == NULL) + return; + + /* do we have a special scale? */ + cqrconf->scale = get_query_value(query_string, "scale", cqrconf->scale, 1, QRCODE_MAX_SCALE); + + /* width of the border? */ + cqrconf->border = get_query_value(query_string, "border", cqrconf->border, 0, QRCODE_MAX_BORDER); + + /* error correction level? */ + cqrconf->level = get_query_value(query_string, "level", cqrconf->level, QR_ECLEVEL_L, QR_ECLEVEL_H); +} diff --git a/lib/libcqrlogo.h b/lib/libcqrlogo.h new file mode 100644 index 0000000..8ce04f2 --- /dev/null +++ b/lib/libcqrlogo.h @@ -0,0 +1,84 @@ +/* + * (C) 2013-2014 by Christian Hesse + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#ifndef _LIBCQRLOGO_H +#define _LIBCQRLOGO_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* a bitmap */ +struct bitmap_t { + unsigned int width; + unsigned int height; + uint8_t *pixel; +}; + +/* finished PNG image */ +struct png_t { + unsigned char * buffer; + size_t size; +}; + +/* config */ +struct cqrconf_t { + uint8_t scale; + uint8_t border; + uint8_t level; + bool overwrite; +}; + +#define CQR_COMMENT 0x1 +#define CQR_REFERER 0x2 +#define CQR_VERSION 0x4 +#define CQR_LIBVERSION 0x8 + +#define VERSIONSTR VERSION " (" __DATE__ ", " __TIME__ ")" +#define LIBSSTR "libqrencode %s, libpng %s, zlib %s" + +/*** png_write_stdout ***/ +void png_write_fn(png_structp png_ptr, png_bytep data, png_size_t length); + +#if defined PNG_TEXT_SUPPORTED +/*** add_png_text ***/ +png_text * add_png_text(png_text *pngtext, unsigned int *textcount, char *key, char *text); +#endif + +/*** generate_png ***/ +struct png_t * generate_png (struct bitmap_t *bitmap, const uint8_t meta, const char *uri); + +/*** bitmap_new ***/ +struct bitmap_t * bitmap_new(int width, int height); +/*** bitmap_free ***/ +void bitmap_free(struct bitmap_t * bitmap); + +/*** encode_qrcode ***/ +struct bitmap_t * encode_qrcode (const char *text, const struct cqrconf_t); + +/*** get_query_value ***/ +unsigned int get_query_value(const char *query_string, const char *pattern, + unsigned int value, unsigned int min, unsigned int max); +/*** get_ini_value ***/ +unsigned int get_ini_value(dictionary * ini, uint8_t type, const char * section, const char * parameter, + unsigned int value, unsigned int min, unsigned int max); + +/*** cqrconf_file ***/ +void cqrconf_file(const char * server_name, struct cqrconf_t * cqrconf); +/*** cqrconf_string ***/ +void cqrconf_string(const char * query_string, struct cqrconf_t * cqrconf); + +#endif /* _LIBCQRLOGO_H */ + +// vim: set syntax=c: -- cgit v1.2.3-54-g00ecf