public static function Utf7ImapToUtf8($str)
{
if ($str instanceof Horde_Imap_Client_Mailbox) {
return $str->utf8;
}
$str = strval($str);
/* Try mbstring, if available, which should be faster. Don't use the
* IMAP utf7_* functions because they are known to be buggy. */
if (is_null(self::$_mbstring)) {
self::$_mbstring = extension_loaded('mbstring');
}
if (self::$_mbstring) {
return @mb_convert_encoding($str, 'UTF-8', 'UTF7-IMAP');
}
$p = '';
$ptr =& self::$_index64;
for ($i = 0, $u7len = strlen($str); $u7len > 0; ++$i, --$u7len) {
$u7 = $str[$i];
if ($u7 === '&') {
$u7 = $str[++$i];
if (--$u7len && $u7 === '-') {
$p .= '&';
continue;
}
$ch = 0;
$k = 10;
for (; $u7len > 0; ++$i, --$u7len) {
$u7 = $str[$i];
if (ord($u7) & 0x80 || ($b = $ptr[ord($u7)]) === -1) {
break;
}
if ($k > 0) {
$ch |= $b << $k;
$k -= 6;
} else {
$ch |= $b >> -$k;
if ($ch < 0x80) {
/* Printable US-ASCII */
if (0x20 <= $ch && $ch < 0x7f) {
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
}
$p .= chr($ch);
} else {
if ($ch < 0x800) {
$p .= chr(0xc0 | $ch >> 6) . chr(0x80 | $ch & 0x3f);
} else {
$p .= chr(0xe0 | $ch >> 12) . chr(0x80 | $ch >> 6 & 0x3f) . chr(0x80 | $ch & 0x3f);
}
}
$ch = $b << 16 + $k & 0xffff;
$k += 10;
}
}
/* Non-zero or too many extra bits -OR-
* Base64 not properly terminated -OR-
* Adjacent Base64 sections. */
if ($ch || $k < 6 || (!$u7len || $u7 !== '-') || $u7len > 2 && $str[$i + 1] === '&' && $str[$i + 2] !== '-') {
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
}
} elseif (ord($u7) < 0x20 || ord($u7) >= 0x7f) {
/* Not printable US-ASCII */
throw new Horde_Imap_Client_Exception(Horde_Imap_Client_Translation::r("Error converting UTF7-IMAP string."), Horde_Imap_Client_Exception::UTF7IMAP_CONVERSION);
} else {
$p .= $u7;
}
}
return $p;
}