Branch data 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 : : }
|