aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christian Hesse <mail@eworm.de>2014-02-25 12:12:30 +0100
committerGravatar Christian Hesse <mail@eworm.de>2014-02-25 12:12:30 +0100
commitf5f01f3ff143edd87b7e36f1b3540cbc5d42c51f (patch)
tree5c2b6f5dbbb342ccc5ba770fd4bb4f73c151c246
parent0f32341ead4f1534270a82c4372d84a1aaa9b0cd (diff)
downloadcqrlogo-f5f01f3ff143edd87b7e36f1b3540cbc5d42c51f.tar.gz
cqrlogo-f5f01f3ff143edd87b7e36f1b3540cbc5d42c51f.tar.zst
build a shared library and rework parts of the code
-rw-r--r--Makefile110
-rw-r--r--config.def.h16
-rw-r--r--cqrlogo.c324
-rw-r--r--cqrlogo.h45
-rw-r--r--lib/.gitignore2
-rw-r--r--lib/Makefile21
-rw-r--r--lib/libcqrlogo.c295
-rw-r--r--lib/libcqrlogo.h84
8 files changed, 496 insertions, 401 deletions
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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-#include <regex.h>
-
-#include <iniparser.h>
-#include <png.h>
-#include <zlib.h>
-#include <qrencode.h>
-
-#if HAVE_FCGI
-#include <fcgi_stdio.h>
-#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <regex.h>
+#include <stdbool.h>
#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 <fcgi_stdio.h>
#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 <libcqrlogo.h>
-/*** 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 <mail@eworm.de>
+ *
+ * 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 <mail@eworm.de>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <png.h>
+#include <zlib.h>
+#include <qrencode.h>
+#include <iniparser.h>
+
+/* 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: