PageRenderTime 58ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/system/rokgzipper.php

https://bitbucket.org/ericrlarson/com_biblestudy
PHP | 447 lines | 344 code | 64 blank | 39 comment | 59 complexity | 427c3d0df5f996fb0cc7c2c50fbb4883 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /**
  3. * RokGZipper Plugin
  4. *
  5. * @package RocketTheme
  6. * @subpackage rokgzipper
  7. * @version 1.8 January 30, 2010
  8. * @author RocketTheme http://www.rockettheme.com
  9. * @copyright Copyright (C) 2007 - 2010 RocketTheme, LLC
  10. * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
  11. *
  12. */
  13. // no direct access
  14. defined( '_JEXEC' ) or die( 'Restricted access' );
  15. jimport( 'joomla.plugin.plugin' );
  16. jimport( 'joomla.filesystem.file' );
  17. /**
  18. * RokGZipper plugin
  19. *
  20. * @author Andy Miller, Brian Towles
  21. * @package RokGZipper
  22. * @subpackage System
  23. */
  24. class plgSystemRokGZipper extends JPlugin
  25. {
  26. var $_ignores = array();
  27. function plgSystemRokGZipper(& $subject, $config)
  28. {
  29. parent::__construct($subject, $config);
  30. $lang =& JFactory::getLanguage();
  31. $lang->load('plg_system_rokgzipper', JPATH_ADMINISTRATOR);
  32. }
  33. function cmp($a, $b)
  34. {
  35. if ($a == $b) {
  36. return 0;
  37. }
  38. return ($a < $b) ? -1 : 1;
  39. }
  40. function onAfterRender()
  41. {
  42. global $mainframe;
  43. if ($mainframe->isAdmin()) return;
  44. $this->_getIgnores();
  45. $this->_processJsFiles();
  46. $this->_processCSSFiles();
  47. }
  48. function _getIgnores(){
  49. $uri =& JURI::getInstance();
  50. $base = $uri->toString( array('scheme', 'host', 'port'));
  51. $path = JURI::Root(true);
  52. $ignored_files_text = $this->params->get('ignored_files');
  53. if (!empty($ignored_files_text)){
  54. $tmp_ignores = explode("\n",$ignored_files_text);
  55. foreach($tmp_ignores as $ignored_file) {
  56. $filepath = $this->_getFilePath($ignored_file,$base,$path);
  57. if (JFile::exists($filepath)){
  58. $this->_ignores[$filepath] = $filepath;
  59. }
  60. }
  61. }
  62. }
  63. function _getFileExtension($filepath)
  64. {
  65. preg_match('/[^?]*/', $filepath, $matches);
  66. $string = $matches[0];
  67. $pattern = preg_split('/\./', $string, -1, PREG_SPLIT_OFFSET_CAPTURE);
  68. # check if there is any extension
  69. if(count($pattern) == 1)
  70. {
  71. return "";
  72. }
  73. if(count($pattern) > 1)
  74. {
  75. $filenamepart = $pattern[count($pattern)-1][0];
  76. preg_match('/[^?]*/', $filenamepart, $matches);
  77. return $matches[0];
  78. }
  79. }
  80. function _stripCSSWhiteSpace($css_content) {
  81. // remove comments
  82. $css_content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css_content);
  83. // remove tabs, spaces, newlines, etc.
  84. $css_content = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $css_content);
  85. return $css_content;
  86. }
  87. function _processCSSFiles() {
  88. $uri =& JURI::getInstance();
  89. $base = $uri->toString( array('scheme', 'host', 'port'));
  90. $path = JURI::root(true);
  91. $cache_time = $this->params->get("cache_time",60);
  92. $expires_time = $this->params->get("expires_header_time",1440);
  93. $strip_css = $this->params->get("strip_css",1);
  94. $body = JResponse::getBody();
  95. $ordered_files = array();
  96. $output = array();
  97. $css_links = $this->_findNonDocumentCSSFiles($body);
  98. $cleaned_css_links = array();
  99. foreach ($css_links as $file => $tag) {
  100. // strip query string if there is one
  101. if (strpos($file, '?') !== false){
  102. $file = substr($file, 0, strpos($file, '?'));
  103. }
  104. $filepath = $this->_getFilePath($file,$base,$path);
  105. if (!array_key_exists($filepath, $this->_ignores) && $this->_getFileExtension($filepath) != "php" && file_exists($filepath) ) {
  106. $ordered_files[dirname($filepath)][basename($filepath)] = $file;
  107. $cleaned_css_links[$file] = $tag;
  108. }
  109. }
  110. $css_links =& $cleaned_css_links;
  111. foreach ($ordered_files as $dir=>$files) {
  112. if(!is_writable($dir)) {
  113. $comment = "\n<!--\n";
  114. $comment .= JText::sprintf('ROKGZIPPER.WARNING.UNABLE_TO_WRITE_TO_DIR', $dir, implode("\n", $files));
  115. $comment .= "\n-->";
  116. $body = str_replace('<head>',"<head>\n".$comment."\n", $body);
  117. continue;
  118. }
  119. $md5sum = "";
  120. $path = "";
  121. //first trip through to build filename
  122. foreach ($files as $file=>$details) {
  123. $md5sum .= md5($details);
  124. $detailspath = $dir.DS.$file;
  125. if (JFile::exists($detailspath)) {
  126. $link = $css_links[$details];
  127. $body = str_replace($link,"",$body);
  128. $path = dirname($details);
  129. }
  130. }
  131. $cache_filename = "css-".md5($md5sum).".php";
  132. $cache_fullpath = $dir.DS.$cache_filename;
  133. //see if file is stale
  134. if (JFile::exists($cache_fullpath)) {
  135. $diff = (time()-filectime($cache_fullpath));
  136. } else {
  137. $diff = $cache_time+1;
  138. }
  139. if ($diff > $cache_time){
  140. $outfile = $this->_getOutHeader("css", $expires_time);
  141. foreach ($files as $file=>$details) {
  142. $detailspath = $dir.DS.$file;
  143. if (JFile::exists($detailspath)) {
  144. $css_content = JFile::read($detailspath);
  145. if ($strip_css){
  146. $css_content = $this->_stripCSSWhiteSpace($css_content);
  147. }
  148. $outfile .= "\n\n/*** " . $file . " ***/\n\n" . $css_content;
  149. }
  150. }
  151. JFile::write($cache_fullpath,$outfile);
  152. }
  153. $cache_file_name = $path."/".$cache_filename;
  154. $line = '';
  155. if ($this->params->get('show_contains_comments',0) ==1){
  156. $line = "<!-- \n" . $cache_file_name . "\nContains the following css files\n";
  157. foreach($files as $file) {
  158. $line .= " - ".$file . "\n";
  159. }
  160. $line .= "-->\n";
  161. }
  162. $line .= "<link rel=\"stylesheet\" href=\"".$cache_file_name."\" type=\"text/css\" />\n";
  163. $output[] = $line;
  164. }
  165. $revoutput = array_reverse($output);
  166. foreach ($revoutput as $line) {
  167. $body = str_replace('<head>',"<head>\n".$line."\n", $body);
  168. }
  169. JResponse::setBody($body);
  170. }
  171. function _processJsFiles() {
  172. $uri =& JURI::getInstance();
  173. $base = $uri->toString( array('scheme', 'host', 'port'));
  174. $path = JURI::Root(true);
  175. $cache_time = $this->params->get("cache_time",60);
  176. $expires_time = $this->params->get("expires_header_time",1440);
  177. $body = JResponse::getBody();
  178. $ordered_files = array();
  179. $output = array();
  180. $md5sum = "";
  181. $script_tags = $this->_findDocumentScriptFiles(JResponse::getBody());
  182. foreach ($script_tags as $file => $script_tag) {
  183. $filepath = $this->_getFilePath($file,$base,$path);
  184. if (JFile::exists($filepath) && !array_key_exists($filepath, $this->_ignores) && $this->_getFileExtension($filepath) != "php" ){
  185. $ordered_files[] = array(dirname($filepath),basename($filepath),$file);
  186. }
  187. }
  188. foreach ($ordered_files as $files) {
  189. if(!is_writable(dirname($files[0]))) {
  190. //make sure the filenames is an array
  191. $filenames = $files[1];
  192. if (!is_array($files[1])) $filenames = array($files[1]);
  193. $comment = "\n<!--\n";
  194. $comment .= JText::sprintf('ROKGZIPPER.WARNING.UNABLE_TO_WRITE_TO_DIR', dirname($files[0]), implode("\n", $filenames));
  195. $comment .= "\n-->";
  196. $body = str_replace('<head>',"<head>\n".$comment."\n", $body);
  197. continue;
  198. }
  199. $dir = $files[0];
  200. $filename = $files[1];
  201. $details = $files[2];
  202. $md5sum .= md5($filename);
  203. $detailspath = $dir.DS.$filename;
  204. if (empty($script_tags[$details]['content'])) {
  205. $link = $script_tags[$details]['block'];
  206. $body = str_replace($link,"",$body);
  207. }
  208. else {
  209. $tag_with_content = '<script type="text/javascript">\n'.$script_tags[$details]['content'].'\n</script>';
  210. $link = $script_tags[$details]['block'];
  211. $body = str_replace($link,$tag_with_content,$body);
  212. }
  213. }
  214. $cache_filename = "js-".md5($md5sum).".php";
  215. $cache_fullpath = JPATH_CACHE.DS.$cache_filename;
  216. //see if file is stale
  217. if (JFile::exists($cache_fullpath)) {
  218. $diff = (time()-filectime($cache_fullpath));
  219. } else {
  220. $diff = $cache_time+1;
  221. }
  222. if ($diff > $cache_time){
  223. $outfile = $this->_getOutHeader("js", $expires_time);
  224. foreach ($ordered_files as $files) {
  225. $dir = $files[0];
  226. $filename = $files[1];
  227. $details = $files[2];
  228. $detailspath = $dir.DS.$filename;
  229. if (JFile::exists($detailspath)) {
  230. $jsfile = JFile::read($detailspath);
  231. // fix for stupid joolma code
  232. if (strpos($filename,'joomla.javascript.js')!==false or strpos($filename,'mambojavascript.js')!==false) {
  233. $jsfile = str_replace("// <?php !!", "// ", $jsfile);
  234. }
  235. $outfile .= "\n\n/*** " . $filename . " ***/\n\n" . $jsfile;
  236. }
  237. }
  238. JFile::write($cache_fullpath,$outfile);
  239. }
  240. $cache_file_name = $path."/cache/".$cache_filename;
  241. $line = '';
  242. if ($this->params->get('show_contains_comments',0) ==1){
  243. $line = "<!-- \n" . $cache_file_name . "\nContains the following javascript files\n";
  244. foreach($ordered_files as $files) {
  245. $details = $files[2];
  246. $line .= " - ".$details . "\n";
  247. }
  248. $line .= "-->\n";
  249. }
  250. $line .= "<script type=\"text/javascript\" src=\"".$cache_file_name."\"></script>\n";
  251. $output[] = $line;
  252. foreach ($output as $line) {
  253. $body = str_replace('<head>',"<head>\n".$line."\n", $body);
  254. }
  255. JResponse::setBody($body);
  256. }
  257. function _getFilePath($url,$base,$path) {
  258. if ($url && $base && strpos($url,$base)!==false) $url = str_replace($base,"",$url);
  259. if ($url && $path && strpos($url,$path)!==false) $url = str_replace($path,"",$url);
  260. if (substr($url,0,1) != DS) $url = DS.$url;
  261. $filepath = JPATH_SITE.$url;
  262. return $filepath;
  263. }
  264. function _getOutHeader($type="css", $expires_time = "1440") {
  265. if ($type=="css") {
  266. $header='<?php
  267. ob_start ("ob_gzhandler");
  268. header("Content-type: text/css; charset: UTF-8");
  269. header("Cache-Control: must-revalidate");
  270. $expires_time = ' . $expires_time . ';
  271. $offset = 60 * $expires_time ;
  272. $ExpStr = "Expires: " .
  273. gmdate("D, d M Y H:i:s",
  274. time() + $offset) . " GMT";
  275. header($ExpStr);
  276. ?>';
  277. } else {
  278. $header='<?php
  279. ob_start ("ob_gzhandler");
  280. header("Content-type: application/x-javascript; charset: UTF-8");
  281. header("Cache-Control: must-revalidate");
  282. $expires_time = ' . $expires_time . ';
  283. $offset = 60 * $expires_time ;
  284. $ExpStr = "Expires: " .
  285. gmdate("D, d M Y H:i:s",
  286. time() + $offset) . " GMT";
  287. header($ExpStr);
  288. ?>';
  289. }
  290. return $header;
  291. }
  292. function _findNonDocumentCSSFiles($body) {
  293. $return_links = array();
  294. $link_tags = array();
  295. $link_matches = array();
  296. $standalone_matches = array();
  297. $stand_alone_links = array();
  298. $link_pattern = '/(<link\b.+href="(?!http)([^"].*)".*>)/i';
  299. $standalones_pattern = '/<!--\[if.*\]>(?<content>.*)<!\[endif\]-->/isU';
  300. $attributes_pattern= '#([^\s=]+)\s*=\s*(\'([^<\']*)\'|"([^<"]*)")#';
  301. // get all links
  302. preg_match_all($link_pattern, $body, $link_matches);
  303. // get the link tags
  304. $link_tags=$link_matches[1];
  305. // get any standalone links
  306. preg_match_all($standalones_pattern, $body, $standalone_matches);
  307. foreach($standalone_matches[1] as $standalone_text) {
  308. preg_match_all($link_pattern, $standalone_text, $stand_alone_links);
  309. foreach($stand_alone_links[1] as $standalone_tag) {
  310. $link_location = array_search($standalone_tag, $link_tags);
  311. if ($link_location) {
  312. unset($link_tags[$link_location]);
  313. }
  314. }
  315. }
  316. foreach($link_tags as $link_tag) {
  317. $attibutes = array();
  318. $found = preg_match_all($attributes_pattern, $link_tag, $attibutes, PREG_SET_ORDER);
  319. if ($found != 0) {
  320. $attribute_array = array();
  321. // Create an associative array that matches attribute
  322. // names to attribute values.
  323. foreach ($attibutes as $attribute) {
  324. $attribute_array[strtolower($attribute[1])] = (!empty($attribute[3]))?$attribute[3]:$attribute[4];
  325. }
  326. // see if this is a stylesheet link
  327. if (array_key_exists('rel',$attribute_array) && strtolower(trim($attribute_array['rel'])) == 'stylesheet' && array_key_exists('href',$attribute_array)){
  328. $return_links[$attribute_array['href']] = $link_tag;
  329. }
  330. }
  331. }
  332. return $return_links;
  333. }
  334. function _findDocumentScriptFiles($body) {
  335. $return_links = array();
  336. $script_tags = array();
  337. $script_matches = array();
  338. $script_pattern ='#((<script(?:(?:.*((?<=src=")(?!http)(?:[^"].*))"[^>]*))/>)|(?:(<script(?:(?:.*((?<=src=")(?!http)(?:[^"].*))"[^>]*))>)((?:(?:\n|.)(?!(?:\n|.)<script))*)</script>))#iU';
  339. // get the script tags
  340. $script_count = preg_match_all($script_pattern, $body, $script_matches);
  341. if ($script_count > 0) {
  342. for($i=0; $i<$script_count; $i++){
  343. $tag = array();
  344. $tag['block'] = $script_matches[1][$i];
  345. $tag['content'] = $script_matches[6][$i];
  346. $tag['src'] = (!empty($script_matches[5][$i]))?$script_matches[5][$i]:$script_matches[3][$i];
  347. $tag['opentag'] = (!empty($script_matches[4][$i]))?$script_matches[4][$i]:$script_matches[2][$i];
  348. $script_tags[$tag['src']] = $tag;
  349. }
  350. }
  351. // get any standalone links and remove them
  352. $stand_alone_links = array();
  353. $standalones_pattern = '/<!--\[if.*\]>(.*)<!\[endif\]-->/isU';
  354. preg_match_all($standalones_pattern, $body, $standalone_matches);
  355. foreach($standalone_matches[1] as $standalone_text) {
  356. preg_match_all($script_pattern, $standalone_text, $stand_alone_links);
  357. foreach($stand_alone_links[3] as $standalone_tag) {
  358. unset($script_tags[$standalone_tag]);
  359. }
  360. foreach($stand_alone_links[5] as $standalone_tag) {
  361. unset($script_tags[$standalone_tag]);
  362. }
  363. }
  364. $attributes_pattern= '#([^\s=]+)\s*=\s*(\'([^<\']*)\'|"([^<"]*)")#';
  365. foreach($script_tags as $script_tag) {
  366. $attibutes = array();
  367. $found = preg_match_all($attributes_pattern, $script_tag['opentag'], $attibutes, PREG_SET_ORDER);
  368. if ($found != 0) {
  369. $attribute_array = array();
  370. // Create an associative array that matches attribute
  371. // names to attribute values.
  372. foreach ($attibutes as $attribute) {
  373. $attribute_array[strtolower($attribute[1])] = (!empty($attribute[3]))?$attribute[3]:$attribute[4];
  374. }
  375. // see if this is a javascript link
  376. if (array_key_exists('type',$attribute_array) && strtolower(trim($attribute_array['type'])) == 'text/javascript'){
  377. $return_links[$script_tag['src']] = $script_tag;
  378. }
  379. }
  380. }
  381. return $return_links;
  382. }
  383. }