Aleksander Machniak
2016-05-20 9e64dc2debfa1c7410f82bf71f4d10856751e258
commit | author | age
a63f14 1 <?php
AM 2
3 /**
4  * @license GNU GPLv3+
5  * @author Thomas Bruederli
6  * @author Aleksander Machniak
7  */
8 class emoticons_engine
9 {
10     const IMG_PATH = 'program/js/tinymce/plugins/emoticons/img/';
11
12     /**
13      * Replaces TinyMCE's emoticon images with plain-text representation
14      *
15      * @param string $html HTML content
16      *
17      * @return string HTML content
18      */
19     public static function icons2text($html)
20     {
21         $emoticons = array(
22             '8-)' => 'smiley-cool',
23             ':-#' => 'smiley-foot-in-mouth',
24             ':-*' => 'smiley-kiss',
25             ':-X' => 'smiley-sealed',
26             ':-P' => 'smiley-tongue-out',
27             ':-@' => 'smiley-yell',
28             ":'(" => 'smiley-cry',
29             ':-(' => 'smiley-frown',
30             ':-D' => 'smiley-laughing',
31             ':-)' => 'smiley-smile',
32             ':-S' => 'smiley-undecided',
33             ':-$' => 'smiley-embarassed',
34             'O:-)' => 'smiley-innocent',
35             ':-|' => 'smiley-money-mouth',
36             ':-O' => 'smiley-surprised',
37             ';-)' => 'smiley-wink',
38         );
39
40         foreach ($emoticons as $idx => $file) {
41             // <img title="Cry" src="http://.../program/js/tinymce/plugins/emoticons/img/smiley-cry.gif" border="0" alt="Cry" />
42             $file      = preg_quote(self::IMG_PATH . $file . '.gif', '/');
43             $search[]  = '/<img (title="[a-z ]+" )?src="[^"]+' . $file . '"[^>]+\/>/i';
44             $replace[] = $idx;
45         }
46
47         return preg_replace($search, $replace, $html);
48     }
49
50     /**
51      * Replace common plain text emoticons with empticon <img> tags
52      *
53      * @param string $text Text
54      *
55      * @return string Converted text
56      */
57     public static function text2icons($text)
58     {
59         // This is a lookbehind assertion which will exclude html entities
60         // E.g. situation when ";)" in "&quot;)" shouldn't be replaced by the icon
61         // It's so long because of assertion format restrictions
62         $entity = '(?<!&'
63             . '[a-zA-Z0-9]{2}' . '|' . '#[0-9]{2}' . '|'
64             . '[a-zA-Z0-9]{3}' . '|' . '#[0-9]{3}' . '|'
65             . '[a-zA-Z0-9]{4}' . '|' . '#[0-9]{4}' . '|'
66             . '[a-zA-Z0-9]{5}' . '|'
67             . '[a-zA-Z0-9]{6}' . '|'
68             . '[a-zA-Z0-9]{7}'
69             . ')';
70
71         // map of emoticon replacements
72         $map = array(
73             '/(?<!mailto):D/'   => self::img_tag('smiley-laughing.gif',    ':D'    ),
74             '/:-D/'             => self::img_tag('smiley-laughing.gif',    ':-D'   ),
75             '/:\(/'             => self::img_tag('smiley-frown.gif',       ':('    ),
76             '/:-\(/'            => self::img_tag('smiley-frown.gif',       ':-('   ),
77             '/'.$entity.';\)/'  => self::img_tag('smiley-wink.gif',        ';)'    ),
78             '/'.$entity.';-\)/' => self::img_tag('smiley-wink.gif',        ';-)'   ),
79             '/8\)/'             => self::img_tag('smiley-cool.gif',        '8)'    ),
80             '/8-\)/'            => self::img_tag('smiley-cool.gif',        '8-)'   ),
81             '/(?<!mailto):O/i'  => self::img_tag('smiley-surprised.gif',   ':O'    ),
82             '/(?<!mailto):-O/i' => self::img_tag('smiley-surprised.gif',   ':-O'   ),
83             '/(?<!mailto):P/i'  => self::img_tag('smiley-tongue-out.gif',  ':P'    ),
84             '/(?<!mailto):-P/i' => self::img_tag('smiley-tongue-out.gif',  ':-P'   ),
85             '/(?<!mailto):@/i'  => self::img_tag('smiley-yell.gif',        ':@'    ),
86             '/(?<!mailto):-@/i' => self::img_tag('smiley-yell.gif',        ':-@'   ),
87             '/O:\)/i'           => self::img_tag('smiley-innocent.gif',    'O:)'   ),
88             '/O:-\)/i'          => self::img_tag('smiley-innocent.gif',    'O:-)'  ),
89             '/(?<!O):\)/'       => self::img_tag('smiley-smile.gif',       ':)'    ),
90             '/(?<!O):-\)/'      => self::img_tag('smiley-smile.gif',       ':-)'   ),
91             '/(?<!mailto):\$/'  => self::img_tag('smiley-embarassed.gif',  ':$'    ),
92             '/(?<!mailto):-\$/' => self::img_tag('smiley-embarassed.gif',  ':-$'   ),
93             '/(?<!mailto):\*/i'  => self::img_tag('smiley-kiss.gif',       ':*'    ),
94             '/(?<!mailto):-\*/i' => self::img_tag('smiley-kiss.gif',       ':-*'   ),
95             '/(?<!mailto):S/i'  => self::img_tag('smiley-undecided.gif',   ':S'    ),
96             '/(?<!mailto):-S/i' => self::img_tag('smiley-undecided.gif',   ':-S'   ),
97         );
98
99         return preg_replace(array_keys($map), array_values($map), $text);
100     }
101
102     protected static function img_tag($ico, $title)
103     {
104         return html::img(array('src' => './' . self::IMG_PATH . $ico, 'title' => $title));
105     }
106
107     /**
108      * Replace emoticon icons <img> 'src' attribute, so it can
109      * be replaced with real file by Mail_Mime.
110      *
111      * @param string &$html HTML content
112      *
113      * @return array List of image files
114      */
115     public static function replace(&$html)
116     {
117         // Replace this:
118         // <img src="http[s]://.../tinymce/plugins/emoticons/img/smiley-cool.gif" ... />
119         // with this:
120         // <img src="/path/on/server/.../tinymce/plugins/emoticons/img/smiley-cool.gif" ... />
121
122         $rcube      = rcube::get_instance();
123         $assets_dir = $rcube->config->get('assets_dir');
124         $path       = unslashify($assets_dir ?: INSTALL_PATH) . '/' . self::IMG_PATH;
125         $offset     = 0;
126         $images     = array();
127
128         // remove any null-byte characters before parsing
129         $html = preg_replace('/\x00/', '', $html);
130
131         if (preg_match_all('# src=[\'"]([^\'"]+)#', $html, $matches, PREG_OFFSET_CAPTURE)) {
132             foreach ($matches[1] as $m) {
133                 // find emoticon image tags
134                 if (preg_match('#'. self::IMG_PATH . '(.*)$#', $m[0], $imatches)) {
135                     $image_name = $imatches[1];
136
137                     // sanitize image name so resulting attachment doesn't leave images dir
138                     $image_name = preg_replace('/[^a-zA-Z0-9_\.\-]/i', '', $image_name);
139                     $image_file = $path . $image_name;
140
141                     // Add the same image only once
142                     $images[$image_name] = $image_file;
143
144                     $html    = substr_replace($html, $image_file, $m[1] + $offset, strlen($m[0]));
145                     $offset += strlen($image_file) - strlen($m[0]);
146                 }
147             }
148         }
149
150         return $images;
151     }
152 }