~fusonic/chive/1.1

« back to all changes in this revision

Viewing changes to yii/vendors/htmlpurifier/standalone/HTMLPurifier/ConfigSchema/Validator.php

  • Committer: Matthias Burtscher
  • Date: 2010-02-12 09:12:35 UTC
  • Revision ID: matthias.burtscher@fusonic.net-20100212091235-jqxrb62klx872ajc
* Updated Yii to 1.1.0
* Removed CodePress and CodeMirror
* Updated jQuery and some plugins
* Cleaned some code ...

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?php
2
 
 
3
 
/**
4
 
 * Performs validations on HTMLPurifier_ConfigSchema_Interchange
5
 
 *
6
 
 * @note If you see '// handled by InterchangeBuilder', that means a
7
 
 *       design decision in that class would prevent this validation from
8
 
 *       ever being necessary. We have them anyway, however, for
9
 
 *       redundancy.
10
 
 */
11
 
class HTMLPurifier_ConfigSchema_Validator
12
 
{
13
 
    
14
 
    /**
15
 
     * Easy to access global objects.
16
 
     */
17
 
    protected $interchange, $aliases;
18
 
    
19
 
    /**
20
 
     * Context-stack to provide easy to read error messages.
21
 
     */
22
 
    protected $context = array();
23
 
    
24
 
    /**
25
 
     * HTMLPurifier_VarParser to test default's type.
26
 
     */
27
 
    protected $parser;
28
 
    
29
 
    public function __construct() {
30
 
        $this->parser = new HTMLPurifier_VarParser();
31
 
    }
32
 
    
33
 
    /**
34
 
     * Validates a fully-formed interchange object. Throws an
35
 
     * HTMLPurifier_ConfigSchema_Exception if there's a problem.
36
 
     */
37
 
    public function validate($interchange) {
38
 
        $this->interchange = $interchange;
39
 
        $this->aliases = array();
40
 
        // PHP is a bit lax with integer <=> string conversions in
41
 
        // arrays, so we don't use the identical !== comparison
42
 
        foreach ($interchange->namespaces as $i => $namespace) {
43
 
            if ($i != $namespace->namespace) $this->error(false, "Integrity violation: key '$i' does not match internal id '{$namespace->namespace}'");
44
 
            $this->validateNamespace($namespace);
45
 
        }
46
 
        foreach ($interchange->directives as $i => $directive) {
47
 
            $id = $directive->id->toString();
48
 
            if ($i != $id) $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");
49
 
            $this->validateDirective($directive);
50
 
        }
51
 
        return true;
52
 
    }
53
 
    
54
 
    /**
55
 
     * Validates a HTMLPurifier_ConfigSchema_Interchange_Namespace object.
56
 
     */
57
 
    public function validateNamespace($n) {
58
 
        $this->context[] = "namespace '{$n->namespace}'";
59
 
        $this->with($n, 'namespace')
60
 
            ->assertNotEmpty()
61
 
            ->assertAlnum(); // implicit assertIsString handled by InterchangeBuilder
62
 
        $this->with($n, 'description')
63
 
            ->assertNotEmpty()
64
 
            ->assertIsString(); // handled by InterchangeBuilder
65
 
        array_pop($this->context);
66
 
    }
67
 
    
68
 
    /**
69
 
     * Validates a HTMLPurifier_ConfigSchema_Interchange_Id object.
70
 
     */
71
 
    public function validateId($id) {
72
 
        $id_string = $id->toString();
73
 
        $this->context[] = "id '$id_string'";
74
 
        if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) {
75
 
            // handled by InterchangeBuilder
76
 
            $this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id');
77
 
        }
78
 
        if (!isset($this->interchange->namespaces[$id->namespace])) {
79
 
            $this->error('namespace', 'does not exist'); // assumes that the namespace was validated already
80
 
        }
81
 
        $this->with($id, 'directive')
82
 
            ->assertNotEmpty()
83
 
            ->assertAlnum(); // implicit assertIsString handled by InterchangeBuilder
84
 
        array_pop($this->context);
85
 
    }
86
 
    
87
 
    /**
88
 
     * Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object.
89
 
     */
