~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

Viewing changes to lib/htmlpurifier/HTMLPurifier/Injector.php

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
 
3
 
/**
4
 
 * Injects tokens into the document while parsing for well-formedness.
5
 
 * This enables "formatter-like" functionality such as auto-paragraphing,
6
 
 * smiley-ification and linkification to take place.
7
 
 *
8
 
 * A note on how handlers create changes; this is done by assigning a new
9
 
 * value to the $token reference. These values can take a variety of forms and
10
 
 * are best described HTMLPurifier_Strategy_MakeWellFormed->processToken()
11
 
 * documentation.
12
 
 *
13
 
 * @todo Allow injectors to request a re-run on their output. This
14
 
 *       would help if an operation is recursive.
15
 
 */
16
 
abstract class HTMLPurifier_Injector
17
 
{
18
 
 
19
 
    /**
20
 
     * Advisory name of injector, this is for friendly error messages
21
 
     */
22
 
    public $name;
23
 
 
24
 
    /**
25
 
     * Instance of HTMLPurifier_HTMLDefinition
26
 
     */
27
 
    protected $htmlDefinition;
28
 
 
29
 
    /**
30
 
     * Reference to CurrentNesting variable in Context. This is an array
31
 
     * list of tokens that we are currently "inside"
32
 
     */
33
 
    protected $currentNesting;
34
 
 
35
 
    /**
36
 
     * Reference to InputTokens variable in Context. This is an array
37
 
     * list of the input tokens that are being processed.
38
 
     */
39
 
    protected $inputTokens;
40
 
 
41
 
    /**
42
 
     * Reference to InputIndex variable in Context. This is an integer
43
 
     * array index for $this->inputTokens that indicates what token
44
 
     * is currently being processed.
45
 
     */
46
 
    protected $inputIndex;
47
 
 
48
 
    /**
49
 
     * Array of elements and attributes this injector creates and therefore
50
 
     * need to be allowed by the definition. Takes form of
51
 
     * array('element' => array('attr', 'attr2'), 'element2')
52
 
     */
53
 
    public $needed = array();
54
 
 
55
 
    /**
56
 
     * Index of inputTokens to rewind to.
57
 
     */
58
 
    protected $rewind = false;
59
 
 
60
 
    /**
61
 
     * Rewind to a spot to re-perform processing. This is useful if you
62
 
     * deleted a node, and now need to see if this change affected any
63
 
     * earlier nodes. Rewinding does not affect other injectors, and can
64
 
     * result in infinite loops if not used carefully.
65
 
     * @warning HTML Purifier will prevent you from fast-forwarding with this
66
 
     *          function.
67
 
     */
68
 
    public function rewind($index) {
69
 
        $this->rewind = $index;
70
 
    }
71
 
 
72
 
    /**
73
 
     * Retrieves rewind, and then unsets it.
74
 
     */
75
 
    public function getRewind() {
76
 
        $r = $this->rewind;
77
 
        $this->rewind = false;
78
 
        return $r;
79
 
    }
80
 
 
81
 
    /**
82
 
     * Prepares the injector by giving it the config and context objects:
83
 
     * this allows references to important variables to be made within
84
 
     * the injector. This function also checks if the HTML environment
85
 
     * will work with the Injector (see checkNeeded()).
86
 
     * @param $config Instance of HTMLPurifier_Config
87
 
     * @param $context Instance of HTMLPurifier_Context
88
 
     * @return Boolean false if success, string of missing needed element/attribute if failure
89
 
     */
90
 
    public function prepare($config, $context) {
91
 
        $this->htmlDefinition = $config->getHTMLDefinition();
92
 
        // Even though this might fail, some unit tests ignore this and
93
 
        // still test checkNeeded, so be careful. Maybe get rid of that
94
 
        // dependency.
95
 
        $result = $this->checkNeeded($config);
96
 
        if ($result !== false) return $result;
97
 
        $this->currentNesting =& $context->get('CurrentNesting');
98
 
        $this->inputTokens    =& $context->get('InputTokens');
99
 
        $this->inputIndex     =& $context->get('InputIndex');
100
 
        return false;
101
 
    }
102
 
 
103
 
    /**
104
 
     * This function checks if the HTML environment
105
 
     * will work with the Injector: if p tags are not allowed, the
106
 
     * Auto-Paragraphing injector should not be enabled.
107
 
     * @param $config Instance of HTMLPurifier_Config
108
 
     * @param $context Instance of HTMLPurifier_Context
109
 
     * @return Boolean false if success, string of missing needed element/attribute if failure
110
 
     */
111
 
    public function checkNeeded($config) {
112
 
        $def = $config->getHTMLDefinition();
113
 
        foreach ($this->needed as $element => $attributes) {
114
 
            if (is_int($element)) $element = $attributes;
115
 
            if (!isset($def->info[$element])) return $element;
116
 
            if (!is_array($attributes)) continue;
117
 
            foreach ($attributes as $name) {
118
 
                if (!isset($def->info[$element]->attr[$name])) return "$element.$name";
119
 
            }
120
 
        }
121
 
        return false;
122
 
    }
123
 
 
124
 
    /**
125
 
     * Tests if the context node allows a certain element
126
 
     * @param $name Name of element to test for
127
 
     * @return True if element is allowed, false if it is not
128
 
     */
129
 
    public function allowsElement($name) {
130
 
        if (!empty($this->currentNesting)) {
131
 
            $parent_token = array_pop($this->currentNesting);
132
 
            $this->currentNesting[] = $parent_token;
133
 
            $parent = $this->htmlDefinition->info[$parent_token->name];
134
 
        } else {
135
 
            $parent = $this->htmlDefinition->info_parent_def;
136
 
        }
137
 
        if (!isset($parent->child->elements[$name]) || isset($parent->excludes[$name])) {
138
 
            return false;
139
 
        }
140
 
        // check for exclusion
141
 
        for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) {
142
 
            $node = $this->currentNesting[$i];
143
 
            $def  = $this->htmlDefinition->info[$node->name];
144
 
            if (isset($def->excludes[$name])) return false;
145
 
        }
146
 
        return true;
147
 
    }
148
 
 
149
 
    /**
150
 
     * Iterator function, which starts with the next token and continues until
151
 
     * you reach the end of the input tokens.
152
 
     * @warning Please prevent previous references from interfering with this
153
 
     *          functions by setting $i = null beforehand!
154
 
     * @param &$i Current integer index variable for inputTokens
155
 
     * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference
156
 
     */
157
 
    protected function forward(&$i, &$current) {
158
 
        if ($i === null) $i = $this->inputIndex + 1;
159
 
        else $i++;
160
 
        if (!isset($this->inputTokens[$i])) return false;
161
 
        $current = $this->inputTokens[$i];
162
 
        return true;
163
 
    }
164
 
 
165
 
    /**
166
 
     * Similar to _forward, but accepts a third parameter $nesting (which
167
 
     * should be initialized at 0) and stops when we hit the end tag
168
 
     * for the node $this->inputIndex starts in.
169
 
     */
170
 
    protected function forwardUntilEndToken(&$i, &$current, &$nesting) {
171
 
        $result = $this->forward($i, $current);
172
 
        if (!$result) return false;
173
 
        if ($nesting === null) $nesting = 0;
174
 
        if     ($current instanceof HTMLPurifier_Token_Start) $nesting++;
175
 
        elseif ($current instanceof HTMLPurifier_Token_End) {
176
 
            if ($nesting <= 0) return false;
177
 
            $nesting--;
178
 
        }
179
 
        return true;
180
 
    }
181
 
 
182
 
    /**
183
 
     * Iterator function, starts with the previous token and continues until
184
 
     * you reach the beginning of input tokens.
185
 
     * @warning Please prevent previous references from interfering with this
186
 
     *          functions by setting $i = null beforehand!
187
 
     * @param &$i Current integer index variable for inputTokens
188
 
     * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference
189
 
     */
