Ticket #3882: tiny_mce_gzip.php

File tiny_mce_gzip.php, 11.4 kB (added by josegonzalez, 2 years ago)
Line 
1 <?php
2 /**
3  * $RCSfile: tiny_mce_gzip.php,v $
4  * $Revision: $
5  * $Date: $
6  *
7  * @version 1.08
8  * @author Moxiecode
9  * @copyright Copyright  2005-2006, Moxiecode Systems AB, All rights reserved.
10  *
11  * This file compresses the TinyMCE JavaScript using GZip and
12  * enables the browser to do two requests instead of one for each .js file.
13  * Notice: This script defaults the button_tile_map option to true for extra performance.
14  */
15
16 @require_once('../../../wp-config.php');
17
18 // gzip_compression();
19
20 // New realpath function
21 {
22    if ($path == "")
23    {
24        return false;
25    }
26
27    $path = trim(preg_replace("/\\\\/", "/", (string)$path));
28
29    if (!preg_match("/(\.\w{1,4})$/", $path)  &&
30        !preg_match("/\?[^\\/]+$/", $path)  &&
31        !preg_match("/\\/$/", $path))
32    {
33        $path .= '/';
34    }
35
36    $pattern = "/^(\\/|\w:\\/|https?:\\/\\/[^\\/]+\\/)?(.*)$/i";
37
38    preg_match_all($pattern, $path, $matches, PREG_SET_ORDER);
39
40    $path_tok_1 = $matches[0][1];
41    $path_tok_2 = $matches[0][2];
42
43    $path_tok_2 = preg_replace(
44                    array("/^\\/+/", "/\\/+/"),
45                    array("", "/"),
46                    $path_tok_2);
47
48    $path_parts = explode("/", $path_tok_2);
49    $real_path_parts = array();
50
51    for ($i = 0, $real_path_parts = array(); $i < count($path_parts); $i++)
52    {
53        if ($path_parts[$i] == '.')
54        {
55            continue;
56        }
57        else if ($path_parts[$i] == '..')
58        {
59            if (  (isset($real_path_parts[0])  &&  $real_path_parts[0] != '..')
60                || ($path_tok_1 != "")  )
61            {
62                array_pop($real_path_parts);
63                continue;
64            }
65        }
66
67        array_push($real_path_parts, $path_parts[$i]);
68    }
69
70    return $path_tok_1 . implode('/', $real_path_parts);
71 }
72
73 // End of real_path function
74
75 function wp_tinymce_lang($path) {
76     global $language;
77
78     $text = '';
79
80     // Look for xx_YY.js, xx_yy.js, xx.js
81     $file = real_path(sprintf($path, $language));
82     if ( file_exists($file) )
83         $text = file_get_contents($file);
84     $file = real_path(sprintf($path, strtolower($language)));
85     if ( file_exists($file) )
86         $text = file_get_contents($file);
87     $file = real_path(sprintf($path, substr($language, 0, 2)));
88     if ( file_exists($file) )
89         $text = file_get_contents($file);
90
91
92     // Fall back on en.js
93     $file = real_path(sprintf($path, 'en'));
94     if ( empty($text) && file_exists($file) )
95         $text = file_get_contents($file);
96
97     // Send lang file through gettext
98     if ( function_exists('__') && strtolower(substr($language, 0, 2)) != 'en' ) {
99         $search1 = "/^tinyMCELang\\[(['\"])(.*)\\1\]( ?= ?)(['\"])(.*)\\4/Uem";
100         $replace1 = "'tinyMCELang[\\1\\2\\1]\\3'.stripslashes('\\4').__('\\5').stripslashes('\\4')";
101
102         $search2 = "/\\s:\\s(['\"])(.*)\\1(,|\\s*})/Uem";
103         $replace2 = "' : '.stripslashes('\\1').__('\\2').stripslashes('\\1').'\\3'";
104
105         $search = array($search1, $search2);
106         $replace = array($replace1, $replace2);
107
108         $text = preg_replace($search, $replace, $text);
109
110         return $text;
111     }
112
113     return $text;
114 }
115
116 function wp_compact_tinymce_js($text) {
117     // This function was custom-made for TinyMCE 2.0, not expected to work with any other JS.
118
119     // Strip comments
120     $text = preg_replace("!(^|\s+)//.*$!m", '', $text);
121     $text = preg_replace("!/\*.*?\*/!s", '', $text);
122
123     // Strip leading tabs, carriage returns and unnecessary line breaks.
124     $text = preg_replace("!^\t+!m", '', $text);
125     $text = str_replace("\r", '', $text);
126     $text = preg_replace("!(^|{|}|;|:|\))\n!m", '\\1', $text);
127
128     return "$text\n";
129 }
130
131
132 // General options
133 $suffix = "";                            // Set to "_src" to use source version
134 $expiresOffset = 3600 * 24 * 10;        // 10 days util client cache expires
135 $diskCache = false;                        // If you enable this option gzip files will be cached on disk.
136 $cacheDir = real_path(".");                // Absolute directory path to where cached gz files will be stored
137 $debug = false;                            // Enable this option if you need debuging info
138
139 // Headers
140 header("Content-Type: text/javascript; charset=" . get_bloginfo('charset'));
141 // header("Cache-Control: must-revalidate");
142 header("Vary: Accept-Encoding"); // Handle proxies
143 header("Expires: " . gmdate("D, d M Y H:i:s", time() + $expiresOffset) . " GMT");
144
145 // Get data to load
146 $theme = isset($_GET['theme']) ? TinyMCE_cleanInput($_GET['theme']) : "";
147 $language = isset($_GET['language']) ? TinyMCE_cleanInput($_GET['language']) : "";
148 $plugins = isset($_GET['plugins']) ? TinyMCE_cleanInput($_GET['plugins']) : "";
149 $lang = isset($_GET['lang']) ? TinyMCE_cleanInput($_GET['lang']) : "en";
150 $index = isset($_GET['index']) ? TinyMCE_cleanInput($_GET['index']) : -1;
151 $cacheKey = md5($theme . $language . $plugins . $lang . $index . $debug);
152 $cacheFile = $cacheDir == "" ? "" : $cacheDir . "/" . "tinymce_" $cacheKey . ".gz";
153 $cacheData = "";
154
155 // Patch older versions of PHP < 4.3.0
156 if (!function_exists('file_get_contents')) {
157     function file_get_contents($filename) {
158         $fd = fopen($filename, 'rb');
159         $content = fread($fd, filesize($filename));
160         fclose($fd);
161         return $content;
162     }
163 }
164
165 // Security check function, can only contain a-z 0-9 , _ - and whitespace.
166 function TinyMCE_cleanInput($str) {
167     return preg_replace("/[^0-9a-z\-_,]+/i", "", $str); // Remove anything but 0-9,a-z,-_
168 }
169
170 function TinyMCE_echo($str) {
171     global $cacheData, $diskCache;
172
173     if ($diskCache)
174         $cacheData .= $str;
175     else
176         echo $str;
177 }
178
179 // Only gzip the contents if clients and server support it
180 $encodings = array();
181
182 if (isset($_SERVER['HTTP_ACCEPT_ENCODING']))
183     $encodings = explode(',', strtolower(preg_replace("/\s+/", "", $_SERVER['HTTP_ACCEPT_ENCODING'])));
184
185 // Check for gzip header or northon internet securities
186 if ((in_array('gzip', $encodings) || in_array('x-gzip', $encodings) || isset($_SERVER['---------------'])) && function_exists('ob_gzhandler') && !ini_get('zlib.output_compression')) {
187     $enc = in_array('x-gzip', $encodings) ? "x-gzip" : "gzip";
188
189     // Use cached file if it exists but not in debug mode
190     if (file_exists($cacheFile) && !$debug) {
191         header("Content-Encoding: " . $enc);
192         echo file_get_contents($cacheFile);
193         die;
194     }
195
196     if (!$diskCache)
197         ob_start("ob_gzhandler");
198 } else
199     $diskCache = false;
200
201
202 if ($index > -1) {
203     // Write main script and patch some things
204     if ($index == 0) {
205         TinyMCE_echo(wp_compact_tinymce_js(file_get_contents(real_path("tiny_mce" . $suffix . ".js")))); // WP
206         TinyMCE_echo('TinyMCE.prototype.orgLoadScript = TinyMCE.prototype.loadScript;');
207         TinyMCE_echo('TinyMCE.prototype.loadScript = function() {};var realTinyMCE = tinyMCE;');
208     } else
209         TinyMCE_echo('tinyMCE = realTinyMCE;');
210
211     // Do init based on index
212     TinyMCE_echo("tinyMCE.init(tinyMCECompressed.configs[" . $index . "]);");
213
214     // Load external plugins
215     if ($index == 0)
216         TinyMCE_echo("tinyMCECompressed.loadPlugins();");
217
218     // Load theme, language pack and theme language packs
219     if ($theme) {
220         TinyMCE_echo(wp_compact_tinymce_js(file_get_contents(real_path("themes/" . $theme . "/editor_template" . $suffix . ".js")))); // WP
221         TinyMCE_echo(wp_tinymce_lang("themes/" . $theme . "/langs/%s.js")); // WP
222     }
223
224     /* WP if ($language) WP */
225         TinyMCE_echo(wp_tinymce_lang("langs/%s.js")); // WP
226
227     // Load all plugins and their language packs
228     $plugins = explode(",", $plugins);
229     foreach ($plugins as $plugin) {
230         $pluginFile = real_path("plugins/" . $plugin . "/editor_plugin" . $suffix . ".js");
231         /* WP $languageFile = realpath("plugins/" . $plugin . "/langs/" . $lang . ".js"); WP */
232
233         if ($pluginFile)
234             TinyMCE_echo(file_get_contents($pluginFile));
235
236         /* WP if ($languageFile) WP */
237             TinyMCE_echo(wp_tinymce_lang("plugins/" . $plugin . "/langs/%s.js")); // WP
238     }
239
240     // Reset tinyMCE compressor engine
241     TinyMCE_echo("tinyMCE = tinyMCECompressed;");
242
243     // Write to cache
244     if ($diskCache) {
245         // Calculate compression ratio and debug target output path
246         if ($debug) {
247             $ratio = round(100 - strlen(gzencode($cacheData, 9, FORCE_GZIP)) / strlen($cacheData) * 100.0);
248             TinyMCE_echo("alert('TinyMCE was compressed by " . $ratio . "%.\\nOutput cache file: " . $cacheFile . "');");
249         }
250
251         $cacheData = gzencode($cacheData, 9, FORCE_GZIP);
252
253         // Write to file if possible
254         $fp = @fopen($cacheFile, "wb");
255         if ($fp) {
256             fwrite($fp, $cacheData);
257             fclose($fp);
258         }
259
260         // Output
261         header("Content-Encoding: " . $enc);
262         echo $cacheData;
263     }
264
265     die;
266 }
267 ?>
268
269 function TinyMCECompressed() {
270     this.configs = new Array();
271     this.loadedFiles = new Array();
272     this.externalPlugins = new Array();
273     this.loadAdded = false;
274     this.isLoaded = false;
275 }
276
277 TinyMCECompressed.prototype.init = function(settings) {
278     var elements = document.getElementsByTagName('script');
279     var scriptURL = "";
280
281     for (var i=0; i<elements.length; i++) {
282         if (elements[i].src && elements[i].src.indexOf("tiny_mce_gzip.php") != -1) {
283             scriptURL = elements[i].src;
284             break;
285         }
286     }
287
288     settings["theme"] = typeof(settings["theme"]) != "undefined" ? settings["theme"] : "default";
289     settings["plugins"] = typeof(settings["plugins"]) != "undefined" ? settings["plugins"] : "";
290     settings["language"] = typeof(settings["language"]) != "undefined" ? settings["language"] : "en";
291     settings["button_tile_map"] = typeof(settings["button_tile_map"]) != "undefined" ? settings["button_tile_map"] : true;
292     this.configs[this.configs.length] = settings;
293     this.settings = settings;
294
295     scriptURL += (scriptURL.indexOf('?') == -1) ? '?' : '&';
296     scriptURL += "theme=" + escape(this.getOnce(settings["theme"])) + "&language=" + escape(this.getOnce(settings["language"])) + "&plugins=" + escape(this.getOnce(settings["plugins"])) + "&lang=" + settings["language"] + "&index=" + escape(this.configs.length-1);
297     document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + scriptURL + '"></script>');
298
299     if (!this.loadAdded) {
300         tinyMCE.addEvent(window, "DOMContentLoaded", TinyMCECompressed.prototype.onLoad);
301         tinyMCE.addEvent(window, "load", TinyMCECompressed.prototype.onLoad);
302         this.loadAdded = true;
303     }
304 }
305
306 TinyMCECompressed.prototype.onLoad = function() {
307     if (tinyMCE.isLoaded)
308         return true;
309
310     tinyMCE = realTinyMCE;
311     TinyMCE_Engine.prototype.onLoad();
312     tinyMCE._addUnloadEvents();
313
314     tinyMCE.isLoaded = true;
315 }
316
317 TinyMCECompressed.prototype.addEvent = function(o, n, h) {
318     if (o.attachEvent)
319         o.attachEvent("on" + n, h);
320     else
321         o.addEventListener(n, h, false);
322 }
323
324 TinyMCECompressed.prototype.getOnce = function(str) {
325     var ar = str.replace(/\s+/g, '').split(',');
326
327     for (var i=0; i<ar.length; i++) {
328         if (ar[i] == '' || ar[i].charAt(0) == '-') {
329             ar[i] = null;
330             continue;
331         }
332
333         // Skip load
334         for (var x=0; x<this.loadedFiles.length; x++) {
335             if (this.loadedFiles[x] == ar[i])
336                 ar[i] = null;
337         }
338
339         this.loadedFiles[this.loadedFiles.length] = ar[i];
340     }
341
342     // Glue
343     str = "";
344     for (var i=0; i<ar.length; i++) {
345         if (ar[i] == null)
346             continue;
347
348         str += ar[i];
349
350         if (i != ar.length-1)
351             str += ",";
352     }
353
354     return str;
355 };
356
357 TinyMCECompressed.prototype.loadPlugins = function() {
358     var i, ar;
359
360     TinyMCE.prototype.loadScript = TinyMCE.prototype.orgLoadScript;
361     tinyMCE = realTinyMCE;
362
363     ar = tinyMCECompressed.externalPlugins;
364     for (i=0; i<ar.length; i++)
365         tinyMCE.loadPlugin(ar[i].name, ar[i].url);
366
367     TinyMCE.prototype.loadScript = function() {};
368 };
369
370 TinyMCECompressed.prototype.loadPlugin = function(n, u) {
371     this.externalPlugins[this.externalPlugins.length] = {name : n, url : u};
372 };
373
374 TinyMCECompressed.prototype.importPluginLanguagePack = function(n, v) {
375     tinyMCE = realTinyMCE;
376     TinyMCE.prototype.loadScript = TinyMCE.prototype.orgLoadScript;
377     tinyMCE.importPluginLanguagePack(n, v);
378 };
379
380 TinyMCECompressed.prototype.addPlugin = function(n, p) {
381     tinyMCE = realTinyMCE;
382     tinyMCE.addPlugin(n, p);
383 };
384
385 var tinyMCE = new TinyMCECompressed();
386 var tinyMCECompressed = tinyMCE;
387