<?php

require_once HORDE_BASE . '/lib/MIME/Contents.php';
require_once IMP_BASE . '/config/mime_drivers.php';

/**
 * The IMP_Contents:: class extends the MIME_Contents:: class and contains
 * all functions related to handling the content and output of mail messages
 * in IMP.
 *
 * $Horde: imp/lib/Contents.php,v 1.123 2003/08/06 21:35:51 slusarz Exp $
 *
 * Copyright 2002-2003 Michael Slusarz <slusarz@bigworm.colorado.edu>
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 *
 * @author  Michael Slusarz <slusarz@bigworm.colorado.edu>
 * @version $Revision: 1.123 $
 * @since   IMP 4.0
 * @package imp
 */
class IMP_Contents extends MIME_Contents {

    /**
     * The text of the body of the message.
     *
     * @var string $_body
     */
    var $_body = '';

    /**
     * The text of various MIME body parts.
     *
     * @var array $_bodypart
     */
    var $_bodypart = array();

    /**
     * The IMAP index of the message.
     *
     * @var integer $_index
     */
    var $_index;

    /**
     * Are we currently in a print view?
     *
     * @var boolean $_print
     */
    var $_print = false;

    /**
     * Should attachment stripping links be generated?
     *
     * @var boolean $_strip
     */
    var $_strip = false;

    /**
     * Constructor
     *
     * @access public
     *
     * @param integer $index  The IMAP message index.
     */
    function IMP_Contents($index)
    {
        global $imp;

        $this->_index = $index;

        /* Get the MIME_Message object for the given index. */
        $structure = @imap_fetchstructure($imp['stream'], $index, FT_UID);
        if (!$structure) {
            return;
        }
        require_once HORDE_BASE . '/lib/MIME/Structure.php';
        $ob = &MIME_Structure::parse($structure);

        parent::MIME_Contents($ob, array('download' => 'download_attach', 'view' => 'view_attach'));
    }

    /**
     * Returns the entire body of the message.
     *
     * @access public
     *
     * @return string  The text of the body of the message.
     */
    function getBody()
    {
        global $imp;

        if (empty($this->_body)) {
            $this->_body = @imap_body($imp['stream'], $this->_index, FT_UID);
        }

        return $this->_body;
    }

    /**
     * Gets the raw text for one section of the message.
     *
     * @access public
     *
     * @param integer $id                The ID of the MIME_Part.
     *
     * @return string  The text of the part.
     */
    function getBodyPart($id)
    {
        global $imp;

        $contents = '';

        if (!array_key_exists($id, $this->_bodypart)) {
            $this->_bodypart[$id] = @imap_fetchbody($imp['stream'], $this->_index, $id, FT_UID);
        }

        return ($contents . $this->_bodypart[$id]);
    }

    /**
     * Allow attachments to be stripped by providing a link in summary
     * view?
     *
     * @access public
     *
     * @param boolean $strip  Should the strip links be generated?
     */
    function setStripLink($strip = false)
    {
        $this->_strip = $strip;
    }

