2 ** Copyright 2000-2003 Double Precision, Inc.
3 ** See COPYING for distribution information.
7 #include "unicode_config.h"
12 static const char rcsid
[]="$Id: utf7imap.c,v 1.6 2004/05/23 14:28:25 mrsam Exp $";
14 static const char mbase64
[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
16 static char mbase64_lookup
[256];
17 static int mbase64_lookup_init
=0;
19 unicode_char
*unicode_modutf7touc(const char *s
, int *err
)
21 size_t l
=strlen(s
), i
;
22 unicode_char
*uc
=malloc(sizeof(unicode_char
)*(l
+1));
23 /* That's the worst case scenario, that's all. */
31 /* First time through - initialize fast lookup table */
33 if (!mbase64_lookup_init
)
35 mbase64_lookup_init
=1;
38 mbase64_lookup
[i
]= (char)-1;
40 for (i
=0; mbase64
[i
]; i
++)
41 mbase64_lookup
[(int)mbase64
[i
]]=i
;
50 if ( s
[l
] < 0x20 || s
[l
] >= 0x7F )
59 uc
[i
++]= (int)(unsigned char)s
[l
];
72 for ( ; s
[l
] != '-'; l
++)
77 mbase64_lookup
[s
[l
] & 255]) == (char)-1)
84 if (bitcount
+ 6 >= 16)
85 /* These six more bits are enough for UCS2 */
87 int n
=bitcount
+ 6 - 16; /* Leftover */
89 uu
= (uu
<< (6-n
)) | (bits
>> n
);
90 uc
[i
++] = (uu
& 0xFFFF);
92 uu
= bits
; /* The leftovers */
97 uu
= (uu
<< 6) | bits
;
106 static size_t uctoutf7_pass(const unicode_char
*, const unicode_char
*,
109 char *unicode_uctomodutf7(const unicode_char
*p
)
111 return unicode_uctomodutf7x(p
, NULL
);
114 char *unicode_uctomodutf7x(const unicode_char
*p
,
115 const unicode_char
*specials
)
117 size_t n
=uctoutf7_pass(p
, specials
, NULL
);
121 uctoutf7_pass(p
, specials
, s
);
125 static int is_special(unicode_char uc
, const unicode_char
*specials
)
127 while (specials
&& *specials
)
128 if (*specials
++ == uc
)
131 return uc
< 0x20 || uc
>= 0x7F;
134 static size_t uctoutf7_pass(const unicode_char
*uc
,
135 const unicode_char
*specials
,
142 unsigned bits
, bitcount
;
144 if (!is_special(*uc
, specials
))
146 /* Straightforward deal for straightforward ASCII */
160 if (p
) *p
++ = '&'; /* Begin modified base64 */
164 while ( *uc
&& is_special(*uc
, specials
))
166 unicode_char uu
= *uc
++ & 0xFFFF;
171 /* Process 16 bits */
177 if (counter
+ bitcount
< 6)
179 /* Add these bits, then we're done */
181 bits
= (bits
<< counter
) |
182 (uu
>> (16-counter
));
187 /* Have enough bits to encode */
191 bits
= (bits
<< x
) | (uu
>> (16-x
));
192 uu
= (uu
<< x
) & 0xFFFF;
196 *p
++ = mbase64
[bits
];
202 if (bitcount
) /* Leftovers */
204 bits
<<= (6-bitcount
);
206 *p
++ = mbase64
[bits
];
213 /* End modified base64 */
222 static char *toupper_func(const struct unicode_info
*u
,
223 const char *cp
, int *ip
)
225 unicode_char
*uc
=unicode_modutf7touc(cp
, ip
), *p
;
233 s
=unicode_uctomodutf7(uc
);
240 static char *tolower_func(const struct unicode_info
*u
,
241 const char *cp
, int *ip
)
243 unicode_char
*uc
=unicode_modutf7touc(cp
, ip
), *p
;
251 s
=unicode_uctomodutf7(uc
);
258 static char *totitle_func(const struct unicode_info
*u
,
259 const char *cp
, int *ip
)
261 unicode_char
*uc
=unicode_modutf7touc(cp
, ip
), *p
;
269 s
=unicode_uctomodutf7(uc
);
276 static unicode_char
*tou(const struct unicode_info
*ui
, const char *cs
,
279 return unicode_modutf7touc(cs
, err
);
283 static char *fromu(const struct unicode_info
*ui
,
284 const unicode_char
*uc
, int *err
)
287 return unicode_uctomodutf7(uc
);
290 const struct unicode_info unicode_IMAP_MODUTF7
= {
292 UNICODE_UTF
| UNICODE_MB
|
293 UNICODE_HEADER_BASE64
,