File indexing completed on 2023-03-17 10:45:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 #include "base64.h"
0049
0050
0051 #include <cstdlib>
0052
0053
0054 #include <climits>
0055
0056 #include <cstring>
0057
0058
0059 static inline unsigned char to_uchar(char ch) { return ch; }
0060
0061
0062
0063
0064
0065 void base64_encode(const char *in, size_t inlen, char *out, size_t outlen) {
0066 static const char *b64str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
0067
0068 while (inlen && outlen) {
0069 *out++ = b64str[(to_uchar(in[0]) >> 2) & 0x3f];
0070 if (!--outlen)
0071 break;
0072 *out++ = b64str[((to_uchar(in[0]) << 4) + (--inlen ? to_uchar(in[1]) >> 4 : 0)) & 0x3f];
0073 if (!--outlen)
0074 break;
0075 *out++ = (inlen ? b64str[((to_uchar(in[1]) << 2) + (--inlen ? to_uchar(in[2]) >> 6 : 0)) & 0x3f] : '=');
0076 if (!--outlen)
0077 break;
0078 *out++ = inlen ? b64str[to_uchar(in[2]) & 0x3f] : '=';
0079 if (!--outlen)
0080 break;
0081 if (inlen)
0082 inlen--;
0083 if (inlen)
0084 in += 3;
0085 }
0086
0087 if (outlen)
0088 *out = '\0';
0089 }
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 size_t base64_encode_alloc(const char *in, size_t inlen, char **out) {
0101 size_t outlen = 1 + BASE64_LENGTH(inlen);
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 if (inlen > outlen) {
0116 *out = nullptr;
0117 return 0;
0118 }
0119
0120 *out = static_cast<char *>(malloc(outlen));
0121 if (!*out)
0122 return outlen;
0123
0124 base64_encode(in, inlen, *out, outlen);
0125
0126 return outlen - 1;
0127 }
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 #define B64(_) \
0141 ((_) == 'A' ? 0 \
0142 : (_) == 'B' ? 1 \
0143 : (_) == 'C' ? 2 \
0144 : (_) == 'D' ? 3 \
0145 : (_) == 'E' ? 4 \
0146 : (_) == 'F' ? 5 \
0147 : (_) == 'G' ? 6 \
0148 : (_) == 'H' ? 7 \
0149 : (_) == 'I' ? 8 \
0150 : (_) == 'J' ? 9 \
0151 : (_) == 'K' ? 10 \
0152 : (_) == 'L' ? 11 \
0153 : (_) == 'M' ? 12 \
0154 : (_) == 'N' ? 13 \
0155 : (_) == 'O' ? 14 \
0156 : (_) == 'P' ? 15 \
0157 : (_) == 'Q' ? 16 \
0158 : (_) == 'R' ? 17 \
0159 : (_) == 'S' ? 18 \
0160 : (_) == 'T' ? 19 \
0161 : (_) == 'U' ? 20 \
0162 : (_) == 'V' ? 21 \
0163 : (_) == 'W' ? 22 \
0164 : (_) == 'X' ? 23 \
0165 : (_) == 'Y' ? 24 \
0166 : (_) == 'Z' ? 25 \
0167 : (_) == 'a' ? 26 \
0168 : (_) == 'b' ? 27 \
0169 : (_) == 'c' ? 28 \
0170 : (_) == 'd' ? 29 \
0171 : (_) == 'e' ? 30 \
0172 : (_) == 'f' ? 31 \
0173 : (_) == 'g' ? 32 \
0174 : (_) == 'h' ? 33 \
0175 : (_) == 'i' ? 34 \
0176 : (_) == 'j' ? 35 \
0177 : (_) == 'k' ? 36 \
0178 : (_) == 'l' ? 37 \
0179 : (_) == 'm' ? 38 \
0180 : (_) == 'n' ? 39 \
0181 : (_) == 'o' ? 40 \
0182 : (_) == 'p' ? 41 \
0183 : (_) == 'q' ? 42 \
0184 : (_) == 'r' ? 43 \
0185 : (_) == 's' ? 44 \
0186 : (_) == 't' ? 45 \
0187 : (_) == 'u' ? 46 \
0188 : (_) == 'v' ? 47 \
0189 : (_) == 'w' ? 48 \
0190 : (_) == 'x' ? 49 \
0191 : (_) == 'y' ? 50 \
0192 : (_) == 'z' ? 51 \
0193 : (_) == '0' ? 52 \
0194 : (_) == '1' ? 53 \
0195 : (_) == '2' ? 54 \
0196 : (_) == '3' ? 55 \
0197 : (_) == '4' ? 56 \
0198 : (_) == '5' ? 57 \
0199 : (_) == '6' ? 58 \
0200 : (_) == '7' ? 59 \
0201 : (_) == '8' ? 60 \
0202 : (_) == '9' ? 61 \
0203 : (_) == '+' ? 62 \
0204 : (_) == '/' ? 63 \
0205 : -1)
0206
0207
0208 static const signed char b64[0x100] = {
0209 B64(0), B64(1), B64(2), B64(3), B64(4), B64(5), B64(6), B64(7), B64(8), B64(9), B64(10),
0210 B64(11), B64(12), B64(13), B64(14), B64(15), B64(16), B64(17), B64(18), B64(19), B64(20), B64(21),
0211 B64(22), B64(23), B64(24), B64(25), B64(26), B64(27), B64(28), B64(29), B64(30), B64(31), B64(32),
0212 B64(33), B64(34), B64(35), B64(36), B64(37), B64(38), B64(39), B64(40), B64(41), B64(42), B64(43),
0213 B64(44), B64(45), B64(46), B64(47), B64(48), B64(49), B64(50), B64(51), B64(52), B64(53), B64(54),
0214 B64(55), B64(56), B64(57), B64(58), B64(59), B64(60), B64(61), B64(62), B64(63), B64(64), B64(65),
0215 B64(66), B64(67), B64(68), B64(69), B64(70), B64(71), B64(72), B64(73), B64(74), B64(75), B64(76),
0216 B64(77), B64(78), B64(79), B64(80), B64(81), B64(82), B64(83), B64(84), B64(85), B64(86), B64(87),
0217 B64(88), B64(89), B64(90), B64(91), B64(92), B64(93), B64(94), B64(95), B64(96), B64(97), B64(98),
0218 B64(99), B64(100), B64(101), B64(102), B64(103), B64(104), B64(105), B64(106), B64(107), B64(108), B64(109),
0219 B64(110), B64(111), B64(112), B64(113), B64(114), B64(115), B64(116), B64(117), B64(118), B64(119), B64(120),
0220 B64(121), B64(122), B64(123), B64(124), B64(125), B64(126), B64(127), B64(128), B64(129), B64(130), B64(131),
0221 B64(132), B64(133), B64(134), B64(135), B64(136), B64(137), B64(138), B64(139), B64(140), B64(141), B64(142),
0222 B64(143), B64(144), B64(145), B64(146), B64(147), B64(148), B64(149), B64(150), B64(151), B64(152), B64(153),
0223 B64(154), B64(155), B64(156), B64(157), B64(158), B64(159), B64(160), B64(161), B64(162), B64(163), B64(164),
0224 B64(165), B64(166), B64(167), B64(168), B64(169), B64(170), B64(171), B64(172), B64(173), B64(174), B64(175),
0225 B64(176), B64(177), B64(178), B64(179), B64(180), B64(181), B64(182), B64(183), B64(184), B64(185), B64(186),
0226 B64(187), B64(188), B64(189), B64(190), B64(191), B64(192), B64(193), B64(194), B64(195), B64(196), B64(197),
0227 B64(198), B64(199), B64(200), B64(201), B64(202), B64(203), B64(204), B64(205), B64(206), B64(207), B64(208),
0228 B64(209), B64(210), B64(211), B64(212), B64(213), B64(214), B64(215), B64(216), B64(217), B64(218), B64(219),
0229 B64(220), B64(221), B64(222), B64(223), B64(224), B64(225), B64(226), B64(227), B64(228), B64(229), B64(230),
0230 B64(231), B64(232), B64(233), B64(234), B64(235), B64(236), B64(237), B64(238), B64(239), B64(240), B64(241),
0231 B64(242), B64(243), B64(244), B64(245), B64(246), B64(247), B64(248), B64(249), B64(250), B64(251), B64(252),
0232 B64(253), B64(254), B64(255)};
0233
0234 #if UCHAR_MAX == 255
0235 #define uchar_in_range(c) true
0236 #else
0237 #define uchar_in_range(c) ((c) <= 255)
0238 #endif
0239
0240
0241
0242
0243 bool isbase64(char ch) { return uchar_in_range(to_uchar(ch)) && 0 <= b64[to_uchar(ch)]; }
0244
0245
0246 void base64_decode_ctx_init(struct base64_decode_context *ctx) { ctx->i = 0; }
0247
0248
0249
0250
0251
0252
0253
0254
0255 static inline char *get_4(struct base64_decode_context *ctx,
0256 char const **in,
0257 char const *in_end,
0258 size_t *n_non_newline) {
0259 if (ctx->i == 4)
0260 ctx->i = 0;
0261
0262 if (ctx->i == 0) {
0263 char const *t = *in;
0264 if (4 <= in_end - *in && memchr(t, '\n', 4) == nullptr) {
0265
0266 *in += 4;
0267 *n_non_newline = 4;
0268 return (char *)t;
0269 }
0270 }
0271
0272 {
0273
0274 char const *p = *in;
0275 while (p < in_end) {
0276 char c = *p++;
0277 if (c != '\n') {
0278 ctx->buf[ctx->i++] = c;
0279 if (ctx->i == 4)
0280 break;
0281 }
0282 }
0283
0284 *in = p;
0285 *n_non_newline = ctx->i;
0286 return ctx->buf;
0287 }
0288 }
0289
0290 #define return_false \
0291 do { \
0292 *outp = out; \
0293 return false; \
0294 } while (false)
0295
0296
0297
0298
0299
0300
0301
0302 static inline bool decode_4(char const *in, size_t inlen, char **outp, size_t *outleft) {
0303 char *out = *outp;
0304 if (inlen < 2)
0305 return false;
0306
0307 if (!isbase64(in[0]) || !isbase64(in[1]))
0308 return false;
0309
0310 if (*outleft) {
0311 *out++ = ((b64[to_uchar(in[0])] << 2) | (b64[to_uchar(in[1])] >> 4));
0312 --*outleft;
0313 }
0314
0315 if (inlen == 2)
0316 return_false;
0317
0318 if (in[2] == '=') {
0319 if (inlen != 4)
0320 return_false;
0321
0322 if (in[3] != '=')
0323 return_false;
0324 } else {
0325 if (!isbase64(in[2]))
0326 return_false;
0327
0328 if (*outleft) {
0329 *out++ = (((b64[to_uchar(in[1])] << 4) & 0xf0) | (b64[to_uchar(in[2])] >> 2));
0330 --*outleft;
0331 }
0332
0333 if (inlen == 3)
0334 return_false;
0335
0336 if (in[3] == '=') {
0337 if (inlen != 4)
0338 return_false;
0339 } else {
0340 if (!isbase64(in[3]))
0341 return_false;
0342
0343 if (*outleft) {
0344 *out++ = (((b64[to_uchar(in[2])] << 6) & 0xc0) | b64[to_uchar(in[3])]);
0345 --*outleft;
0346 }
0347 }
0348 }
0349
0350 *outp = out;
0351 return true;
0352 }
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372 bool base64_decode_ctx(struct base64_decode_context *ctx, const char *in, size_t inlen, char *out, size_t *outlen) {
0373 size_t outleft = *outlen;
0374 bool ignore_newlines = ctx != nullptr;
0375 bool flush_ctx = false;
0376 unsigned int ctx_i = 0;
0377
0378 if (ignore_newlines) {
0379 ctx_i = ctx->i;
0380 flush_ctx = inlen == 0;
0381 }
0382
0383 while (true) {
0384 size_t outleft_save = outleft;
0385 if (ctx_i == 0 && !flush_ctx) {
0386 while (true) {
0387
0388
0389 outleft_save = outleft;
0390 if (!decode_4(in, inlen, &out, &outleft))
0391 break;
0392
0393 in += 4;
0394 inlen -= 4;
0395 }
0396 }
0397
0398 if (inlen == 0 && !flush_ctx)
0399 break;
0400
0401
0402
0403 if (inlen && *in == '\n' && ignore_newlines) {
0404 ++in;
0405 --inlen;
0406 continue;
0407 }
0408
0409
0410 out -= outleft_save - outleft;
0411 outleft = outleft_save;
0412
0413 {
0414 char const *in_end = in + inlen;
0415 char const *non_nl;
0416
0417 if (ignore_newlines)
0418 non_nl = get_4(ctx, &in, in_end, &inlen);
0419 else
0420 non_nl = in;
0421
0422
0423
0424
0425 if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines)) {
0426 inlen = 0;
0427 break;
0428 }
0429 if (!decode_4(non_nl, inlen, &out, &outleft))
0430 break;
0431
0432 inlen = in_end - in;
0433 }
0434 }
0435
0436 *outlen -= outleft;
0437
0438 return inlen == 0;
0439 }
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 bool base64_decode_alloc_ctx(
0453 struct base64_decode_context *ctx, const char *in, size_t inlen, char **out, size_t *outlen) {
0454
0455
0456
0457
0458
0459 size_t needlen = 3 * (inlen / 4) + 3;
0460
0461 *out = static_cast<char *>(malloc(needlen));
0462 if (!*out)
0463 return true;
0464
0465 if (!base64_decode_ctx(ctx, in, inlen, *out, &needlen)) {
0466 free(*out);
0467 *out = nullptr;
0468 return false;
0469 }
0470
0471 if (outlen)
0472 *outlen = needlen;
0473
0474 return true;
0475 }