Overview

Packages

  • Imap
    • Client

Classes

  • Horde_Imap_Client
  • Horde_Imap_Client_Auth_DigestMD5
  • Horde_Imap_Client_Base
  • Horde_Imap_Client_Cache
  • Horde_Imap_Client_Data_Acl
  • Horde_Imap_Client_Data_AclCommon
  • Horde_Imap_Client_Data_AclNegative
  • Horde_Imap_Client_Data_AclRights
  • Horde_Imap_Client_Data_Envelope
  • Horde_Imap_Client_Data_Fetch
  • Horde_Imap_Client_Data_Fetch_Pop3
  • Horde_Imap_Client_Data_Thread
  • Horde_Imap_Client_DateTime
  • Horde_Imap_Client_Exception
  • Horde_Imap_Client_Exception_NoSupportExtension
  • Horde_Imap_Client_Fetch_Query
  • Horde_Imap_Client_Ids
  • Horde_Imap_Client_Ids_Pop3
  • Horde_Imap_Client_Mailbox
  • Horde_Imap_Client_Search_Query
  • Horde_Imap_Client_Socket
  • Horde_Imap_Client_Socket_Pop3
  • Horde_Imap_Client_Sort
  • Horde_Imap_Client_Translation
  • Horde_Imap_Client_Utf7imap
  • Horde_Imap_Client_Utils
  • Horde_Imap_Client_Utils_Pop3
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Allows conversions between UTF-8 and UTF7-IMAP (RFC 3501 [5.1.3]).
  4:  *
  5:  * Originally based on code:
  6:  *
  7:  *  Copyright (C) 2000 Edmund Grimley Evans <edmundo@rano.org>
  8:  *  Released under the GPL (version 2)
  9:  *
 10:  *  Translated from C to PHP by Thomas Bruederli <roundcube@gmail.com>
 11:  *  Code extracted from the RoundCube Webmail (http://roundcube.net) project,
 12:  *    SVN revision 1757
 13:  *  The RoundCube project is released under the GPL (version 2)
 14:  *
 15:  * Copyright 2008-2012 Horde LLC (http://www.horde.org/)
 16:  *
 17:  * See the enclosed file COPYING for license information (LGPL). If you
 18:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 19:  *
 20:  * @author   Michael Slusarz <slusarz@horde.org>
 21:  * @category Horde
 22:  * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
 23:  * @package  Imap_Client
 24:  */
 25: class Horde_Imap_Client_Utf7imap
 26: {
 27:     /**
 28:      * Lookup table for conversion.
 29:      *
 30:      * @var array
 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:      * Lookup table for conversion.
 45:      *
 46:      * @var array
 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:      * Is mbstring extension available?
 58:      *
 59:      * @var array
 60:      */
 61:     private static $_mbstring = null;
 62: 
 63:     /**
 64:      * Convert a string from UTF7-IMAP to UTF-8.
 65:      *
 66:      * @param string $str  The UTF7-IMAP string.
 67:      *
 68:      * @return string  The converted UTF-8 string.
 69:      * @throws Horde_Imap_Client_Exception
 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:         /* Try mbstring, if available, which should be faster. Don't use the
 80:          * IMAP utf7_* functions because they are known to be buggy. */
 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:                             /* Printable US-ASCII */
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:                 /* Non-zero or too many extra bits -OR-
135:                  * Base64 not properly terminated -OR-
136:                  * Adjacent Base64 sections. */
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:                 /* Not printable US-ASCII */
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:      * Convert a string from UTF-8 to UTF7-IMAP.
157:      *
158:      * @param string $str     The UTF-8 string.
159:      * @param boolean $force  Assume $str is UTF-8 (no-autodetection)? If
160:      *                        false, attempts to auto-detect if string is
161:      *                        already in UTF7-IMAP. (Since 1.2.0)
162:      *
163:      * @return string  The converted UTF7-IMAP string.
164:      * @throws Horde_Imap_Client_Exception
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:         /* No need to do conversion if all chars are in US-ASCII range or if
175:          * no ampersand is present. But will assume that an already encoded
176:          * ampersand means string is in UTF7-IMAP already. */
177:         if (!$force &&
178:             !preg_match('/[\x80-\xff]|&$|&(?![,+A-Za-z0-9]*-)/', $str)) {
179:             return $str;
180:         }
181: 
182:         /* Try mbstring, if available, which should be faster. Don't use the
183:          * IMAP utf7_* functions because they are known to be buggy. */
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: 
API documentation generated by ApiGen