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 public $name = 'MakeAbsolute';
22 protected $basePathStack = array();
23 public 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 public 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
84 private function _collapseStack($stack) {
86 for ($i = 0; isset($stack[$i]); $i++
) {
88 // absorb an internally duplicated slash
89 if ($stack[$i] == '' && $i && isset($stack[$i+
1])) continue;
90 if ($stack[$i] == '..') {
91 if (!empty($result)) {
92 $segment = array_pop($result);
93 if ($segment === '' && empty($result)) {
94 // error case: attempted to back out too far:
95 // restore the leading slash
97 } elseif ($segment === '..') {
98 $result[] = '..'; // cannot remove .. with ..
101 // relative path, preserve the double-dots
107 if ($stack[$i] == '.') {
112 $result[] = $stack[$i];
114 if ($is_folder) $result[] = '';