1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/*
* (C) 2013 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <qrencode.h>
#define QRCODE_SCALE 2
GdkPixbuf * encode_qrcode (char *text) {
QRcode *qrcode;
GdkPixbuf *pixbuf, *pixbuf_scaled;
int i, j, k, rowstride, channels;
gchar *pixel;
unsigned char *data;
qrcode = QRcode_encodeData(strlen(text), text, 0, QR_ECLEVEL_L);
if (qrcode == NULL)
return NULL;
data = qrcode->data;
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, qrcode->width + 2, qrcode->width + 2);
pixel = gdk_pixbuf_get_pixels (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
channels = gdk_pixbuf_get_n_channels (pixbuf);
gdk_pixbuf_fill(pixbuf, 0xffffffff);
for (i = 1; i <= qrcode->width; i++)
for (j = 1; j <= qrcode->width; j++) {
for (k = 0; k < channels; k++)
pixel[i * rowstride + j * channels + k] = !(*data & 0x1) * 0xff;
data++;
}
pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf,
(qrcode->width + 2) * QRCODE_SCALE,
(qrcode->width + 2) * QRCODE_SCALE,
GDK_INTERP_NEAREST);
QRcode_free(qrcode);
g_object_unref(pixbuf);
return pixbuf_scaled;
}
int main(int argc, char **argv) {
char * http_referer, * server_name, * pattern;
regex_t preg;
size_t nmatch = 1;
regmatch_t pmatch[1];
int rc;
GdkPixbuf *pixbuf;
gchar *buffer;
gsize size;
/* check if we have environment variables from CGI */
if ((http_referer = getenv("HTTP_REFERER")) == NULL ||
(server_name = getenv("SERVER_NAME")) == NULL) {
fprintf(stderr, "This is a CGI executable. Running without a web service is not supported.\n"
"Note that HTTP_REFERER and SERVER_NAME need to be defined.\n");
return EXIT_FAILURE;
}
/* prepare pattern matching */
pattern = malloc(10 + strlen(server_name));
sprintf(pattern, "^http://%s/", server_name);
if ((rc = regcomp(&preg, pattern, 0)) != 0)
fprintf(stderr, "regcomp() failed, returning nonzero (%d)\n", rc);
/* check if the QR-Code is for the correct server */
if ((rc = regexec(&preg, http_referer, nmatch, pmatch, 0)) != 0) {
http_referer = malloc(44 + strlen(server_name));
sprintf(http_referer, "This QR Code has been stolen from http://%s/!", server_name);
}
regfree(&preg);
free(pattern);
/* initialize type system for glib < 2.36 */
#ifndef GLIB_VERSION_2_36
g_type_init();
#endif
if ((pixbuf = encode_qrcode(http_referer)) == NULL) {
if ((pixbuf = encode_qrcode(server_name)) == NULL) {
fprintf(stderr, "Could not generate QR-Code.\n");
return EXIT_FAILURE;
}
}
/* print HTTP header */
printf("Content-Type: image/png\n\n");
/* print PNG data */
gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &size, "png", NULL, NULL);
fwrite (buffer, 1, size, stdout);
if (rc)
free(http_referer);
g_object_unref(pixbuf);
return EXIT_SUCCESS;
}
// vim: set syntax=c:
|