Wiki source for WikkaOptimizationCompressedStaticFiles
===Compressed output for static files===
To achieve this, these are only 2 files to add (./compressingoutput.inc and ./handlers/page/co.php), and 2 or 3 files with small updates (./actions/header.php, ./mime_types.txt, and maybe ./handlers/page/edit.php)
Create a file named {{color c="green" text="compressingoutput.inc"}} in ./
The content of that file is :
%%(php)<?php
# Each time this file, or a file including this one is changed,
# you should modify the REINITIALIZE_ETAG value by anything you want
define ('REINITIALIZE_ETAG', 'something_new');
define ('STORE_GZ_FILE', true);
define ('CHARSET', 'iso-8859-1');
function ParseHeaderLine($hl)
{
# Parse a server value like HTTP_ACCEPT_ENCODING
# ( Accept-Encoding: gzip; q= 0.00, deflate ; q =0.5
# ( ==> array ('gzip' => 0, 'deflate' => 0.5);
$ar_hl = explode(',', $hl);
foreach ($ar_hl as $val)
{
if (preg_match('/^(.*);\s*q\s*=\s*([0-9\.]*)/i', $val, $match))
{
$res[trim(strtolower($match[1]))] = doubleval($match[2]);
}
else
{
$res[strtolower($val)] = 1;
}
}
return ($res);
}
function Response($code)
{
# Apache ignores these texts. It stands here just for developpers.
$text = array('404' => 'Not Found', '304' => 'Not Modified');
header ("HTTP/1.1 $code {$text[$code]}");
}
function compressed_output($tag, $content_type='auto', $path_to_file='css/')
{
for($i=0; $i<6; $i++)
{ # Clean all possible opened buffers
@ob_end_clean();
}
if ($content_type == 'auto')
{ # Automatically determine content-type with file extension
$filetype = explode('.', $tag);
$pathinfo = pathinfo($tag);
$extension = $pathinfo['extension'];
$mimes = file('mime_types.txt');
$type = preg_grep("/^([^#]+).*\t.*$extension\s*/i", $mimes);
foreach ($type as $typeline)
{
$content_type = preg_split("/\s+/", $typeline, -1, PREG_SPLIT_NO_EMPTY);
$content_type = $content_type[0];
break;
}
}
$accept_encoding = $_SERVER['HTTP_ACCEPT_ENCODING'];
$zlib_outputcompression = ini_get('zlib.output_compression');
if (preg_match('=[1-9]+|on=i', $zlib_outputcompression)) $accept_encoding = '';
header("Content-type: $content_type; charset=".CHARSET);
$filename = $path_to_file.strtolower($tag);
if (!file_exists($filename)) die (Response('404'));
$filemtime = filemtime($filename);
$last_modified = gmdate("D, d M Y H:i:s", $filemtime)." GMT";
$etag = md5("$tag:$filemtime:".REINITIALIZE_ETAG);
#Id est: when file is modified or when REINITIALIZE_ETAG changes, Etag also changes
header("Etag: $etag");
header("Last-modified: $last_modified");
$expires = gmdate("D, d M Y H:i:s", $filemtime+31536000);
header("Expires: $expires");
header("Cache-Control: public");// HTTP/1.1
header("Pragma: cache");
if (isset($_SERVER['HTTP_IF_NONE_MATCH']))
{
if ($etag == $_SERVER['HTTP_IF_NONE_MATCH']) die(Response('304'));
}
else if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
$last_modified = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
if ($filemtime <= $last_modified) die(Response('304'));
}
#Dealing accept encoding
$accept_encoding = ParseHeaderLine($accept_encoding);
if (isset($accept_encoding['gzip']) && ($accept_encoding['gzip'] > 0))
{
header ("Content-Encoding: gzip");
if (STORE_GZ_FILE)
{ # Assumed that storing .gz file in server decreases CPU Load, but to be proven
if ((!file_exists("$filename.gz")) ||
(filemtime("$filename.gz") != $filemtime) )
{
$zp = @gzopen("$filename.gz", "wb9");
if (!$zp)
{ # No write access?
die ("/*You should give write access to folder css/, or change STORE_GZ_FILE in functions.inc*/");
}
ob_start();
readfile($filename);
$contents = ob_get_contents();
ob_end_clean();
gzwrite($zp, $contents);
gzclose($zp);
if (!touch("$filename.gz", $filemtime))
{ # todo: You could create a file in css/, but couldn't change its date.
}
}
$filename=$filename.".gz";
header ("Content-Length: ".filesize($filename));
header ("Vary: Accept-Encoding");
}
else
{ # todo: And if ob_gzhandler() was unavailable?
ob_start('ob_gzhandler');
}
}
readfile($filename);
if (!STORE_GZ_FILE)
{
ob_end_flush();
}
die();
}
?>
%%
Add a file named {{color c="red" text="co.php"}} in ./handlers/page/ (you can use another name like css.css.php, co stands for compressed output)
The content of co.php is
%%(php)<?php
/**
* @name css.css
* @author {@link http://wikka.jsnx.com/DotMG DotMG}
* @version 0.1
* @link http://wikka.jsnx.com/WikkaOptimizationCompressedStaticFiles
* @summary
> URL like /yourcssname.css/css.css has the same content as /css/yourcssname.css
> but the output is gz-compressed.
> All the code is in compressingoutput.inc, so that you can use another file like js.js.php
> to compress javascript files.
* @requires functions.inc
* To do elsewhere :
> Modify header.php, change url css/filename.css to $this->Href('co', 'filename.css')
> Modify mime_types.txt, uncomment line "text/css css" and comment on application/x-ilinc-pointplus
**/
include ('compressingoutput.inc');
$tag = $this->GetPageTag();
$path = 'css/'; # Actually, co.php is mainly used for css files
if (preg_match('/^(protoedit\.js|wikiedit2\.js)$/i', $tag))
{
$path = '3rdparty/plugins/wikiedit/';
}
compressed_output($tag, 'auto', $path);
?>%%
Modify ./actions/header.php and ./mime_types.txt as shown in source of co.php, ie
%%(php) <link rel="stylesheet" type="text/css" href="<?php echo $this->Href('co', $this->GetConfigValue("stylesheet")); ?>" />
<link rel="stylesheet" type="text/css" href="<?php echo $this->Href('co', 'print.css'); ?>" media="print" /> %%
and
%%# ILinc support
# COMMENTED application/x-ilinc-pointplus css
(...)
# conflict with ILinc? UNCOMMENTED
text/css css
%%
You could also change ./handlers/page/edit.php like this :
%%(php) '<script language="JavaScript" src="'.$this->Href('co', 'protoedit.js').'"></script>'."\n".
'<script language="JavaScript" src="'.$this->Href('co', 'wikiedit2.js).'"></script>'."\n";%%
----
CategoryUserContributions CategoryDevelopmentArchitecture
To achieve this, these are only 2 files to add (./compressingoutput.inc and ./handlers/page/co.php), and 2 or 3 files with small updates (./actions/header.php, ./mime_types.txt, and maybe ./handlers/page/edit.php)
Create a file named {{color c="green" text="compressingoutput.inc"}} in ./
The content of that file is :
%%(php)<?php
# Each time this file, or a file including this one is changed,
# you should modify the REINITIALIZE_ETAG value by anything you want
define ('REINITIALIZE_ETAG', 'something_new');
define ('STORE_GZ_FILE', true);
define ('CHARSET', 'iso-8859-1');
function ParseHeaderLine($hl)
{
# Parse a server value like HTTP_ACCEPT_ENCODING
# ( Accept-Encoding: gzip; q= 0.00, deflate ; q =0.5
# ( ==> array ('gzip' => 0, 'deflate' => 0.5);
$ar_hl = explode(',', $hl);
foreach ($ar_hl as $val)
{
if (preg_match('/^(.*);\s*q\s*=\s*([0-9\.]*)/i', $val, $match))
{
$res[trim(strtolower($match[1]))] = doubleval($match[2]);
}
else
{
$res[strtolower($val)] = 1;
}
}
return ($res);
}
function Response($code)
{
# Apache ignores these texts. It stands here just for developpers.
$text = array('404' => 'Not Found', '304' => 'Not Modified');
header ("HTTP/1.1 $code {$text[$code]}");
}
function compressed_output($tag, $content_type='auto', $path_to_file='css/')
{
for($i=0; $i<6; $i++)
{ # Clean all possible opened buffers
@ob_end_clean();
}
if ($content_type == 'auto')
{ # Automatically determine content-type with file extension
$filetype = explode('.', $tag);
$pathinfo = pathinfo($tag);
$extension = $pathinfo['extension'];
$mimes = file('mime_types.txt');
$type = preg_grep("/^([^#]+).*\t.*$extension\s*/i", $mimes);
foreach ($type as $typeline)
{
$content_type = preg_split("/\s+/", $typeline, -1, PREG_SPLIT_NO_EMPTY);
$content_type = $content_type[0];
break;
}
}
$accept_encoding = $_SERVER['HTTP_ACCEPT_ENCODING'];
$zlib_outputcompression = ini_get('zlib.output_compression');
if (preg_match('=[1-9]+|on=i', $zlib_outputcompression)) $accept_encoding = '';
header("Content-type: $content_type; charset=".CHARSET);
$filename = $path_to_file.strtolower($tag);
if (!file_exists($filename)) die (Response('404'));
$filemtime = filemtime($filename);
$last_modified = gmdate("D, d M Y H:i:s", $filemtime)." GMT";
$etag = md5("$tag:$filemtime:".REINITIALIZE_ETAG);
#Id est: when file is modified or when REINITIALIZE_ETAG changes, Etag also changes
header("Etag: $etag");
header("Last-modified: $last_modified");
$expires = gmdate("D, d M Y H:i:s", $filemtime+31536000);
header("Expires: $expires");
header("Cache-Control: public");// HTTP/1.1
header("Pragma: cache");
if (isset($_SERVER['HTTP_IF_NONE_MATCH']))
{
if ($etag == $_SERVER['HTTP_IF_NONE_MATCH']) die(Response('304'));
}
else if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
$last_modified = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
if ($filemtime <= $last_modified) die(Response('304'));
}
#Dealing accept encoding
$accept_encoding = ParseHeaderLine($accept_encoding);
if (isset($accept_encoding['gzip']) && ($accept_encoding['gzip'] > 0))
{
header ("Content-Encoding: gzip");
if (STORE_GZ_FILE)
{ # Assumed that storing .gz file in server decreases CPU Load, but to be proven
if ((!file_exists("$filename.gz")) ||
(filemtime("$filename.gz") != $filemtime) )
{
$zp = @gzopen("$filename.gz", "wb9");
if (!$zp)
{ # No write access?
die ("/*You should give write access to folder css/, or change STORE_GZ_FILE in functions.inc*/");
}
ob_start();
readfile($filename);
$contents = ob_get_contents();
ob_end_clean();
gzwrite($zp, $contents);
gzclose($zp);
if (!touch("$filename.gz", $filemtime))
{ # todo: You could create a file in css/, but couldn't change its date.
}
}
$filename=$filename.".gz";
header ("Content-Length: ".filesize($filename));
header ("Vary: Accept-Encoding");
}
else
{ # todo: And if ob_gzhandler() was unavailable?
ob_start('ob_gzhandler');
}
}
readfile($filename);
if (!STORE_GZ_FILE)
{
ob_end_flush();
}
die();
}
?>
%%
Add a file named {{color c="red" text="co.php"}} in ./handlers/page/ (you can use another name like css.css.php, co stands for compressed output)
The content of co.php is
%%(php)<?php
/**
* @name css.css
* @author {@link http://wikka.jsnx.com/DotMG DotMG}
* @version 0.1
* @link http://wikka.jsnx.com/WikkaOptimizationCompressedStaticFiles
* @summary
> URL like /yourcssname.css/css.css has the same content as /css/yourcssname.css
> but the output is gz-compressed.
> All the code is in compressingoutput.inc, so that you can use another file like js.js.php
> to compress javascript files.
* @requires functions.inc
* To do elsewhere :
> Modify header.php, change url css/filename.css to $this->Href('co', 'filename.css')
> Modify mime_types.txt, uncomment line "text/css css" and comment on application/x-ilinc-pointplus
**/
include ('compressingoutput.inc');
$tag = $this->GetPageTag();
$path = 'css/'; # Actually, co.php is mainly used for css files
if (preg_match('/^(protoedit\.js|wikiedit2\.js)$/i', $tag))
{
$path = '3rdparty/plugins/wikiedit/';
}
compressed_output($tag, 'auto', $path);
?>%%
Modify ./actions/header.php and ./mime_types.txt as shown in source of co.php, ie
%%(php) <link rel="stylesheet" type="text/css" href="<?php echo $this->Href('co', $this->GetConfigValue("stylesheet")); ?>" />
<link rel="stylesheet" type="text/css" href="<?php echo $this->Href('co', 'print.css'); ?>" media="print" /> %%
and
%%# ILinc support
# COMMENTED application/x-ilinc-pointplus css
(...)
# conflict with ILinc? UNCOMMENTED
text/css css
%%
You could also change ./handlers/page/edit.php like this :
%%(php) '<script language="JavaScript" src="'.$this->Href('co', 'protoedit.js').'"></script>'."\n".
'<script language="JavaScript" src="'.$this->Href('co', 'wikiedit2.js).'"></script>'."\n";%%
----
CategoryUserContributions CategoryDevelopmentArchitecture