1
0
mirror of https://github.com/mrclay/minify.git synced 2025-08-08 15:16:56 +02:00

Work on Issue 160, Issue 169, Issue 178, Issue 68

This commit is contained in:
Steve Clay
2010-05-17 04:31:48 +00:00
parent f2ebbeb526
commit a8f8897fbb
5 changed files with 177 additions and 73 deletions

View File

@@ -14,5 +14,4 @@
return array(
// 'js' => array('//js/file1.js', '//js/file2.js'),
// 'css' => array('//css/file1.css', '//css/file2.css'),
);

View File

@@ -30,15 +30,18 @@ class Minify_Cache_File {
$flag = $this->_locking
? LOCK_EX
: null;
if (is_file($this->_path . '/' . $id)) {
@unlink($this->_path . '/' . $id);
$file = $this->_path . '/' . $id;
if (is_file($file)) {
@unlink($file);
}
if (! @file_put_contents($this->_path . '/' . $id, $data, $flag)) {
if (! @file_put_contents($file, $data, $flag)) {
$this->_log("Minify_Cache_File: Write failed to '$file'");
return false;
}
// write control
if ($data !== $this->fetch($id)) {
@unlink($file);
$this->_log("Minify_Cache_File: Post-write read failed for '$file'");
return false;
}
return true;
@@ -120,6 +123,17 @@ class Minify_Cache_File {
return $this->_path;
}
/**
* Send message to the Minify logger
* @param string $msg
* @return null
*/
protected function _log($msg)
{
require_once 'Minify/Logger.php';
Minify_Logger::log($msg);
}
private $_path = null;
private $_locking = null;
}

View File

@@ -118,6 +118,8 @@ abstract class Minify_Controller_Base {
* be in subdirectories of these directories.
*
* @return bool file is safe
*
* @deprecated use checkAllowDirs, checkNotHidden instead
*/
public static function _fileIsSafe($file, $safeDirs)
{
@@ -136,6 +138,27 @@ abstract class Minify_Controller_Base {
return in_array(strrev($revExt), array('js', 'css', 'html', 'txt'));
}
public static function checkAllowDirs($file, $allowDirs, $uri)
{
foreach ((array)$allowDirs as $allowDir) {
if (strpos($file, $allowDir) === 0) {
return true;
}
}
throw new Exception("File '$file' is outside \$allowDirs. If the path is"
. " resolved via an alias/symlink, look into the \$min_symlinks option."
. " E.g. \$min_symlinks = array('/" . dirname($uri) . "' => '" . dirname($file) . "');");
}
public static function checkNotHidden($file)
{
$b = basename($file);
if (0 === strpos($b, '.')) {
throw new Exception("Filename '$b' starts with period (may be hidden)");
}
}
/**
* @var array instances of Minify_Source, which provide content and
* any individual minification needs.

View File

@@ -34,15 +34,23 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
);
unset($options['minApp']);
$sources = array();
$this->selectionId = '';
$missingUri = '';
if (isset($_GET['g'])) {
// try groups
if (! isset($cOptions['groups'][$_GET['g']])) {
$this->log("A group configuration for \"{$_GET['g']}\" was not set");
// add group(s)
$this->selectionId .= 'g=' . $_GET['g'];
$keys = explode(',', $_GET['g']);
if ($keys != array_unique($keys)) {
$this->log("Duplicate group key found.");
return $options;
}
$this->selectionId = "g=" . $_GET['g'];
$files = $cOptions['groups'][$_GET['g']];
foreach (explode(',', $_GET['g']) as $key) {
if (! isset($cOptions['groups'][$key])) {
$this->log("A group configuration for \"{$key}\" was not found");
return $options;
}
$files = $cOptions['groups'][$key];
// if $files is a single object, casting will break it
if (is_object($files)) {
$files = array($files);
@@ -58,14 +66,24 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
$file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
}
$file = realpath($file);
if (is_file($file)) {
if ($file && is_file($file)) {
$sources[] = $this->_getFileSource($file, $cOptions);
} else {
$this->log("The path \"{$file}\" could not be found (or was not a file)");
return $options;
}
}
} elseif (! $cOptions['groupsOnly'] && isset($_GET['f'])) {
if ($sources) {
try {
$this->checkType($sources[0]);
} catch (Exception $e) {
$this->log($e->getMessage());
return $options;
}
}
}
}
if (! $cOptions['groupsOnly'] && isset($_GET['f'])) {
// try user files
// The following restrictions are to limit the URLs that minify will
// respond to. Ideally there should be only one way to reference a file.
@@ -83,12 +101,17 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
return $options;
}
$ext = ".{$m[1]}";
try {
$this->checkType($m[1]);
} catch (Exception $e) {
$this->log($e->getMessage());
return $options;
}
$files = explode(',', $_GET['f']);
if ($files != array_unique($files)) {
$this->log("Duplicate files specified");
return $options;
}
if (isset($_GET['b'])) {
// check for validity
if (preg_match('@^[^/]+(?:/[^/]+)*$@', $_GET['b'])
@@ -109,22 +132,42 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
}
$basenames = array(); // just for cache id
foreach ($files as $file) {
$path = $_SERVER['DOCUMENT_ROOT'] . $base . $file;
$uri = $base . $file;
$path = $_SERVER['DOCUMENT_ROOT'] . $uri;
$file = realpath($path);
if (false === $file) {
$this->log("Path \"{$path}\" failed realpath()");
return $options;
} elseif (! parent::_fileIsSafe($file, $allowDirs)) {
$this->log("Path \"{$path}\" failed Minify_Controller_Base::_fileIsSafe()");
return $options;
if (false === $file || ! is_file($file)) {
if (! $missingUri) {
$missingUri = $uri;
continue;
} else {
$this->log("At least two files missing: '$missingUri', '$uri'");
return $options;
}
}
try {
parent::checkNotHidden($file);
parent::checkAllowDirs($file, $allowDirs, $uri);
} catch (Exception $e) {
$this->log($e->getMessage());
return $options;
}
$sources[] = $this->_getFileSource($file, $cOptions);
$basenames[] = basename($file, $ext);
}
if ($this->selectionId) {
$this->selectionId .= '_f=';
}
$this->selectionId = implode(',', $basenames) . $ext;
$this->selectionId .= implode(',', $basenames) . $ext;
}
if ($sources) {
if ($missingUri) {
array_unshift($sources, new Minify_Source(array(
'id' => 'missingFile'
,'lastModified' => 0
,'content' => "/* Minify: missing file '" . ltrim($missingUri, '/') . "' */\n"
,'minifier' => ''
)));
}
$this->sources = $sources;
} else {
$this->log("No sources to serve");
@@ -141,4 +184,27 @@ class Minify_Controller_MinApp extends Minify_Controller_Base {
}
return new Minify_Source($spec);
}
protected $_type = null;
/*
* Make sure that only source files of a single type are registered
*/
public function checkType($sourceOrExt)
{
if ($sourceOrExt === 'js') {
$type = Minify::TYPE_JS;
} elseif ($sourceOrExt === 'css') {
$type = Minify::TYPE_CSS;
} elseif ($sourceOrExt->contentType !== null) {
$type = $sourceOrExt->contentType;
} else {
return;
}
if ($this->_type === null) {
$this->_type = $type;
} elseif ($this->_type !== $type) {
throw new Exception('Content-Type mismatch');
}
}
}

View File

@@ -9,6 +9,8 @@
*
* @package Minify
* @author Stephen Clay <steve@mrclay.org>
*
* @todo lose this singleton! pass log object in Minify::serve and distribute to others
*/
class Minify_Logger {