diff --git a/core/imageboard.pack.php b/core/imageboard.pack.php index 9ce34abe..b586dd56 100644 --- a/core/imageboard.pack.php +++ b/core/imageboard.pack.php @@ -93,6 +93,7 @@ class Image { public static function by_random($tags=array()) { assert(is_array($tags)); $max = Image::count_images($tags); + if ($max < 1) return null; // From Issue #22 - opened by HungryFeline on May 30, 2011. $rand = mt_rand(0, $max-1); $set = Image::find_images($rand, 1, $tags); if(count($set) > 0) return $set[0]; diff --git a/core/page.class.php b/core/page.class.php index d3879853..ae801576 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -167,8 +167,8 @@ class Page { public function display() { global $page; - $this->add_http_header("Content-type: {$this->type}", 1); - $this->add_http_header("X-Powered-By: SCore-".SCORE_VERSION, 2); + header("Content-type: ".$this->type); + header("X-Powered-By: SCore-".SCORE_VERSION); if (!headers_sent()) { foreach($this->http_headers as $head){ header($head); } @@ -200,29 +200,132 @@ class Page { break; } } - + protected function add_auto_html_headers() { $data_href = get_base_href(); - - foreach(glob("lib/*.css") as $css) { - $this->add_html_header(""); + + /* Attempt to cache the CSS & JavaScript files */ + if ($this->add_cached_auto_html_headers() === FALSE) { + // caching failed, add all files to html_headers. + + foreach(glob("lib/*.css") as $css) { + $this->add_html_header(""); + } + $css_files = glob("ext/*/style.css"); + if($css_files) { + foreach($css_files as $css_file) { + $this->add_html_header(""); + } + } + + foreach(glob("lib/*.js") as $js) { + $this->add_html_header(""); + } + $js_files = glob("ext/*/script.js"); + if($js_files) { + foreach($js_files as $js_file) { + $this->add_html_header(""); + } + } } - $css_files = glob("ext/*/style.css"); - if($css_files) { - foreach($css_files as $css_file) { - $this->add_html_header(""); + } + + /* + This function caches the CSS and JavaScript files. + This is done to reduce the number of HTTP requests (recommended by + the Yahoo high-performance guidelines). It combines all of the CSS + and JavaScript files into one for each type, and stores them in + cached files to serve the client. Changes to the CSS or JavaScript + files are caught by taking the md5sum of the concatenated files. + */ + private function add_cached_auto_html_headers() + { + $cache_location = 'data/cache/'; + $data_href = get_base_href(); + + if(!file_exists($cache_location)) { + if (!mkdir($cache_location, 0750, true)) { + return false; // failed to create directory } } - foreach(glob("lib/*.js") as $js) { - $this->add_html_header(""); + /* ----- CSS Files ----- */ + // First get all the CSS from the lib directory + $data_1 = ''; + $css_files = glob("lib/*.css"); + if($css_files) { + foreach($css_files as $css_file) { + $data_1 .= file_get_contents($css_file); + } + // Can't directly cache the CSS files, as they might have relative locations to images, etc. in them. + // We have to adjust the URLs accordingly before saving the cached file. + $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; + $replace = 'url("../../lib/${1}")'; + $data_1 = preg_replace($pattern, $replace, $data_1); + } + // Next get all the CSS from the extensions + $data_2 = ''; + $css_files = glob("ext/*/style.css"); + if($css_files) { + foreach($css_files as $css_file) { + $data_2 .= file_get_contents($css_file); + } + // Can't directly cache the CSS files, as they might have relative locations to images, etc. in them. + // We have to adjust the URLs accordingly before saving the cached file. + $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; + $replace = 'url("../../${1}")'; + $data_2 = preg_replace($pattern, $replace, $data_2); + } + // Combine the two + $data = $data_1 . $data_2; + // compute the MD5 sum of the concatenated CSS files + $md5sum = md5($data); + + if (!file_exists($cache_location.$md5sum.'.css')) { + // remove any old cached CSS files. + $mask = '*.css'; + array_map( 'unlink', glob( $mask ) ); + + // output the combined file + if (file_put_contents($cache_location.$md5sum.'.css', $data, LOCK_EX) === FALSE) { + return false; + } + } + // tell the client where to get the css cache file + $this->add_html_header(''); + + + /* ----- JavaScript Files ----- */ + $data = ''; + $js_files = glob("lib/*.js"); + if($js_files) { + foreach($js_files as $js_file) { + $data .= file_get_contents($js_file); + } } $js_files = glob("ext/*/script.js"); if($js_files) { foreach($js_files as $js_file) { - $this->add_html_header(""); + $data .= file_get_contents($js_file); } } + // compute the MD5 sum of the concatenated JavaScript files + $md5sum = md5($data); + + if (!file_exists($cache_location.$md5sum.'.js')) { + // remove any old cached js files. + $mask = '*.js'; + array_map( 'unlink', glob( $mask ) ); + // output the combined file + if (file_put_contents($cache_location.$md5sum.'.js', $data, LOCK_EX) === FALSE) { + return false; + } + } + // tell the client where to get the js cache file + $this->add_html_header(''); + + return true; } + } ?>