190
 
    protected function backward(&$i, &$current) {
191
 
        if ($i === null) $i = $this->inputIndex - 1;
192
 
        else $i--;
193
 
        if ($i < 0) return false;
194
 
        $current = $this->inputTokens[$i];
195
 
        return true;
196
 
    }
197
 
 
198
 
    /**
199
 
     * Initializes the iterator at the current position. Use in a do {} while;
200
 
     * loop to force the _forward and _backward functions to start at the
201
 
     * current location.
202
 
     * @warning Please prevent previous references from interfering with this
203
 
     *          functions by setting $i = null beforehand!
204
 
     * @param &$i Current integer index variable for inputTokens
205
 
     * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference
206
 
     */
207
 
    protected function current(&$i, &$current) {
208
 
        if ($i === null) $i = $this->inputIndex;
209
 
        $current = $this->inputTokens[$i];
210
 
    }
211
 
 
212
 
    /**
213
 
     * Handler that is called when a text token is processed
214
 
     */
215
 
    public function handleText(&$token) {}
216
 
 
217
 
    /**
218
 
     * Handler that is called when a start or empty token is processed
219
 
     */
220
 
    public function handleElement(&$token) {}
221
 
 
222
 
    /**
223
 
     * Handler that is called when an end token is processed
224
 
     */
225
 
    public function handleEnd(&$token) {
226
 
        $this->notifyEnd($token);
227
 
    }
228
 
 
229
 
    /**
230
 
     * Notifier that is called when an end token is processed
231
 
     * @note This differs from handlers in that the token is read-only
232
 
     * @deprecated
233
 
     */
234
 
    public function notifyEnd($token) {}
235
 
 
236
 
 
237
 
}
238
 
 
239
 
// vim: et sw=4 sts=4
 
1
<?php
 
2
 
 
3
/**
 
4
 * Injects tokens into the document while parsing for well-formedness.
 
5
 * This enables "formatter-like" functionality such as auto-paragraphing,
 
6
 * smiley-ification and linkification to take place.
 
7
 *
 
8
 * A note on how handlers create changes; this is done by assigning a new
 
9
 * value to the $token reference. These values can take a variety of forms and
 
10
 * are best described HTMLPurifier_Strategy_MakeWellFormed->processToken()
 
11
 * documentation.
 
12
 *
 
13
 * @todo Allow injectors to request a re-run on their output. This
 
14
 *       would help if an operation is recursive.
 
15
 */
 
16
abstract class HTMLPurifier_Injector
 