90
 
    public function validateDirective($d) {
91
 
        $id = $d->id->toString();
92
 
        $this->context[] = "directive '$id'";
93
 
        $this->validateId($d->id);
94
 
        
95
 
        $this->with($d, 'description')
96
 
            ->assertNotEmpty();
97
 
        
98
 
        // BEGIN - handled by InterchangeBuilder
99
 
        $this->with($d, 'type')
100
 
            ->assertNotEmpty();
101
 
        $this->with($d, 'typeAllowsNull')
102
 
            ->assertIsBool();
103
 
        try {
104
 
            // This also tests validity of $d->type
105
 
            $this->parser->parse($d->default, $d->type, $d->typeAllowsNull);
106
 
        } catch (HTMLPurifier_VarParserException $e) {
107
 
            $this->error('default', 'had error: ' . $e->getMessage());
108
 
        }
109
 
        // END - handled by InterchangeBuilder
110
 
        
111
 
        if (!is_null($d->allowed) || !empty($d->valueAliases)) {
112
 
            // allowed and valueAliases require that we be dealing with
113
 
            // strings, so check for that early.
114
 
            $d_int = HTMLPurifier_VarParser::$types[$d->type];
115
 
            if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) {
116
 
                $this->error('type', 'must be a string type when used with allowed or value aliases');
117
 
            }
118
 
        }
119
 
        
120
 
        $this->validateDirectiveAllowed($d);
121
 
        $this->validateDirectiveValueAliases($d);
122
 
        $this->validateDirectiveAliases($d);
123
 
        
124
 
        array_pop($this->context);
125
 
    }
126
 
    
127
 
    /**
128
 
     * Extra validation if $allowed member variable of
129
 
     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
130
 
     */
131
 
    public function validateDirectiveAllowed($d) {
132
 
        if (is_null($d->allowed)) return;
133
 
        $this->with($d, 'allowed')
134
 
            ->assertNotEmpty()
135
 
            ->assertIsLookup(); // handled by InterchangeBuilder
136
 
        if (is_string($d->default) && !isset($d->allowed[$d->default])) {
137
 
            $this->error('default', 'must be an allowed value');
138
 
        }
139
 
        $this->context[] = 'allowed';
140
 
        foreach ($d->allowed as $val => $x) {
141
 
            if (!is_string($val)) $this->error("value $val", 'must be a string');
142
 
        }
143
 
        array_pop($this->context);
144
 
    }
145
 
    
146
 
    /**
147
 
     * Extra validation if $valueAliases member variable of
148
 
     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
149
 
     */
150
 
    public function validateDirectiveValueAliases($d) {
151
 
        if (is_null($d->valueAliases)) return;
152
 
        $this->with($d, 'valueAliases')
153
 
            ->assertIsArray(); // handled by InterchangeBuilder
154
 
        $this->context[] = 'valueAliases';
155
 
        foreach ($d->valueAliases as $alias => $real) {
156
 
            if (!is_string($alias)) $this->error("alias $alias", 'must be a string');
157
 
            if (!is_string($real))  $this->error("alias target $real from alias '$alias'",  'must be a string');
158
 
            if ($alias === $real) {
159
 
                $this->error("alias '$alias'", "must not be an alias to itself");
160
 
            }
161
 
        }
162
 
        if (!is_null($d->allowed)) {
163
 
            foreach ($d->valueAliases as $alias => $real) {
164
 
                if (isset($d->allowed[$alias])) {
165
 
                    $this->error("alias '$alias'", 'must not be an allowed value');
166
 
                } elseif (!isset($d->allowed[$real])) {
167
 
                    $this->error("alias '$alias'", 'must be an alias to an allowed value');
168
 
                }
169
 
            }
170
 
        }
171
 
        array_pop($this->context);
172
 
    }
173
 
    
174
 
    /**
175
 
     * Extra validation if $aliases member variable of
176
 
     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
177
 
     */
178
 
    public function validateDirectiveAliases($d) {
179
 
        $this->with($d, 'aliases')
180
 
            ->assertIsArray(); // handled by InterchangeBuilder
181
 
        $this->context[] = 'aliases';
182
 
        foreach ($d->aliases as $alias) {
183
 
            $this->validateId($alias);
184
 
            $s = $alias->toString();
185
 
            if (isset($this->interchange->directives[$s])) {
186
 
                $this->error("alias '$s'", 'collides with another directive');
187
 
            }
188
 
            if (isset($this->aliases[$s])) {
189
 
                $other_directive = $this->aliases[$s];
190
 
                $this->error("alias '$s'", "collides with alias for directive '$other_directive'");
191
 
            }
192
 
            $this->aliases[$s] = $d->id->toString();
193
 
        }
194
 
        array_pop($this->context);
195
 
    }
196
 
    
197
 
    // protected helper functions
198
 
    
199
 
    /**
200
 
     * Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom
201
 
     * for validating simple member variables of objects.
202
 
     */
