PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/edit_area/edit_area_compressor.php

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