0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-12-22 16:31:53 +00:00

Add new Cache.SerializerPermissions option.

This commit is contained in:
Petr Skoda 2011-01-13 15:05:12 +01:00 committed by Edward Z. Yang
parent 5803c06765
commit 78c4e62245
6 changed files with 74 additions and 15 deletions

2
NEWS
View File

@ -18,6 +18,8 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
! More types of SPL autoloaders allowed on later versions of PHP. ! More types of SPL autoloaders allowed on later versions of PHP.
! Implementations for position, top, left, right, bottom, z-index ! Implementations for position, top, left, right, bottom, z-index
when %CSS.Trusted is on. when %CSS.Trusted is on.
! Add %Cache.SerializerPermissions option for custom serializer
directory/file permissions
- Make removal of conditional IE comments ungreedy; thanks Bernd - Make removal of conditional IE comments ungreedy; thanks Bernd
for reporting. for reporting.
- Escape CDATA before removing Internet Explorer comments. - Escape CDATA before removing Internet Explorer comments.

View File

@ -380,6 +380,12 @@
<line>91</line> <line>91</line>
</file> </file>
</directive> </directive>
<directive id="Cache.SerializerPermissions">
<file name="HTMLPurifier/DefinitionCache/Serializer.php">
<line>107</line>
<line>124</line>
</file>
</directive>
<directive id="Filter.ExtractStyleBlocks.TidyImpl"> <directive id="Filter.ExtractStyleBlocks.TidyImpl">
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php"> <file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
<line>41</line> <line>41</line>

View File

@ -0,0 +1,11 @@
Cache.SerializerPermissions
TYPE: int
VERSION: 4.2.1
DEFAULT: 0755
--DESCRIPTION--
<p>
Directory permissions of the files and directories created inside
the DefinitionCache/Serializer or other custom serializer path.
</p>
--# vim: et sw=4 sts=4

View File