203
 
    protected function with($obj, $member) {
204
 
        return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member);
205
 
    }
206
 
    
207
 
    /**
208
 
     * Emits an error, providing helpful context.
209
 
     */
210
 
    protected function error($target, $msg) {
211
 
        if ($target !== false) $prefix = ucfirst($target) . ' in ' .  $this->getFormattedContext();
212
 
        else $prefix = ucfirst($this->getFormattedContext());
213
 
        throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg));
214
 
    }
215
 
    
216
 
    /**
217
 
     * Returns a formatted context string.
218
 
     */
219
 
    protected function getFormattedContext() {
220
 
        return implode(' in ', array_reverse($this->context));
221
 
    }
222
 
    
223
 
}
 
1
<?php
 
2
 
 
3
/**
 
4
 * Performs validations on HTMLPurifier_ConfigSchema_Interchange
 
5
 *
 
6
 * @note If you see '// handled by InterchangeBuilder', that means a
 
7
 *       design decision in that class would prevent this validation from
 
8
 *       ever being necessary. We have them anyway, however, for
 
9
 *       redundancy.
 
10
 */
 
11
class HTMLPurifier_ConfigSchema_Validator
 
12
{
 
13
 
 
14
    /**
 
15
     * Easy to access global objects.
 
16
     */
 
17
    protected $interchange, $aliases;
 
18
 
 
19
    /**
 
20
     * Context-stack to provide easy to read error messages.
 
21
     */
 
22
    protected $context = array();
 
23
 
 
24
    /**
 
25
     * HTMLPurifier_VarParser to test default's type.
 
26
     */
 
27
    protected $parser;
 
28
 
 
29
    public function __construct() {
 
30
        $this->parser = new HTMLPurifier_VarParser();
 
31
    }
 
32
 
 
33
    /**
 
34
     * Validates a fully-formed interchange object. Throws an
 
35
     * HTMLPurifier_ConfigSchema_Exception if there's a problem.
 
36
     */
 
37
    public function validate($interchange) {
 
38
        $this->interchange = $interchange;
 
39
        $this->aliases = array();
 
40
        // PHP is a bit lax with integer <=> string conversions in
 
41
        // arrays, so we don't use the identical !== comparison
 
42
        foreach ($interchange->directives as $i => $directive) {
 
43
            $id = $directive->id->toString();
 
44
            if ($i != $id) $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");
 
45
            $this->validateDirective($directive);
 
46
        }
 
47
        return true;
 
48
    }
 
49
 
 
50
    /**
 
51
     * Validates a HTMLPurifier_ConfigSchema_Interchange_Id object.
 
52
     */
 
53
    public function validateId($id) {
 
54
        $id_string = $id->toString();
 
55
        $this->context[] = "id '$id_string'";
 
56
        if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) {
 
57
            // handled by InterchangeBuilder
 
58
            $this->error(false, 'is not an instance of HTMLPurifier_ConfigSchema_Interchange_Id');
 
59
        }
 
60
        // keys are now unconstrained (we might want to narrow down to A-Za-z0-9.)
 
61
        // we probably should check that it has at least one namespace
 
62
        $this->with($id, 'key')
 
63
            ->assertNotEmpty()
 
64
            ->assertIsString(); // implicit assertIsString handled by InterchangeBuilder
 
65
        array_pop($this->context);
 
66
    }
 
67
 
 
68
    /**
 
69
     * Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object.
 
70
     */
 
71
    public function validateDirective($d) {
 
72
        $id = $d->id->toString();
 
73
        $this->context[] = "directive '$id'";
 
74
        $this->validateId($d->id);
 
75
 
 
76
        $this->with($d, 'description')
 
77
            ->assertNotEmpty();
 
78
 
 
79
        // BEGIN - handled by InterchangeBuilder
 
80
        $this->with($d, 'type')
 
81
            ->assertNotEmpty();
 
82
        $this->with($d, 'typeAllowsNull')
 
83
            ->assertIsBool();
 
84
        try {
 
85
            // This also tests validity of $d->type
 
86
            $this->parser->parse($d->default, $d->type, $d->typeAllowsNull);
 
87
        } catch (HTMLPurifier_VarParserException $e) {
 
88
            $this->error('default', 'had error: ' . $e->getMessage());
 
89
        }
 
90
        // END - handled by InterchangeBuilder
 
91
 
 
92
        if (!is_null($d->allowed) || !empty($d->valueAliases)) {
 
93
            // allowed and valueAliases require that we be dealing with
 
94
            // strings, so check for that early.
 
95
            $d_int = HTMLPurifier_VarParser::$types[$d->type];
 
96
            if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) {
 
97
                $this->error('type', 'must be a string type when used with allowed or value aliases');
 
98
            }
 
99
        }
 
