~horux-dev/horux-webcli/thfo

« back to all changes in this revision

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

  • Committer: Thierry Forchelet
  • Date: 2011-02-25 13:30:15 UTC
  • Revision ID: thierry.forchelet@letux.ch-20110225133015-zxyj9w7sqv8ly971
Initial commit

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->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