]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journal-qrcode.c
Merge pull request #2495 from heftig/master
[thirdparty/systemd.git] / src / journal / journal-qrcode.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2012 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <assert.h>
21 #include <errno.h>
22 #include <qrencode.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #include "journal-qrcode.h"
28
29 #define WHITE_ON_BLACK "\033[40;37;1m"
30 #define NORMAL "\033[0m"
31
32 static void print_border(FILE *output, unsigned width) {
33 unsigned x, y;
34
35 /* Four rows of border */
36 for (y = 0; y < 4; y += 2) {
37 fputs(WHITE_ON_BLACK, output);
38
39 for (x = 0; x < 4 + width + 4; x++)
40 fputs("\342\226\210", output);
41
42 fputs(NORMAL "\n", output);
43 }
44 }
45
46 int print_qr_code(
47 FILE *output,
48 const void *seed,
49 size_t seed_size,
50 uint64_t start,
51 uint64_t interval,
52 const char *hn,
53 sd_id128_t machine) {
54
55 FILE *f;
56 char *url = NULL;
57 size_t url_size = 0, i;
58 QRcode* qr;
59 unsigned x, y;
60
61 assert(seed);
62 assert(seed_size > 0);
63
64 f = open_memstream(&url, &url_size);
65 if (!f)
66 return -ENOMEM;
67
68 fputs("fss://", f);
69
70 for (i = 0; i < seed_size; i++) {
71 if (i > 0 && i % 3 == 0)
72 fputc('-', f);
73 fprintf(f, "%02x", ((uint8_t*) seed)[i]);
74 }
75
76 fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR,
77 start,
78 interval,
79 SD_ID128_FORMAT_VAL(machine));
80
81 if (hn)
82 fprintf(f, ";hostname=%s", hn);
83
84 if (ferror(f)) {
85 fclose(f);
86 free(url);
87 return -ENOMEM;
88 }
89
90 fclose(f);
91
92 qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
93 free(url);
94
95 if (!qr)
96 return -ENOMEM;
97
98 print_border(output, qr->width);
99
100 for (y = 0; y < (unsigned) qr->width; y += 2) {
101 const uint8_t *row1, *row2;
102
103 row1 = qr->data + qr->width * y;
104 row2 = row1 + qr->width;
105
106 fputs(WHITE_ON_BLACK, output);
107 for (x = 0; x < 4; x++)
108 fputs("\342\226\210", output);
109
110 for (x = 0; x < (unsigned) qr->width; x ++) {
111 bool a, b;
112
113 a = row1[x] & 1;
114 b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false;
115
116 if (a && b)
117 fputc(' ', output);
118 else if (a)
119 fputs("\342\226\204", output);
120 else if (b)
121 fputs("\342\226\200", output);
122 else
123 fputs("\342\226\210", output);
124 }
125
126 for (x = 0; x < 4; x++)
127 fputs("\342\226\210", output);
128 fputs(NORMAL "\n", output);
129 }
130
131 print_border(output, qr->width);
132
133 QRcode_free(qr);
134 return 0;
135 }