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);
45 for ($i=0; $u7len > 0; $i++, $u7len--)
54 if ($u7len && $u7 == '-')
62 for (; $u7len > 0; $i++, $u7len--)
66 if ((ord($u7) & 0x80) || ($b = $Index_64[ord($u7)]) == -1)
79 /* Printable US-ASCII */
80 if (0x20 <= $ch && $ch < 0x7f)
86 $p .= chr(0xc0 | ($ch >> 6));
87 $p .= chr(0x80 | ($ch & 0x3f));
91 $p .= chr(0xe0 | ($ch >> 12));
92 $p .= chr(0x80 | (($ch >> 6) & 0x3f));
93 $p .= chr(0x80 | ($ch & 0x3f));
96 $ch = ($b << (16 + $k)) & 0xffff;
101 /* Non-zero or too many extra bits */
105 /* BASE64 not properly terminated */
106 if (!$u7len || $u7 != '-')
109 /* Adjacent BASE64 sections */
110 if ($u7len > 2 && $str[$i+1] == '&' && $str[$i+2] != '-')
113 /* Not printable US-ASCII */
114 else if (ord($u7) < 0x20 || ord($u7) >= 0x7f)
125 * Convert the data ($str) from UTF-8 to RFC 2060's UTF-7.
126 * Unicode characters above U+FFFF are replaced by U+FFFE.
127 * If input data is invalid, return an empty string.
129 function utf8_to_utf7($str)
132 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
133 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
134 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
135 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
139 $u8len = strlen($str);
189 for ($j=0; $j < $n; $j++)
191 $o = ord($str[$i+$j]);
192 if (($o & 0xc0) != 0x80)
194 $ch = ($ch << 6) | ($o & 0x3f);
197 if ($n > 1 && !($ch >> ($n * 5 + 1)))
203 if ($ch < 0x20 || $ch >= 0x7f)
215 $p .= $B64Chars[($b | $ch >> $k)];
217 for (; $k >= 0; $k -= 6)
218 $p .= $B64Chars[(($ch >> $k) & 0x3f)];
220 $b = ($ch << (-$k)) & 0x3f;