PageRenderTime 1086ms CodeModel.GetById 43ms RepoModel.GetById 6ms app.codeStats 0ms

/moodle/lib/htmlpurifier/HTMLPurifier/URIFilter/MakeAbsolute.php

https://bitbucket.org/geek745/moodle-db2
PHP | 119 lines | 95 code | 6 blank | 18 comment | 29 complexity | f8fd8be5d2176a4d78585cfb683396df MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, LGPL-2.0
  1. <?php
  2. // does not support network paths
  3. require_once 'HTMLPurifier/URIFilter.php';
  4. HTMLPurifier_ConfigSchema::define(
  5. 'URI', 'MakeAbsolute', false, 'bool', '
  6. <p>
  7. Converts all URIs into absolute forms. This is useful when the HTML
  8. being filtered assumes a specific base path, but will actually be
  9. viewed in a different context (and setting an alternate base URI is
  10. not possible). %URI.Base must be set for this directive to work.
  11. This directive has been available since 2.1.0.
  12. </p>
  13. ');
  14. class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
  15. {
  16. var $name = 'MakeAbsolute';
  17. var $base;
  18. var $basePathStack = array();
  19. function prepare($config) {
  20. $def = $config->getDefinition('URI');
  21. $this->base = $def->base;
  22. if (is_null($this->base)) {
  23. trigger_error('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration', E_USER_ERROR);
  24. return;
  25. }
  26. $this->base->fragment = null; // fragment is invalid for base URI
  27. $stack = explode('/', $this->base->path);
  28. array_pop($stack); // discard last segment
  29. $stack = $this->_collapseStack($stack); // do pre-parsing
  30. $this->basePathStack = $stack;
  31. }
  32. function filter(&$uri, $config, &$context) {
  33. if (is_null($this->base)) return true; // abort early
  34. if (
  35. $uri->path === '' && is_null($uri->scheme) &&
  36. is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)
  37. ) {
  38. // reference to current document
  39. $uri = $this->base->copy();
  40. return true;
  41. }
  42. if (!is_null($uri->scheme)) {
  43. // absolute URI already: don't change
  44. if (!is_null($uri->host)) return true;
  45. $scheme_obj = $uri->getSchemeObj($config, $context);
  46. if (!$scheme_obj) {
  47. // scheme not recognized
  48. return false;
  49. }
  50. if (!$scheme_obj->hierarchical) {
  51. // non-hierarchal URI with explicit scheme, don't change
  52. return true;
  53. }
  54. // special case: had a scheme but always is hierarchical and had no authority
  55. }
  56. if (!is_null($uri->host)) {
  57. // network path, don't bother
  58. return true;
  59. }
  60. if ($uri->path === '') {
  61. $uri->path = $this->base->path;
  62. }elseif ($uri->path[0] !== '/') {
  63. // relative path, needs more complicated processing
  64. $stack = explode('/', $uri->path);
  65. $new_stack = array_merge($this->basePathStack, $stack);
  66. $new_stack = $this->_collapseStack($new_stack);
  67. $uri->path = implode('/', $new_stack);
  68. }
  69. // re-combine
  70. $uri->scheme = $this->base->scheme;
  71. if (is_null($uri->userinfo)) $uri->userinfo = $this->base->userinfo;
  72. if (is_null($uri->host)) $uri->host = $this->base->host;
  73. if (is_null($uri->port)) $uri->port = $this->base->port;
  74. return true;
  75. }
  76. /**
  77. * Resolve dots and double-dots in a path stack
  78. * @private
  79. */
  80. function _collapseStack($stack) {
  81. $result = array();
  82. for ($i = 0; isset($stack[$i]); $i++) {
  83. $is_folder = false;
  84. // absorb an internally duplicated slash
  85. if ($stack[$i] == '' && $i && isset($stack[$i+1])) continue;
  86. if ($stack[$i] == '..') {
  87. if (!empty($result)) {
  88. $segment = array_pop($result);
  89. if ($segment === '' && empty($result)) {
  90. // error case: attempted to back out too far:
  91. // restore the leading slash
  92. $result[] = '';
  93. } elseif ($segment === '..') {
  94. $result[] = '..'; // cannot remove .. with ..
  95. }
  96. } else {
  97. // relative path, preserve the double-dots
  98. $result[] = '..';
  99. }
  100. $is_folder = true;
  101. continue;
  102. }
  103. if ($stack[$i] == '.') {
  104. // silently absorb
  105. $is_folder = true;
  106. continue;
  107. }
  108. $result[] = $stack[$i];
  109. }
  110. if ($is_folder) $result[] = '';
  111. return $result;
  112. }
  113. }