ILIAS  Release_4_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 {
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; // 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;
22  return true;
23  }
24  public function filter(&$uri, $config, $context) {
25  if (is_null($this->base)) return true; // abort early
26  if (
27  $uri->path === '' && is_null($uri->scheme) &&
28  is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)
29  ) {
30  // reference to current document
31  $uri = clone $this->base;
32  return true;
33  }
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);
38  if (!$scheme_obj) {
39  // scheme not recognized
40  return false;
41  }
42  if (!$scheme_obj->hierarchical) {
43  // non-hierarchal URI with explicit scheme, don't change
44  return true;
45  }
46  // special case: had a scheme but always is hierarchical and had no authority
47  }
48  if (!is_null($uri->host)) {
49  // network path, don't bother
50  return true;
51  }
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, '');
60  }
61  $new_stack = $this->_collapseStack($new_stack);
62  $uri->path = implode('/', $new_stack);
63  } else {
64  // absolute path, but still we should collapse
65  $uri->path = implode('/', $this->_collapseStack(explode('/', $uri->path)));
66  }
67  // re-combine
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 
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  // 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
91  $result[] = '';
92  } elseif ($segment === '..') {
93  $result[] = '..'; // cannot remove .. with ..
94  }
95  } else {
96  // relative path, preserve the double-dots
97  $result[] = '..';
98  }
99  $is_folder = true;
100  continue;
101  }
102  if ($stack[$i] == '.') {
103  // silently absorb
104  $is_folder = true;
105  continue;
106  }
107  $result[] = $stack[$i];
108  }
109  if ($is_folder) $result[] = '';
110  return $result;
111  }
112 }
113 
114 // vim: et sw=4 sts=4