/**
  * @param string $str
  * @return string
  */
 function Utf7to8($str)
 {
     if (!ConvertUtils::IsUtf7($str)) {
         return $str;
     }
     $array = array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, 63, -1, -1, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
     $result = '';
     $error = '';
     $strlen = strlen($str);
     for ($i = 0; $strlen > 0; $i++, $strlen--) {
         $char = $str[$i];
         if ($char == '&') {
             $i++;
             $strlen--;
             $char = isset($str[$i]) ? $str[$i] : null;
             if ($char === null) {
                 break;
             }
             if ($strlen && $char == '-') {
                 $result .= '&';
                 continue;
             }
             $ch = 0;
             $k = 10;
             for (; $strlen > 0; $i++, $strlen--) {
                 $char = $str[$i];
                 $b = $array[ord($char)];
                 if (ord($char) & 0x80 || $b == -1) {
                     break;
                 }
                 if ($k > 0) {
                     $ch |= $b << $k;
                     $k -= 6;
                 } else {
                     $ch |= $b >> -$k;
                     if ($ch < 0x80) {
                         if (0x20 <= $ch && $ch < 0x7f) {
                             return $error;
                         }
                         $result .= chr($ch);
                     } else {
                         if ($ch < 0x800) {
                             $result .= chr(0xc0 | $ch >> 6);
                             $result .= chr(0x80 | $ch & 0x3f);
                         } else {
                             $result .= chr(0xe0 | $ch >> 12);
                             $result .= chr(0x80 | $ch >> 6 & 0x3f);
                             $result .= chr(0x80 | $ch & 0x3f);
                         }
                     }
                     $ch = $b << 16 + $k & 0xffff;
                     $k += 10;
                 }
             }
             if ($ch || $k < 6) {
                 return $error;
             }
             if (!$strlen || $char != '-') {
                 return $error;
             }
             if ($strlen > 2 && $str[$i + 1] == '&' && $str[$i + 2] != '-') {
                 return $error;
             }
         } else {
             if (ord($char) < 0x20 || ord($char) >= 0x7f) {
                 return $error;
             } else {
                 $result .= $char;
             }
         }
     }
     return $result;
 }