Thomas Bruederli
2012-11-17 be9aacaa5296dfca63fb3a01c2dc52538d1546aa
program/include/rcube_message.php
@@ -24,7 +24,8 @@
 * Logical representation of a mail message with all its data
 * and related functions
 *
 * @package    Mail
 * @package    Framework
 * @subpackage Storage
 * @author     Thomas Bruederli <roundcube@gmail.com>
 */
class rcube_message
@@ -50,13 +51,14 @@
     */
    private $mime;
    private $opt = array();
    private $inline_parts = array();
    private $parse_alternative = false;
    public $uid = null;
    public $uid;
    public $folder;
    public $headers;
    public $parts = array();
    public $mime_parts = array();
    public $inline_parts = array();
    public $attachments = array();
    public $subject = '';
    public $sender = null;
@@ -68,16 +70,21 @@
     *
     * Provide a uid, and parse message structure.
     *
     * @param string $uid The message UID.
     * @param string $uid    The message UID.
     * @param string $folder Folder name
     *
     * @see self::$app, self::$storage, self::$opt, self::$parts
     */
    function __construct($uid)
    function __construct($uid, $folder = null)
    {
        $this->uid  = $uid;
        $this->app  = rcube::get_instance();
        $this->storage = $this->app->get_storage();
        $this->folder  = strlen($folder) ? $folder : $this->storage->get_folder();
        $this->storage->set_options(array('all_headers' => true));
        // Set current folder
        $this->storage->set_folder($this->folder);
        $this->headers = $this->storage->get_message($uid);
@@ -179,10 +186,12 @@
                }
                return $fp ? true : $part->body;
            }
            // get from IMAP
            $this->storage->set_folder($this->folder);
            return $this->storage->get_message_part($this->uid, $mime_id, $part, NULL, $fp, $skip_charset_conv);
        } else
            return null;
        }
    }
@@ -190,27 +199,29 @@
     * Determine if the message contains a HTML part
     *
     * @param bool $recursive Enables checking in all levels of the structure
     * @param bool $enriched  Enables checking for text/enriched parts too
     *
     * @return bool True if a HTML is available, False if not
     */
    function has_html_part($recursive = true)
    function has_html_part($recursive = true, $enriched = false)
    {
        // check all message parts
        foreach ($this->parts as $part) {
            if ($part->mimetype == 'text/html') {
            if ($part->mimetype == 'text/html' || ($enriched && $part->mimetype == 'text/enriched')) {
                // Level check, we'll skip e.g. HTML attachments
                if (!$recursive) {
                    $level = explode('.', $part->mime_id);
                    // Level too high
                    if (count($level) > 2) {
                    // Skip if level too deep or part has a file name
                    if (count($level) > 2 || $part->filename) {
                        continue;
                    }
                    // HTML part can be on the lower level, if not...
                    if (count($level) > 1) {
                        // It can be an alternative or related message part
                        $parent = $this->mime_parts[0];
                        array_pop($level);
                        $parent = $this->mime_parts[join('.', $level)];
                        // ... parent isn't multipart/alternative or related
                        if ($parent->mimetype != 'multipart/alternative' && $parent->mimetype != 'multipart/related') {
                            continue;
                        }
@@ -261,10 +272,6 @@
            else if ($part->mimetype == 'text/html') {
                $out = $this->get_part_content($mime_id);
                // remove special chars encoding
                $trans = array_flip(get_html_translation_table(HTML_ENTITIES));
                $out = strtr($out, $trans);
                // create instance of html2text class
                $txt = new html2text($out);
                return $txt->get_text();
@@ -273,6 +280,32 @@
        $part = null;
        return null;
    }
    /**
     * Checks if part of the message is an attachment (or part of it)
     *
     * @param rcube_message_part $part Message part
     *
     * @return bool True if the part is an attachment part
     */
    public function is_attachment($part)
    {
        foreach ($this->attachments as $att_part) {
            if ($att_part->mime_id == $part->mime_id) {
                return true;
            }
            // check if the part is a subpart of another attachment part (message/rfc822)
            if ($att_part->mimetype == 'message/rfc822') {
                if (in_array($part, (array)$att_part->parts)) {
                    return true;
                }
            }
        }
        return false;
    }
@@ -336,6 +369,11 @@
            foreach ($structure->parts as $p => $sub_part) {
                $sub_mimetype = $sub_part->mimetype;
                // skip empty text parts
                if (!$sub_part->size && preg_match('#^text/(plain|html|enriched)$#', $sub_mimetype)) {
                    continue;
                }
                // check if sub part is
                if ($sub_mimetype == 'text/plain')
@@ -443,7 +481,7 @@
                    if ($plugin['abort'])
                        continue;
                    if ($part_mimetype == 'text/html') {
                    if ($part_mimetype == 'text/html' && $mail_part->size) {
                        $got_html_part = true;
                    }
@@ -460,8 +498,13 @@
                    }
                    // list as attachment as well
                    if (!empty($mail_part->filename))
                    if (!empty($mail_part->filename)) {
                        $this->attachments[] = $mail_part;
                    }
                    // list html part as attachment (here the part is most likely inside a multipart/related part)
                    else if ($this->parse_alternative && ($secondary_type == 'html' && !$this->opt['prefer_html'])) {
                        $this->attachments[] = $mail_part;
                    }
                }
                // part message/*
                else if ($primary_type == 'message') {
@@ -611,8 +654,10 @@
    function tnef_decode(&$part)
    {
        // @TODO: attachment may be huge, hadle it via file
        if (!isset($part->body))
        if (!isset($part->body)) {
            $this->storage->set_folder($this->folder);
            $part->body = $this->storage->get_message_part($this->uid, $part->mime_id, $part);
        }
        $parts = array();
        $tnef = new tnef_decoder;
@@ -647,8 +692,10 @@
    function uu_decode(&$part)
    {
        // @TODO: messages may be huge, hadle body via file
        if (!isset($part->body))
        if (!isset($part->body)) {
            $this->storage->set_folder($this->folder);
            $part->body = $this->storage->get_message_part($this->uid, $part->mime_id, $part);
        }
        $parts = array();
        // FIXME: line length is max.65?