4ba45610feb9c3aaa172dccab1e7c3e4fa83786d
[yaffs-website] / vendor / ezyang / htmlpurifier / library / HTMLPurifier / AttrDef / HTML / ID.php
1 <?php
2
3 /**
4  * Validates the HTML attribute ID.
5  * @warning Even though this is the id processor, it
6  *          will ignore the directive Attr:IDBlacklist, since it will only
7  *          go according to the ID accumulator. Since the accumulator is
8  *          automatically generated, it will have already absorbed the
9  *          blacklist. If you're hacking around, make sure you use load()!
10  */
11
12 class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
13 {
14
15     // selector is NOT a valid thing to use for IDREFs, because IDREFs
16     // *must* target IDs that exist, whereas selector #ids do not.
17
18     /**
19      * Determines whether or not we're validating an ID in a CSS
20      * selector context.
21      * @type bool
22      */
23     protected $selector;
24
25     /**
26      * @param bool $selector
27      */
28     public function __construct($selector = false)
29     {
30         $this->selector = $selector;
31     }
32
33     /**
34      * @param string $id
35      * @param HTMLPurifier_Config $config
36      * @param HTMLPurifier_Context $context
37      * @return bool|string
38      */
39     public function validate($id, $config, $context)
40     {
41         if (!$this->selector && !$config->get('Attr.EnableID')) {
42             return false;
43         }
44
45         $id = trim($id); // trim it first
46
47         if ($id === '') {
48             return false;
49         }
50
51         $prefix = $config->get('Attr.IDPrefix');
52         if ($prefix !== '') {
53             $prefix .= $config->get('Attr.IDPrefixLocal');
54             // prevent re-appending the prefix
55             if (strpos($id, $prefix) !== 0) {
56                 $id = $prefix . $id;
57             }
58         } elseif ($config->get('Attr.IDPrefixLocal') !== '') {
59             trigger_error(
60                 '%Attr.IDPrefixLocal cannot be used unless ' .
61                 '%Attr.IDPrefix is set',
62                 E_USER_WARNING
63             );
64         }
65
66         if (!$this->selector) {
67             $id_accumulator =& $context->get('IDAccumulator');
68             if (isset($id_accumulator->ids[$id])) {
69                 return false;
70             }
71         }
72
73         // we purposely avoid using regex, hopefully this is faster
74
75         if ($config->get('Attr.ID.HTML5') === true) {
76             if (preg_match('/[\t\n\x0b\x0c ]/', $id)) {
77                 return false;
78             }
79         } else {
80             if (ctype_alpha($id)) {
81                 // OK
82             } else {
83                 if (!ctype_alpha(@$id[0])) {
84                     return false;
85                 }
86                 // primitive style of regexps, I suppose
87                 $trim = trim(
88                     $id,
89                     'A..Za..z0..9:-._'
90                 );
91                 if ($trim !== '') {
92                     return false;
93                 }
94             }
95         }
96
97         $regexp = $config->get('Attr.IDBlacklistRegexp');
98         if ($regexp && preg_match($regexp, $id)) {
99             return false;
100         }
101
102         if (!$this->selector) {
103             $id_accumulator->add($id);
104         }
105
106         // if no change was made to the ID, return the result
107         // else, return the new id if stripping whitespace made it
108         //     valid, or return false.
109         return $id;
110     }
111 }
112
113 // vim: et sw=4 sts=4