1: <?php
2:
3:
4:
5: class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
6: {
7: public $name = 'MakeAbsolute';
8: protected $base;
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);
15: return false;
16: }
17: $this->base->fragment = null;
18: $stack = explode('/', $this->base->path);
19: array_pop($stack);
20: $stack = $this->_collapseStack($stack);
21: $this->basePathStack = $stack;
22: return true;
23: }
24: public function filter(&$uri, $config, $context) {
25: if (is_null($this->base)) return true;
26: if (
27: $uri->path === '' && is_null($uri->scheme) &&
28: is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)
29: ) {
30:
31: $uri = clone $this->base;
32: return true;
33: }
34: if (!is_null($uri->scheme)) {
35:
36: if (!is_null($uri->host)) return true;
37: $scheme_obj = $uri->getSchemeObj($config, $context);
38: if (!$scheme_obj) {
39:
40: return false;
41: }
42: if (!$scheme_obj->hierarchical) {
43:
44: return true;
45: }
46:
47: }
48: if (!is_null($uri->host)) {
49:
50: return true;
51: }
52: if ($uri->path === '') {
53: $uri->path = $this->base->path;
54: } elseif ($uri->path[0] !== '/') {
55:
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, '');
60: }
61: $new_stack = $this->_collapseStack($new_stack);
62: $uri->path = implode('/', $new_stack);
63: } else {
64:
65: $uri->path = implode('/', $this->_collapseStack(explode('/', $uri->path)));
66: }
67:
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;
72: return true;
73: }
74:
75: 76: 77:
78: private function _collapseStack($stack) {
79: $result = array();
80: $is_folder = false;
81: for ($i = 0; isset($stack[$i]); $i++) {
82: $is_folder = false;
83:
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:
90:
91: $result[] = '';
92: } elseif ($segment === '..') {
93: $result[] = '..';
94: }
95: } else {
96:
97: $result[] = '..';
98: }
99: $is_folder = true;
100: continue;
101: }
102: if ($stack[$i] == '.') {
103:
104: $is_folder = true;
105: continue;
106: }
107: $result[] = $stack[$i];
108: }
109: if ($is_folder) $result[] = '';
110: return $result;
111: }
112: }
113:
114:
115: