]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journal-qrcode.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / journal / journal-qrcode.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <qrencode.h>
5 #include <stdbool.h>
6 #include <stdio.h>
7 #include <stdio_ext.h>
8 #include <stdlib.h>
9
10 #include "journal-qrcode.h"
11 #include "macro.h"
12
13 #define WHITE_ON_BLACK "\033[40;37;1m"
14 #define NORMAL "\033[0m"
15
16 static void print_border(FILE *output, unsigned width) {
17 unsigned x, y;
18
19 /* Four rows of border */
20 for (y = 0; y < 4; y += 2) {
21 fputs(WHITE_ON_BLACK, output);
22
23 for (x = 0; x < 4 + width + 4; x++)
24 fputs("\342\226\210", output);
25
26 fputs(NORMAL "\n", output);
27 }
28 }
29
30 int print_qr_code(
31 FILE *output,
32 const void *seed,
33 size_t seed_size,
34 uint64_t start,
35 uint64_t interval,
36 const char *hn,
37 sd_id128_t machine) {
38
39 FILE *f;
40 char *url = NULL;
41 size_t url_size = 0, i;
42 QRcode* qr;
43 unsigned x, y;
44
45 assert(seed);
46 assert(seed_size > 0);
47
48 f = open_memstream(&url, &url_size);
49 if (!f)
50 return -ENOMEM;
51
52 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
53
54 fputs("fss://", f);
55
56 for (i = 0; i < seed_size; i++) {
57 if (i > 0 && i % 3 == 0)
58 fputc('-', f);
59 fprintf(f, "%02x", ((uint8_t*) seed)[i]);
60 }
61
62 fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR,
63 start,
64 interval,
65 SD_ID128_FORMAT_VAL(machine));
66
67 if (hn)
68 fprintf(f, ";hostname=%s", hn);
69
70 if (ferror(f)) {
71 fclose(f);
72 free(url);
73 return -ENOMEM;
74 }
75
76 fclose(f);
77
78 qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
79 free(url);
80
81 if (!qr)
82 return -ENOMEM;
83
84 print_border(output, qr->width);
85
86 for (y = 0; y < (unsigned) qr->width; y += 2) {
87 const uint8_t *row1, *row2;
88
89 row1 = qr->data + qr->width * y;
90 row2 = row1 + qr->width;
91
92 fputs(WHITE_ON_BLACK, output);
93 for (x = 0; x < 4; x++)
94 fputs("\342\226\210", output);
95
96 for (x = 0; x < (unsigned) qr->width; x ++) {
97 bool a, b;
98
99 a = row1[x] & 1;
100 b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false;
101
102 if (a && b)
103 fputc(' ', output);
104 else if (a)
105 fputs("\342\226\204", output);
106 else if (b)
107 fputs("\342\226\200", output);
108 else
109 fputs("\342\226\210", output);
110 }
111
112 for (x = 0; x < 4; x++)
113 fputs("\342\226\210", output);
114 fputs(NORMAL "\n", output);
115 }
116
117 print_border(output, qr->width);
118
119 QRcode_free(qr);
120 return 0;
121 }