<?php

require_once 'Horde/MIME/Viewer/html.php';

/**
 * The MIME_Viewer_html class renders out HTML text with an effort to
 * remove potentially malicious code.
 *
 * $Horde: imp/lib/MIME/Viewer/html.php,v 1.75.2.1 2005/01/03 12:25:35 jan Exp $
 *
 * Copyright 1999-2005 Anil Madhavapeddy <anil@recoil.org>
 * Copyright 1999-2005 Jon Parise <jon@recoil.org>
 * Copyright 2002-2005 Michael Slusarz <slusarz@horde.org>
 *
 * 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  Anil Madhavapeddy <anil@recoil.org>
 * @author  Jon Parise <jon@horde.org>
 * @author  Michael Slusarz <slusarz@horde.org>
 * @version $Revision: 1.75.2.1 $
 * @since   IMP 3.0
 * @package Horde_MIME_Viewer
 */
class IMP_MIME_Viewer_html extends MIME_Viewer_html {

    /**
     * Render out the currently set contents.
     *
     * @access public
     *
     * @param array $params  An array with a reference to a MIME_Contents
     *                       object.
     *
     * @return string  The rendered text in HTML.
     */
    function render($params)
    {
        $contents = &$params[0];

        $attachment = $contents->viewAsAttachment();

        /* Sanitize the HTML. */
        $data = $this->_cleanHTML($this->mime_part->getContents());

        /* Search for inlined images that we can display. */
        $related = $this->mime_part->getInformation('related_part');
        if ($related !== false) {
            $relatedPart = $contents->getMIMEPart($related);
            foreach ($relatedPart->getCIDList() as $ref => $id) {
                $id = trim($id, '<>');
                $cid_part = $contents->getDecodedMIMEPart($ref);
                $data = str_replace("cid:$id", $contents->urlView($cid_part, 'view_attach'), $data);
            }
        }

        /* Convert links to open in new windows. But first we hide all
           links that have an "#xyz" anchor. */
        $data = preg_replace('|<a([^>]*href=["\']?#)|i', "<\x01\\1", $data);
        $data = str_replace('<a', '<a target="_blank"', $data);
        $data = str_replace('<A', '<a target="_blank"', $data);
        $data = preg_replace("|\x01|", 'a', $data);

        /* Filter bad language. */
        $data = IMP::filterText($data);

        /* Put div around message. */
        $data = '<div id="html-message">' . $data . '</div>';

        /* Only display images if specifically allowed by user. */
        if (!$attachment &&
            (!is_a($contents, 'IMP_Contents') ||
             !$contents->getPrintMode()) &&
            $GLOBALS['prefs']->getValue('html_image_replacement')) {

            /* Check to see if images exist. */
            $img_regex = '/(<img[^>]*src=|<input[^>]*src=|<body[^>]*background=|<td[^>]*background=|<table[^>]*background=|style=[^>]*background-image:.*url\()(")?(?(2)[^">]*"([>)])|[^\s]*(\s+))/iUs';
            if (preg_match($img_regex, $data)) {
                /* Make sure the URL parameters are correct for the current
                   message. */
                $url = Util::removeParameter(Horde::selfUrl(true), array('index', 'actionID'));
                $base_ob = &$contents->getBaseObjectPtr();
                $url = Util::addParameter($url, 'index', $base_ob->getMessageIndex());

                $view_img = Util::getFormData('view_html_images');
                $addr_check = ($GLOBALS['prefs']->getValue('html_image_addrbook') && $this->_inAddressBook($contents));

                if (!$view_img && !$addr_check) {
                    $block_img = 'spacer_red.png';
                    $msg = array(_("This HTML message has images embedded in it. Blocked images appear like this: ") . Horde::img($block_img, null, 'height="10" width="10"'));
                    $newSrc = Horde::url($GLOBALS['registry']->getImageDir('imp') . '/' . $block_img);
                    $data = preg_replace($img_regex, '\\1"' . $newSrc . '"\\3', $data);
                } else {
                    $msg[] = _("This HTML message has images embedded in it.");
                    if ($addr_check) {
                        $msg[] = _("The images will be displayed because the sender is present in your addressbook.");
                    }
                }

                /* Print link to view/hide images now. */
                if (!$addr_check) {
                    if ($view_img) {
                        $url = Util::removeParameter($url, array('view_html_images'));
                        $msg[] = Horde::link($url, _("Hide the Images"), null, null, null, _("Hide the Images"), null) . _("Click here to HIDE the Images") . '</a>.';
                    } else {
                        $url = Util::addParameter($url, 'view_html_images', 1);
                        $msg[] = Horde::link($url, _("Show the Images"), null, null, null, _("Show the Images"), null) . _("Click here to SHOW the Images") . '</a>.';
                    }
                }

                $data = $contents->formatStatusMsg($msg, Horde::img('mime/image.png', _("View the Images")), false) . $data;
            }
        }

        /* If we are viewing inline, give option to view in separate window. */
        if (!$attachment && $this->getConfigParam('external')) {
            $msg = sprintf(_("Click %s to view HTML content in a separate window."), $contents->linkViewJS($this->mime_part, 'view_attach', _("HERE"), _("View HTML content in a separate window")));
            $data = $contents->formatStatusMsg($msg, Horde::img('mime/html.png', _("HTML")), false) . $data;
        }

        return $data;
    }

    /**
     * Determine whether the sender appears in an available addressbook.
     *
     * @access private
     *
     * @param object MIME_Contents &$contents  The MIME_Contents object.
     *
     * @return boolean  Does the sender appear in an addressbook?
     */
    function _inAddressBook(&$contents)
    {
        global $registry, $prefs;

        /* If we don't have access to the sender information, return false. */
        $base_ob = &$contents->getBaseObjectPtr();

        /* If we don't have a contacts provider available, give up. */
        if (!$registry->hasMethod('contacts/getField')) {
            return false;
        }

        $sources = explode("\t", $prefs->getValue('search_sources'));
        if ((count($sources) == 1) && empty($sources[0])) {
            $sources = array();
        }

        /* Try to get back a result from the search. */
        $result = $registry->call('contacts/getField', array($base_ob->getFromAddress(), '__key', $sources));
        if (is_a($result, 'PEAR_Error')) {
            return false;
        } else {
            return (count($result) ? true : false);
        }
    }

}
