diff options
| author | Pierre Téchoueyres | 2019-05-21 23:00:13 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2019-06-08 10:49:35 +0300 |
| commit | 7541b06872ba134bfaa51b1aca7755a617fff807 (patch) | |
| tree | 0190a36f96e0b37f1ea7f97e6b89975a155436af /src | |
| parent | faf10bd8eb3272880b774fe220fa9916ed1f00c0 (diff) | |
| download | emacs-7541b06872ba134bfaa51b1aca7755a617fff807.tar.gz emacs-7541b06872ba134bfaa51b1aca7755a617fff807.zip | |
Add support for base64url variant of base-64 encoding/decoding
Implement the RFC4648 variant of base64 encoding used by URLs.
* doc/lispref/text.texi (base64url-encode-region,
base64url-encode-string): Document new functions.
(base64-decode-region, base64-decode-string): Document new optional
parameter 'base64url' used to use url variant when decoding data.
* src/fns.c (base64url-encode-region, base64url-encode-region): New
functions to manage url variant.
(base64-decode-region, base64-decode-string): Add optional
parameter to indicate use of url-variant.
(base64_encode_region_1, base64_encode_string_1): Internal functions
with extracted code from 'base64_encode_region' and
'base64_encode_string' and optional parameters to manage padding and
url variant.
(base64-encode-region, base64-encode-string) : Use
base64_encode_region_1 and base64_encode_string_1.
(base64-encode-1): Add parameters to manage padding and url variant.
(base64-decode-1): Add parameter to manage url variant.
* test/src/fns-tests.el (fns-tests--with-region): New helper macro to
test region variant of base64 encode / decode functions.
(fns-tests--string-repeat): Helper function used in base64 tests.
(fns-tests-base64-encode-region, fns-tests-base64-encode-string):
Tests for standard base64 function.
(fns-test-base64url-encode-region,
fns-test-base64url-encode-string): Tests for url variant.
(fns-tests-base64-decode-string): Tests for decoding part.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 166 |
1 files changed, 137 insertions, 29 deletions
| @@ -3189,7 +3189,7 @@ The data read from the system are decoded using `locale-coding-system'. */) | |||
| 3189 | #define IS_ASCII(Character) \ | 3189 | #define IS_ASCII(Character) \ |
| 3190 | ((Character) < 128) | 3190 | ((Character) < 128) |
| 3191 | #define IS_BASE64(Character) \ | 3191 | #define IS_BASE64(Character) \ |
| 3192 | (IS_ASCII (Character) && base64_char_to_value[Character] >= 0) | 3192 | (IS_ASCII (Character) && b64_char_to_value[Character] >= 0) |
| 3193 | #define IS_BASE64_IGNORABLE(Character) \ | 3193 | #define IS_BASE64_IGNORABLE(Character) \ |
| 3194 | ((Character) == ' ' || (Character) == '\t' || (Character) == '\n' \ | 3194 | ((Character) == ' ' || (Character) == '\t' || (Character) == '\n' \ |
| 3195 | || (Character) == '\f' || (Character) == '\r') | 3195 | || (Character) == '\f' || (Character) == '\r') |
| @@ -3222,6 +3222,17 @@ static const char base64_value_to_char[64] = | |||
| 3222 | '8', '9', '+', '/' /* 60-63 */ | 3222 | '8', '9', '+', '/' /* 60-63 */ |
| 3223 | }; | 3223 | }; |
| 3224 | 3224 | ||
| 3225 | static const char base64url_value_to_char[64] = | ||
| 3226 | { | ||
| 3227 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */ | ||
| 3228 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */ | ||
| 3229 | 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */ | ||
| 3230 | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 30-39 */ | ||
| 3231 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */ | ||
| 3232 | 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */ | ||
| 3233 | '8', '9', '-', '_' /* 60-63 */ | ||
| 3234 | }; | ||
| 3235 | |||
| 3225 | /* Table of base64 values for first 128 characters. */ | 3236 | /* Table of base64 values for first 128 characters. */ |
| 3226 | static const short base64_char_to_value[128] = | 3237 | static const short base64_char_to_value[128] = |
| 3227 | { | 3238 | { |
| @@ -3240,6 +3251,23 @@ static const short base64_char_to_value[128] = | |||
| 3240 | 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ | 3251 | 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ |
| 3241 | }; | 3252 | }; |
| 3242 | 3253 | ||
| 3254 | static const short base64url_char_to_value[128] = | ||
| 3255 | { | ||
| 3256 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */ | ||
| 3257 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */ | ||
| 3258 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */ | ||
| 3259 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */ | ||
| 3260 | -1, -1, -1, -1, -1, 62, -1, -1, 52, 53, /* 40- 49 */ | ||
| 3261 | 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */ | ||
| 3262 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */ | ||
| 3263 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */ | ||
| 3264 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */ | ||
| 3265 | 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, /* 90- 99 */ | ||
| 3266 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */ | ||
| 3267 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */ | ||
| 3268 | 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ | ||
| 3269 | }; | ||
| 3270 | |||
| 3243 | /* The following diagram shows the logical steps by which three octets | 3271 | /* The following diagram shows the logical steps by which three octets |
| 3244 | get transformed into four base64 characters. | 3272 | get transformed into four base64 characters. |
| 3245 | 3273 | ||
| @@ -3259,9 +3287,17 @@ static const short base64_char_to_value[128] = | |||
| 3259 | base64 characters. */ | 3287 | base64 characters. */ |
| 3260 | 3288 | ||
| 3261 | 3289 | ||
| 3262 | static ptrdiff_t base64_encode_1 (const char *, char *, ptrdiff_t, bool, bool); | 3290 | static ptrdiff_t base64_encode_1 (const char *, char *, ptrdiff_t, bool, bool, |
| 3291 | bool, bool); | ||
| 3263 | static ptrdiff_t base64_decode_1 (const char *, char *, ptrdiff_t, bool, | 3292 | static ptrdiff_t base64_decode_1 (const char *, char *, ptrdiff_t, bool, |
| 3264 | ptrdiff_t *); | 3293 | bool, ptrdiff_t *); |
| 3294 | |||
| 3295 | Lisp_Object base64_encode_region_1 (Lisp_Object, Lisp_Object, bool, | ||
| 3296 | bool, bool); | ||
| 3297 | |||
| 3298 | Lisp_Object base64_encode_string_1(Lisp_Object, bool, | ||
| 3299 | bool, bool); | ||
| 3300 | |||
| 3265 | 3301 | ||
| 3266 | DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region, | 3302 | DEFUN ("base64-encode-region", Fbase64_encode_region, Sbase64_encode_region, |
| 3267 | 2, 3, "r", | 3303 | 2, 3, "r", |
| @@ -3271,6 +3307,26 @@ Optional third argument NO-LINE-BREAK means do not break long lines | |||
| 3271 | into shorter lines. */) | 3307 | into shorter lines. */) |
| 3272 | (Lisp_Object beg, Lisp_Object end, Lisp_Object no_line_break) | 3308 | (Lisp_Object beg, Lisp_Object end, Lisp_Object no_line_break) |
| 3273 | { | 3309 | { |
| 3310 | return base64_encode_region_1(beg, end, NILP (no_line_break), true, false); | ||
| 3311 | } | ||
| 3312 | |||
| 3313 | |||
| 3314 | DEFUN ("base64url-encode-region", Fbase64url_encode_region, Sbase64url_encode_region, | ||
| 3315 | 2, 3, "r", | ||
| 3316 | doc: /* Base64url-encode the region between BEG and END. | ||
| 3317 | Return the length of the encoded text. | ||
| 3318 | Optional second argument NO-PAD means do not add padding char =. | ||
| 3319 | |||
| 3320 | This is the variant defined in RFC4648. */) | ||
| 3321 | (Lisp_Object beg, Lisp_Object end, Lisp_Object no_pad) | ||
| 3322 | { | ||
| 3323 | return base64_encode_region_1(beg, end, false, NILP(no_pad), true); | ||
| 3324 | } | ||
| 3325 | |||
| 3326 | Lisp_Object | ||
| 3327 | base64_encode_region_1 (Lisp_Object beg, Lisp_Object end, bool line_break, | ||
| 3328 | bool pad, bool base64url) | ||
| 3329 | { | ||
| 3274 | char *encoded; | 3330 | char *encoded; |
| 3275 | ptrdiff_t allength, length; | 3331 | ptrdiff_t allength, length; |
| 3276 | ptrdiff_t ibeg, iend, encoded_length; | 3332 | ptrdiff_t ibeg, iend, encoded_length; |
| @@ -3292,7 +3348,8 @@ into shorter lines. */) | |||
| 3292 | 3348 | ||
| 3293 | encoded = SAFE_ALLOCA (allength); | 3349 | encoded = SAFE_ALLOCA (allength); |
| 3294 | encoded_length = base64_encode_1 ((char *) BYTE_POS_ADDR (ibeg), | 3350 | encoded_length = base64_encode_1 ((char *) BYTE_POS_ADDR (ibeg), |
| 3295 | encoded, length, NILP (no_line_break), | 3351 | encoded, length, line_break, |
| 3352 | pad, base64url, | ||
| 3296 | !NILP (BVAR (current_buffer, enable_multibyte_characters))); | 3353 | !NILP (BVAR (current_buffer, enable_multibyte_characters))); |
| 3297 | if (encoded_length > allength) | 3354 | if (encoded_length > allength) |
| 3298 | emacs_abort (); | 3355 | emacs_abort (); |
| @@ -3330,6 +3387,26 @@ Optional second argument NO-LINE-BREAK means do not break long lines | |||
| 3330 | into shorter lines. */) | 3387 | into shorter lines. */) |
| 3331 | (Lisp_Object string, Lisp_Object no_line_break) | 3388 | (Lisp_Object string, Lisp_Object no_line_break) |
| 3332 | { | 3389 | { |
| 3390 | |||
| 3391 | return base64_encode_string_1(string, NILP (no_line_break), true, false); | ||
| 3392 | } | ||
| 3393 | |||
| 3394 | DEFUN ("base64url-encode-string", Fbase64url_encode_string, Sbase64url_encode_string, | ||
| 3395 | 1, 2, 0, | ||
| 3396 | doc: /* Base64url-encode STRING and return the result. | ||
| 3397 | Optional second argument NO-PAD means do not add padding char =. | ||
| 3398 | |||
| 3399 | This is the variant defined in RFC4648. */) | ||
| 3400 | (Lisp_Object string, Lisp_Object no_pad) | ||
| 3401 | { | ||
| 3402 | |||
| 3403 | return base64_encode_string_1(string, false, NILP(no_pad), true); | ||
| 3404 | } | ||
| 3405 | |||
| 3406 | Lisp_Object | ||
| 3407 | base64_encode_string_1(Lisp_Object string, bool line_break, | ||
| 3408 | bool pad, bool base64url) | ||
| 3409 | { | ||
| 3333 | ptrdiff_t allength, length, encoded_length; | 3410 | ptrdiff_t allength, length, encoded_length; |
| 3334 | char *encoded; | 3411 | char *encoded; |
| 3335 | Lisp_Object encoded_string; | 3412 | Lisp_Object encoded_string; |
| @@ -3348,7 +3425,8 @@ into shorter lines. */) | |||
| 3348 | encoded = SAFE_ALLOCA (allength); | 3425 | encoded = SAFE_ALLOCA (allength); |
| 3349 | 3426 | ||
| 3350 | encoded_length = base64_encode_1 (SSDATA (string), | 3427 | encoded_length = base64_encode_1 (SSDATA (string), |
| 3351 | encoded, length, NILP (no_line_break), | 3428 | encoded, length, line_break, |
| 3429 | pad, base64url, | ||
| 3352 | STRING_MULTIBYTE (string)); | 3430 | STRING_MULTIBYTE (string)); |
| 3353 | if (encoded_length > allength) | 3431 | if (encoded_length > allength) |
| 3354 | emacs_abort (); | 3432 | emacs_abort (); |
| @@ -3367,7 +3445,8 @@ into shorter lines. */) | |||
| 3367 | 3445 | ||
| 3368 | static ptrdiff_t | 3446 | static ptrdiff_t |
| 3369 | base64_encode_1 (const char *from, char *to, ptrdiff_t length, | 3447 | base64_encode_1 (const char *from, char *to, ptrdiff_t length, |
| 3370 | bool line_break, bool multibyte) | 3448 | bool line_break, bool pad, bool base64url, |
| 3449 | bool multibyte) | ||
| 3371 | { | 3450 | { |
| 3372 | int counter = 0; | 3451 | int counter = 0; |
| 3373 | ptrdiff_t i = 0; | 3452 | ptrdiff_t i = 0; |
| @@ -3375,6 +3454,7 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3375 | int c; | 3454 | int c; |
| 3376 | unsigned int value; | 3455 | unsigned int value; |
| 3377 | int bytes; | 3456 | int bytes; |
| 3457 | char const *b64_value_to_char = (base64url) ? base64url_value_to_char : base64_value_to_char; | ||
| 3378 | 3458 | ||
| 3379 | while (i < length) | 3459 | while (i < length) |
| 3380 | { | 3460 | { |
| @@ -3405,16 +3485,19 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3405 | 3485 | ||
| 3406 | /* Process first byte of a triplet. */ | 3486 | /* Process first byte of a triplet. */ |
| 3407 | 3487 | ||
| 3408 | *e++ = base64_value_to_char[0x3f & c >> 2]; | 3488 | *e++ = b64_value_to_char[0x3f & c >> 2]; |
| 3409 | value = (0x03 & c) << 4; | 3489 | value = (0x03 & c) << 4; |
| 3410 | 3490 | ||
| 3411 | /* Process second byte of a triplet. */ | 3491 | /* Process second byte of a triplet. */ |
| 3412 | 3492 | ||
| 3413 | if (i == length) | 3493 | if (i == length) |
| 3414 | { | 3494 | { |
| 3415 | *e++ = base64_value_to_char[value]; | 3495 | *e++ = b64_value_to_char[value]; |
| 3416 | *e++ = '='; | 3496 | if (pad) |
| 3417 | *e++ = '='; | 3497 | { |
| 3498 | *e++ = '='; | ||
| 3499 | *e++ = '='; | ||
| 3500 | } | ||
| 3418 | break; | 3501 | break; |
| 3419 | } | 3502 | } |
| 3420 | 3503 | ||
| @@ -3430,15 +3513,18 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3430 | else | 3513 | else |
| 3431 | c = from[i++]; | 3514 | c = from[i++]; |
| 3432 | 3515 | ||
| 3433 | *e++ = base64_value_to_char[value | (0x0f & c >> 4)]; | 3516 | *e++ = b64_value_to_char[value | (0x0f & c >> 4)]; |
| 3434 | value = (0x0f & c) << 2; | 3517 | value = (0x0f & c) << 2; |
| 3435 | 3518 | ||
| 3436 | /* Process third byte of a triplet. */ | 3519 | /* Process third byte of a triplet. */ |
| 3437 | 3520 | ||
| 3438 | if (i == length) | 3521 | if (i == length) |
| 3439 | { | 3522 | { |
| 3440 | *e++ = base64_value_to_char[value]; | 3523 | *e++ = b64_value_to_char[value]; |
| 3441 | *e++ = '='; | 3524 | if (pad) |
| 3525 | { | ||
| 3526 | *e++ = '='; | ||
| 3527 | } | ||
| 3442 | break; | 3528 | break; |
| 3443 | } | 3529 | } |
| 3444 | 3530 | ||
| @@ -3454,8 +3540,8 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3454 | else | 3540 | else |
| 3455 | c = from[i++]; | 3541 | c = from[i++]; |
| 3456 | 3542 | ||
| 3457 | *e++ = base64_value_to_char[value | (0x03 & c >> 6)]; | 3543 | *e++ = b64_value_to_char[value | (0x03 & c >> 6)]; |
| 3458 | *e++ = base64_value_to_char[0x3f & c]; | 3544 | *e++ = b64_value_to_char[0x3f & c]; |
| 3459 | } | 3545 | } |
| 3460 | 3546 | ||
| 3461 | return e - to; | 3547 | return e - to; |
| @@ -3463,11 +3549,13 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3463 | 3549 | ||
| 3464 | 3550 | ||
| 3465 | DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region, | 3551 | DEFUN ("base64-decode-region", Fbase64_decode_region, Sbase64_decode_region, |
| 3466 | 2, 2, "r", | 3552 | 2, 3, "r", |
| 3467 | doc: /* Base64-decode the region between BEG and END. | 3553 | doc: /* Base64-decode the region between BEG and END. |
| 3468 | Return the length of the decoded text. | 3554 | Return the length of the decoded text. |
| 3469 | If the region can't be decoded, signal an error and don't modify the buffer. */) | 3555 | If the region can't be decoded, signal an error and don't modify the buffer. |
| 3470 | (Lisp_Object beg, Lisp_Object end) | 3556 | Optional third argument BASE64URL define if base64Url variant will be used |
| 3557 | see RFC4648. */) | ||
| 3558 | (Lisp_Object beg, Lisp_Object end, Lisp_Object base64url) | ||
| 3471 | { | 3559 | { |
| 3472 | ptrdiff_t ibeg, iend, length, allength; | 3560 | ptrdiff_t ibeg, iend, length, allength; |
| 3473 | char *decoded; | 3561 | char *decoded; |
| @@ -3492,7 +3580,7 @@ If the region can't be decoded, signal an error and don't modify the buffer. */ | |||
| 3492 | 3580 | ||
| 3493 | move_gap_both (XFIXNAT (beg), ibeg); | 3581 | move_gap_both (XFIXNAT (beg), ibeg); |
| 3494 | decoded_length = base64_decode_1 ((char *) BYTE_POS_ADDR (ibeg), | 3582 | decoded_length = base64_decode_1 ((char *) BYTE_POS_ADDR (ibeg), |
| 3495 | decoded, length, | 3583 | decoded, length, !NILP (base64url), |
| 3496 | multibyte, &inserted_chars); | 3584 | multibyte, &inserted_chars); |
| 3497 | if (decoded_length > allength) | 3585 | if (decoded_length > allength) |
| 3498 | emacs_abort (); | 3586 | emacs_abort (); |
| @@ -3526,9 +3614,11 @@ If the region can't be decoded, signal an error and don't modify the buffer. */ | |||
| 3526 | } | 3614 | } |
| 3527 | 3615 | ||
| 3528 | DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string, | 3616 | DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string, |
| 3529 | 1, 1, 0, | 3617 | 1, 2, 0, |
| 3530 | doc: /* Base64-decode STRING and return the result. */) | 3618 | doc: /* Base64-decode STRING and return the result |
| 3531 | (Lisp_Object string) | 3619 | Optional argument BASE64URL define if base64Url variant will be used |
| 3620 | see RFC4648. */) | ||
| 3621 | (Lisp_Object string, Lisp_Object base64url) | ||
| 3532 | { | 3622 | { |
| 3533 | char *decoded; | 3623 | char *decoded; |
| 3534 | ptrdiff_t length, decoded_length; | 3624 | ptrdiff_t length, decoded_length; |
| @@ -3543,7 +3633,7 @@ DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string, | |||
| 3543 | 3633 | ||
| 3544 | /* The decoded result should be unibyte. */ | 3634 | /* The decoded result should be unibyte. */ |
| 3545 | decoded_length = base64_decode_1 (SSDATA (string), decoded, length, | 3635 | decoded_length = base64_decode_1 (SSDATA (string), decoded, length, |
| 3546 | 0, NULL); | 3636 | !NILP (base64url), 0, NULL); |
| 3547 | if (decoded_length > length) | 3637 | if (decoded_length > length) |
| 3548 | emacs_abort (); | 3638 | emacs_abort (); |
| 3549 | else if (decoded_length >= 0) | 3639 | else if (decoded_length >= 0) |
| @@ -3565,6 +3655,7 @@ DEFUN ("base64-decode-string", Fbase64_decode_string, Sbase64_decode_string, | |||
| 3565 | 3655 | ||
| 3566 | static ptrdiff_t | 3656 | static ptrdiff_t |
| 3567 | base64_decode_1 (const char *from, char *to, ptrdiff_t length, | 3657 | base64_decode_1 (const char *from, char *to, ptrdiff_t length, |
| 3658 | bool base64url, | ||
| 3568 | bool multibyte, ptrdiff_t *nchars_return) | 3659 | bool multibyte, ptrdiff_t *nchars_return) |
| 3569 | { | 3660 | { |
| 3570 | ptrdiff_t i = 0; /* Used inside READ_QUADRUPLET_BYTE */ | 3661 | ptrdiff_t i = 0; /* Used inside READ_QUADRUPLET_BYTE */ |
| @@ -3572,6 +3663,7 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3572 | unsigned char c; | 3663 | unsigned char c; |
| 3573 | unsigned long value; | 3664 | unsigned long value; |
| 3574 | ptrdiff_t nchars = 0; | 3665 | ptrdiff_t nchars = 0; |
| 3666 | short const *b64_char_to_value = (base64url) ? base64url_char_to_value : base64_char_to_value; | ||
| 3575 | 3667 | ||
| 3576 | while (1) | 3668 | while (1) |
| 3577 | { | 3669 | { |
| @@ -3581,7 +3673,7 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3581 | 3673 | ||
| 3582 | if (!IS_BASE64 (c)) | 3674 | if (!IS_BASE64 (c)) |
| 3583 | return -1; | 3675 | return -1; |
| 3584 | value = base64_char_to_value[c] << 18; | 3676 | value = b64_char_to_value[c] << 18; |
| 3585 | 3677 | ||
| 3586 | /* Process second byte of a quadruplet. */ | 3678 | /* Process second byte of a quadruplet. */ |
| 3587 | 3679 | ||
| @@ -3589,7 +3681,7 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3589 | 3681 | ||
| 3590 | if (!IS_BASE64 (c)) | 3682 | if (!IS_BASE64 (c)) |
| 3591 | return -1; | 3683 | return -1; |
| 3592 | value |= base64_char_to_value[c] << 12; | 3684 | value |= b64_char_to_value[c] << 12; |
| 3593 | 3685 | ||
| 3594 | c = (unsigned char) (value >> 16); | 3686 | c = (unsigned char) (value >> 16); |
| 3595 | if (multibyte && c >= 128) | 3687 | if (multibyte && c >= 128) |
| @@ -3600,7 +3692,14 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3600 | 3692 | ||
| 3601 | /* Process third byte of a quadruplet. */ | 3693 | /* Process third byte of a quadruplet. */ |
| 3602 | 3694 | ||
| 3603 | READ_QUADRUPLET_BYTE (-1); | 3695 | if (!base64url) |
| 3696 | { | ||
| 3697 | READ_QUADRUPLET_BYTE (-1); | ||
| 3698 | } | ||
| 3699 | else | ||
| 3700 | { | ||
| 3701 | READ_QUADRUPLET_BYTE (e-to); | ||
| 3702 | } | ||
| 3604 | 3703 | ||
| 3605 | if (c == '=') | 3704 | if (c == '=') |
| 3606 | { | 3705 | { |
| @@ -3613,7 +3712,7 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3613 | 3712 | ||
| 3614 | if (!IS_BASE64 (c)) | 3713 | if (!IS_BASE64 (c)) |
| 3615 | return -1; | 3714 | return -1; |
| 3616 | value |= base64_char_to_value[c] << 6; | 3715 | value |= b64_char_to_value[c] << 6; |
| 3617 | 3716 | ||
| 3618 | c = (unsigned char) (0xff & value >> 8); | 3717 | c = (unsigned char) (0xff & value >> 8); |
| 3619 | if (multibyte && c >= 128) | 3718 | if (multibyte && c >= 128) |
| @@ -3624,14 +3723,21 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3624 | 3723 | ||
| 3625 | /* Process fourth byte of a quadruplet. */ | 3724 | /* Process fourth byte of a quadruplet. */ |
| 3626 | 3725 | ||
| 3627 | READ_QUADRUPLET_BYTE (-1); | 3726 | if (!base64url) |
| 3727 | { | ||
| 3728 | READ_QUADRUPLET_BYTE (-1); | ||
| 3729 | } | ||
| 3730 | else | ||
| 3731 | { | ||
| 3732 | READ_QUADRUPLET_BYTE (e-to); | ||
| 3733 | } | ||
| 3628 | 3734 | ||
| 3629 | if (c == '=') | 3735 | if (c == '=') |
| 3630 | continue; | 3736 | continue; |
| 3631 | 3737 | ||
| 3632 | if (!IS_BASE64 (c)) | 3738 | if (!IS_BASE64 (c)) |
| 3633 | return -1; | 3739 | return -1; |
| 3634 | value |= base64_char_to_value[c]; | 3740 | value |= b64_char_to_value[c]; |
| 3635 | 3741 | ||
| 3636 | c = (unsigned char) (0xff & value); | 3742 | c = (unsigned char) (0xff & value); |
| 3637 | if (multibyte && c >= 128) | 3743 | if (multibyte && c >= 128) |
| @@ -5461,6 +5567,8 @@ this variable. */); | |||
| 5461 | defsubr (&Sbase64_decode_region); | 5567 | defsubr (&Sbase64_decode_region); |
| 5462 | defsubr (&Sbase64_encode_string); | 5568 | defsubr (&Sbase64_encode_string); |
| 5463 | defsubr (&Sbase64_decode_string); | 5569 | defsubr (&Sbase64_decode_string); |
| 5570 | defsubr (&Sbase64url_encode_region); | ||
| 5571 | defsubr (&Sbase64url_encode_string); | ||
| 5464 | defsubr (&Smd5); | 5572 | defsubr (&Smd5); |
| 5465 | defsubr (&Ssecure_hash_algorithms); | 5573 | defsubr (&Ssecure_hash_algorithms); |
| 5466 | defsubr (&Ssecure_hash); | 5574 | defsubr (&Ssecure_hash); |