3
// does not support network paths
5
require_once 'HTMLPurifier/URIFilter.php';
7
HTMLPurifier_ConfigSchema::define(
8
'URI', 'MakeAbsolute', false, 'bool', '
10
Converts all URIs into absolute forms. This is useful when the HTML
11
being filtered assumes a specific base path, but will actually be
12
viewed in a different context (and setting an alternate base URI is
13
not possible). %URI.Base must be set for this directive to work.
14
This directive has been available since 2.1.0.
18
class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
20
var $name = 'MakeAbsolute';
22
var $basePathStack = array();
23
function prepare($config) {
24
$def = $config->getDefinition('URI');
25
$this->base = $def->base;
26
if (is_null($this->base)) {
27
trigger_error('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration', E_USER_ERROR);
30
$this->base->fragment = null; // fragment is invalid for base URI
31
$stack = explode('/', $this->base->path);
32
array_pop($stack); // discard last segment
33
$stack = $this->_collapseStack($stack); // do pre-parsing
34
$this->basePathStack = $stack;
36
function filter(&$uri, $config, &$context) {
37
if (is_null($this->base)) return true; // abort early
39
$uri->path === '' && is_null($uri->scheme) &&
40
is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)
42
// reference to current document
43
$uri = $this->base->copy();
46
if (!is_null($uri->scheme)) {
47
// absolute URI already: don't change
48
if (!is_null($uri->host)) return true;
49
$scheme_obj = $uri->getSchemeObj($config, $context);
51
// scheme not recognized
54
if (!$scheme_obj->hierarchical) {
55
// non-hierarchal URI with explicit scheme, don't change
58
// special case: had a scheme but always is hierarchical and had no authority
60
if (!is_null($uri->host)) {
61
// network path, don't bother
64
if ($uri->path === '') {
65
$uri->path = $this->base->path;
66
}elseif ($uri->path[0] !== '/') {
67
// relative path, needs more complicated processing
68
$stack = explode('/', $uri->path);
69
$new_stack = array_merge($this->basePathStack, $stack);
70
$new_stack = $this->_collapseStack($new_stack);
71
$uri->path = implode('/', $new_stack);
74
$uri->scheme = $this->base->scheme;
75
if (is_null($uri->userinfo)) $uri->userinfo = $this->base->userinfo;
76
if (is_null($uri->host)) $uri->host = $this->base->host;
77
if (is_null($uri->port)) $uri->port = $this->base->port;
82
* Resolve dots and double-dots in a path stack
85
function _collapseStack($stack) {
87
for ($i = 0; isset($stack[$i]); $i++) {
89
// absorb an internally duplicated slash
90
if ($stack[$i] == '' && $i && isset($stack[$i+1])) continue;
91
if ($stack[$i] == '..') {
92
if (!empty($result)) {
93
$segment = array_pop($result);
94
if ($segment === '' && empty($result)) {
95
// error case: attempted to back out too far:
96
// restore the leading slash
98
} elseif ($segment === '..') {
99
$result[] = '..'; // cannot remove .. with ..
102
// relative path, preserve the double-dots
108
if ($stack[$i] == '.') {
113
$result[] = $stack[$i];
115
if ($is_folder) $result[] = '';