17
{
 
18
 
 
19
    /**
 
20
     * Advisory name of injector, this is for friendly error messages.
 
21
     * @type string
 
22
     */
 
23
    public $name;
 
24
 
 
25
    /**
 
26
     * @type HTMLPurifier_HTMLDefinition
 
27
     */
 
28
    protected $htmlDefinition;
 
29
 
 
30
    /**
 
31
     * Reference to CurrentNesting variable in Context. This is an array
 
32
     * list of tokens that we are currently "inside"
 
33
     * @type array
 
34
     */
 
35
    protected $currentNesting;
 
36
 
 
37
    /**
 
38
     * Reference to current token.
 
39
     * @type HTMLPurifier_Token
 
40
     */
 
41
    protected $currentToken;
 
42
 
 
43
    /**
 
44
     * Reference to InputZipper variable in Context.
 
45
     * @type HTMLPurifier_Zipper
 
46
     */
 
47
    protected $inputZipper;
 
48
 
 
49
    /**
 
50
     * Array of elements and attributes this injector creates and therefore
 
51
     * need to be allowed by the definition. Takes form of
 
52
     * array('element' => array('attr', 'attr2'), 'element2')
 
53
     * @type array
 
54
     */
 
55
    public $needed = array();
 
56
 
 
57
    /**
 
58
     * Number of elements to rewind backwards (relative).
 
59
     * @type bool|int
 
60
     */
 
61
    protected $rewindOffset = false;
 
62
 
 
63
    /**
 
64
     * Rewind to a spot to re-perform processing. This is useful if you
 
65
     * deleted a node, and now need to see if this change affected any
 
66
     * earlier nodes. Rewinding does not affect other injectors, and can
 
67
     * result in infinite loops if not used carefully.
 
68
     * @param bool|int $offset
 
69
     * @warning HTML Purifier will prevent you from fast-forwarding with this
 
70
     *          function.
 
71
     */
 
72
    public function rewindOffset($offset)
 
73
    {
 
74
        $this->rewindOffset = $offset;
 
75
    }
 
76
 
 
77
    /**
 
78
     * Retrieves rewind offset, and then unsets it.
 
79
     * @return bool|int
 
80
     */
 
81
    public function getRewindOffset()
 
82
    {
 
83
        $r = $this->rewindOffset;
 
84
        $this->rewindOffset = false;
 
85
        return $r;
 
86
    }
 
87
 
 
88
    /**
 
89
     * Prepares the injector by giving it the config and context objects:
 
90
     * this allows references to important variables to be made within
 
91
     * the injector. This function also checks if the HTML environment
 
92
     * will work with the Injector (see checkNeeded()).
 
93
     * @param HTMLPurifier_Config $config
 
94
     * @param HTMLPurifier_Context $context
 
95
     * @return bool|string Boolean false if success, string of missing needed element/attribute if failure
 
96
     */
 
97
    public function prepare($config, $context)
 
98
    {
 
99
        $this->htmlDefinition = $config->getHTMLDefinition();
 
100
        // Even though this might fail, some unit tests ignore this and
 
101
        // still test checkNeeded, so be careful. Maybe get rid of that
 
102
        // dependency.
 
103
        $result = $this->checkNeeded($config);
 
104
        if ($result !== false) {
 
105
            return $result;
 
106
        }
 
107
        $this->currentNesting =& $context->get('CurrentNesting');
 
108
        $this->currentToken   =& $context->get('CurrentToken');
 
109
        $this->inputZipper    =& $context->get('InputZipper');
 
110
        return false;
 
111
    }
 
112
 
 
113
    /**
 
114
     * This function checks if the HTML environment
 
115
     * will work with the Injector: if p tags are not allowed, the
 
116
     * Auto-Paragraphing injector should not be enabled.
 
117
     * @param HTMLPurifier_Config $config
 
118
     * @return bool|string Boolean false if success, string of missing needed element/attribute if failure
 
119
     */
 
120
    public function checkNeeded($config)
 
121
    {
 
122
        $def = $config->getHTMLDefinition();
 
123
        foreach ($this->needed as $element => $attributes) {
 
124
            if (is_int($element)) {
 
125
                $element = $attributes;
 
126
            }
 
127
            if (!isset($def->info[$element])) {
 
128
                return $element;
 
129
            }
 
130
            if (!is_array($attributes)) {
 
131
                continue;
 
132
            }
 
133
            foreach ($attributes as $name) {
 
134
                if (!isset($def->info[$element]->attr[$name])) {
 
135
                    return "$element.$name";
 
136
                }
 
137
            }
 
138
        }
 
139
        return false;
 
140
    }
 
141
 
 
142
    /**
 
143
     * Tests if the context node allows a certain element
 
144
     * @param string $name Name of element to test for
 
145
     * @return bool True if element is allowed, false if it is not
 
146
     */
 
147
    public function allowsElement($name)
 
148
    {
 
149
        if (!empty($this->currentNesting)) {
 
150
            $parent_token = array_pop($this->currentNesting);
 
151
            $this->currentNesting[] = $parent_token;
 
152
            $parent = $this->htmlDefinition->info[$parent_token->name];
 
153
        } else {
 
154
            $parent = $this->htmlDefinition->info_parent_def;
 
155
        }
 
156
        if (!isset($parent->child->elements[$name]) || isset($parent->excludes[$name])) {
 
157
            return false;
 
158
        }
 
159
        // check for exclusion
 
160
        for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) {
 
161
            $node = $this->currentNesting[$i];
 
162
            $def  = $this->htmlDefinition->info[$node->name];
 
163
            if (isset($def->excludes[$name])) {
 
164
                return false;
 
165
            }
 
166
        }
 
167
        return true;
 
168
    }
 
