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