1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
25: class Horde_Imap_Client_Utf7imap
26: {
27: 28: 29: 30: 31:
32: private static $_index64 = array(
33: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
34: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
35: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, 63, -1, -1, -1,
36: 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
37: -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
38: 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
39: -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
40: 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
41: );
42:
43: 44: 45: 46: 47:
48: private static $_base64 = array(
49: 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
50: 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
51: 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
52: 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
53: '4', '5', '6', '7', '8', '9', '+', ','
54: );
55:
56: 57: 58: 59: 60:
61: private static $_mbstring = null;
62:
63: 64: 65: 66: 67: 68: 69: 70:
71: public static function Utf7ImapToUtf8($str)
72: {
73: if ($str instanceof Horde_Imap_Client_Mailbox) {
74: return $str->utf8;
75: }
76:
77: $str = strval($str);
78:
79: 80:
81: if (is_null(self::$_mbstring)) {
82: self::$_mbstring = extension_loaded('mbstring');
83: }
84: if (self::$_mbstring) {
85: return @mb_convert_encoding($str, 'UTF-8', 'UTF7-IMAP');
86: }
87:
88: $p = '';
89: $ptr = &self::$_index64;
90:
91: for ($i = 0, $u7len = strlen($str); $u7len > 0; ++$i, --$u7len) {
92: $u7 = $str[$i];
93: if ($u7 == '&') {
94: $u7 = $str[++$i];
95: if (--$u7len && ($u7 == '-')) {
96: $p .= '&';
97: continue;
98: }
99:
100: $ch = 0;
101: $k = 10;
102: for (; $u7len > 0; ++$i, --$u7len) {
103: $u7 = $str[$i];
104:
105: if ((ord($u7) & 0x80) || ($b = $ptr[ord($u7)]) == -1) {
106: break;
107: }
108:
109: if ($k > 0) {
110: $ch |= $b << $k;
111: $k -= 6;
112: } else {
113: $ch |= $b >> (-$k);
114: if ($ch < 0x80) {
115:
116: if ((0x20 <= $ch) && ($ch < 0x7f)) {
117: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
118: }
119: $p .= chr($ch);
120: } else if ($ch < 0x800) {
121: $p .= chr(0xc0 | ($ch >> 6)) .
122: chr(0x80 | ($ch & 0x3f));
123: } else {
124: $p .= chr(0xe0 | ($ch >> 12)) .
125: chr(0x80 | (($ch >> 6) & 0x3f)) .
126: chr(0x80 | ($ch & 0x3f));
127: }
128:
129: $ch = ($b << (16 + $k)) & 0xffff;
130: $k += 10;
131: }
132: }
133:
134: 135: 136:
137: if (($ch || ($k < 6)) ||
138: (!$u7len || $u7 != '-') ||
139: (($u7len > 2) &&
140: ($str[$i + 1] == '&') &&
141: ($str[$i + 2] != '-'))) {
142: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
143: }
144: } elseif ((ord($u7) < 0x20) || (ord($u7) >= 0x7f)) {
145:
146: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
147: } else {
148: $p .= $u7;
149: }
150: }
151:
152: return $p;
153: }
154:
155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165:
166: public static function Utf8ToUtf7Imap($str, $force = false)
167: {
168: if ($str instanceof Horde_Imap_Client_Mailbox) {
169: return $str->utf7imap;
170: }
171:
172: $str = strval($str);
173:
174: 175: 176:
177: if (!$force &&
178: !preg_match('/[\x80-\xff]|&$|&(?![,+A-Za-z0-9]*-)/', $str)) {
179: return $str;
180: }
181:
182: 183:
184: if (is_null(self::$_mbstring)) {
185: self::$_mbstring = extension_loaded('mbstring');
186: }
187: if (self::$_mbstring) {
188: return @mb_convert_encoding($str, 'UTF7-IMAP', 'UTF-8');
189: }
190:
191: $u8len = strlen($str);
192: $i = 0;
193: $base64 = false;
194: $p = '';
195: $ptr = &self::$_base64;
196:
197: while ($u8len) {
198: $u8 = $str[$i];
199: $c = ord($u8);
200:
201: if ($c < 0x80) {
202: $ch = $c;
203: $n = 0;
204: } elseif ($c < 0xc2) {
205: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
206: } elseif ($c < 0xe0) {
207: $ch = $c & 0x1f;
208: $n = 1;
209: } elseif ($c < 0xf0) {
210: $ch = $c & 0x0f;
211: $n = 2;
212: } elseif ($c < 0xf8) {
213: $ch = $c & 0x07;
214: $n = 3;
215: } elseif ($c < 0xfc) {
216: $ch = $c & 0x03;
217: $n = 4;
218: } elseif ($c < 0xfe) {
219: $ch = $c & 0x01;
220: $n = 5;
221: } else {
222: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
223: }
224:
225: if ($n > --$u8len) {
226: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
227: }
228:
229: ++$i;
230:
231: for ($j = 0; $j < $n; ++$j) {
232: $o = ord($str[$i + $j]);
233: if (($o & 0xc0) != 0x80) {
234: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
235: }
236: $ch = ($ch << 6) | ($o & 0x3f);
237: }
238:
239: if (($n > 1) && !($ch >> ($n * 5 + 1))) {
240: throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::t("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
241: }
242:
243: $i += $n;
244: $u8len -= $n;
245:
246: if (($ch < 0x20) || ($ch >= 0x7f)) {
247: if (!$base64) {
248: $p .= '&';
249: $base64 = true;
250: $b = 0;
251: $k = 10;
252: }
253:
254: if ($ch & ~0xffff) {
255: $ch = 0xfffe;
256: }
257:
258: $p .= $ptr[($b | $ch >> $k)];
259: $k -= 6;
260: for (; $k >= 0; $k -= 6) {
261: $p .= $ptr[(($ch >> $k) & 0x3f)];
262: }
263:
264: $b = ($ch << (-$k)) & 0x3f;
265: $k += 16;
266: } else {
267: if ($base64) {
268: if ($k > 10) {
269: $p .= $ptr[$b];
270: }
271: $p .= '-';
272: $base64 = false;
273: }
274:
275: $p .= chr($ch);
276: if (chr($ch) == '&') {
277: $p .= '-';
278: }
279: }
280: }
281:
282: if ($base64) {
283: if ($k > 10) {
284: $p .= $ptr[$b];
285: }
286: $p .= '-';
287: }
288:
289: return $p;
290: }
291:
292: }
293: