]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
4368277c | 2 | |
da3920c3 | 3 | #include "qrcode-util.h" |
f1b82359 ZJS |
4 | |
5 | #if HAVE_QRENCODE | |
6 | #include <qrencode.h> | |
7 | ||
8 | #include "dlfcn-util.h" | |
9 | #include "locale-util.h" | |
da3920c3 LP |
10 | #include "terminal-util.h" |
11 | ||
12 | #define ANSI_WHITE_ON_BLACK "\033[40;37;1m" | |
13 | ||
14 | static void print_border(FILE *output, unsigned width) { | |
da3920c3 | 15 | /* Four rows of border */ |
c9e9a57f | 16 | for (unsigned y = 0; y < 4; y += 2) { |
da3920c3 LP |
17 | fputs(ANSI_WHITE_ON_BLACK, output); |
18 | ||
c9e9a57f | 19 | for (unsigned x = 0; x < 4 + width + 4; x++) |
da3920c3 LP |
20 | fputs("\342\226\210", output); |
21 | ||
22 | fputs(ANSI_NORMAL "\n", output); | |
23 | } | |
24 | } | |
25 | ||
f1b82359 | 26 | static void write_qrcode(FILE *output, QRcode *qr) { |
da3920c3 LP |
27 | assert(qr); |
28 | ||
29 | if (!output) | |
30 | output = stdout; | |
31 | ||
32 | print_border(output, qr->width); | |
33 | ||
c9e9a57f ZJS |
34 | for (unsigned y = 0; y < (unsigned) qr->width; y += 2) { |
35 | const uint8_t *row1 = qr->data + qr->width * y; | |
36 | const uint8_t *row2 = row1 + qr->width; | |
da3920c3 LP |
37 | |
38 | fputs(ANSI_WHITE_ON_BLACK, output); | |
c9e9a57f | 39 | for (unsigned x = 0; x < 4; x++) |
da3920c3 LP |
40 | fputs("\342\226\210", output); |
41 | ||
c9e9a57f | 42 | for (unsigned x = 0; x < (unsigned) qr->width; x++) { |
da3920c3 LP |
43 | bool a, b; |
44 | ||
45 | a = row1[x] & 1; | |
46 | b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false; | |
47 | ||
48 | if (a && b) | |
49 | fputc(' ', output); | |
50 | else if (a) | |
51 | fputs("\342\226\204", output); | |
52 | else if (b) | |
53 | fputs("\342\226\200", output); | |
54 | else | |
55 | fputs("\342\226\210", output); | |
56 | } | |
57 | ||
c9e9a57f | 58 | for (unsigned x = 0; x < 4; x++) |
da3920c3 LP |
59 | fputs("\342\226\210", output); |
60 | fputs(ANSI_NORMAL "\n", output); | |
61 | } | |
62 | ||
63 | print_border(output, qr->width); | |
64 | fflush(output); | |
65 | } | |
f1b82359 ZJS |
66 | |
67 | int print_qrcode(FILE *out, const char *header, const char *string) { | |
68 | QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); | |
69 | void (*sym_QRcode_free)(QRcode *qrcode); | |
70 | _cleanup_(dlclosep) void *dl = NULL; | |
71 | QRcode* qr; | |
72 | int r; | |
73 | ||
74 | /* If this is not an UTF-8 system or ANSI colors aren't supported/disabled don't print any QR | |
75 | * codes */ | |
76 | if (!is_locale_utf8() || !colors_enabled()) | |
77 | return -EOPNOTSUPP; | |
78 | ||
79 | dl = dlopen("libqrencode.so.4", RTLD_LAZY); | |
80 | if (!dl) | |
81 | return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), | |
82 | "QRCODE support is not installed: %s", dlerror()); | |
83 | ||
84 | r = dlsym_many_and_warn( | |
85 | dl, | |
86 | LOG_DEBUG, | |
87 | &sym_QRcode_encodeString, "QRcode_encodeString", | |
88 | &sym_QRcode_free, "QRcode_free", | |
89 | NULL); | |
90 | if (r < 0) | |
91 | return r; | |
92 | ||
93 | qr = sym_QRcode_encodeString(string, 0, QR_ECLEVEL_L, QR_MODE_8, 0); | |
94 | if (!qr) | |
95 | return -ENOMEM; | |
96 | ||
97 | if (header) | |
98 | fprintf(out, "\n%s:\n\n", header); | |
99 | ||
100 | write_qrcode(out, qr); | |
101 | ||
102 | fputc('\n', out); | |
103 | ||
104 | sym_QRcode_free(qr); | |
105 | return 0; | |
106 | } | |
107 | #endif |