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