@ -9,14 +9,14 @@ class HTMLPurifier_DefinitionCache_Serializer extends
$file = $this->generateFilePath($config); $file = $this->generateFilePath($config);
if (file_exists($file)) return false; if (file_exists($file)) return false;
if (!$this->_prepareDir($config)) return false; if (!$this->_prepareDir($config)) return false;
return $this->_write($file, serialize($def)); return $this->_write($file, serialize($def), $config);
} }
public function set($def, $config) { public function set($def, $config) {
if (!$this->checkDefType($def)) return; if (!$this->checkDefType($def)) return;
$file = $this->generateFilePath($config); $file = $this->generateFilePath($config);
if (!$this->_prepareDir($config)) return false; if (!$this->_prepareDir($config)) return false;
return $this->_write($file, serialize($def)); return $this->_write($file, serialize($def), $config);
} }
public function replace($def, $config) { public function replace($def, $config) {
@ -24,7 +24,7 @@ class HTMLPurifier_DefinitionCache_Serializer extends
$file = $this->generateFilePath($config); $file = $this->generateFilePath($config);
if (!file_exists($file)) return false; if (!file_exists($file)) return false;
if (!$this->_prepareDir($config)) return false; if (!$this->_prepareDir($config)) return false;
return $this->_write($file, serialize($def)); return $this->_write($file, serialize($def), $config);
} }
public function get($config) { public function get($config) {
@ -97,18 +97,34 @@ class HTMLPurifier_DefinitionCache_Serializer extends
* Convenience wrapper function for file_put_contents * Convenience wrapper function for file_put_contents
* @param $file File name to write to * @param $file File name to write to
* @param $data Data to write into file * @param $data Data to write into file
* @param $config Config object
* @return Number of bytes written if success, or false if failure. * @return Number of bytes written if success, or false if failure.
*/ */
private function _write($file, $data) { private function _write($file, $data, $config) {
return file_put_contents($file, $data); $result = file_put_contents($file, $data);
if ($result !== false) {
// set permissions of the new file (no execute)
$chmod = $config->get('Cache.SerializerPermissions');
if (!$chmod) {
$chmod = 0644; // invalid config or simpletest
}
$chmod = $chmod & 0666;
chmod($file, $chmod);
}
return $result;
} }
/** /**
* Prepares the directory that this type stores the serials in * Prepares the directory that this type stores the serials in
* @param $config Config object
* @return True if successful * @return True if successful
*/ */
private function _prepareDir($config) { private function _prepareDir($config) {
$directory = $this->generateDirectoryPath($config); $directory = $this->generateDirectoryPath($config);
$chmod = $config->get('Cache.SerializerPermissions');
if (!$chmod) {
$chmod = 0755; // invalid config or simpletest
}
if (!is_dir($directory)) { if (!is_dir($directory)) {
$base = $this->generateBaseDirectoryPath($config); $base = $this->generateBaseDirectoryPath($config);
if (!is_dir($base)) { if (!is_dir($base)) {
@ -116,13 +132,13 @@ class HTMLPurifier_DefinitionCache_Serializer extends
please create or change using %Cache.SerializerPath', please create or change using %Cache.SerializerPath',
E_USER_WARNING); E_USER_WARNING);
return false; return false;
} elseif (!$this->_testPermissions($base)) { } elseif (!$this->_testPermissions($base, $chmod)) {
return false; return false;
} }
$old = umask(0022); // disable group and world writes $old = umask(0000);
mkdir($directory); mkdir($directory, $chmod);
umask($old); umask($old);
} elseif (!$this->_testPermissions($directory)) { } elseif (!$this->_testPermissions($directory, $chmod)) {
return false; return false;
} }
return true; return true;
@ -131,8 +147,11 @@ class HTMLPurifier_DefinitionCache_Serializer extends
/** /**
* Tests permissions on a directory and throws out friendly * Tests permissions on a directory and throws out friendly
* error messages and attempts to chmod it itself if possible * error messages and attempts to chmod it itself if possible
* @param $dir Directory path
* @param $chmod Permissions
* @return True if directory writable
*/ */
private function _testPermissions($dir) { private function _testPermissions($dir, $chmod) {
// early abort, if it is writable, everything is hunky-dory // early abort, if it is writable, everything is hunky-dory
if (is_writable($dir)) return true; if (is_writable($dir)) return true;
if (!is_dir($dir)) { if (!is_dir($dir)) {
@ -146,17 +165,17 @@ class HTMLPurifier_DefinitionCache_Serializer extends
// POSIX system, we can give more specific advice // POSIX system, we can give more specific advice
if (fileowner($dir) === posix_getuid()) { if (fileowner($dir) === posix_getuid()) {
// we can chmod it ourselves // we can chmod it ourselves
chmod($dir, 0755); $chmod = $chmod | 0700;
return true; if (chmod($dir, $chmod)) return true;
} elseif (filegroup($dir) === posix_getgid()) { } elseif (filegroup($dir) === posix_getgid()) {
$chmod = '775'; $chmod = $chmod | 0070;
} else { } else {
// PHP's probably running as nobody, so we'll // PHP's probably running as nobody, so we'll
// need to give global permissions // need to give global permissions
$chmod = '777'; $chmod = $chmod | 0777;
} }
trigger_error('Directory '.$dir.' not writable, '. trigger_error('Directory '.$dir.' not writable, '.
'please chmod to ' . $chmod, 'please chmod to ' . decoct($chmod),
E_USER_WARNING); E_USER_WARNING);
} else { } else {
// generic error message // generic error message

View File

@ -194,6 +194,27 @@ class HTMLPurifier_DefinitionCache_SerializerTest extends HTMLPurifier_Definitio
} }
function testAlternatePermissions() {
$cache = new HTMLPurifier_DefinitionCache_Serializer('Test');
$config = $this->generateConfigMock('serial');
$config->version = '1.0.0';
$config->setReturnValue('get', 1, array('Test.DefinitionRev'));
$dir = dirname(__FILE__) . '/SerializerTest';
$config->setReturnValue('get', $dir, array('Cache.SerializerPath'));
$config->setReturnValue('get', 0777, array('Cache.SerializerPermissions'));
$def_original = $this->generateDefinition();
$cache->add($def_original, $config);
$this->assertFileExist($dir . '/Test/1.0.0,serial,1.ser');
$this->assertEqual(0666, 0777 & fileperms($dir . '/Test/1.0.0,serial,1.ser'));
$this->assertEqual(0777, 0777 & fileperms($dir . '/Test'));
unlink($dir . '/Test/1.0.0,serial,1.ser');
rmdir( $dir . '/Test');
}
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4