diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 221 |
1 files changed, 124 insertions, 97 deletions
| @@ -3186,33 +3186,11 @@ The data read from the system are decoded using `locale-coding-system'. */) | |||
| 3186 | 3186 | ||
| 3187 | #define MIME_LINE_LENGTH 76 | 3187 | #define MIME_LINE_LENGTH 76 |
| 3188 | 3188 | ||
| 3189 | #define IS_ASCII(Character) \ | 3189 | /* Tables of characters coding the 64 values. */ |
| 3190 | ((Character) < 128) | 3190 | static char const base64_value_to_char[2][64] = |
| 3191 | #define IS_BASE64(Character) \ | ||
| 3192 | (IS_ASCII (Character) && b64_char_to_value[Character] >= 0) | ||
| 3193 | #define IS_BASE64_IGNORABLE(Character) \ | ||
| 3194 | ((Character) == ' ' || (Character) == '\t' || (Character) == '\n' \ | ||
| 3195 | || (Character) == '\f' || (Character) == '\r') | ||
| 3196 | |||
| 3197 | /* Used by base64_decode_1 to retrieve a non-base64-ignorable | ||
| 3198 | character or return retval if there are no characters left to | ||
| 3199 | process. */ | ||
| 3200 | #define READ_QUADRUPLET_BYTE(retval) \ | ||
| 3201 | do \ | ||
| 3202 | { \ | ||
| 3203 | if (i == length) \ | ||
| 3204 | { \ | ||
| 3205 | if (nchars_return) \ | ||
| 3206 | *nchars_return = nchars; \ | ||
| 3207 | return (retval); \ | ||
| 3208 | } \ | ||
| 3209 | c = from[i++]; \ | ||
| 3210 | } \ | ||
| 3211 | while (IS_BASE64_IGNORABLE (c)) | ||
| 3212 | |||
| 3213 | /* Table of characters coding the 64 values. */ | ||
| 3214 | static const char base64_value_to_char[64] = | ||
| 3215 | { | 3191 | { |
| 3192 | /* base64 */ | ||
| 3193 | { | ||
| 3216 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */ | 3194 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */ |
| 3217 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */ | 3195 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */ |
| 3218 | 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */ | 3196 | 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */ |
| @@ -3220,10 +3198,9 @@ static const char base64_value_to_char[64] = | |||
| 3220 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */ | 3198 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */ |
| 3221 | 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */ | 3199 | 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */ |
| 3222 | '8', '9', '+', '/' /* 60-63 */ | 3200 | '8', '9', '+', '/' /* 60-63 */ |
| 3223 | }; | 3201 | }, |
| 3224 | 3202 | /* base64url */ | |
| 3225 | static const char base64url_value_to_char[64] = | 3203 | { |
| 3226 | { | ||
| 3227 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */ | 3204 | '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 */ | 3205 | '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 */ | 3206 | 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */ |
| @@ -3231,41 +3208,47 @@ static const char base64url_value_to_char[64] = | |||
| 3231 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */ | 3208 | '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 */ | 3209 | 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */ |
| 3233 | '8', '9', '-', '_' /* 60-63 */ | 3210 | '8', '9', '-', '_' /* 60-63 */ |
| 3211 | } | ||
| 3234 | }; | 3212 | }; |
| 3235 | 3213 | ||
| 3236 | /* Table of base64 values for first 128 characters. */ | 3214 | /* Tables of base64 values for bytes. -1 means ignorable, 0 invalid, |
| 3237 | static const short base64_char_to_value[128] = | 3215 | positive means 1 + the represented value. */ |
| 3238 | { | 3216 | static signed char const base64_char_to_value[2][UCHAR_MAX] = |
| 3239 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */ | 3217 | { |
| 3240 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */ | 3218 | /* base64 */ |
| 3241 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */ | 3219 | { |
| 3242 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */ | 3220 | ['\t']= -1, ['\n']= -1, ['\f']= -1, ['\r']= -1, [' '] = -1, |
| 3243 | -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */ | 3221 | ['A'] = 1, ['B'] = 2, ['C'] = 3, ['D'] = 4, ['E'] = 5, |
| 3244 | 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */ | 3222 | ['F'] = 6, ['G'] = 7, ['H'] = 8, ['I'] = 9, ['J'] = 10, |
| 3245 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */ | 3223 | ['K'] = 11, ['L'] = 12, ['M'] = 13, ['N'] = 14, ['O'] = 15, |
| 3246 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */ | 3224 | ['P'] = 16, ['Q'] = 17, ['R'] = 18, ['S'] = 19, ['T'] = 20, |
| 3247 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */ | 3225 | ['U'] = 21, ['V'] = 22, ['W'] = 23, ['X'] = 24, ['Y'] = 25, ['Z'] = 26, |
| 3248 | 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */ | 3226 | ['a'] = 27, ['b'] = 28, ['c'] = 29, ['d'] = 30, ['e'] = 31, |
| 3249 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */ | 3227 | ['f'] = 32, ['g'] = 33, ['h'] = 34, ['i'] = 35, ['j'] = 36, |
| 3250 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */ | 3228 | ['k'] = 37, ['l'] = 38, ['m'] = 39, ['n'] = 40, ['o'] = 41, |
| 3251 | 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ | 3229 | ['p'] = 42, ['q'] = 43, ['r'] = 44, ['s'] = 45, ['t'] = 46, |
| 3252 | }; | 3230 | ['u'] = 47, ['v'] = 48, ['w'] = 49, ['x'] = 50, ['y'] = 51, ['z'] = 52, |
| 3253 | 3231 | ['0'] = 53, ['1'] = 54, ['2'] = 55, ['3'] = 56, ['4'] = 57, | |
| 3254 | static const short base64url_char_to_value[128] = | 3232 | ['5'] = 58, ['6'] = 59, ['7'] = 60, ['8'] = 61, ['9'] = 62, |
| 3255 | { | 3233 | ['+'] = 63, ['/'] = 64 |
| 3256 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */ | 3234 | }, |
| 3257 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */ | 3235 | /* base64url */ |
| 3258 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */ | 3236 | { |
| 3259 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */ | 3237 | ['\t']= -1, ['\n']= -1, ['\f']= -1, ['\r']= -1, [' '] = -1, |
| 3260 | -1, -1, -1, -1, -1, 62, -1, -1, 52, 53, /* 40- 49 */ | 3238 | ['A'] = 1, ['B'] = 2, ['C'] = 3, ['D'] = 4, ['E'] = 5, |
| 3261 | 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */ | 3239 | ['F'] = 6, ['G'] = 7, ['H'] = 8, ['I'] = 9, ['J'] = 10, |
| 3262 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */ | 3240 | ['K'] = 11, ['L'] = 12, ['M'] = 13, ['N'] = 14, ['O'] = 15, |
| 3263 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */ | 3241 | ['P'] = 16, ['Q'] = 17, ['R'] = 18, ['S'] = 19, ['T'] = 20, |
| 3264 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */ | 3242 | ['U'] = 21, ['V'] = 22, ['W'] = 23, ['X'] = 24, ['Y'] = 25, ['Z'] = 26, |
| 3265 | 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, /* 90- 99 */ | 3243 | ['a'] = 27, ['b'] = 28, ['c'] = 29, ['d'] = 30, ['e'] = 31, |
| 3266 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */ | 3244 | ['f'] = 32, ['g'] = 33, ['h'] = 34, ['i'] = 35, ['j'] = 36, |
| 3267 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */ | 3245 | ['k'] = 37, ['l'] = 38, ['m'] = 39, ['n'] = 40, ['o'] = 41, |
| 3268 | 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ | 3246 | ['p'] = 42, ['q'] = 43, ['r'] = 44, ['s'] = 45, ['t'] = 46, |
| 3247 | ['u'] = 47, ['v'] = 48, ['w'] = 49, ['x'] = 50, ['y'] = 51, ['z'] = 52, | ||
| 3248 | ['0'] = 53, ['1'] = 54, ['2'] = 55, ['3'] = 56, ['4'] = 57, | ||
| 3249 | ['5'] = 58, ['6'] = 59, ['7'] = 60, ['8'] = 61, ['9'] = 62, | ||
| 3250 | ['-'] = 63, ['_'] = 64 | ||
| 3251 | } | ||
| 3269 | }; | 3252 | }; |
| 3270 | 3253 | ||
| 3271 | /* The following diagram shows the logical steps by which three octets | 3254 | /* The following diagram shows the logical steps by which three octets |
| @@ -3454,7 +3437,7 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3454 | int c; | 3437 | int c; |
| 3455 | unsigned int value; | 3438 | unsigned int value; |
| 3456 | int bytes; | 3439 | int bytes; |
| 3457 | char const *b64_value_to_char = (base64url) ? base64url_value_to_char : base64_value_to_char; | 3440 | char const *b64_value_to_char = base64_value_to_char[base64url]; |
| 3458 | 3441 | ||
| 3459 | while (i < length) | 3442 | while (i < length) |
| 3460 | { | 3443 | { |
| @@ -3632,8 +3615,9 @@ the base 64 encoding, as defined in RFC 4648. */) | |||
| 3632 | decoded = SAFE_ALLOCA (length); | 3615 | decoded = SAFE_ALLOCA (length); |
| 3633 | 3616 | ||
| 3634 | /* The decoded result should be unibyte. */ | 3617 | /* The decoded result should be unibyte. */ |
| 3618 | ptrdiff_t decoded_chars; | ||
| 3635 | decoded_length = base64_decode_1 (SSDATA (string), decoded, length, | 3619 | decoded_length = base64_decode_1 (SSDATA (string), decoded, length, |
| 3636 | !NILP (base64url), 0, NULL); | 3620 | !NILP (base64url), 0, &decoded_chars); |
| 3637 | if (decoded_length > length) | 3621 | if (decoded_length > length) |
| 3638 | emacs_abort (); | 3622 | emacs_abort (); |
| 3639 | else if (decoded_length >= 0) | 3623 | else if (decoded_length >= 0) |
| @@ -3650,41 +3634,60 @@ the base 64 encoding, as defined in RFC 4648. */) | |||
| 3650 | 3634 | ||
| 3651 | /* Base64-decode the data at FROM of LENGTH bytes into TO. If | 3635 | /* Base64-decode the data at FROM of LENGTH bytes into TO. If |
| 3652 | MULTIBYTE, the decoded result should be in multibyte | 3636 | MULTIBYTE, the decoded result should be in multibyte |
| 3653 | form. If NCHARS_RETURN is not NULL, store the number of produced | 3637 | form. Store the number of produced characters in *NCHARS_RETURN. */ |
| 3654 | characters in *NCHARS_RETURN. */ | ||
| 3655 | 3638 | ||
| 3656 | static ptrdiff_t | 3639 | static ptrdiff_t |
| 3657 | base64_decode_1 (const char *from, char *to, ptrdiff_t length, | 3640 | base64_decode_1 (const char *from, char *to, ptrdiff_t length, |
| 3658 | bool base64url, | 3641 | bool base64url, |
| 3659 | bool multibyte, ptrdiff_t *nchars_return) | 3642 | bool multibyte, ptrdiff_t *nchars_return) |
| 3660 | { | 3643 | { |
| 3661 | ptrdiff_t i = 0; /* Used inside READ_QUADRUPLET_BYTE */ | 3644 | char const *f = from; |
| 3645 | char const *flim = from + length; | ||
| 3662 | char *e = to; | 3646 | char *e = to; |
| 3663 | unsigned char c; | ||
| 3664 | unsigned long value; | ||
| 3665 | ptrdiff_t nchars = 0; | 3647 | ptrdiff_t nchars = 0; |
| 3666 | short const *b64_char_to_value = (base64url) ? base64url_char_to_value : base64_char_to_value; | 3648 | signed char const *b64_char_to_value = base64_char_to_value[base64url]; |
| 3649 | unsigned char multibyte_bit = multibyte << 7; | ||
| 3667 | 3650 | ||
| 3668 | while (1) | 3651 | while (true) |
| 3669 | { | 3652 | { |
| 3653 | unsigned char c; | ||
| 3654 | int v1; | ||
| 3655 | |||
| 3670 | /* Process first byte of a quadruplet. */ | 3656 | /* Process first byte of a quadruplet. */ |
| 3671 | 3657 | ||
| 3672 | READ_QUADRUPLET_BYTE (e-to); | 3658 | do |
| 3659 | { | ||
| 3660 | if (f == flim) | ||
| 3661 | { | ||
| 3662 | *nchars_return = nchars; | ||
| 3663 | return e - to; | ||
| 3664 | } | ||
| 3665 | c = *f++; | ||
| 3666 | v1 = b64_char_to_value[c]; | ||
| 3667 | } | ||
| 3668 | while (v1 < 0); | ||
| 3673 | 3669 | ||
| 3674 | if (!IS_BASE64 (c)) | 3670 | if (v1 == 0) |
| 3675 | return -1; | 3671 | return -1; |
| 3676 | value = b64_char_to_value[c] << 18; | 3672 | unsigned int value = (v1 - 1) << 18; |
| 3677 | 3673 | ||
| 3678 | /* Process second byte of a quadruplet. */ | 3674 | /* Process second byte of a quadruplet. */ |
| 3679 | 3675 | ||
| 3680 | READ_QUADRUPLET_BYTE (-1); | 3676 | do |
| 3677 | { | ||
| 3678 | if (f == flim) | ||
| 3679 | return -1; | ||
| 3680 | c = *f++; | ||
| 3681 | v1 = b64_char_to_value[c]; | ||
| 3682 | } | ||
| 3683 | while (v1 < 0); | ||
| 3681 | 3684 | ||
| 3682 | if (!IS_BASE64 (c)) | 3685 | if (v1 == 0) |
| 3683 | return -1; | 3686 | return -1; |
| 3684 | value |= b64_char_to_value[c] << 12; | 3687 | value += (v1 - 1) << 12; |
| 3685 | 3688 | ||
| 3686 | c = (unsigned char) (value >> 16); | 3689 | c = value >> 16 & 0xff; |
| 3687 | if (multibyte && c >= 128) | 3690 | if (c & multibyte_bit) |
| 3688 | e += BYTE8_STRING (c, e); | 3691 | e += BYTE8_STRING (c, e); |
| 3689 | else | 3692 | else |
| 3690 | *e++ = c; | 3693 | *e++ = c; |
| @@ -3692,26 +3695,41 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3692 | 3695 | ||
| 3693 | /* Process third byte of a quadruplet. */ | 3696 | /* Process third byte of a quadruplet. */ |
| 3694 | 3697 | ||
| 3695 | if (!base64url) | 3698 | do |
| 3696 | READ_QUADRUPLET_BYTE (-1); | 3699 | { |
| 3697 | else | 3700 | if (f == flim) |
| 3698 | READ_QUADRUPLET_BYTE (e-to); | 3701 | { |
| 3702 | if (!base64url) | ||
| 3703 | return -1; | ||
| 3704 | *nchars_return = nchars; | ||
| 3705 | return e - to; | ||
| 3706 | } | ||
| 3707 | c = *f++; | ||
| 3708 | v1 = b64_char_to_value[c]; | ||
| 3709 | } | ||
| 3710 | while (v1 < 0); | ||
| 3699 | 3711 | ||
| 3700 | if (c == '=') | 3712 | if (c == '=') |
| 3701 | { | 3713 | { |
| 3702 | READ_QUADRUPLET_BYTE (-1); | 3714 | do |
| 3715 | { | ||
| 3716 | if (f == flim) | ||
| 3717 | return -1; | ||
| 3718 | c = *f++; | ||
| 3719 | } | ||
| 3720 | while (b64_char_to_value[c] < 0); | ||
| 3703 | 3721 | ||
| 3704 | if (c != '=') | 3722 | if (c != '=') |
| 3705 | return -1; | 3723 | return -1; |
| 3706 | continue; | 3724 | continue; |
| 3707 | } | 3725 | } |
| 3708 | 3726 | ||
| 3709 | if (!IS_BASE64 (c)) | 3727 | if (v1 == 0) |
| 3710 | return -1; | 3728 | return -1; |
| 3711 | value |= b64_char_to_value[c] << 6; | 3729 | value += (v1 - 1) << 6; |
| 3712 | 3730 | ||
| 3713 | c = (unsigned char) (0xff & value >> 8); | 3731 | c = value >> 8 & 0xff; |
| 3714 | if (multibyte && c >= 128) | 3732 | if (c & multibyte_bit) |
| 3715 | e += BYTE8_STRING (c, e); | 3733 | e += BYTE8_STRING (c, e); |
| 3716 | else | 3734 | else |
| 3717 | *e++ = c; | 3735 | *e++ = c; |
| @@ -3719,20 +3737,29 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length, | |||
| 3719 | 3737 | ||
| 3720 | /* Process fourth byte of a quadruplet. */ | 3738 | /* Process fourth byte of a quadruplet. */ |
| 3721 | 3739 | ||
| 3722 | if (!base64url) | 3740 | do |
| 3723 | READ_QUADRUPLET_BYTE (-1); | 3741 | { |
| 3724 | else | 3742 | if (f == flim) |
| 3725 | READ_QUADRUPLET_BYTE (e-to); | 3743 | { |
| 3744 | if (!base64url) | ||
| 3745 | return -1; | ||
| 3746 | *nchars_return = nchars; | ||
| 3747 | return e - to; | ||
| 3748 | } | ||
| 3749 | c = *f++; | ||
| 3750 | v1 = b64_char_to_value[c]; | ||
| 3751 | } | ||
| 3752 | while (v1 < 0); | ||
| 3726 | 3753 | ||
| 3727 | if (c == '=') | 3754 | if (c == '=') |
| 3728 | continue; | 3755 | continue; |
| 3729 | 3756 | ||
| 3730 | if (!IS_BASE64 (c)) | 3757 | if (v1 < 0) |
| 3731 | return -1; | 3758 | return -1; |
| 3732 | value |= b64_char_to_value[c]; | 3759 | value += v1 - 1; |
| 3733 | 3760 | ||
| 3734 | c = (unsigned char) (0xff & value); | 3761 | c = value & 0xff; |
| 3735 | if (multibyte && c >= 128) | 3762 | if (c & multibyte_bit) |
| 3736 | e += BYTE8_STRING (c, e); | 3763 | e += BYTE8_STRING (c, e); |
| 3737 | else | 3764 | else |
| 3738 | *e++ = c; | 3765 | *e++ = c; |