/** * Performs the decoding. Decodes the body string passed to it * If it finds certain content-types it will call itself in a * recursive fashion * * @param string $headers Header section * @param string $body Body section * @param string $default_ctype Default content type * * @return object|bool Decoded results or False on error */ protected function do_decode($headers, $body, $default_ctype = 'text/plain') { $return = new stdClass(); $headers = $this->parseHeaders($headers); while (list($key, $value) = each($headers)) { $header_name = strtolower($value['name']); if (isset($return->headers[$header_name]) && !is_array($return->headers[$header_name])) { $return->headers[$header_name] = array($return->headers[$header_name]); $return->headers[$header_name][] = $value['value']; } else { if (isset($return->headers[$header_name])) { $return->headers[$header_name][] = $value['value']; } else { $return->headers[$header_name] = $value['value']; } } switch ($header_name) { case 'content-type': $content_type = $this->parseHeaderValue($value['value']); if (preg_match('/([0-9a-z+.-]+)\\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) { $return->ctype_primary = $regs[1]; $return->ctype_secondary = $regs[2]; } if (isset($content_type['other'])) { while (list($p_name, $p_value) = each($content_type['other'])) { $return->ctype_parameters[$p_name] = $p_value; } } break; case 'content-disposition': $content_disposition = $this->parseHeaderValue($value['value']); $return->disposition = $content_disposition['value']; if (isset($content_disposition['other'])) { while (list($p_name, $p_value) = each($content_disposition['other'])) { $return->d_parameters[$p_name] = $p_value; } } break; case 'content-transfer-encoding': $content_transfer_encoding = $this->parseHeaderValue($value['value']); break; } } if (isset($content_type)) { $ctype = strtolower($content_type['value']); switch ($ctype) { case 'text/plain': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; if ($this->params['include_bodies']) { $return->body = $this->params['decode_bodies'] ? rcube_mime::decode($body, $encoding) : $body; } break; case 'text/html': $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; if ($this->params['include_bodies']) { $return->body = $this->params['decode_bodies'] ? rcube_mime::decode($body, $encoding) : $body; } break; case 'multipart/digest': case 'multipart/alternative': case 'multipart/related': case 'multipart/mixed': if (!isset($content_type['other']['boundary'])) { return false; } $default_ctype = $ctype === 'multipart/digest' ? 'message/rfc822' : 'text/plain'; $parts = $this->boundarySplit($body, $content_type['other']['boundary']); for ($i = 0; $i < count($parts); $i++) { list($part_header, $part_body) = $this->splitBodyHeader($parts[$i]); $return->parts[] = $this->do_decode($part_header, $part_body, $default_ctype); } break; case 'message/rfc822': $obj = new rcube_mime_decode($this->params); $return->parts[] = $obj->decode($body); unset($obj); break; default: if ($this->params['include_bodies']) { $return->body = $this->params['decode_bodies'] ? rcube_mime::decode($body, $content_transfer_encoding['value']) : $body; } break; } } else { $ctype = explode('/', $default_ctype); $return->ctype_primary = $ctype[0]; $return->ctype_secondary = $ctype[1]; if ($this->params['include_bodies']) { $return->body = $this->params['decode_bodies'] ? rcube_mime::decode($body) : $body; } } return $return; }
/** * Parse the given raw message source and return a structure * of rcube_message_part objects. * * It makes use of the rcube_mime_decode library * * @param string $raw_body The message source * * @return object rcube_message_part The message structure */ public static function parse_message($raw_body) { $conf = array('include_bodies' => true, 'decode_bodies' => true, 'decode_headers' => false, 'default_charset' => self::get_charset()); $mime = new rcube_mime_decode($conf); return $mime->decode($raw_body); }