169
 
 
170
    /**
 
171
     * Iterator function, which starts with the next token and continues until
 
172
     * you reach the end of the input tokens.
 
173
     * @warning Please prevent previous references from interfering with this
 
174
     *          functions by setting $i = null beforehand!
 
175
     * @param int $i Current integer index variable for inputTokens
 
176
     * @param HTMLPurifier_Token $current Current token variable.
 
177
     *          Do NOT use $token, as that variable is also a reference
 
178
     * @return bool
 
179
     */
 
180
    protected function forward(&$i, &$current)
 
181
    {
 
182
        if ($i === null) {
 
183
            $i = count($this->inputZipper->back) - 1;
 
184
        } else {
 
185
            $i--;
 
186
        }
 
187
        if ($i < 0) {
 
188
            return false;
 
189
        }
 
190
        $current = $this->inputZipper->back[$i];
 
191
        return true;
 
192
    }
 
193
 
 
194
    /**
 
195
     * Similar to _forward, but accepts a third parameter $nesting (which
 
196
     * should be initialized at 0) and stops when we hit the end tag
 
197
     * for the node $this->inputIndex starts in.
 
198
     * @param int $i Current integer index variable for inputTokens
 
199
     * @param HTMLPurifier_Token $current Current token variable.
 
200
     *          Do NOT use $token, as that variable is also a reference
 
201
     * @param int $nesting
 
202
     * @return bool
 
203
     */
 
204
    protected function forwardUntilEndToken(&$i, &$current, &$nesting)
 
205
    {
 
206
        $result = $this->forward($i, $current);
 
207
        if (!$result) {
 
208
            return false;
 
209
        }
 
210
        if ($nesting === null) {
 
211
            $nesting = 0;
 
212
        }
 
213
        if ($current instanceof HTMLPurifier_Token_Start) {
 
214
            $nesting++;
 
215
        } elseif ($current instanceof HTMLPurifier_Token_End) {
 
216
            if ($nesting <= 0) {
 
217
                return false;
 
218
            }
 
219
            $nesting--;
 
220
        }
 
221
        return true;
 
222
    }
 
223
 
 
224
    /**
 
225
     * Iterator function, starts with the previous token and continues until
 
226
     * you reach the beginning of input tokens.
 
227
     * @warning Please prevent previous references from interfering with this
 
228
     *          functions by setting $i = null beforehand!
 
229
     * @param int $i Current integer index variable for inputTokens
 
230
     * @param HTMLPurifier_Token $current Current token variable.
 
231
     *          Do NOT use $token, as that variable is also a reference
 
232
     * @return bool
 
233
     */
 
234
    protected function backward(&$i, &$current)
 
235
    {
 
236
        if ($i === null) {
 
237
            $i = count($this->inputZipper->front) - 1;
 
238
        } else {
 
239
            $i--;
 
240
        }
 
241
        if ($i < 0) {
 
242
            return false;
 
243
        }
 
244
        $current = $this->inputZipper->front[$i];
 
245
        return true;
 
246
    }
 
247
 
 
248
    /**
 
249
     * Handler that is called when a text token is processed
 
250
     */
 
251
    public function handleText(&$token)
 
252
    {
 
253
    }
 
254
 
 
255
    /**
 
256
     * Handler that is called when a start or empty token is processed
 
257
     */
 
258
    public function handleElement(&$token)
 
259
    {
 
260
    }
 
261
 
 
262
    /**
 
263
     * Handler that is called when an end token is processed
 
264
     */
 
265
    public function handleEnd(&$token)
 
266
    {
 
267
        $this->notifyEnd($token);
 
268
    }
 
269
 
 
270
    /**
 
271
     * Notifier that is called when an end token is processed
 
272
     * @param HTMLPurifier_Token $token Current token variable.
 
273
     * @note This differs from handlers in that the token is read-only
 
274
     * @deprecated
 
275
     */
 
276
    public function notifyEnd($token)
 
277
    {
 
278
    }
 
279
}
 
280
 
 
281
// vim: et sw=4 sts=4