3 // does not support network paths
5 class HTMLPurifier_URIFilter_MakeAbsolute
extends HTMLPurifier_URIFilter
7 public $name = 'MakeAbsolute';
9 protected $basePathStack = array();
10 public function prepare($config) {
11 $def = $config->getDefinition('URI');
12 $this->base
= $def->base
;
13 if (is_null($this->base
)) {
14 trigger_error('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration', E_USER_WARNING
);
17 $this->base
->fragment
= null; // fragment is invalid for base URI
18 $stack = explode('/', $this->base
->path
);
19 array_pop($stack); // discard last segment
20 $stack = $this->_collapseStack($stack); // do pre-parsing
21 $this->basePathStack
= $stack;
24 public function filter(&$uri, $config, $context) {
25 if (is_null($this->base
)) return true; // abort early
27 $uri->path
=== '' && is_null($uri->scheme
) &&
28 is_null($uri->host
) && is_null($uri->query
) && is_null($uri->fragment
)
30 // reference to current document
31 $uri = clone $this->base
;
34 if (!is_null($uri->scheme
)) {
35 // absolute URI already: don't change
36 if (!is_null($uri->host
)) return true;
37 $scheme_obj = $uri->getSchemeObj($config, $context);
39 // scheme not recognized
42 if (!$scheme_obj->hierarchical
) {
43 // non-hierarchal URI with explicit scheme, don't change
46 // special case: had a scheme but always is hierarchical and had no authority
48 if (!is_null($uri->host
)) {
49 // network path, don't bother
52 if ($uri->path
=== '') {
53 $uri->path
= $this->base
->path
;
54 } elseif ($uri->path
[0] !== '/') {
55 // relative path, needs more complicated processing
56 $stack = explode('/', $uri->path
);
57 $new_stack = array_merge($this->basePathStack
, $stack);
58 if ($new_stack[0] !== '' && !is_null($this->base
->host
)) {
59 array_unshift($new_stack, '');
61 $new_stack = $this->_collapseStack($new_stack);
62 $uri->path
= implode('/', $new_stack);
64 // absolute path, but still we should collapse
65 $uri->path
= implode('/', $this->_collapseStack(explode('/', $uri->path
)));
68 $uri->scheme
= $this->base
->scheme
;
69 if (is_null($uri->userinfo
)) $uri->userinfo
= $this->base
->userinfo
;
70 if (is_null($uri->host
)) $uri->host
= $this->base
->host
;
71 if (is_null($uri->port
)) $uri->port
= $this->base
->port
;
76 * Resolve dots and double-dots in a path stack
78 private function _collapseStack($stack) {
81 for ($i = 0; isset($stack[$i]); $i++
) {
83 // absorb an internally duplicated slash
84 if ($stack[$i] == '' && $i && isset($stack[$i+
1])) continue;
85 if ($stack[$i] == '..') {
86 if (!empty($result)) {
87 $segment = array_pop($result);
88 if ($segment === '' && empty($result)) {
89 // error case: attempted to back out too far:
90 // restore the leading slash
92 } elseif ($segment === '..') {
93 $result[] = '..'; // cannot remove .. with ..
96 // relative path, preserve the double-dots
102 if ($stack[$i] == '.') {
107 $result[] = $stack[$i];
109 if ($is_folder) $result[] = '';
114 // vim: et sw=4 sts=4