mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2024-12-22 16:31:53 +00:00
[1.2.0]
- Added %URI.DisableExternal, which prevents links to external websites. You can also use %URI.Host to permit absolute linking to subdomains - Fixed a few bugs involving null configuration values git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@522 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
parent
926b94bdd3
commit
f38fe431ed
2
NEWS
2
NEWS
@ -13,6 +13,8 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
||||
! Added percent encoding normalization
|
||||
! XSS attacks smoketest given facelift
|
||||
! Configuration documentation now has table of contents
|
||||
! Added %URI.DisableExternal, which prevents links to external websites. You
|
||||
can also use %URI.Host to permit absolute linking to subdomains
|
||||
- Documentation updated
|
||||
+ TODO added request Phalanger
|
||||
+ TODO added request Native compression
|
||||
|
@ -39,8 +39,4 @@ time. Note the naming convention: %Namespace.Directive
|
||||
%URI.AddRelNofollow - will add rel="nofollow" to all links, preventing the
|
||||
spread of ill-gotten pagerank
|
||||
|
||||
%URI.Host - host of website, for external link checks
|
||||
|
||||
%URI.RelativeToAbsolute - transforms all relative URIs to absolute form
|
||||
|
||||
%URI.DisableExternal - disable external links
|
||||
|
@ -12,6 +12,28 @@ HTMLPurifier_ConfigSchema::define(
|
||||
'select the proper object validator when no scheme information is present.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'Host', null, 'string/null',
|
||||
'Defines the domain name of the server, so we can determine whether or '.
|
||||
'an absolute URI is from your website or not. Not strictly necessary, '.
|
||||
'as users should be using relative URIs to reference resources on your '.
|
||||
'website. It will, however, let you use absolute URIs to link to '.
|
||||
'subdomains of the domain you post here: i.e. example.com will allow '.
|
||||
'sub.example.com. However, higher up domains will still be excluded: '.
|
||||
'if you set %URI.Host to sub.example.com, example.com will be blocked. '.
|
||||
'This directive has been available since 1.2.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::Define(
|
||||
'URI', 'DisableExternal', false, 'bool',
|
||||
'Disables links to external websites. This is a highly effective '.
|
||||
'anti-spam and anti-pagerank-leech measure, but comes at a hefty price: no'.
|
||||
'links or images outside of your domain will be allowed. Non-linkified '.
|
||||
'URIs will still be preserved. If you want to be able to link to '.
|
||||
'subdomains or use absolute URIs, specify %URI.Host for your website. '.
|
||||
'This directive has been available since 1.2.0.'
|
||||
);
|
||||
|
||||
/**
|
||||
* Validates a URI as defined by RFC 3986.
|
||||
* @note Scheme-specific mechanics deferred to HTMLPurifier_URIScheme
|
||||
@ -81,6 +103,13 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
|
||||
if ($authority !== null) {
|
||||
|
||||
// remove URI if it's absolute and we disallow externals
|
||||
unset($our_host);
|
||||
if ($config->get('URI', 'DisableExternal')) {
|
||||
$our_host = $config->get('URI', 'Host');
|
||||
if ($our_host === null) return false;
|
||||
}
|
||||
|
||||
$HEXDIG = '[A-Fa-f0-9]';
|
||||
$unreserved = 'A-Za-z0-9-._~'; // make sure you wrap with []
|
||||
$sub_delims = '!$&\'()'; // needs []
|
||||
@ -103,6 +132,17 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
$host = $this->host->validate($host, $config, $context);
|
||||
if ($host === false) $host = null;
|
||||
|
||||
// more lenient absolute checking
|
||||
if (isset($our_host)) {
|
||||
$host_parts = array_reverse(explode('.', $host));
|
||||
// could be cached
|
||||
$our_host_parts = array_reverse(explode('.', $our_host));
|
||||
foreach ($our_host_parts as $i => $discard) {
|
||||
if (!isset($host_parts[$i])) return false;
|
||||
if ($host_parts[$i] != $our_host_parts[$i]) return false;
|
||||
}
|
||||
}
|
||||
|
||||
// userinfo and host are validated within the regexp
|
||||
|
||||
} else {
|
||||
|
@ -60,7 +60,7 @@ class HTMLPurifier_Config
|
||||
* @param $key String key
|
||||
*/
|
||||
function get($namespace, $key) {
|
||||
if (!isset($this->conf[$namespace][$key])) {
|
||||
if (!isset($this->def->info[$namespace][$key])) {
|
||||
trigger_error('Cannot retrieve value of undefined directive',
|
||||
E_USER_WARNING);
|
||||
return;
|
||||
@ -75,7 +75,7 @@ class HTMLPurifier_Config
|
||||
* @param $value Mixed value
|
||||
*/
|
||||
function set($namespace, $key, $value) {
|
||||
if (!isset($this->conf[$namespace][$key])) {
|
||||
if (!isset($this->def->info[$namespace][$key])) {
|
||||
trigger_error('Cannot set undefined directive to value',
|
||||
E_USER_WARNING);
|
||||
return;
|
||||
|
@ -233,7 +233,6 @@ class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
|
||||
function testIntegration() {
|
||||
|
||||
$this->def = new HTMLPurifier_AttrDef_URI();
|
||||
$this->config = $this->context = null;
|
||||
|
||||
$this->assertDef('http://www.google.com/');
|
||||
$this->assertDef('javascript:bad_stuff();', false);
|
||||
@ -244,6 +243,24 @@ class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
|
||||
|
||||
}
|
||||
|
||||
function testDisableExternal() {
|
||||
|
||||
$this->def = new HTMLPurifier_AttrDef_URI();
|
||||
$this->config->set('URI', 'DisableExternal', true);
|
||||
|
||||
$this->assertDef('/foobar.txt');
|
||||
$this->assertDef('http://google.com/', false);
|
||||
$this->assertDef('http://sub.example.com/alas?foo=asd', false);
|
||||
|
||||
$this->config->set('URI', 'Host', 'sub.example.com');
|
||||
|
||||
$this->assertDef('http://sub.example.com/alas?foo=asd');
|
||||
$this->assertDef('http://example.com/teehee', false);
|
||||
$this->assertDef('http://www.example.com/#man', false);
|
||||
$this->assertDef('http://go.sub.example.com/perhaps?p=foo');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -37,6 +37,10 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
|
||||
'Core', 'Encoding', 'utf-8', 'istring', 'Case insensitivity!'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Extension', 'CanBeNull', null, 'string/null', 'Null or string!'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::defineAllowedValues(
|
||||
'Extension', 'Pert', array('foo', 'moo')
|
||||
);
|
||||
@ -92,6 +96,21 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
|
||||
$this->assertNoErrors();
|
||||
$this->assertIdentical($config->get('Core', 'Encoding'), 'iso-8859-1');
|
||||
|
||||
// set null to directive that allows null
|
||||
$config->set('Extension', 'CanBeNull', null);
|
||||
$this->assertNoErrors();
|
||||
$this->assertIdentical($config->get('Extension', 'CanBeNull'), null);
|
||||
|
||||
$config->set('Extension', 'CanBeNull', 'foobar');
|
||||
$this->assertNoErrors();
|
||||
$this->assertIdentical($config->get('Extension', 'CanBeNull'), 'foobar');
|
||||
|
||||
// set null to directive that doesn't allow null
|
||||
$config->set('Extension', 'Pert', null);
|
||||
$this->assertError('Value is of invalid type');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
}
|
||||
|
||||
function test_getDefinition() {
|
||||
|
Loading…
Reference in New Issue
Block a user