Munge.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter
  3. {
  4. /**
  5. * @type string
  6. */
  7. public $name = 'Munge';
  8. /**
  9. * @type bool
  10. */
  11. public $post = true;
  12. /**
  13. * @type string
  14. */
  15. private $target;
  16. /**
  17. * @type HTMLPurifier_URIParser
  18. */
  19. private $parser;
  20. /**
  21. * @type bool
  22. */
  23. private $doEmbed;
  24. /**
  25. * @type string
  26. */
  27. private $secretKey;
  28. /**
  29. * @type array
  30. */
  31. protected $replace = array();
  32. /**
  33. * @param HTMLPurifier_Config $config
  34. * @return bool
  35. */
  36. public function prepare($config)
  37. {
  38. $this->target = $config->get('URI.' . $this->name);
  39. $this->parser = new HTMLPurifier_URIParser();
  40. $this->doEmbed = $config->get('URI.MungeResources');
  41. $this->secretKey = $config->get('URI.MungeSecretKey');
  42. if ($this->secretKey && !function_exists('hash_hmac')) {
  43. throw new Exception("Cannot use %URI.MungeSecretKey without hash_hmac support.");
  44. }
  45. return true;
  46. }
  47. /**
  48. * @param HTMLPurifier_URI $uri
  49. * @param HTMLPurifier_Config $config
  50. * @param HTMLPurifier_Context $context
  51. * @return bool
  52. */
  53. public function filter(&$uri, $config, $context)
  54. {
  55. if ($context->get('EmbeddedURI', true) && !$this->doEmbed) {
  56. return true;
  57. }
  58. $scheme_obj = $uri->getSchemeObj($config, $context);
  59. if (!$scheme_obj) {
  60. return true;
  61. } // ignore unknown schemes, maybe another postfilter did it
  62. if (!$scheme_obj->browsable) {
  63. return true;
  64. } // ignore non-browseable schemes, since we can't munge those in a reasonable way
  65. if ($uri->isBenign($config, $context)) {
  66. return true;
  67. } // don't redirect if a benign URL
  68. $this->makeReplace($uri, $config, $context);
  69. $this->replace = array_map('rawurlencode', $this->replace);
  70. $new_uri = strtr($this->target, $this->replace);
  71. $new_uri = $this->parser->parse($new_uri);
  72. // don't redirect if the target host is the same as the
  73. // starting host
  74. if ($uri->host === $new_uri->host) {
  75. return true;
  76. }
  77. $uri = $new_uri; // overwrite
  78. return true;
  79. }
  80. /**
  81. * @param HTMLPurifier_URI $uri
  82. * @param HTMLPurifier_Config $config
  83. * @param HTMLPurifier_Context $context
  84. */
  85. protected function makeReplace($uri, $config, $context)
  86. {
  87. $string = $uri->toString();
  88. // always available
  89. $this->replace['%s'] = $string;
  90. $this->replace['%r'] = $context->get('EmbeddedURI', true);
  91. $token = $context->get('CurrentToken', true);
  92. $this->replace['%n'] = $token ? $token->name : null;
  93. $this->replace['%m'] = $context->get('CurrentAttr', true);
  94. $this->replace['%p'] = $context->get('CurrentCSSProperty', true);
  95. // not always available
  96. if ($this->secretKey) {
  97. $this->replace['%t'] = hash_hmac("sha256", $string, $this->secretKey);
  98. }
  99. }
  100. }
  101. // vim: et sw=4 sts=4