84static size_t mb_utf7imap_to_wchar(
unsigned char **in,
size_t *in_len, uint32_t *
buf,
size_t bufsize,
unsigned int *
state);
86static bool mb_check_utf7imap(
unsigned char *in,
size_t in_len);
88static const char *mbfl_encoding_utf7imap_aliases[] = {
"mUTF-7",
NULL};
94 mbfl_encoding_utf7imap_aliases,
100 mb_wchar_to_utf7imap,
111 mbfl_filt_conv_utf7imap_wchar_flush,
121 mbfl_filt_conv_wchar_utf7imap_flush,
125#define CK(statement) do { if ((statement) < 0) return (-1); } while (0)
131 if (filter->
status != 0) {
132 if (c >=
'A' && c <=
'Z') {
134 }
else if (c >=
'a' && c <=
'z') {
136 }
else if (c >=
'0' && c <=
'9') {
138 }
else if (c ==
'+') {
140 }
else if (c ==
',') {
146 if (filter->
status == 1) {
149 }
else if (filter->
cache) {
171 }
else if (c >= 0x20 && c <= 0x7E) {
189 s = ((
n >> 2) & 0xf) | (filter->
cache & 0xffff);
192 if (
s >= 0xd800 &&
s < 0xdc00) {
194 s = (((
s & 0x3ff) << 16) + 0x400000) |
n;
196 }
else if (
s >= 0xdc00 &&
s < 0xe000) {
198 if (filter->
cache & 0xfff0000) {
200 s |= (filter->
cache & 0xfff0000) >> 6;
227 s = ((
n >> 4) & 0x3) | (filter->
cache & 0xffff);
230 if (
s >= 0xd800 &&
s < 0xdc00) {
231 s = (((
s & 0x3ff) << 16) + 0x400000) |
n;
233 }
else if (
s >= 0xdc00 &&
s < 0xe000) {
234 if (filter->
cache & 0xfff0000) {
236 s |= (filter->
cache & 0xfff0000) >> 6;
259 s =
n | (filter->
cache & 0xffff);
261 if (
s >= 0xd800 &&
s < 0xdc00) {
262 s = (((
s & 0x3ff) << 16) + 0x400000);
264 }
else if (
s >= 0xdc00 &&
s < 0xe000) {
265 if (filter->
cache & 0xfff0000) {
267 s |= (filter->
cache & 0xfff0000) >> 6;
307static const unsigned char mbfl_utf7imap_base64_table[] =
310 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,
312 0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,
314 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
316 0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,
318 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2b,0x2c,0x00
327 }
else if ((c >= 0x20 && c <= 0x7e) || c == 0) {
332 s = ((c >> 10) - 0x40) | 0xd800;
334 s = (c & 0x3ff) | 0xdc00;
371 filter->
cache = ((
s & 0xf) << 16) | c;
390 filter->
cache = ((
s & 0x3) << 16) | c;
451static inline bool is_base64_end(
unsigned char c)
456static unsigned char decode_base64(
unsigned char c)
458 if (c >=
'A' && c <=
'Z') {
460 }
else if (c >=
'a' && c <=
'z') {
462 }
else if (c >=
'0' && c <=
'9') {
464 }
else if (c ==
'+') {
466 }
else if (c ==
',') {
468 }
else if (c ==
'-') {
474static uint32_t* handle_utf16_cp(uint16_t
cp, uint32_t *
out, uint16_t *surrogate1)
478 if (
cp >= 0xDC00 &&
cp <= 0xDFFF) {
479 *
out++ = ((*surrogate1 & 0x3FF) << 10) + (
cp & 0x3FF) + 0x10000;
486 }
else if (
cp >= 0xD800 &&
cp <= 0xDBFF) {
488 }
else if (
cp >= 0xDC00 &&
cp <= 0xDFFF) {
491 }
else if (
cp >= 0x20 &&
cp <= 0x7E &&
cp !=
'&') {
499static uint32_t* handle_base64_end(
unsigned char n, uint32_t *
out,
bool *base64,
bool abrupt, uint16_t *surrogate1)
501 if (abrupt ||
n ==
ILLEGAL || *surrogate1) {
510static size_t mb_utf7imap_to_wchar(
unsigned char **in,
size_t *in_len, uint32_t *
buf,
size_t bufsize,
unsigned int *
state)
518 unsigned char *
p = *in, *e =
p + *in_len;
521 uint32_t *
out =
buf, *limit =
buf + bufsize - 1;
523 bool base64 = *
state & 1;
524 uint16_t surrogate1 = (*
state >> 1);
526 while (
p < e &&
out < limit) {
529 if ((limit -
out) < 4) {
533 unsigned char n1 = decode_base64(*
p++);
534 if (is_base64_end(n1)) {
535 out = handle_base64_end(n1,
out, &base64,
false, &surrogate1);
538 out = handle_base64_end(n1,
out, &base64,
true, &surrogate1);
541 unsigned char n2 = decode_base64(*
p++);
542 if (is_base64_end(n2) ||
p == e) {
543 out = handle_base64_end(n2,
out, &base64,
true, &surrogate1);
546 unsigned char n3 = decode_base64(*
p++);
547 if (is_base64_end(n3)) {
548 out = handle_base64_end(n3,
out, &base64,
true, &surrogate1);
551 out = handle_utf16_cp((n1 << 10) | (n2 << 4) | ((n3 & 0x3C) >> 2),
out, &surrogate1);
555 if ((n3 & 0x3) || surrogate1)
560 unsigned char n4 = decode_base64(*
p++);
561 if (is_base64_end(n4)) {
562 out = handle_base64_end(n4,
out, &base64, n3 & 0x3, &surrogate1);
565 out = handle_base64_end(n4,
out, &base64,
true, &surrogate1);
568 unsigned char n5 = decode_base64(*
p++);
569 if (is_base64_end(n5) ||
p == e) {
570 out = handle_base64_end(n5,
out, &base64,
true, &surrogate1);
573 unsigned char n6 = decode_base64(*
p++);
574 if (is_base64_end(n6)) {
575 out = handle_base64_end(n6,
out, &base64,
true, &surrogate1);
578 out = handle_utf16_cp((n3 << 14) | (n4 << 8) | (n5 << 2) | ((n6 & 0x30) >> 4),
out, &surrogate1);
580 if ((n6 & 0xF) || surrogate1)
585 unsigned char n7 = decode_base64(*
p++);
586 if (is_base64_end(n7)) {
587 out = handle_base64_end(n7,
out, &base64, n6 & 0xF, &surrogate1);
590 out = handle_base64_end(n7,
out, &base64,
true, &surrogate1);
593 unsigned char n8 = decode_base64(*
p++);
594 if (is_base64_end(n8)) {
595 out = handle_base64_end(n8,
out, &base64,
true, &surrogate1);
598 out = handle_utf16_cp((n6 << 12) | (n7 << 6) | n8,
out, &surrogate1);
600 unsigned char c = *
p++;
603 if (
p < e && *
p ==
'-') {
609 }
else if (c >= 0x20 && c <= 0x7E) {
617 if (
p == e && base64) {
624 *
state = (surrogate1 << 1) | base64;
630#define SAVE_CONVERSION_STATE() buf->state = (cache << 4) | (nbits << 1) | base64
631#define RESTORE_CONVERSION_STATE() base64 = (buf->state & 1); nbits = (buf->state >> 1) & 0x7; cache = (buf->state >> 4)
633static const unsigned char mbfl_base64_table[] = {
635 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,
637 0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,
639 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,
641 0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,
643 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2b,0x2c,0x00
648 unsigned char *
out, *limit;
653 unsigned char nbits, cache;
659 if (w >= 0x20 && w <= 0x7E) {
668 out = mb_convert_buf_add(
out, mbfl_base64_table[(cache << (6 - nbits)) & 0x3F]);
671 out = mb_convert_buf_add(
out,
'-');
688 bits = ((uint64_t)cache << 32) | 0xD800DC00L | ((w & 0xFFC00) << 6) | (w & 0x3FF);
692 bits = (cache << 16) | w;
697 out = mb_convert_buf_add(
out, mbfl_base64_table[(bits >> (nbits - 6)) & 0x3F]);
706 out = mb_convert_buf_add2(
out,
'&',
'-');
707 }
else if (w >= 0x20 && w <= 0x7E) {
708 out = mb_convert_buf_add(
out, w);
715 out = mb_convert_buf_add(
out,
'&');
724 out = mb_convert_buf_add(
out, mbfl_base64_table[(cache << (6 - nbits)) & 0x3F]);
728 out = mb_convert_buf_add(
out,
'-');
737static bool is_utf16_cp_valid(uint16_t
cp,
bool is_surrogate)
740 return cp >= 0xDC00 &&
cp <= 0xDFFF;
741 }
else if (
cp >= 0xDC00 &&
cp <= 0xDFFF) {
744 }
else if (
cp >= 0x20 &&
cp <= 0x7E &&
cp !=
'&') {
750static bool mb_check_utf7imap(
unsigned char *in,
size_t in_len)
752 unsigned char *
p = in, *e =
p + in_len;
754 bool is_surrogate =
false;
759 unsigned char n1 = decode_base64(*
p++);
760 if (is_base64_end(n1)) {
761 if (!is_base64_end_valid(n1,
false, is_surrogate)) {
769 unsigned char n2 = decode_base64(*
p++);
770 if (is_base64_end(n2) ||
p == e) {
773 unsigned char n3 = decode_base64(*
p++);
774 if (is_base64_end(n3)) {
777 uint16_t cp1 = (n1 << 10) | (n2 << 4) | ((n3 & 0x3C) >> 2);
778 if (!is_utf16_cp_valid(cp1, is_surrogate)) {
781 is_surrogate = has_surrogate(cp1, is_surrogate);
786 unsigned char n4 = decode_base64(*
p++);
787 if (is_base64_end(n4)) {
788 if (!is_base64_end_valid(n4, n3 & 0x3, is_surrogate)) {
796 unsigned char n5 = decode_base64(*
p++);
797 if (is_base64_end(n5) ||
p == e) {
800 unsigned char n6 = decode_base64(*
p++);
801 if (is_base64_end(n6)) {
804 uint16_t cp2 = (n3 << 14) | (n4 << 8) | (n5 << 2) | ((n6 & 0x30) >> 4);
805 if (!is_utf16_cp_valid(cp2, is_surrogate)) {
808 is_surrogate = has_surrogate(cp2, is_surrogate);
813 unsigned char n7 = decode_base64(*
p++);
814 if (is_base64_end(n7)) {
815 if (!is_base64_end_valid(n7, n6 & 0xF, is_surrogate)) {
823 unsigned char n8 = decode_base64(*
p++);
824 if (is_base64_end(n8)) {
827 uint16_t cp3 = (n6 << 12) | (n7 << 6) | n8;
828 if (!is_utf16_cp_valid(cp3, is_surrogate)) {
831 is_surrogate = has_surrogate(cp3, is_surrogate);
834 unsigned char c = *
p++;
840 unsigned char n = decode_base64(*
p);
848 }
else if (c >= 0x20 && c <= 0x7E) {
zend_ffi_ctype_name_buf buf
const struct mbfl_convert_vtbl vtbl_utf7imap_wchar
int mbfl_filt_conv_wchar_utf7imap(int c, mbfl_convert_filter *filter)
int mbfl_filt_conv_utf7imap_wchar(int c, mbfl_convert_filter *filter)
#define SAVE_CONVERSION_STATE()
const mbfl_encoding mbfl_encoding_utf7imap
#define RESTORE_CONVERSION_STATE()
const struct mbfl_convert_vtbl vtbl_wchar_utf7imap
#define MBFL_WCSPLANE_UCS2MAX
#define MBFL_WCSPLANE_SUPMAX
#define MBFL_WCSPLANE_UTF32MAX
#define MBFL_WCSPLANE_SUPMIN
int mbfl_filt_conv_illegal_output(int c, mbfl_convert_filter *filter)
void mbfl_filt_conv_common_ctor(mbfl_convert_filter *filter)
struct _mbfl_convert_filter mbfl_convert_filter
@ mbfl_no_encoding_utf7imap
#define MB_CONVERT_BUF_STORE(buf, _out, _limit)
#define MB_CONVERT_BUF_ENSURE(buf, out, limit, needed)
#define MB_CONVERT_ERROR(buf, out, limit, bad_cp, conv_fn)
#define MB_CONVERT_BUF_LOAD(buf, _out, _limit)
unsigned const char * end
output_function_t output_function
int(* filter_function)(int c, mbfl_convert_filter *filter)
flush_function_t flush_function
#define EMPTY_SWITCH_DEFAULT_CASE()