1: | <?php
|
2: |
|
3: |
|
4: |
|
5: | class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
|
6: | {
|
7: | |
8: | |
9: |
|
10: | public $name = 'MakeAbsolute';
|
11: |
|
12: | |
13: | |
14: |
|
15: | protected $base;
|
16: |
|
17: | |
18: | |
19: |
|
20: | protected $basePathStack = array();
|
21: |
|
22: | |
23: | |
24: | |
25: |
|
26: | public function prepare($config)
|
27: | {
|
28: | $def = $config->getDefinition('URI');
|
29: | $this->base = $def->base;
|
30: | if (is_null($this->base)) {
|
31: | trigger_error(
|
32: | 'URI.MakeAbsolute is being ignored due to lack of ' .
|
33: | 'value for URI.Base configuration',
|
34: | E_USER_WARNING
|
35: | );
|
36: | return false;
|
37: | }
|
38: | $this->base->fragment = null;
|
39: | $stack = explode('/', $this->base->path);
|
40: | array_pop($stack);
|
41: | $stack = $this->_collapseStack($stack);
|
42: | $this->basePathStack = $stack;
|
43: | return true;
|
44: | }
|
45: |
|
46: | |
47: | |
48: | |
49: | |
50: | |
51: |
|
52: | public function filter(&$uri, $config, $context)
|
53: | {
|
54: | if (is_null($this->base)) {
|
55: | return true;
|
56: | }
|
57: | if ($uri->path === '' && is_null($uri->scheme) &&
|
58: | is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)) {
|
59: |
|
60: | $uri = clone $this->base;
|
61: | return true;
|
62: | }
|
63: | if (!is_null($uri->scheme)) {
|
64: |
|
65: | if (!is_null($uri->host)) {
|
66: | return true;
|
67: | }
|
68: | $scheme_obj = $uri->getSchemeObj($config, $context);
|
69: | if (!$scheme_obj) {
|
70: |
|
71: | return false;
|
72: | }
|
73: | if (!$scheme_obj->hierarchical) {
|
74: |
|
75: | return true;
|
76: | }
|
77: |
|
78: | }
|
79: | if (!is_null($uri->host)) {
|
80: |
|
81: | return true;
|
82: | }
|
83: | if ($uri->path === '') {
|
84: | $uri->path = $this->base->path;
|
85: | } elseif ($uri->path[0] !== '/') {
|
86: |
|
87: | $stack = explode('/', $uri->path);
|
88: | $new_stack = array_merge($this->basePathStack, $stack);
|
89: | if ($new_stack[0] !== '' && !is_null($this->base->host)) {
|
90: | array_unshift($new_stack, '');
|
91: | }
|
92: | $new_stack = $this->_collapseStack($new_stack);
|
93: | $uri->path = implode('/', $new_stack);
|
94: | } else {
|
95: |
|
96: | $uri->path = implode('/', $this->_collapseStack(explode('/', $uri->path)));
|
97: | }
|
98: |
|
99: | $uri->scheme = $this->base->scheme;
|
100: | if (is_null($uri->userinfo)) {
|
101: | $uri->userinfo = $this->base->userinfo;
|
102: | }
|
103: | if (is_null($uri->host)) {
|
104: | $uri->host = $this->base->host;
|
105: | }
|
106: | if (is_null($uri->port)) {
|
107: | $uri->port = $this->base->port;
|
108: | }
|
109: | return true;
|
110: | }
|
111: |
|
112: | |
113: | |
114: | |
115: | |
116: |
|
117: | private function _collapseStack($stack)
|
118: | {
|
119: | $result = array();
|
120: | $is_folder = false;
|
121: | for ($i = 0; isset($stack[$i]); $i++) {
|
122: | $is_folder = false;
|
123: |
|
124: | if ($stack[$i] == '' && $i && isset($stack[$i + 1])) {
|
125: | continue;
|
126: | }
|
127: | if ($stack[$i] == '..') {
|
128: | if (!empty($result)) {
|
129: | $segment = array_pop($result);
|
130: | if ($segment === '' && empty($result)) {
|
131: |
|
132: |
|
133: | $result[] = '';
|
134: | } elseif ($segment === '..') {
|
135: | $result[] = '..';
|
136: | }
|
137: | } else {
|
138: |
|
139: | $result[] = '..';
|
140: | }
|
141: | $is_folder = true;
|
142: | continue;
|
143: | }
|
144: | if ($stack[$i] == '.') {
|
145: |
|
146: | $is_folder = true;
|
147: | continue;
|
148: | }
|
149: | $result[] = $stack[$i];
|
150: | }
|
151: | if ($is_folder) {
|
152: | $result[] = '';
|
153: | }
|
154: | return $result;
|
155: | }
|
156: | }
|
157: |
|
158: |
|
159: | |