diff --git a/library/HTMLPurifier/URI.php b/library/HTMLPurifier/URI.php
index 79b7a71f..f158ef5e 100644
--- a/library/HTMLPurifier/URI.php
+++ b/library/HTMLPurifier/URI.php
@@ -40,7 +40,7 @@ class HTMLPurifier_URI
} else {
// no scheme: retrieve the default one
$def = $config->getDefinition('URI');
- $scheme_obj = $registry->getScheme($def->defaultScheme, $config, $context);
+ $scheme_obj = $def->getDefaultScheme($config, $context);
if (!$scheme_obj) {
// something funky happened to the default scheme object
trigger_error(
@@ -204,8 +204,9 @@ class HTMLPurifier_URI
* the current context. This is true when the host is null, or
* when it matches the host supplied to the configuration.
*
- * Note that this does not do any scheme checking (URI.Munge, I'm
- * looking at you).
+ * Note that this does not do any scheme checking, so it is mostly
+ * only appropriate for metadata that doesn't care about protocol
+ * security. isBenign is probably what you actually want.
*/
public function isLocal($config, $context) {
if ($this->host === null) return true;
@@ -214,6 +215,28 @@ class HTMLPurifier_URI
return false;
}
+ /**
+ * Returns true if this URL should be considered a 'benign' URL,
+ * that is:
+ *
+ * - It is a local URL (isLocal), and
+ * - It has a equal or better level of security
+ */
+ public function isBenign($config, $context) {
+ if (!$this->isLocal($config, $context)) return false;
+
+ $scheme_obj = $this->getSchemeObj($config, $context);
+ if (!$scheme_obj) return false; // conservative approach
+
+ $current_scheme_obj = $config->getDefinition('URI')->getDefaultScheme($config, $context);
+ if ($current_scheme_obj->secure) {
+ if (!$scheme_obj->secure) {
+ return false;
+ }
+ }
+ return true;
+ }
+
}
// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIDefinition.php b/library/HTMLPurifier/URIDefinition.php
index ea2b8fe2..ded5b9b6 100644
--- a/library/HTMLPurifier/URIDefinition.php
+++ b/library/HTMLPurifier/URIDefinition.php
@@ -72,6 +72,10 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
if (is_null($this->defaultScheme)) $this->defaultScheme = $config->get('URI.DefaultScheme');
}
+ public function getDefaultScheme($config, $context) {
+ return HTMLPurifier_URISchemeRegistry::instance()->getScheme($this->defaultScheme, $config, $context);
+ }
+
public function filter(&$uri, $config, $context) {
foreach ($this->filters as $name => $f) {
$result = $f->filter($uri, $config, $context);
diff --git a/library/HTMLPurifier/URIFilter/Munge.php b/library/HTMLPurifier/URIFilter/Munge.php
index 448f7646..de695df1 100644
--- a/library/HTMLPurifier/URIFilter/Munge.php
+++ b/library/HTMLPurifier/URIFilter/Munge.php
@@ -20,19 +20,8 @@ class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter
$scheme_obj = $uri->getSchemeObj($config, $context);
if (!$scheme_obj) return true; // ignore unknown schemes, maybe another postfilter did it
- if (!$scheme_obj->browsable) return true; // ignore non-browseable schemes
-
- // don't redirect if target host is our host
- if ($uri->isLocal($config, $context)) {
- $uri_definition = $config->getDefinition('URI');
- // but do redirect if we're currently on a secure scheme,
- // and the target scheme is insecure
- $current_scheme_obj = HTMLPurifier_URISchemeRegistry::instance()->getScheme($uri_definition->defaultScheme, $config, $context);
- if ($scheme_obj->secure || !$current_scheme_obj->secure) {
- return true;
- }
- // target scheme was not secure, but we were secure
- }
+ if (!$scheme_obj->browsable) return true; // ignore non-browseable schemes, since we can't munge those in a reasonable way
+ if ($uri->isBenign($config, $context)) return true; // don't redirect if a benign URL
$this->makeReplace($uri, $config, $context);
$this->replace = array_map('rawurlencode', $this->replace);