f2cc532aff39441fae15c30a2037522cf60b3f25
[redakcja.git] / project / static / js / edit_area_compressor.php
1 <?php\r
2         /******\r
3          *\r
4          *      EditArea PHP compressor\r
5          *      Developped by Christophe Dolivet\r
6          *      Released under LGPL, Apache and BSD licenses\r
7          *      v1.1.3 (2007/01/18)      \r
8          *\r
9         ******/\r
10         \r
11         // CONFIG\r
12         $param['cache_duration']= 3600 * 24 * 10;               // 10 days util client cache expires\r
13         $param['compress'] = true;                                              // enable the code compression, should be activated but it can be usefull to desactivate it for easier error retrieving (true or false)\r
14         $param['debug'] = false;                                                // Enable this option if you need debuging info\r
15         $param['use_disk_cache']= true;                                 // If you enable this option gzip files will be cached on disk.\r
16         $param['use_gzip']= true;                                               // Enable gzip compression\r
17         // END CONFIG\r
18         \r
19         $compressor= new Compressor($param);\r
20         \r
21         class Compressor{\r
22         \r
23                 \r
24                 function compressor($param)\r
25                 {\r
26                         $this->__construct($param);\r
27                 }\r
28                 \r
29                 function __construct($param)\r
30                 {\r
31                         $this->start_time= $this->get_microtime();\r
32                         $this->file_loaded_size=0;\r
33                         $this->param= $param;\r
34                         $this->script_list="";\r
35                         $this->path= dirname(__FILE__)."/";\r
36                         if(isset($_GET['plugins'])){\r
37                                 $this->load_all_plugins= true;\r
38                                 $this->full_cache_file= $this->path."edit_area_full_with_plugins.js";\r
39                                 $this->gzip_cache_file= $this->path."edit_area_full_with_plugins.gz";\r
40                         }else{\r
41                                 $this->load_all_plugins= false;\r
42                                 $this->full_cache_file= $this->path."edit_area_full.js";\r
43                                 $this->gzip_cache_file= $this->path."edit_area_full.gz";\r
44                         }\r
45                         \r
46                         $this->check_gzip_use();\r
47                         $this->send_headers();\r
48                         $this->check_cache();\r
49                         $this->load_files();\r
50                         $this->send_datas();\r
51                 }\r
52                 \r
53                 function send_headers()\r
54                 {\r
55                         header("Content-type: text/javascript; charset: UTF-8");\r
56                         header("Vary: Accept-Encoding"); // Handle proxies\r
57                         header(sprintf("Expires: %s GMT", gmdate("D, d M Y H:i:s", time() + $this->param['cache_duration'])) );\r
58                         if($this->use_gzip)\r
59                                 header("Content-Encoding: ".$this->gzip_enc_header);\r
60                 }\r
61                 \r
62                 function check_gzip_use()\r
63                 {\r
64                         $encodings = array();\r
65                         $desactivate_gzip=false;\r
66                                         \r
67                         if (isset($_SERVER['HTTP_ACCEPT_ENCODING']))\r
68                                 $encodings = explode(',', strtolower(preg_replace("/\s+/", "", $_SERVER['HTTP_ACCEPT_ENCODING'])));\r
69                         \r
70                         // desactivate gzip for IE version < 7\r
71                         if(preg_match("/(?:msie )([0-9.]+)/i", $_SERVER['HTTP_USER_AGENT'], $ie))\r
72                         {\r
73                                 if($ie[1]<7)\r
74                                         $desactivate_gzip=true; \r
75                         }\r
76                         \r
77                         // Check for gzip header or northon internet securities\r
78                         if (!$desactivate_gzip && $this->param['use_gzip'] && (in_array('gzip', $encodings) || in_array('x-gzip', $encodings) || isset($_SERVER['---------------'])) && function_exists('ob_gzhandler') && !ini_get('zlib.output_compression')) {\r
79                                 $this->gzip_enc_header= in_array('x-gzip', $encodings) ? "x-gzip" : "gzip";\r
80                                 $this->use_gzip=true;\r
81                                 $this->cache_file=$this->gzip_cache_file;\r
82                         }else{\r
83                                 $this->use_gzip=false;\r
84                                 $this->cache_file=$this->full_cache_file;\r
85                         }\r
86                 }\r
87                 \r
88                 function check_cache()\r
89                 {\r
90                         // Only gzip the contents if clients and server support it\r
91                         if (file_exists($this->cache_file)) {\r
92                                 // check if cache file must be updated\r
93                                 $cache_date=0;                          \r
94                                 if ($dir = opendir($this->path)) {\r
95                                         while (($file = readdir($dir)) !== false) {\r
96                                                 if(is_file($this->path.$file) && $file!="." && $file!="..")\r
97                                                         $cache_date= max($cache_date, filemtime($this->path.$file));\r
98                                         }\r
99                                         closedir($dir);\r
100                                 }\r
101                                 if($this->load_all_plugins){\r
102                                         $plug_path= $this->path."plugins/";\r
103                                         if (($dir = @opendir($plug_path)) !== false)\r
104                                         {\r
105                                                 while (($file = readdir($dir)) !== false)\r
106                                                 {\r
107                                                         if ($file !== "." && $file !== "..")\r
108                                                         {\r
109                                                                 if(is_dir($plug_path.$file) && file_exists($plug_path.$file."/".$file.".js"))\r
110                                                                         $cache_date= max($cache_date, filemtime("plugins/".$file."/".$file.".js"));\r
111                                                         }\r
112                                                 }\r
113                                                 closedir($dir);\r
114                                         }\r
115                                 }\r
116 \r
117                                 if(filemtime($this->cache_file) >= $cache_date){\r
118                                         // if cache file is up to date\r
119                                         $last_modified = gmdate("D, d M Y H:i:s",filemtime($this->cache_file))." GMT";\r
120                                         if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && strcasecmp($_SERVER["HTTP_IF_MODIFIED_SINCE"], $last_modified) === 0)\r
121                                         {\r
122                                                 header("HTTP/1.1 304 Not Modified");\r
123                                                 header("Last-modified: ".$last_modified);\r
124                                                 header("Cache-Control: Public"); // Tells HTTP 1.1 clients to cache\r
125                                                 header("Pragma:"); // Tells HTTP 1.0 clients to cache\r
126                                         }\r
127                                         else\r
128                                         {\r
129                                                 header("Last-modified: ".$last_modified);\r
130                                                 header("Cache-Control: Public"); // Tells HTTP 1.1 clients to cache\r
131                                                 header("Pragma:"); // Tells HTTP 1.0 clients to cache\r
132                                                 header('Content-Length: '.filesize($this->cache_file));\r
133                                                 echo file_get_contents($this->cache_file);\r
134                                         }                               \r
135                                         die;\r
136                                 }\r
137                         }\r
138                         return false;\r
139                 }\r
140                 \r
141                 function load_files()\r
142                 {\r
143                         $loader= $this->get_content("edit_area_loader.js")."\n";\r
144                         \r
145                         // get the list of other files to load\r
146                 $loader= preg_replace("/(t\.scripts_to_load=\s*)\[([^\]]*)\];/e"\r
147                                                 , "\$this->replace_scripts('script_list', '\\1', '\\2')"\r
148                                                 , $loader);\r
149                 \r
150                         $loader= preg_replace("/(t\.sub_scripts_to_load=\s*)\[([^\]]*)\];/e"\r
151                                                 , "\$this->replace_scripts('sub_script_list', '\\1', '\\2')"\r
152                                                 , $loader);\r
153 \r
154                         $this->datas= $loader;\r
155                         $this->compress_javascript($this->datas);\r
156                         \r
157                         // load other scripts needed for the loader\r
158                         preg_match_all('/"([^"]*)"/', $this->script_list, $match);\r
159                         foreach($match[1] as $key => $value)\r
160                         {\r
161                                 $content= $this->get_content(preg_replace("/\\|\//i", "", $value).".js");\r
162                                 $this->compress_javascript($content);\r
163                                 $this->datas.= $content."\n";\r
164                         }\r
165                         //$this->datas);\r
166                         //$this->datas= preg_replace('/(( |\t|\r)*\n( |\t)*)+/s', "", $this->datas);\r
167                         \r
168                         // improved compression step 1/2        \r
169                         $this->datas= preg_replace(array("/(\b)EditAreaLoader(\b)/", "/(\b)editAreaLoader(\b)/", "/(\b)editAreas(\b)/"), array("EAL", "eAL", "eAs"), $this->datas);\r
170                         //$this->datas= str_replace(array("EditAreaLoader", "editAreaLoader", "editAreas"), array("EAL", "eAL", "eAs"), $this->datas);\r
171                         $this->datas.= "var editAreaLoader= eAL;var editAreas=eAs;EditAreaLoader=EAL;";\r
172                 \r
173                         // load sub scripts\r
174                         $sub_scripts="";\r
175                         $sub_scripts_list= array();\r
176                         preg_match_all('/"([^"]*)"/', $this->sub_script_list, $match);\r
177                         foreach($match[1] as $value){\r
178                                 $sub_scripts_list[]= preg_replace("/\\|\//i", "", $value).".js";\r
179                         }\r
180                 \r
181                         if($this->load_all_plugins){\r
182                                 // load plugins scripts\r
183                                 $plug_path= $this->path."plugins/";\r
184                                 if (($dir = @opendir($plug_path)) !== false)\r
185                                 {\r
186                                         while (($file = readdir($dir)) !== false)\r
187                                         {\r
188                                                 if ($file !== "." && $file !== "..")\r
189                                                 {\r
190                                                         if(is_dir($plug_path.$file) && file_exists($plug_path.$file."/".$file.".js"))\r
191                                                                 $sub_scripts_list[]= "plugins/".$file."/".$file.".js";\r
192                                                 }\r
193                                         }\r
194                                         closedir($dir);\r
195                                 }\r
196                         }\r
197                                                         \r
198                         foreach($sub_scripts_list as $value){\r
199                                 $sub_scripts.= $this->get_javascript_content($value);\r
200                         }\r
201                         // improved compression step 2/2        \r
202                         $sub_scripts= preg_replace(array("/(\b)editAreaLoader(\b)/", "/(\b)editAreas(\b)/", "/(\b)editArea(\b)/", "/(\b)EditArea(\b)/"), array("eAL", "eAs", "eA", "EA"), $sub_scripts);\r
203                 //      $sub_scripts= str_replace(array("editAreaLoader", "editAreas", "editArea", "EditArea"), array("eAL", "eAs", "eA", "EA"), $sub_scripts);\r
204                         $sub_scripts.= "var editArea= eA;EditArea=EA;";\r
205                         \r
206                         \r
207                         // add the scripts\r
208                 //      $this->datas.= sprintf("editAreaLoader.iframe_script= \"<script type='text/javascript'>%s</script>\";\n", $sub_scripts);\r
209                 \r
210                 \r
211                         // add the script and use a last compression \r
212                         if( $this->param['compress'] )\r
213                         {\r
214                                 $last_comp      = array( 'Á' => 'this',\r
215                                                                  'Â' => 'textarea',\r
216                                                                  'Ã' => 'function',\r
217                                                                  'Ä' => 'prototype',\r
218                                                                  'Å' => 'settings',\r
219                                                                  'Æ' => 'length',\r
220                                                                  'Ç' => 'style',\r
221                                                                  'È' => 'parent',\r
222                                                                  'É' => 'last_selection',\r
223                                                                  'Ê' => 'value',\r
224                                                                  'Ë' => 'true',\r
225                                                                  'Ì' => 'false'\r
226                                                                  /*,\r
227                                                                         'Î' => '"',\r
228                                                                  'Ï' => "\n",\r
229                                                                  'À' => "\r"*/);\r
230                         }\r
231                         else\r
232                         {\r
233                                 $last_comp      = array();\r
234                         }\r
235                         \r
236                         $js_replace= '';\r
237                         foreach( $last_comp as $key => $val )\r
238                                 $js_replace .= ".replace(/". $key ."/g,'". str_replace( array("\n", "\r"), array('\n','\r'), $val ) ."')";\r
239                         \r
240                         $this->datas.= sprintf("editAreaLoader.iframe_script= \"<script type='text/javascript'>%s</script>\"%s;\n",\r
241                                                                 str_replace( array_values($last_comp), array_keys($last_comp), $sub_scripts ), \r
242                                                                 $js_replace);\r
243                         \r
244                         if($this->load_all_plugins)\r
245                                 $this->datas.="editAreaLoader.all_plugins_loaded=true;\n";\r
246                 \r
247                         \r
248                         // load the template\r
249                         $this->datas.= sprintf("editAreaLoader.template= \"%s\";\n", $this->get_html_content("template.html"));\r
250                         // load the css\r
251                         $this->datas.= sprintf("editAreaLoader.iframe_css= \"<style>%s</style>\";\n", $this->get_css_content("edit_area.css"));\r
252                                         \r
253                 //      $this->datas= "function editArea(){};editArea.prototype.loader= function(){alert('bouhbouh');} var a= new editArea();a.loader();";\r
254                                         \r
255                 }\r
256                 \r
257                 function send_datas()\r
258                 {\r
259                         if($this->param['debug']){\r
260                                 $header=sprintf("/* USE PHP COMPRESSION\n");\r
261                                 $header.=sprintf("javascript size: based files: %s => PHP COMPRESSION => %s ", $this->file_loaded_size, strlen($this->datas));\r
262                                 if($this->use_gzip){\r
263                                         $gzip_datas=  gzencode($this->datas, 9, FORCE_GZIP);                            \r
264                                         $header.=sprintf("=> GZIP COMPRESSION => %s", strlen($gzip_datas));\r
265                                         $ratio = round(100 - strlen($gzip_datas) / $this->file_loaded_size * 100.0);                    \r
266                                 }else{\r
267                                         $ratio = round(100 - strlen($this->datas) / $this->file_loaded_size * 100.0);\r
268                                 }\r
269                                 $header.=sprintf(", reduced by %s%%\n", $ratio);\r
270                                 $header.=sprintf("compression time: %s\n", $this->get_microtime()-$this->start_time); \r
271                                 $header.=sprintf("%s\n", implode("\n", $this->infos));\r
272                                 $header.=sprintf("*/\n");\r
273                                 $this->datas= $header.$this->datas;     \r
274                         }\r
275                         $mtime= time(); // ensure that the 2 disk files will have the same update time\r
276                         // generate gzip file and cahce it if using disk cache\r
277                         if($this->use_gzip){\r
278                                 $this->gzip_datas= gzencode($this->datas, 9, FORCE_GZIP);\r
279                                 if($this->param['use_disk_cache'])\r
280                                         $this->file_put_contents($this->gzip_cache_file, $this->gzip_datas, $mtime);\r
281                         }\r
282                         \r
283                         // generate full js file and cache it if using disk cache                       \r
284                         if($this->param['use_disk_cache'])\r
285                                 $this->file_put_contents($this->full_cache_file, $this->datas, $mtime);\r
286                         \r
287                         // generate output\r
288                         if($this->use_gzip)\r
289                                 echo $this->gzip_datas;\r
290                         else\r
291                                 echo $this->datas;\r
292                                 \r
293 //                      die;\r
294                 }\r
295                                 \r
296                 \r
297                 function get_content($end_uri)\r
298                 {\r
299                         $end_uri=preg_replace("/\.\./", "", $end_uri); // Remove any .. (security)\r
300                         $file= $this->path.$end_uri;\r
301                         if(file_exists($file)){\r
302                                 $this->infos[]=sprintf("'%s' loaded", $end_uri);\r
303                                 /*$fd = fopen($file, 'rb');\r
304                                 $content = fread($fd, filesize($file));\r
305                                 fclose($fd);\r
306                                 return $content;*/\r
307                                 return $this->file_get_contents($file);\r
308                         }else{\r
309                                 $this->infos[]=sprintf("'%s' not loaded", $end_uri);\r
310                                 return "";\r
311                         }\r
312                 }\r
313                 \r
314                 function get_javascript_content($end_uri)\r
315                 {\r
316                         $val=$this->get_content($end_uri);\r
317         \r
318                         $this->compress_javascript($val);\r
319                         $this->prepare_string_for_quotes($val);\r
320                         return $val;\r
321                 }\r
322                 \r
323                 function compress_javascript(&$code)\r
324                 {\r
325                         if($this->param['compress'])\r
326                         {\r
327                                 // remove all comments\r
328                                 //      (\"(?:[^\"\\]*(?:\\\\)*(?:\\\"?)?)*(?:\"|$))|(\'(?:[^\'\\]*(?:\\\\)*(?:\\'?)?)*(?:\'|$))|(?:\/\/(?:.|\r|\t)*?(\n|$))|(?:\/\*(?:.|\n|\r|\t)*?(?:\*\/|$))\r
329                                 $code= preg_replace("/(\"(?:[^\"\\\\]*(?:\\\\\\\\)*(?:\\\\\"?)?)*(?:\"|$))|(\'(?:[^\'\\\\]*(?:\\\\\\\\)*(?:\\\\\'?)?)*(?:\'|$))|(?:\/\/(?:.|\r|\t)*?(\n|$))|(?:\/\*(?:.|\n|\r|\t)*?(?:\*\/|$))/s", "$1$2$3", $code);\r
330                                 // remove line return, empty line and tabulation\r
331                                 $code= preg_replace('/(( |\t|\r)*\n( |\t)*)+/s', " ", $code);\r
332                                 // add line break before "else" otherwise navigators can't manage to parse the file\r
333                                 $code= preg_replace('/(\b(else)\b)/', "\n$1", $code);\r
334                                 // remove unnecessary spaces\r
335                                 $code= preg_replace('/( |\t|\r)*(;|\{|\}|=|==|\-|\+|,|\(|\)|\|\||&\&|\:)( |\t|\r)*/', "$2", $code);\r
336                         }\r
337                 }\r
338                 \r
339                 function get_css_content($end_uri){\r
340                         $code=$this->get_content($end_uri);\r
341                         // remove comments\r
342                         $code= preg_replace("/(?:\/\*(?:.|\n|\r|\t)*?(?:\*\/|$))/s", "", $code);\r
343                         // remove spaces\r
344                         $code= preg_replace('/(( |\t|\r)*\n( |\t)*)+/s', "", $code);\r
345                         // remove spaces\r
346                         $code= preg_replace('/( |\t|\r)?(\:|,|\{|\})( |\t|\r)+/', "$2", $code);\r
347                 \r
348                         $this->prepare_string_for_quotes($code);\r
349                         return $code;\r
350                 }\r
351                 \r
352                 function get_html_content($end_uri){\r
353                         $code=$this->get_content($end_uri);\r
354                         //$code= preg_replace('/(\"(?:\\\"|[^\"])*(?:\"|$))|' . "(\'(?:\\\'|[^\'])*(?:\'|$))|(?:\/\/(?:.|\r|\t)*?(\n|$))|(?:\/\*(?:.|\n|\r|\t)*?(?:\*\/|$))/s", "$1$2$3", $code);\r
355                         $code= preg_replace('/(( |\t|\r)*\n( |\t)*)+/s', " ", $code);\r
356                         $this->prepare_string_for_quotes($code);\r
357                         return $code;\r
358                 }\r
359                 \r
360                 function prepare_string_for_quotes(&$str){\r
361                         // prepare the code to be putted into quotes \r
362                         /*$pattern= array("/(\\\\)?\"/", '/\\\n/'       , '/\\\r/'      , "/(\r?\n)/");\r
363                         $replace= array('$1$1\\"', '\\\\\\n', '\\\\\\r' , '\\\n"$1+"');*/\r
364                         $pattern= array("/(\\\\)?\"/", '/\\\n/' , '/\\\r/'      , "/(\r?\n)/");\r
365                         if($this->param['compress'])\r
366                                 $replace= array('$1$1\\"', '\\\\\\n', '\\\\\\r' , '\n');\r
367                         else\r
368                                 $replace= array('$1$1\\"', '\\\\\\n', '\\\\\\r' , "\\n\"\n+\"");\r
369                         $str= preg_replace($pattern, $replace, $str);\r
370                 }\r
371                 \r
372                 function replace_scripts($var, $param1, $param2)\r
373                 {\r
374                         $this->$var=stripslashes($param2);\r
375                 return $param1."[];";\r
376                 }\r
377 \r
378                 /* for php version that have not thoses functions */\r
379                 function file_get_contents($file)\r
380                 {\r
381                         $fd = fopen($file, 'rb');\r
382                         $content = fread($fd, filesize($file));\r
383                         fclose($fd);\r
384                         $this->file_loaded_size+= strlen($content);\r
385                         return $content;                                \r
386                 }\r
387                 \r
388                 function file_put_contents($file, &$content, $mtime=-1)\r
389                 {\r
390                         if($mtime==-1)\r
391                                 $mtime=time();\r
392                         $fp = @fopen($file, "wb");\r
393                         if ($fp) {\r
394                                 fwrite($fp, $content);\r
395                                 fclose($fp);\r
396                                 touch($file, $mtime);\r
397                                 return true;\r
398                         }\r
399                         return false;\r
400                 }\r
401                 \r
402                 function get_microtime()\r
403                 {\r
404                    list($usec, $sec) = explode(" ", microtime());\r
405                    return ((float)$usec + (float)$sec);\r
406                 }\r
407         }       \r
408 ?>\r