ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
MakeAbsolute.php
Go to the documentation of this file.
1 <?php
2 
3 // does not support network paths
4 
6 {
10  public $name = 'MakeAbsolute';
11 
15  protected $base;
16 
20  protected $basePathStack = array();
21 
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; // fragment is invalid for base URI
39  $stack = explode('/', $this->base->path);
40  array_pop($stack); // discard last segment
41  $stack = $this->_collapseStack($stack); // do pre-parsing
42  $this->basePathStack = $stack;
43  return true;
44  }
45 
52  public function filter(&$uri, $config, $context)
53  {
54  if (is_null($this->base)) {
55  return true;
56  } // abort early
57  if ($uri->path === '' && is_null($uri->scheme) &&
58  is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)) {
59  // reference to current document
60  $uri = clone $this->base;
61  return true;
62  }
63  if (!is_null($uri->scheme)) {
64  // absolute URI already: don't change
65  if (!is_null($uri->host)) {
66  return true;
67  }
68  $scheme_obj = $uri->getSchemeObj($config, $context);
69  if (!$scheme_obj) {
70  // scheme not recognized
71  return false;
72  }
73  if (!$scheme_obj->hierarchical) {
74  // non-hierarchal URI with explicit scheme, don't change
75  return true;
76  }
77  // special case: had a scheme but always is hierarchical and had no authority
78  }
79  if (!is_null($uri->host)) {
80  // network path, don't bother
81  return true;
82  }
83  if ($uri->path === '') {
84  $uri->path = $this->base->path;
85  } elseif ($uri->path[0] !== '/') {
86  // relative path, needs more complicated processing
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  // absolute path, but still we should collapse
96  $uri->path = implode('/', $this->_collapseStack(explode('/', $uri->path)));
97  }
98  // re-combine
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 
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  // absorb an internally duplicated slash
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  // error case: attempted to back out too far:
132  // restore the leading slash
133  $result[] = '';
134  } elseif ($segment === '..') {
135  $result[] = '..'; // cannot remove .. with ..
136  }
137  } else {
138  // relative path, preserve the double-dots
139  $result[] = '..';
140  }
141  $is_folder = true;
142  continue;
143  }
144  if ($stack[$i] == '.') {
145  // silently absorb
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 // vim: et sw=4 sts=4