Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
// does not support network paths
4
 
5
class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
6
{
7
    /**
8
     * @type string
9
     */
10
    public $name = 'MakeAbsolute';
11
 
12
    /**
13
     * @type
14
     */
15
    protected $base;
16
 
17
    /**
18
     * @type array
19
     */
20
    protected $basePathStack = array();
21
 
22
    /**
23
     * @param HTMLPurifier_Config $config
24
     * @return bool
25
     */
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
 
46
    /**
47
     * @param HTMLPurifier_URI $uri
48
     * @param HTMLPurifier_Config $config
49
     * @param HTMLPurifier_Context $context
50
     * @return bool
51
     */
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
 
112
    /**
113
     * Resolve dots and double-dots in a path stack
114
     * @param array $stack
115
     * @return array
116
     */
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