    /**
     * Returns an array summarizing a part of a MIME message.
     *
     * @access public
     *
     * @param object MIME_Part &$mime_part  See MIME_Contents::partSummary().
     * @param optional boolean $guess       See MIME_Contents::partSummary().
     *
     * @return array  See MIME_Contents::partSummary().
     *                Adds the following key to that return:
     *                [6] = Compressed Download Link
     *                [7] = Strip Attachment Link (if allowed)
     */
    function partSummary(&$mime_part, $guess = false)
    {
        global $registry;

        $summary = parent::partSummary($mime_part, $guess);

        /* Don't add extra links if not requested or if this is a guessed
           part. */
        if ($guess || !$this->_links) {
            return $summary;
        }

        /* Display the compressed download link only if size is greater
           than 200 KB. */
        if (($mime_part->getBytes() > 204800) &&
            Horde::extensionExists('zlib') &&
            ($mime_part->getType() != 'application/zip') &&
            ($mime_part->getType() != 'application/x-zip-compressed')) {
            $summary[] = $this->linkView($mime_part, 'download_attach', Horde::img('compressed.gif', _("Download in .zip Format"), null, $registry->getParam('graphics', 'horde') . '/mime'), array('jstext' => sprintf(_("Download %s in .zip Format"), $mime_part->getDescription(true, true)), 'viewparams' => array('zip' => 1)), true);
        } else {
            $summary[] = null;
        }

        /* Strip the Attachment? */
        if ($this->_strip &&
            !$mime_part->getInformation('rfc822_part')) {
            $url = Horde::selfUrl(true);
            $url = Horde::removeParameter($url, array('actionID', 'imapid', 'index'));
            $url = Horde::addParameter($url, 'actionID', 'strip_attachment');
            $url = Horde::addParameter($url, 'imapid', $this->_getMIMEKey($mime_part, false));
            $url = Horde::addParameter($url, 'index', $this->getMessageIndex());
            $summary[] = Horde::link($url, _("Strip Attachment"), null, null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete this attachment?")) . "');") . Horde::img('deleted.gif', _("Strip Attachment")) . '</a>';
        } else {
            $summary[] = null;
        }

        return $summary;
    }

    /**
     * Return the URL to the view.php page.
     *
     * @access public
     *
     * @param object MIME_Part &$mime_part  See MIME_Contents::urlView().
     * @param integer $actionID             See MIME_Contents::urlView().
     * @param optional array $params        See MIME_Contents::urlView().
     * @param optional boolean $dload       See MIME_Contents::urlView().
     * The following parameter names will be overwritten by this function:
     *   id, index, mailbox
     *
     * @return string  The URL to view.php.
     */
    function urlView(&$mime_part, $actionID, $params = array(), $dload = false)
    {
        global $imp;

        require_once IMP_BASE . '/lib/Search.php';

        /* Add the necessary local parameters. */
        $params = array_merge($params, IMP_Search::getSearchParameters(IMP::getThisMailbox()));
        $params['index'] = $this->_index;
        if (!isset($params['mailbox'])) {
            $params['mailbox'] = $imp['mailbox'];
        }

        /* Should this be a download link? */
        $dload = (($actionID == 'download_attach') ||
                  ($actionID == 'download_render') ||
                  ($actionID == 'save_message'));

        return parent::urlView($mime_part, $actionID, $params, $dload);
    }

    /**
     * Generate a link to the view.php page.
     *
     * @access public
     *
     * @param object MIME_Part &$mime_part  See MIME_Contents::linkView().
     * @param integer $actionID             See MIME_Contents::linkView().
     * @param string $text                  See MIME_Contents::linkView().
     * @param optional array $params        See MIME_Contents::linkView().
     *
     * @return string  See MIME_Contents::linkView().
     */
    function linkView(&$mime_part, $actionID, $text, $params = array())
    {
        /* If this is a 'download_attach or 'download_render' link, we do not
           want to show in a new window. */
        $dload = (($actionID == 'download_attach') ||
                  ($actionID == 'download_render'));

        /* If download attachment, add the 'thismailbox' param. */
        if ($actionID == 'download_attach') {
            $params['viewparams']['thismailbox'] = IMP::getThisMailbox();
        }

        return parent::linkView($mime_part, $actionID, $text, $params, $dload);
    }

    /**
     * Returns the full message text for a given message/mailbox.
     *
     * @access public
     *
     * @param optional integer $index  The index/mailbox of the message. If
     *                                 empty, will use the current message
     *                                 index.
     *
     * @return string  The full message text.
     */
    function fullMessageText($index = null)
    {
        if (is_null($index)) {
            $index = $this->_index;
        } elseif ($index != $this->_index) {
            if (strstr($index, IMP_IDX_SEP)) {
                require_once IMP_BASE . '/lib/base.php';
                $imp_imap = &IMP_IMAP::singleton();
                list($index, $mailbox) = explode(IMP_IDX_SEP, $index);
                $imp_imap->changeMbox($mailbox);
            }
            if ($index != $this->_index) {
                $this->_body = '';
                $this->_index = $index;
            }
        }

        require_once IMP_BASE . '/lib/Headers.php';
        $imp_headers = &new IMP_Headers($index);
        return $imp_headers->getHeaderText() . $this->getBody();
    }

    /**
     * Returns the IMAP index for the current message.
     *
     * @access public
     *
     * @return integer  The message index.
     */
    function getMessageIndex()
    {
        return $this->_index;
    }

    /**
     * Rebuild the MIME_Part structure of a message from IMAP data.
     *
     * @access public
     *
     * @param optional boolean $decode  Decode the body parts?
     *
     * @return object MIME_Message  A MIME_Message object with all of the body
     *                              text stored in the individual MIME_Parts.
     */
    function rebuildMessage($decode = false)
    {
        $part = $this->_message->getBasePart();
        $this->_rebuildMessage($part, $decode);

        return $this->_message;
    }

    /**
     * Recursive function used to rebuild the MIME_Part structure of a
     * message.
     *
     * @access private
     *
     * @param object MIME_Part &$part  A MIME_Part object.
     * @param boolean $decode          Decode the body parts?
     */
    function _rebuildMessage(&$part, $decode)
    {
        $id = $part->getMIMEId();

        if ($part->getPrimaryType() == 'multipart') {
            /* Recursively process any subparts. */
            foreach ($part->getParts() as $mime) {
                $this->_rebuildMessage($mime, $decode);
            }
        } elseif ($part->getType() == 'message/rfc822') {
            $part->setContents($this->getBodyPart(substr($id, 0, strrpos($id, '.'))));
            $this->_message->alterPart($id, $part);
        } else {
            if ($decode) {
                $this->_message->alterPart($id, $this->getDecodedMIMEPart($id));
            } else {
                $mime_part = &$this->getMIMEPart($id);
                $mime_part->setContents($this->getBodyPart($id));
                $mime_part->setTransferEncoding($mime_part->getTransferEncoding(), true);
                $this->_message->alterPart($id, $mime_part);
            }
        }
    }

    /**
     * Render a MIME Part.
     *
     * @param object MIME_Part &$mime_part  A MIME_Part object.
     *
     * @return string  The rendered data.
     */
    function renderMIMEPart(&$mime_part)
    {
        if (!$mime_part->getContents()) {
            $mime_part->setContents($this->getBodyPart($mime_part->getMIMEId()));
        }
        return parent::renderMIMEPart($mime_part);
    }

    /**
     * Saves a copy of the MIME_Contents object at the end of a request.
     *
     * @access private
     */
    function _addCacheShutdown()
    {
        /* Don't save the cached $_body or $_bodypart arrays since we most
           likely will not use them in the cached object (since the cache
           will generally be used to view parts that _weren't* displayed
           originally. */
        $this->_body = null;
        $this->_bodypart = array();

        parent::_addCacheShutdown();
    }

    /**
     * Get the from address of the message.
     *
     * @access public
     *
     * @return string  The from address of the message.
     */
    function getFromAddress()
    {
        require_once IMP_BASE . '/lib/Headers.php';
        $headers = &new IMP_Headers($this->getMessageIndex());
        return $headers->getFromAddress();
    }

    /**
     * Generate the list of MIME IDs to use for download all.
     *
     * @access public
     *
     * @return array  The list of MIME IDs that should be downloaded when
     *                downloading all attachments.
     */
    function getDownloadAllList()
    {
        $downloads = array();

        /* Here is what we don't consider 'downloadable':
           Any 'multipart/*' part
           All 'message/*' parts except for 'message/rfc822'
           The first viewable part */
        foreach ($this->_message->contentTypeMap() as $key => $val) {
            if (($key == 0) && (strstr($val, 'multipart/mixed') === false)) {
                break;
            }

            if ((intval($key) != 1) &&
                (strstr($val, '1.') === false) &&
                (strstr($val, 'multipart/') === false) &&
                (strstr($val, 'message/') === false)) {
                $downloads[] = $key;
            }
        }

        return $downloads;
    }

    /**
     * Generate a download all link, if possible.
     *
     * @access public
     *
     * @return string  The download link.
     */
    function getDownloadAllLink()
    {
        $url = null;

        $downloads_list = $this->getDownloadAllList();
        if (!empty($downloads_list)) {
            /* Create a dummy variable to pass to urlView() since we don't
               have a MIME_Part and we can't pass null by reference. */
            $dummy = 0;
            $url = $this->urlView($dummy, 'download_all', array('id' => 1));
            $url = Horde::removeParameter($url, array('id'));
        }

        return $url;
    }

    /**
     * Sets the print mode.
     *
     * @access public
     *
     * @param boolean $mode  True = print mode; False = non-print mode.
     */
    function setPrintMode($mode)
    {
        $this->_print = $mode;
    }

    /**
     * Gets the print mode.
     *
     * @access public
     *
     * @return boolean  True = print mode; False = non-print mode.
     */
    function getPrintMode()
    {
        return $this->_print;
    }

    /**
     * Prints out the status message for a given MIME Part.
     *
     * @access public
     *
     * @param mixed $msg               See MIME_Contents::formatStatusMsg().
     * @param optional string $img     See MIME_Contents::formatStatusMsg().
     * @param optional boolean $print  Output this message when in a print
     *                                 view?
     *
     * @return string  The formatted status message.
     */
    function formatStatusMsg($msg, $img = null, $printable = true)
    {
        if (!$printable && $this->_print) {
            return '';
        } else {
            return parent::formatStatusMsg($msg, $img);
        }
    }

}
