/usr/share/php/Horde/Mime/Viewer/Enriched.php is in php-horde-mime-viewer 2.0.5-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | <?php
/**
* The Horde_Mime_Viewer_Enriched class renders out plain text from enriched
* content tags, ala RFC 1896.
*
* By RFC, we must do the minimal conformance measures of: A minimal
* text/enriched implementation is one that converts "<<" to "<",
* removes everything between a <param> command and the next balancing
* </param> removes all other formatting commands (all text enclosed
* in angle brackets), and outside of <nofill> environments converts
* any series of n CRLFs to n-1 CRLFs, and converts any lone CRLF
* pairs to SPACE.
*
* We don't qualify as we don't currently track the <nofill>
* environment, that is we do CRLF conversion even if <nofill> is
* specified in the text, but we're close at least.
*
* Copyright 2001-2013 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @author Eric Rostetter <eric.rostetter@physics.utexas.edu>
* @category Horde
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Mime_Viewer
*/
class Horde_Mime_Viewer_Enriched extends Horde_Mime_Viewer_Base
{
/**
* This driver's display capabilities.
*
* @var array
*/
protected $_capability = array(
'full' => true,
'info' => false,
'inline' => true,
'raw' => false
);
/**
* Return the full rendered version of the Horde_Mime_Part object.
*
* @return array See parent::render().
*/
protected function _render()
{
return $this->_renderReturn(
'<html><body>' . $this->_toHTML(false) . '</body></html>',
'text/html; charset=' . $this->_mimepart->getCharset()
);
}
/**
* Return the rendered inline version of the Horde_Mime_Part object.
*
* @return array See parent::render().
*/
protected function _renderInline()
{
return $this->_renderReturn(
Horde_String::convertCharset($this->_toHTML(true), $this->_mimepart->getCharset(), 'UTF-8'),
'text/html; charset=UTF-8'
);
}
/**
* Convert the enriched text to HTML.
*
* @param string $inline Rendered inline?
*
* @return string The HTML-ified version of the MIME part contents.
*/
protected function _toHTML($inline)
{
$text = trim($this->_mimepart->getContents());
if (!strlen($text)) {
return array();
}
// We add space at the beginning and end of the string as it will
// make some regular expression checks later much easier (so we
// don't have to worry about start/end of line characters)
$text = ' ' . $text . ' ';
// We need to preserve << tags, so map them to ascii 1 or ascii 255
// We make the assumption here that there would never be an ascii
// 1 in an email, which may not be valid, but seems reasonable...
// ascii 255 would work if for some reason you don't like ascii 1
// ascii 0 does NOT seem to work for this, though I'm not sure why
$text = str_replace('<<', chr(1), $text);
// Remove any unrecognized tags in the text (via RFC minimal specs)
// any tags we just don't want to implement can also be removed here
// Note that this will remove any html links, but this is intended
$implementedTags = '<param><bold><italic><underline><fixed><excerpt>' .
'<smaller><bigger><center><color><fontfamily>' .
'<flushleft><flushright><flushboth><paraindent>';
// $unImplementedTags = '<nofill><lang>';
$text = strip_tags($text, $implementedTags);
// restore the << tags as < tags now...
$text = str_replace(chr(1), '<<', $text);
// $text = str_replace(chr(255), '<', $text);
$replace = array(
// Get color parameters into a more useable format.
'/<color><param>([\da-fA-F]+),([\da-fA-F]+),([\da-fA-F]+)<\/param>/Uis' => '<color r=\1 g=\2 b=\3>',
'/<color><param>(red|blue|green|yellow|cyan|magenta|black|white)<\/param>/Uis' => '<color n=\1>',
// Get font family parameters into a more useable format.
'/<fontfamily><param>(\w+)<\/param>/Uis' => '<fontfamily f=\1>',
/* Just remove any remaining parameters -- we won't use them.
* Any tags with parameters that we want to implement will have
* come before this. Someday we hope to use these tags (e.g. for
* <color><param> tags). */
'/<param>.*<\/param>/Uis' => '',
/* Single line breaks become spaces, double line breaks are a
* real break. This needs to do <nofill> tracking to be compliant
* but we don't want to deal with state at this time, so we fake
* it some day we should rewrite this to handle <nofill>
* correctly. */
'/([^\n])\r\n([^\r])/' => '\1 \2',
'/(\r\n)\r\n/' => '\1'
);
$text = preg_replace(array_keys($replace), array_values($replace), $text);
// We try to protect against bad stuff here.
$text = @htmlspecialchars($text, ENT_QUOTES, $this->_mimepart->getCharset());
// Now convert the known tags to html. Try to remove any tag
// parameters to stop people from trying to pull a fast one
$replace = array(
'/(?<!<)<bold.*>(.*)<\/bold>/Uis' => '<span style="font-weight: bold">\1</span>',
'/(?<!<)<italic.*>(.*)<\/italic>/Uis' => '<span style="font-style: italic">\1</span>',
'/(?<!<)<underline.*>(.*)<\/underline>/Uis' => '<span style="text-decoration: underline">\1</span>'
);
$text = preg_replace(array_keys($replace), array_values($replace), $text);
$text = preg_replace_callback('/(?<!<)<color r=([\da-fA-F]+) g=([\da-fA-F]+) b=([\da-fA-F]+)>(.*)<\/color>/Uis', array($this, 'colorize'), $text);
$replace = array(
'/(?<!<)<color n=(red|blue|green|yellow|cyan|magenta|black|white)>(.*)<\/color>/Uis' => '<span style="color: \1">\2</span>',
'/(?<!<)<fontfamily>(.*)<\/fontfamily>/Uis' => '\1',
'/(?<!<)<fontfamily f=(\w+)>(.*)<\/fontfamily>/Uis' => '<span style="font-family: \1">\2</span>',
'/(?<!<)<smaller.*>/Uis' => '<span style="font-size: smaller">',
'/(?<!<)<\/smaller>/Uis' => '</span>',
'/(?<!<)<bigger.*>/Uis' => '<span style="font-size: larger">',
'/(?<!<)<\/bigger>/Uis' => '</span>',
'/(?<!<)<fixed.*>(.*)<\/fixed>/Uis' => '<font face="fixed">\1</font>',
'/(?<!<)<center.*>(.*)<\/center>/Uis' => '<div align="center">\1</div>',
'/(?<!<)<flushleft.*>(.*)<\/flushleft>/Uis' => '<div align="left">\1</div>',
'/(?<!<)<flushright.*>(.*)<\/flushright>/Uis' => '<div align="right">\1</div>',
'/(?<!<)<flushboth.*>(.*)<\/flushboth>/Uis' => '<div align="justify">\1</div>',
'/(?<!<)<paraindent.*>(.*)<\/paraindent>/Uis' => '<blockquote>\1</blockquote>',
'/(?<!<)<excerpt.*>(.*)<\/excerpt>/Uis' => '<blockquote>\1</blockquote>'
);
$text = preg_replace(array_keys($replace), array_values($replace), $text);
// Replace << with < now (from translated HTML form).
$text = str_replace('<<', '<', $text);
// Now we remove the leading/trailing space we added at the
// start.
$text = preg_replace('/^ (.*) $/s', '\1', $text);
// Make URLs clickable.
$text = $this->_textFilter($text, 'linkurls');
/* Wordwrap -- note this could impact on our above RFC compliance *IF*
* we honored nofill tags (which we don't yet). */
$text = str_replace(array("\t", ' ', "\n "), array(' ', ' ', "\n "), $text);
if ($text[0] == ' ') {
$text = ' ' . substr($text, 1);
}
return '<p class="fixed">' . nl2br($text) . '</p>';
}
/**
* TODO
*/
public function colorize($colors)
{
for ($i = 1; $i < 4; $i++) {
$colors[$i] = sprintf('%02X', round(hexdec($colors[$i]) / 255));
}
return '<span style="color: #' . $colors[1] . $colors[2] . $colors[3] . '">' . $colors[4] . '</span>';
}
}
|