function decode($input, $default_ctype = 'text/plain', $crlf = "\r\n") { $back = array(); $pos = strpos($input, $crlf . $crlf); if (!$pos) { $crlf = "\n"; $pos = strpos($input, $crlf . $crlf); if (!$pos) { return false; } } $header = substr($input, 0, $pos); $body = substr($input, $pos + 2 * strlen($crlf)); $headparsed = preg_replace('/' . $crlf . "(\t| )/", ' ', $header); $heads = explode($crlf, trim($headparsed)); if (substr($heads[0], 0, 5) == 'From ') { $heads[0] = str_replace('From ', 'x-From: ', $heads[0]); } foreach ($heads as $line) { $hdr_name = trim(substr($line, 0, strpos($line, ':'))); $hdr_value = trim(substr($line, strpos($line, ':') + 1)); if (substr($hdr_value, 0, 1) == ' ') { $hdr_value = substr($hdr_value, 1); } $hdr_value = preg_replace('/(=\\?[^?]+\\?(Q|B|q|b)\\?[^?]*\\?=)( |' . "\t|" . $crlf . ')+=\\?/', '\\1=?', $hdr_value); while (preg_match('/(=\\?([^?]+)\\?(Q|B|q|b)\\?([^?]*)\\?=)/', $hdr_value, $matches)) { list(, $encoded, $charset, $encoding, $text) = $matches; switch ($encoding) { case 'B': case 'b': $text = base64_decode($text); break; case 'Q': case 'q': $text = str_replace('_', ' ', $text); preg_match_all('/=([A-F0-9]{2})/', $text, $matches); foreach ($matches[1] as $value) { $text = str_replace('=' . $value, chr(hexdec($value)), $text); } break; } if ($charset == 'iso-8859-1') { $text = utf8_encode($text); } elseif ($charset != 'utf-8' && function_exists('mb_convert_encoding')) { $text = mb_convert_encoding($text, 'utf-8', $charset); } $hdr_value = str_replace($encoded, $text, $hdr_value); } $lname = strtolower($hdr_name); if (isset($back['header'][$lname]) and !is_array($back['header'][$lname])) { $back['header'][$lname] = array($back['header'][$lname]); $back['header'][$lname][] = $hdr_value; } elseif (isset($back['header'][$lname])) { $back['header'][$lname][] = $hdr_value; } else { $back['header'][$lname] = $hdr_value; } $headers["{$lname}"] = $hdr_value; } while (list($key, $value) = each($headers)) { $input = $headers[$key]; $it = array(); if (($pos = strpos($input, ';')) !== false) { $it['value'] = trim(substr($input, 0, $pos)); $input = trim(substr($input, $pos + 1)); if (strlen($input) > 0) { preg_match_all('/(([[:alnum:]]+)="?([^"]*)"?\\s?;?)+/i', $input, $matches); for ($i = 0, $icount_matches = count($matches[2]); $i < $icount_matches; $i++) { $it['other'][strtolower($matches[2][$i])] = $matches[3][$i]; } } } else { $it['value'] = trim($input); } switch ($key) { case 'content-type': $content_type = $it; $back['type'] = $content_type['value']; if (isset($content_type['other'])) { while (list($p_name, $p_value) = each($content_type['other'])) { $back['ctype_parameters'][$p_name] = $p_value; } } break; case 'content-disposition': $content_disposition = $it; $back['disposition'] = $content_disposition['value']; if (isset($content_disposition['other'])) { while (list($p_name, $p_value) = each($content_disposition['other'])) { $back['d_parameters'][$p_name] = $p_value; } } break; case 'content-transfer-encoding': $content_transfer_encoding = $it; break; } } if (isset($content_type)) { $type = 'text'; switch (strtolower($content_type['value'])) { case 'text/html': $type = 'html'; case 'text/plain': if (!empty($content_disposition) && $content_disposition['value'] == 'attachment') { $back['attachments'][] = $back['d_parameters']; } $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; $back['body'] = mime::decodeBody($body, $encoding); if (array_key_exists('ctype_parameters', $back) and isset($back['ctype_parameters']) and $back['ctype_parameters'] and (!isset($back['ctype_parameters']['charset']) or strtolower($back['ctype_parameters']['charset']) == 'iso-8858-1') and function_exists('utf8_encode')) { $back[$type][] = utf8_encode($back['body']); } elseif (array_key_exists('ctype_parameters', $back) and isset($back['ctype_parameters']) and $back['ctype_parameters'] and strtolower($back['ctype_parameters']['charset']) != 'utf-8' and function_exists('mb_convert_encoding')) { $back[$type][] = mb_convert_encoding($back['body'], 'utf-8', $back['ctype_parameters']['charset']); } else { $back[$type][] = $back['body']; } break; case 'multipart/signed': case 'multipart/digest': case 'multipart/alternative': case 'multipart/related': case 'multipart/mixed': $default_ctype = strtolower($content_type['value']) === 'multipart/digest' ? 'message/rfc822' : 'text/plain'; $tmp = explode('--' . $content_type['other']['boundary'], $body); for ($i = 1, $icount_tmp = count($tmp); $i < $icount_tmp - 1; $i++) { $parts[] = $tmp[$i]; } for ($i = 0, $icount_parts = count($parts); $i < $icount_parts; $i++) { $back['parts'][] = mime::decode($parts[$i], $default_ctype); } break; case 'message/rfc822': $back['parts'][] = mime::decode($body); break; default: if (!isset($content_transfer_encoding['value'])) { $content_transfer_encoding['value'] = '7bit'; } $back['body'] = mime::decodeBody($body, $content_transfer_encoding['value']); break; } } else { $back['body'] = mime::decodeBody($body); } $ctype = explode('/', $default_ctype); $back['ctype_primary'] = $ctype[0]; $back['ctype_secondary'] = $ctype[1]; return $back; }