Overview

Packages

  • Mime
    • Viewer

Classes

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