100
 
 
101
        $this->validateDirectiveAllowed($d);
 
102
        $this->validateDirectiveValueAliases($d);
 
103
        $this->validateDirectiveAliases($d);
 
104
 
 
105
        array_pop($this->context);
 
106
    }
 
107
 
 
108
    /**
 
109
     * Extra validation if $allowed member variable of
 
110
     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
 
111
     */
 
112
    public function validateDirectiveAllowed($d) {
 
113
        if (is_null($d->allowed)) return;
 
114
        $this->with($d, 'allowed')
 
115
            ->assertNotEmpty()
 
116
            ->assertIsLookup(); // handled by InterchangeBuilder
 
117
        if (is_string($d->default) && !isset($d->allowed[$d->default])) {
 
118
            $this->error('default', 'must be an allowed value');
 
119
        }
 
120
        $this->context[] = 'allowed';
 
121
        foreach ($d->allowed as $val => $x) {
 
122
            if (!is_string($val)) $this->error("value $val", 'must be a string');
 
123
        }
 
124
        array_pop($this->context);
 
125
    }
 
126
 
 
127
    /**
 
128
     * Extra validation if $valueAliases member variable of
 
129
     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
 
130
     */
 
131
    public function validateDirectiveValueAliases($d) {
 
132
        if (is_null($d->valueAliases)) return;
 
133
        $this->with($d, 'valueAliases')
 
134
            ->assertIsArray(); // handled by InterchangeBuilder
 
135
        $this->context[] = 'valueAliases';
 
136
        foreach ($d->valueAliases as $alias => $real) {
 
137
            if (!is_string($alias)) $this->error("alias $alias", 'must be a string');
 
138
            if (!is_string($real))  $this->error("alias target $real from alias '$alias'",  'must be a string');
 
139
            if ($alias === $real) {
 
140
                $this->error("alias '$alias'", "must not be an alias to itself");
 
141
            }
 
142
        }
 
143
        if (!is_null($d->allowed)) {
 
144
            foreach ($d->valueAliases as $alias => $real) {
 
145
                if (isset($d->allowed[$alias])) {
 
146
                    $this->error("alias '$alias'", 'must not be an allowed value');
 
147
                } elseif (!isset($d->allowed[$real])) {
 
148
                    $this->error("alias '$alias'", 'must be an alias to an allowed value');
 
149
                }
 
150
            }
 
151
        }
 
152
        array_pop($this->context);
 
153
    }
 
154
 
 
155
    /**
 
156
     * Extra validation if $aliases member variable of
 
157
     * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
 
158
     */
 
159
    public function validateDirectiveAliases($d) {
 
160
        $this->with($d, 'aliases')
 
161
            ->assertIsArray(); // handled by InterchangeBuilder
 
162
        $this->context[] = 'aliases';
 
163
        foreach ($d->aliases as $alias) {
 
164
            $this->validateId($alias);
 
165
            $s = $alias->toString();
 
166
            if (isset($this->interchange->directives[$s])) {
 
167
                $this->error("alias '$s'", 'collides with another directive');
 
168
            }
 
169
            if (isset($this->aliases[$s])) {
 
170
                $other_directive = $this->aliases[$s];
 
171
                $this->error("alias '$s'", "collides with alias for directive '$other_directive'");
 
172
            }
 
173
            $this->aliases[$s] = $d->id->toString();
 
174
        }
 
175
        array_pop($this->context);
 
176
    }
 
177
 
 
178
    // protected helper functions
 
179
 
 
180
    /**
 
181
     * Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom
 
182
     * for validating simple member variables of objects.
 
183
     */
 
184
    protected function with($obj, $member) {
 
185
        return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member);
 
186
    }
 
187
 
 
188
    /**
 
189
     * Emits an error, providing helpful context.
 
190
     */
 
191
    protected function error($target, $msg) {
 
192
        if ($target !== false) $prefix = ucfirst($target) . ' in ' .  $this->getFormattedContext();
 
193
        else $prefix = ucfirst($this->getFormattedContext());
 
194
        throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg));
 
195
    }
 
196
 
 
197
    /**
 
198
     * Returns a formatted context string.
 
199
     */
 
200
    protected function getFormattedContext() {
 
201
        return implode(' in ', array_reverse($this->context));
 
202
    }
 
203
 
 
204
}
 
205
 
 
206
// vim: et sw=4 sts=4