Line data Source code
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 <stdlib.h>
8 :
9 : #include "fileio.h"
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 0 : static void print_border(FILE *output, unsigned width) {
17 : unsigned x, y;
18 :
19 : /* Four rows of border */
20 0 : for (y = 0; y < 4; y += 2) {
21 0 : fputs(WHITE_ON_BLACK, output);
22 :
23 0 : for (x = 0; x < 4 + width + 4; x++)
24 0 : fputs("\342\226\210", output);
25 :
26 0 : fputs(NORMAL "\n", output);
27 : }
28 0 : }
29 :
30 0 : 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 0 : char *url = NULL;
41 0 : size_t url_size = 0, i;
42 : QRcode* qr;
43 : unsigned x, y;
44 :
45 0 : assert(seed);
46 0 : assert(seed_size > 0);
47 :
48 0 : f = open_memstream_unlocked(&url, &url_size);
49 0 : if (!f)
50 0 : return -ENOMEM;
51 :
52 0 : fputs("fss://", f);
53 :
54 0 : for (i = 0; i < seed_size; i++) {
55 0 : if (i > 0 && i % 3 == 0)
56 0 : fputc('-', f);
57 0 : fprintf(f, "%02x", ((uint8_t*) seed)[i]);
58 : }
59 :
60 0 : fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR,
61 : start,
62 : interval,
63 0 : SD_ID128_FORMAT_VAL(machine));
64 :
65 0 : if (hn)
66 0 : fprintf(f, ";hostname=%s", hn);
67 :
68 0 : if (ferror(f)) {
69 0 : fclose(f);
70 0 : free(url);
71 0 : return -ENOMEM;
72 : }
73 :
74 0 : fclose(f);
75 :
76 0 : qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1);
77 0 : free(url);
78 :
79 0 : if (!qr)
80 0 : return -ENOMEM;
81 :
82 0 : print_border(output, qr->width);
83 :
84 0 : for (y = 0; y < (unsigned) qr->width; y += 2) {
85 : const uint8_t *row1, *row2;
86 :
87 0 : row1 = qr->data + qr->width * y;
88 0 : row2 = row1 + qr->width;
89 :
90 0 : fputs(WHITE_ON_BLACK, output);
91 0 : for (x = 0; x < 4; x++)
92 0 : fputs("\342\226\210", output);
93 :
94 0 : for (x = 0; x < (unsigned) qr->width; x ++) {
95 : bool a, b;
96 :
97 0 : a = row1[x] & 1;
98 0 : b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false;
99 :
100 0 : if (a && b)
101 0 : fputc(' ', output);
102 0 : else if (a)
103 0 : fputs("\342\226\204", output);
104 0 : else if (b)
105 0 : fputs("\342\226\200", output);
106 : else
107 0 : fputs("\342\226\210", output);
108 : }
109 :
110 0 : for (x = 0; x < 4; x++)
111 0 : fputs("\342\226\210", output);
112 0 : fputs(NORMAL "\n", output);
113 : }
114 :
115 0 : print_border(output, qr->width);
116 :
117 0 : QRcode_free(qr);
118 0 : return 0;
119 : }
|