File: enriched.php

package info (click to toggle)
horde2 2.2.8-1sarge3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 3,832 kB
  • ctags: 2,897
  • sloc: php: 12,784; sh: 954; sql: 149; makefile: 104; perl: 97; xml: 24; pascal: 6
file content (170 lines) | stat: -rw-r--r-- 8,253 bytes parent folder | download
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
<?php
/*
 * $Horde: horde/lib/MIME/Viewer/enriched.php,v 1.4.2.5 2003/01/03 12:48:28 jan Exp $
 *
 * Copyright 2001-2003 Eric Rostetter <eric.rostetter@physics.utexas.edu>
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 */

/**
 * The MIME_Viewer_enriched class renders out plain text from
 * enriched content tags, ala RFC 1896
 *
 * @author  Eric Rostetter <eric.rostetter@physics.utexas.edu>
 * @version $Revision: 1.4.2.5 $
 * @since   Horde 2.1
 * @package horde.mime.viewer
 */

// 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.

class MIME_Viewer_enriched extends MIME_Viewer {

    /**
     * Render out the currently set contents in HTML format.  The
     * $mime_part class variable has the information to render out,
     * encapsulated in a MIME_Part object.
     */
    function render(&$mime)
    {
        include_once HORDE_BASE . '/lib/Text.php';

        $text = $this->mime_part->getContents();
        if ($text === false) {
            return false;
        }

        if (trim($text) == '') {
            return $text;
        }

        // 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 . ' ';

        $charset = $this->getCharset($mime);

        // 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);
        // $text = str_replace('<<', chr(255), $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);

        // Get color parameters into a more useable format.
        $text = preg_replace('/<color><param>([\da-fA-F]+),([\da-fA-F]+),([\da-fA-F]+)<\/param>/Uis', '<color r=\1 g=\2 b=\3>', $text);
        $text = preg_replace('/<color><param>(red|blue|green|yellow|cyan|magenta|black|white)<\/param>/Uis', '<color n=\1>', $text);

        // Get font family parameters into a more useable format.
        $text = preg_replace('/<fontfamily><param>(\w+)<\/param>/Uis', '<fontfamily f=\1>', $text);

        // Just remove any remaining parameters -- we won't use
        // them. Any tags with parameters that we want to implement
        // will have to come before this Someday we hope to use these
        // tags (e.g. for <color><param> tags)
        $text = preg_replace('/<param>.*<\/param>/Uis', '', $text);

        // 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.
        $text = preg_replace('/([^\n])\r\n([^\r])/', '\1 \2', $text);
        $text = preg_replace('/(\r\n)\r\n/', '\1', $text);

        // We try to protect against bad stuff here.
        $text = @htmlspecialchars($text, ENT_QUOTES, $charset);

        // Now convert the known tags to html. Try to remove any tag
        // parameters to stop people from trying to pull a fast one
        $text = preg_replace('/(?<!&lt;)&lt;bold.*&gt;(.*)&lt;\/bold&gt;/Uis', '<span style="font-weight: bold">\1</span>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;italic.*&gt;(.*)&lt;\/italic&gt;/Uis', '<span style="font-style: italic">\1</span>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;underline.*&gt;(.*)&lt;\/underline&gt;/Uis', '<span style="text-decoration: underline">\1</span>', $text);
        $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);
        $text = preg_replace('/(?<!&lt;)&lt;color n=(red|blue|green|yellow|cyan|magenta|black|white)&gt;(.*)&lt;\/color&gt;/Uis', '<span style="color: \1">\2</span>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;fontfamily f=(\w+)&gt;(.*)&lt;\/fontfamily&gt;/Uis', '<span style="font-family: \1">\2</span>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;smaller.*&gt;/Uis', '<span style="font-size: smaller">', $text);
        $text = preg_replace('/(?<!&lt;)&lt;\/smaller&gt;/Uis', '</span>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;bigger.*&gt;/Uis', '<span style="font-size: larger">', $text);
        $text = preg_replace('/(?<!&lt;)&lt;\/bigger&gt;/Uis', '</span>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;fixed.*&gt;(.*)&lt;\/fixed&gt;/Uis', '<font face="fixed">\1</font>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;center.*&gt;(.*)&lt;\/center&gt;/Uis', '<div align="center">\1</div>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;flushleft.*&gt;(.*)&lt;\/flushleft&gt;/Uis', '<div align="left">\1</div>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;flushright.*&gt;(.*)&lt;\/flushright&gt;/Uis', '<div align="right">\1</div>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;flushboth.*&gt;(.*)&lt;\/flushboth&gt;/Uis', '<div align="justify">\1</div>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;paraindent.*&gt;(.*)&lt;\/paraindent&gt;/Uis', '<blockquote>\1</blockquote>', $text);
        $text = preg_replace('/(?<!&lt;)&lt;excerpt.*&gt;(.*)&lt;\/excerpt&gt;/Uis', '<blockquote>\1</blockquote>', $text);

        // replace << with < now (from translated html form)
        $text = str_replace('&lt;&lt;', '&lt;', $text);

        // Now we remove the leading/trailing space we added at the
        // start.
        $text = preg_replace('/^ (.*) $/s', '\1', $text);

        // Wordwrap -- note this could impact on our above RFC
        // compliance *IF* we honored nofill tags (which we don't
        // yet).
        $text = str_replace("\t", '        ', $text);
        $text = str_replace('  ', ' &nbsp;', $text);
        $text = str_replace("\n ", "\n&nbsp;", $text);
        if ($text[0] == ' ') {
            $text = '&nbsp;' . substr($text, 1);
        }
        $text = nl2br($text);
        $text = '<p class="fixed">' . $text . '</p>';

        return $text;
    }

    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>';
    }

    /**
     * Return text/html as the content-type
     * @return string "text/html" constant
     */
    function getType()
    {
        return 'text/html';
    }

    function getCharset($mime)
    {
        return !empty($mime->charset) ? $mime->charset : $GLOBALS['registry']->getCharset();
    }

}
?>