4 * Copyright (C) 2000 Edmund Grimley Evans <edmundo@rano.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * Translated from C to PHP by Thomas Bruederli <roundcube@gmail.com>
21 * Convert the data ($str) from RFC 2060's UTF-7 to UTF-8.
22 * If input data is invalid, return the original input string.
23 * RFC 2060 obviously intends the encoding to be unique (see
24 * point 5 in section 5.1.3), so we reject any non-canonical
25 * form, such as &ACY- (instead of &-) or &AMA-&AMA- (instead
28 function utf7_to_utf8($str)
31 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
32 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
33 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, 63,-1,-1,-1,
34 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
35 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
36 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
37 -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
38 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
41 $u7len = strlen($str);
44 for ($i=0; $u7len > 0; $i++, $u7len--)
53 if ($u7len && $u7 == '-')
61 for (; $u7len > 0; $i++, $u7len--)
65 if ((ord($u7) & 0x80) || ($b = $Index_64[ord($u7)]) == -1)
78 /* Printable US-ASCII */
79 if (0x20 <= $ch && $ch < 0x7f)
85 $p .= chr(0xc0 | ($ch >> 6));
86 $p .= chr(0x80 | ($ch & 0x3f));
90 $p .= chr(0xe0 | ($ch >> 12));
91 $p .= chr(0x80 | (($ch >> 6) & 0x3f));
92 $p .= chr(0x80 | ($ch & 0x3f));
95 $ch = ($b << (16 + $k)) & 0xffff;
100 /* Non-zero or too many extra bits */
104 /* BASE64 not properly terminated */
105 if (!$u7len || $u7 != '-')
108 /* Adjacent BASE64 sections */
109 if ($u7len > 2 && $str{$i+1} == '&' && $str{$i+2} != '-')
112 /* Not printable US-ASCII */
113 else if (ord($u7) < 0x20 || ord($u7) >= 0x7f)
124 * Convert the data ($str) from UTF-8 to RFC 2060's UTF-7.
125 * Unicode characters above U+FFFF are replaced by U+FFFE.
126 * If input data is invalid, return an empty string.
128 function utf8_to_utf7($str)
131 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
132 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
133 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
134 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
138 $u8len = strlen($str);
188 for ($j=0; $j < $n; $j++)
190 $o = ord($str{$i+$j});
191 if (($o & 0xc0) != 0x80)
193 $ch = ($ch << 6) | ($o & 0x3f);
196 if ($n > 1 && !($ch >> ($n * 5 + 1)))
202 if ($ch < 0x20 || $ch >= 0x7f)
214 $p .= $B64Chars[($b | $ch >> $k)];
216 for (; $k >= 0; $k -= 6)
217 $p .= $B64Chars[(($ch >> $k) & 0x3f)];
219 $b = ($ch << (-$k)) & 0x3f;