From c545dffa2922d7c179910c0dcc82bbb360b63bc4 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 19 Feb 2014 23:24:57 +0100 Subject: add support for FastCGI --- .gitignore | 2 + Makefile | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- README.md | 1 + cqrlogo.c | 60 ++++++++++++++++++++++++--- 4 files changed, 170 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 7732015..f7f46a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ config.h cqrlogo +cqrlogo.cgi +cqrlogo.fcgi *.png README.html version.h diff --git a/Makefile b/Makefile index b212967..8286b06 100644 --- a/Makefile +++ b/Makefile @@ -19,10 +19,13 @@ CFLAGS += $(shell pkg-config --cflags --libs libqrencode) # a release tarball... VERSION := 0.3.6 -all: cqrlogo README.html cqrlogo.png +all: cqrlogo.cgi cqrlogo.fcgi README.html cqrlogo.png -cqrlogo: cqrlogo.c config.h version.h - $(CC) $(CFLAGS) $(LDFLAGS) -o cqrlogo cqrlogo.c +cqrlogo.cgi: cqrlogo.c config.h version.h + $(CC) $(CFLAGS) $(LDFLAGS) -DHAVE_FCGI=0 -o cqrlogo.cgi cqrlogo.c + +cqrlogo.fcgi: cqrlogo.c config.h version.h + $(CC) $(CFLAGS) $(LDFLAGS) -lfcgi -DHAVE_FCGI=1 -o cqrlogo.fcgi cqrlogo.c version.h: $(wildcard .git/HEAD .git/index .git/refs/tags/*) Makefile echo "#ifndef VERSION" > $@ @@ -35,15 +38,16 @@ config.h: README.html: README.md $(MD) README.md > README.html -cqrlogo.png: cqrlogo +cqrlogo.png: cqrlogo.cgi SERVER_NAME="github.com" HTTP_REFERER="https://github.com/eworm-de/cqrlogo" \ QUERY_STRING='scale=4' \ - ./cqrlogo | $(SED) '1,/^$$/d' > cqrlogo.png + ./cqrlogo.cgi | $(SED) '1,/^$$/d' > cqrlogo.png install: install-bin install-doc -install-bin: cqrlogo - $(INSTALL) -D -m0755 cqrlogo $(DESTDIR)$(PREFIX)/share/webapps/cqrlogo/cqrlogo +install-bin: cqrlogo.cgi cqrlogo.fcgi + $(INSTALL) -D -m0755 cqrlogo.cgi $(DESTDIR)$(PREFIX)/share/webapps/cqrlogo/cqrlogo.cgi + $(INSTALL) -D -m0755 cqrlogo.fcgi $(DESTDIR)$(PREFIX)/share/webapps/cqrlogo/cqrlogo.fcgi $(INSTALL) -D -m0644 cqrlogo.conf $(DESTDIR)/etc/cqrlogo.conf install-doc: README.html cqrlogo.png @@ -56,97 +60,184 @@ check: $(RM) -f check.png SERVER_NAME=$(SERVER) HTTP_REFERER=http://$(SERVER)/ \ - ./cqrlogo | $(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 + $(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' > \ + 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' > \ + 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=10' \ + ./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' > \ + 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' > \ + 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' > \ + 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' > \ + 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' > \ + 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' > \ + 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' > \ + 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' > \ + 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 $(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 | $(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 | $(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 | $(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=10' \ - ./cqrlogo | $(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 | $(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 | $(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 | $(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 | $(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 | $(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 | $(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 | $(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 | $(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 version.h + $(RM) -f *.o *~ *.png README.html cqrlogo.cgi cqrlogo.fcgi version.h distclean: - $(RM) -f *.o *~ *.png README.html cqrlogo version.h config.h + $(RM) -f *.o *~ *.png README.html 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/README.md b/README.md index 612ef4d..dd9fa9a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ To compile and run `cqrlogo` you need: * [libpng](http://www.libpng.org/pub/png/libpng.html) * [zlib](http://www.zlib.net/) (which is a dependency for libpng) * [qrencode](http://megaui.net/fukuchi/works/qrencode/index.en.html) +* [fcgi](http://www.fastcgi.com/) (for FastCGI support) * [markdown](http://daringfireball.net/projects/markdown/) (HTML documentation) Additionally it is expected to have `make` and `pkg-config` around to diff --git a/cqrlogo.c b/cqrlogo.c index 4121b20..1681531 100644 --- a/cqrlogo.c +++ b/cqrlogo.c @@ -16,6 +16,10 @@ #include #include +#if HAVE_FCGI +#include +#endif + #include "config.h" #include "version.h" @@ -39,6 +43,19 @@ png_text * add_png_text(png_text *pngtext, unsigned int *textcount, char *key, c } #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; @@ -76,7 +93,11 @@ int generate_png (struct bitmap_t *bitmap, const char *uri) { # endif # if PNG_ENABLE_TEXT_VERSIONS -# define VERSIONSTR VERSION " (" __DATE__ ", " __TIME__ ")" +#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(); @@ -109,7 +130,14 @@ int generate_png (struct bitmap_t *bitmap, const char *uri) { } } +#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); @@ -118,8 +146,6 @@ int generate_png (struct bitmap_t *bitmap, const char *uri) { png_free (png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(stdout); - return 0; } @@ -251,13 +277,30 @@ unsigned int get_ini_value(dictionary * ini, uint8_t type, const char * section, int main(int argc, char **argv) { dictionary * ini; const char * http_referer, * server_name, * query_string, * uri; - char * uri_server_name = NULL, * uri_png = NULL, * pattern = NULL, * stolen = NULL; + char * uri_server_name, * uri_png, * pattern, * stolen; regex_t preg; regmatch_t pmatch[1]; - uint8_t https = 0, overwrite = ALLOW_OVERWRITE; + uint8_t https, overwrite; struct bitmap_t * bitmap; - unsigned int scale = QRCODE_SCALE, border = QRCODE_BORDER, level = QRCODE_LEVEL; + unsigned int scale, border, level; + +#if HAVE_FCGI + /* loop for requests */ + while (FCGI_Accept() >= 0) { +#endif + /* do the variable initialization within the loop! */ + uri_server_name = NULL; + uri_png = NULL; + pattern = NULL; + stolen = NULL; + + https = 0; + overwrite = ALLOW_OVERWRITE; + + scale = QRCODE_SCALE; + border = QRCODE_BORDER; + level = QRCODE_LEVEL; /* check if we have environment variables from CGI */ if ((server_name = getenv("SERVER_NAME")) == NULL) { @@ -367,6 +410,11 @@ int main(int argc, char **argv) { free(uri_png); bitmap_free(bitmap); +#if HAVE_FCGI + /* end of loop */ + } +#endif + return EXIT_SUCCESS; } -- cgit v1.2.3-54-g00ecf