aboutsummaryrefslogtreecommitdiffhomepage
path: root/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef
diff options
context:
space:
mode:
authorNicolas Lœuillet <nicolas.loeuillet@gmail.com>2014-02-21 15:43:14 +0100
committerNicolas Lœuillet <nicolas.loeuillet@gmail.com>2014-02-21 15:43:14 +0100
commitd4949327efa15b492cab1bef3fe074290a328a17 (patch)
treee89e0322bb1f1b06d663fd10fdded21bac867e5d /inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef
parentc9bd17a1007bb78e5de0775efca01df0fb515031 (diff)
downloadwallabag-d4949327efa15b492cab1bef3fe074290a328a17.tar.gz
wallabag-d4949327efa15b492cab1bef3fe074290a328a17.tar.zst
wallabag-d4949327efa15b492cab1bef3fe074290a328a17.zip
[add] HTML Purifier added to clean code
Diffstat (limited to 'inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef')
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS.php106
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/AlphaValue.php34
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Background.php111
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php157
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Border.php56
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Color.php105
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Composite.php48
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php44
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Filter.php77
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Font.php176
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php219
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Ident.php32
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php56
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Length.php77
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ListStyle.php112
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Multiple.php71
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Number.php84
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Percentage.php54
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/TextDecoration.php46
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/URI.php74
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Clone.php44
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Enum.php73
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Bool.php51
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Class.php48
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Color.php51
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php38
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/ID.php105
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Length.php56
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php72
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/MultiLength.php60
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php70
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Pixels.php76
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Integer.php91
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Lang.php86
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Switch.php53
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Text.php21
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI.php111
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email.php20
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php29
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Host.php128
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv4.php45
-rw-r--r--inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv6.php89
42 files changed, 3156 insertions, 0 deletions
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS.php
new file mode 100644
index 00000000..81afcf96
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS.php
@@ -0,0 +1,106 @@
1<?php
2
3/**
4 * Validates the HTML attribute style, otherwise known as CSS.
5 * @note We don't implement the whole CSS specification, so it might be
6 * difficult to reuse this component in the context of validating
7 * actual stylesheet declarations.
8 * @note If we were really serious about validating the CSS, we would
9 * tokenize the styles and then parse the tokens. Obviously, we
10 * are not doing that. Doing that could seriously harm performance,
11 * but would make these components a lot more viable for a CSS
12 * filtering solution.
13 */
14class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
15{
16
17 /**
18 * @param string $css
19 * @param HTMLPurifier_Config $config
20 * @param HTMLPurifier_Context $context
21 * @return bool|string
22 */
23 public function validate($css, $config, $context)
24 {
25 $css = $this->parseCDATA($css);
26
27 $definition = $config->getCSSDefinition();
28
29 // we're going to break the spec and explode by semicolons.
30 // This is because semicolon rarely appears in escaped form
31 // Doing this is generally flaky but fast
32 // IT MIGHT APPEAR IN URIs, see HTMLPurifier_AttrDef_CSSURI
33 // for details
34
35 $declarations = explode(';', $css);
36 $propvalues = array();
37
38 /**
39 * Name of the current CSS property being validated.
40 */
41 $property = false;
42 $context->register('CurrentCSSProperty', $property);
43
44 foreach ($declarations as $declaration) {
45 if (!$declaration) {
46 continue;
47 }
48 if (!strpos($declaration, ':')) {
49 continue;
50 }
51 list($property, $value) = explode(':', $declaration, 2);
52 $property = trim($property);
53 $value = trim($value);
54 $ok = false;
55 do {
56 if (isset($definition->info[$property])) {
57 $ok = true;
58 break;
59 }
60 if (ctype_lower($property)) {
61 break;
62 }
63 $property = strtolower($property);
64 if (isset($definition->info[$property])) {
65 $ok = true;
66 break;
67 }
68 } while (0);
69 if (!$ok) {
70 continue;
71 }
72 // inefficient call, since the validator will do this again
73 if (strtolower(trim($value)) !== 'inherit') {
74 // inherit works for everything (but only on the base property)
75 $result = $definition->info[$property]->validate(
76 $value,
77 $config,
78 $context
79 );
80 } else {
81 $result = 'inherit';
82 }
83 if ($result === false) {
84 continue;
85 }
86 $propvalues[$property] = $result;
87 }
88
89 $context->destroy('CurrentCSSProperty');
90
91 // procedure does not write the new CSS simultaneously, so it's
92 // slightly inefficient, but it's the only way of getting rid of
93 // duplicates. Perhaps config to optimize it, but not now.
94
95 $new_declarations = '';
96 foreach ($propvalues as $prop => $value) {
97 $new_declarations .= "$prop:$value;";
98 }
99
100 return $new_declarations ? $new_declarations : false;
101
102 }
103
104}
105
106// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/AlphaValue.php
new file mode 100644
index 00000000..1a30e8fe
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/AlphaValue.php
@@ -0,0 +1,34 @@
1<?php
2
3class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
4{
5
6 public function __construct()
7 {
8 parent::__construct(false); // opacity is non-negative, but we will clamp it
9 }
10
11 /**
12 * @param string $number
13 * @param HTMLPurifier_Config $config
14 * @param HTMLPurifier_Context $context
15 * @return string
16 */
17 public function validate($number, $config, $context)
18 {
19 $result = parent::validate($number, $config, $context);
20 if ($result === false) {
21 return $result;
22 }
23 $float = (float)$result;
24 if ($float < 0.0) {
25 $result = '0';
26 }
27 if ($float > 1.0) {
28 $result = '1';
29 }
30 return $result;
31 }
32}
33
34// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Background.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Background.php
new file mode 100644
index 00000000..ecd6e276
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Background.php
@@ -0,0 +1,111 @@
1<?php
2
3/**
4 * Validates shorthand CSS property background.
5 * @warning Does not support url tokens that have internal spaces.
6 */
7class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
8{
9
10 /**
11 * Local copy of component validators.
12 * @type HTMLPurifier_AttrDef[]
13 * @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
14 */
15 protected $info;
16
17 /**
18 * @param HTMLPurifier_Config $config
19 */
20 public function __construct($config)
21 {
22 $def = $config->getCSSDefinition();
23 $this->info['background-color'] = $def->info['background-color'];
24 $this->info['background-image'] = $def->info['background-image'];
25 $this->info['background-repeat'] = $def->info['background-repeat'];
26 $this->info['background-attachment'] = $def->info['background-attachment'];
27 $this->info['background-position'] = $def->info['background-position'];
28 }
29
30 /**
31 * @param string $string
32 * @param HTMLPurifier_Config $config
33 * @param HTMLPurifier_Context $context
34 * @return bool|string
35 */
36 public function validate($string, $config, $context)
37 {
38 // regular pre-processing
39 $string = $this->parseCDATA($string);
40 if ($string === '') {
41 return false;
42 }
43
44 // munge rgb() decl if necessary
45 $string = $this->mungeRgb($string);
46
47 // assumes URI doesn't have spaces in it
48 $bits = explode(' ', $string); // bits to process
49
50 $caught = array();
51 $caught['color'] = false;
52 $caught['image'] = false;
53 $caught['repeat'] = false;
54 $caught['attachment'] = false;
55 $caught['position'] = false;
56
57 $i = 0; // number of catches
58
59 foreach ($bits as $bit) {
60 if ($bit === '') {
61 continue;
62 }
63 foreach ($caught as $key => $status) {
64 if ($key != 'position') {
65 if ($status !== false) {
66 continue;
67 }
68 $r = $this->info['background-' . $key]->validate($bit, $config, $context);
69 } else {
70 $r = $bit;
71 }
72 if ($r === false) {
73 continue;
74 }
75 if ($key == 'position') {
76 if ($caught[$key] === false) {
77 $caught[$key] = '';
78 }
79 $caught[$key] .= $r . ' ';
80 } else {
81 $caught[$key] = $r;
82 }
83 $i++;
84 break;
85 }
86 }
87
88 if (!$i) {
89 return false;
90 }
91 if ($caught['position'] !== false) {
92 $caught['position'] = $this->info['background-position']->
93 validate($caught['position'], $config, $context);
94 }
95
96 $ret = array();
97 foreach ($caught as $value) {
98 if ($value === false) {
99 continue;
100 }
101 $ret[] = $value;
102 }
103
104 if (empty($ret)) {
105 return false;
106 }
107 return implode(' ', $ret);
108 }
109}
110
111// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
new file mode 100644
index 00000000..f95de5bb
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
@@ -0,0 +1,157 @@
1<?php
2
3/* W3C says:
4 [ // adjective and number must be in correct order, even if
5 // you could switch them without introducing ambiguity.
6 // some browsers support that syntax
7 [
8 <percentage> | <length> | left | center | right
9 ]
10 [
11 <percentage> | <length> | top | center | bottom
12 ]?
13 ] |
14 [ // this signifies that the vertical and horizontal adjectives
15 // can be arbitrarily ordered, however, there can only be two,
16 // one of each, or none at all
17 [
18 left | center | right
19 ] ||
20 [
21 top | center | bottom
22 ]
23 ]
24 top, left = 0%
25 center, (none) = 50%
26 bottom, right = 100%
27*/
28
29/* QuirksMode says:
30 keyword + length/percentage must be ordered correctly, as per W3C
31
32 Internet Explorer and Opera, however, support arbitrary ordering. We
33 should fix it up.
34
35 Minor issue though, not strictly necessary.
36*/
37
38// control freaks may appreciate the ability to convert these to
39// percentages or something, but it's not necessary
40
41/**
42 * Validates the value of background-position.
43 */
44class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
45{
46
47 /**
48 * @type HTMLPurifier_AttrDef_CSS_Length
49 */
50 protected $length;
51
52 /**
53 * @type HTMLPurifier_AttrDef_CSS_Percentage
54 */
55 protected $percentage;
56
57 public function __construct()
58 {
59 $this->length = new HTMLPurifier_AttrDef_CSS_Length();
60 $this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
61 }
62
63 /**
64 * @param string $string
65 * @param HTMLPurifier_Config $config
66 * @param HTMLPurifier_Context $context
67 * @return bool|string
68 */
69 public function validate($string, $config, $context)
70 {
71 $string = $this->parseCDATA($string);
72 $bits = explode(' ', $string);
73
74 $keywords = array();
75 $keywords['h'] = false; // left, right
76 $keywords['v'] = false; // top, bottom
77 $keywords['ch'] = false; // center (first word)
78 $keywords['cv'] = false; // center (second word)
79 $measures = array();
80
81 $i = 0;
82
83 $lookup = array(
84 'top' => 'v',
85 'bottom' => 'v',
86 'left' => 'h',
87 'right' => 'h',
88 'center' => 'c'
89 );
90
91 foreach ($bits as $bit) {
92 if ($bit === '') {
93 continue;
94 }
95
96 // test for keyword
97 $lbit = ctype_lower($bit) ? $bit : strtolower($bit);
98 if (isset($lookup[$lbit])) {
99 $status = $lookup[$lbit];
100 if ($status == 'c') {
101 if ($i == 0) {
102 $status = 'ch';
103 } else {
104 $status = 'cv';
105 }
106 }
107 $keywords[$status] = $lbit;
108 $i++;
109 }
110
111 // test for length
112 $r = $this->length->validate($bit, $config, $context);
113 if ($r !== false) {
114 $measures[] = $r;
115 $i++;
116 }
117
118 // test for percentage
119 $r = $this->percentage->validate($bit, $config, $context);
120 if ($r !== false) {
121 $measures[] = $r;
122 $i++;
123 }
124 }
125
126 if (!$i) {
127 return false;
128 } // no valid values were caught
129
130 $ret = array();
131
132 // first keyword
133 if ($keywords['h']) {
134 $ret[] = $keywords['h'];
135 } elseif ($keywords['ch']) {
136 $ret[] = $keywords['ch'];
137 $keywords['cv'] = false; // prevent re-use: center = center center
138 } elseif (count($measures)) {
139 $ret[] = array_shift($measures);
140 }
141
142 if ($keywords['v']) {
143 $ret[] = $keywords['v'];
144 } elseif ($keywords['cv']) {
145 $ret[] = $keywords['cv'];
146 } elseif (count($measures)) {
147 $ret[] = array_shift($measures);
148 }
149
150 if (empty($ret)) {
151 return false;
152 }
153 return implode(' ', $ret);
154 }
155}
156
157// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Border.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Border.php
new file mode 100644
index 00000000..bd310ff2
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Border.php
@@ -0,0 +1,56 @@
1<?php
2
3/**
4 * Validates the border property as defined by CSS.
5 */
6class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * Local copy of properties this property is shorthand for.
11 * @type HTMLPurifier_AttrDef[]
12 */
13 protected $info = array();
14
15 /**
16 * @param HTMLPurifier_Config $config
17 */
18 public function __construct($config)
19 {
20 $def = $config->getCSSDefinition();
21 $this->info['border-width'] = $def->info['border-width'];
22 $this->info['border-style'] = $def->info['border-style'];
23 $this->info['border-top-color'] = $def->info['border-top-color'];
24 }
25
26 /**
27 * @param string $string
28 * @param HTMLPurifier_Config $config
29 * @param HTMLPurifier_Context $context
30 * @return bool|string
31 */
32 public function validate($string, $config, $context)
33 {
34 $string = $this->parseCDATA($string);
35 $string = $this->mungeRgb($string);
36 $bits = explode(' ', $string);
37 $done = array(); // segments we've finished
38 $ret = ''; // return value
39 foreach ($bits as $bit) {
40 foreach ($this->info as $propname => $validator) {
41 if (isset($done[$propname])) {
42 continue;
43 }
44 $r = $validator->validate($bit, $config, $context);
45 if ($r !== false) {
46 $ret .= $r . ' ';
47 $done[$propname] = true;
48 break;
49 }
50 }
51 }
52 return rtrim($ret);
53 }
54}
55
56// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Color.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Color.php
new file mode 100644
index 00000000..e553c65e
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Color.php
@@ -0,0 +1,105 @@
1<?php
2
3/**
4 * Validates Color as defined by CSS.
5 */
6class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @param string $color
11 * @param HTMLPurifier_Config $config
12 * @param HTMLPurifier_Context $context
13 * @return bool|string
14 */
15 public function validate($color, $config, $context)
16 {
17 static $colors = null;
18 if ($colors === null) {
19 $colors = $config->get('Core.ColorKeywords');
20 }
21
22 $color = trim($color);
23 if ($color === '') {
24 return false;
25 }
26
27 $lower = strtolower($color);
28 if (isset($colors[$lower])) {
29 return $colors[$lower];
30 }
31
32 if (strpos($color, 'rgb(') !== false) {
33 // rgb literal handling
34 $length = strlen($color);
35 if (strpos($color, ')') !== $length - 1) {
36 return false;
37 }
38 $triad = substr($color, 4, $length - 4 - 1);
39 $parts = explode(',', $triad);
40 if (count($parts) !== 3) {
41 return false;
42 }
43 $type = false; // to ensure that they're all the same type
44 $new_parts = array();
45 foreach ($parts as $part) {
46 $part = trim($part);
47 if ($part === '') {
48 return false;
49 }
50 $length = strlen($part);
51 if ($part[$length - 1] === '%') {
52 // handle percents
53 if (!$type) {
54 $type = 'percentage';
55 } elseif ($type !== 'percentage') {
56 return false;
57 }
58 $num = (float)substr($part, 0, $length - 1);
59 if ($num < 0) {
60 $num = 0;
61 }
62 if ($num > 100) {
63 $num = 100;
64 }
65 $new_parts[] = "$num%";
66 } else {
67 // handle integers
68 if (!$type) {
69 $type = 'integer';
70 } elseif ($type !== 'integer') {
71 return false;
72 }
73 $num = (int)$part;
74 if ($num < 0) {
75 $num = 0;
76 }
77 if ($num > 255) {
78 $num = 255;
79 }
80 $new_parts[] = (string)$num;
81 }
82 }
83 $new_triad = implode(',', $new_parts);
84 $color = "rgb($new_triad)";
85 } else {
86 // hexadecimal handling
87 if ($color[0] === '#') {
88 $hex = substr($color, 1);
89 } else {
90 $hex = $color;
91 $color = '#' . $color;
92 }
93 $length = strlen($hex);
94 if ($length !== 3 && $length !== 6) {
95 return false;
96 }
97 if (!ctype_xdigit($hex)) {
98 return false;
99 }
100 }
101 return $color;
102 }
103}
104
105// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Composite.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Composite.php
new file mode 100644
index 00000000..38900232
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Composite.php
@@ -0,0 +1,48 @@
1<?php
2
3/**
4 * Allows multiple validators to attempt to validate attribute.
5 *
6 * Composite is just what it sounds like: a composite of many validators.
7 * This means that multiple HTMLPurifier_AttrDef objects will have a whack
8 * at the string. If one of them passes, that's what is returned. This is
9 * especially useful for CSS values, which often are a choice between
10 * an enumerated set of predefined values or a flexible data type.
11 */
12class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
13{
14
15 /**
16 * List of objects that may process strings.
17 * @type HTMLPurifier_AttrDef[]
18 * @todo Make protected
19 */
20 public $defs;
21
22 /**
23 * @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects
24 */
25 public function __construct($defs)
26 {
27 $this->defs = $defs;
28 }
29
30 /**
31 * @param string $string
32 * @param HTMLPurifier_Config $config
33 * @param HTMLPurifier_Context $context
34 * @return bool|string
35 */
36 public function validate($string, $config, $context)
37 {
38 foreach ($this->defs as $i => $def) {
39 $result = $this->defs[$i]->validate($string, $config, $context);
40 if ($result !== false) {
41 return $result;
42 }
43 }
44 return false;
45 }
46}
47
48// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
new file mode 100644
index 00000000..ff0d897e
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
@@ -0,0 +1,44 @@
1<?php
2
3/**
4 * Decorator which enables CSS properties to be disabled for specific elements.
5 */
6class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
7{
8 /**
9 * @type HTMLPurifier_AttrDef
10 */
11 public $def;
12 /**
13 * @type string
14 */
15 public $element;
16
17 /**
18 * @param HTMLPurifier_AttrDef $def Definition to wrap
19 * @param string $element Element to deny
20 */
21 public function __construct($def, $element)
22 {
23 $this->def = $def;
24 $this->element = $element;
25 }
26
27 /**
28 * Checks if CurrentToken is set and equal to $this->element
29 * @param string $string
30 * @param HTMLPurifier_Config $config
31 * @param HTMLPurifier_Context $context
32 * @return bool|string
33 */
34 public function validate($string, $config, $context)
35 {
36 $token = $context->get('CurrentToken', true);
37 if ($token && $token->name == $this->element) {
38 return false;
39 }
40 return $this->def->validate($string, $config, $context);
41 }
42}
43
44// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Filter.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Filter.php
new file mode 100644
index 00000000..019722a4
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Filter.php
@@ -0,0 +1,77 @@
1<?php
2
3/**
4 * Microsoft's proprietary filter: CSS property
5 * @note Currently supports the alpha filter. In the future, this will
6 * probably need an extensible framework
7 */
8class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
9{
10 /**
11 * @type HTMLPurifier_AttrDef_Integer
12 */
13 protected $intValidator;
14
15 public function __construct()
16 {
17 $this->intValidator = new HTMLPurifier_AttrDef_Integer();
18 }
19
20 /**
21 * @param string $value
22 * @param HTMLPurifier_Config $config
23 * @param HTMLPurifier_Context $context
24 * @return bool|string
25 */
26 public function validate($value, $config, $context)
27 {
28 $value = $this->parseCDATA($value);
29 if ($value === 'none') {
30 return $value;
31 }
32 // if we looped this we could support multiple filters
33 $function_length = strcspn($value, '(');
34 $function = trim(substr($value, 0, $function_length));
35 if ($function !== 'alpha' &&
36 $function !== 'Alpha' &&
37 $function !== 'progid:DXImageTransform.Microsoft.Alpha'
38 ) {
39 return false;
40 }
41 $cursor = $function_length + 1;
42 $parameters_length = strcspn($value, ')', $cursor);
43 $parameters = substr($value, $cursor, $parameters_length);
44 $params = explode(',', $parameters);
45 $ret_params = array();
46 $lookup = array();
47 foreach ($params as $param) {
48 list($key, $value) = explode('=', $param);
49 $key = trim($key);
50 $value = trim($value);
51 if (isset($lookup[$key])) {
52 continue;
53 }
54 if ($key !== 'opacity') {
55 continue;
56 }
57 $value = $this->intValidator->validate($value, $config, $context);
58 if ($value === false) {
59 continue;
60 }
61 $int = (int)$value;
62 if ($int > 100) {
63 $value = '100';
64 }
65 if ($int < 0) {
66 $value = '0';
67 }
68 $ret_params[] = "$key=$value";
69 $lookup[$key] = true;
70 }
71 $ret_parameters = implode(',', $ret_params);
72 $ret_function = "$function($ret_parameters)";
73 return $ret_function;
74 }
75}
76
77// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Font.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Font.php
new file mode 100644
index 00000000..b9b63f8e
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Font.php
@@ -0,0 +1,176 @@
1<?php
2
3/**
4 * Validates shorthand CSS property font.
5 */
6class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * Local copy of validators
11 * @type HTMLPurifier_AttrDef[]
12 * @note If we moved specific CSS property definitions to their own
13 * classes instead of having them be assembled at run time by
14 * CSSDefinition, this wouldn't be necessary. We'd instantiate
15 * our own copies.
16 */
17 protected $info = array();
18
19 /**
20 * @param HTMLPurifier_Config $config
21 */
22 public function __construct($config)
23 {
24 $def = $config->getCSSDefinition();
25 $this->info['font-style'] = $def->info['font-style'];
26 $this->info['font-variant'] = $def->info['font-variant'];
27 $this->info['font-weight'] = $def->info['font-weight'];
28 $this->info['font-size'] = $def->info['font-size'];
29 $this->info['line-height'] = $def->info['line-height'];
30 $this->info['font-family'] = $def->info['font-family'];
31 }
32
33 /**
34 * @param string $string
35 * @param HTMLPurifier_Config $config
36 * @param HTMLPurifier_Context $context
37 * @return bool|string
38 */
39 public function validate($string, $config, $context)
40 {
41 static $system_fonts = array(
42 'caption' => true,
43 'icon' => true,
44 'menu' => true,
45 'message-box' => true,
46 'small-caption' => true,
47 'status-bar' => true
48 );
49
50 // regular pre-processing
51 $string = $this->parseCDATA($string);
52 if ($string === '') {
53 return false;
54 }
55
56 // check if it's one of the keywords
57 $lowercase_string = strtolower($string);
58 if (isset($system_fonts[$lowercase_string])) {
59 return $lowercase_string;
60 }
61
62 $bits = explode(' ', $string); // bits to process
63 $stage = 0; // this indicates what we're looking for
64 $caught = array(); // which stage 0 properties have we caught?
65 $stage_1 = array('font-style', 'font-variant', 'font-weight');
66 $final = ''; // output
67
68 for ($i = 0, $size = count($bits); $i < $size; $i++) {
69 if ($bits[$i] === '') {
70 continue;
71 }
72 switch ($stage) {
73 case 0: // attempting to catch font-style, font-variant or font-weight
74 foreach ($stage_1 as $validator_name) {
75 if (isset($caught[$validator_name])) {
76 continue;
77 }
78 $r = $this->info[$validator_name]->validate(
79 $bits[$i],
80 $config,
81 $context
82 );
83 if ($r !== false) {
84 $final .= $r . ' ';
85 $caught[$validator_name] = true;
86 break;
87 }
88 }
89 // all three caught, continue on
90 if (count($caught) >= 3) {
91 $stage = 1;
92 }
93 if ($r !== false) {
94 break;
95 }
96 case 1: // attempting to catch font-size and perhaps line-height
97 $found_slash = false;
98 if (strpos($bits[$i], '/') !== false) {
99 list($font_size, $line_height) =
100 explode('/', $bits[$i]);
101 if ($line_height === '') {
102 // ooh, there's a space after the slash!
103 $line_height = false;
104 $found_slash = true;
105 }
106 } else {
107 $font_size = $bits[$i];
108 $line_height = false;
109 }
110 $r = $this->info['font-size']->validate(
111 $font_size,
112 $config,
113 $context
114 );
115 if ($r !== false) {
116 $final .= $r;
117 // attempt to catch line-height
118 if ($line_height === false) {
119 // we need to scroll forward
120 for ($j = $i + 1; $j < $size; $j++) {
121 if ($bits[$j] === '') {
122 continue;
123 }
124 if ($bits[$j] === '/') {
125 if ($found_slash) {
126 return false;
127 } else {
128 $found_slash = true;
129 continue;
130 }
131 }
132 $line_height = $bits[$j];
133 break;
134 }
135 } else {
136 // slash already found
137 $found_slash = true;
138 $j = $i;
139 }
140 if ($found_slash) {
141 $i = $j;
142 $r = $this->info['line-height']->validate(
143 $line_height,
144 $config,
145 $context
146 );
147 if ($r !== false) {
148 $final .= '/' . $r;
149 }
150 }
151 $final .= ' ';
152 $stage = 2;
153 break;
154 }
155 return false;
156 case 2: // attempting to catch font-family
157 $font_family =
158 implode(' ', array_slice($bits, $i, $size - $i));
159 $r = $this->info['font-family']->validate(
160 $font_family,
161 $config,
162 $context
163 );
164 if ($r !== false) {
165 $final .= $r . ' ';
166 // processing completed successfully
167 return rtrim($final);
168 }
169 return false;
170 }
171 }
172 return false;
173 }
174}
175
176// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php
new file mode 100644
index 00000000..f9af36d7
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/FontFamily.php
@@ -0,0 +1,219 @@
1<?php
2
3/**
4 * Validates a font family list according to CSS spec
5 */
6class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
7{
8
9 protected $mask = null;
10
11 public function __construct()
12 {
13 $this->mask = '_- ';
14 for ($c = 'a'; $c <= 'z'; $c++) {
15 $this->mask .= $c;
16 }
17 for ($c = 'A'; $c <= 'Z'; $c++) {
18 $this->mask .= $c;
19 }
20 for ($c = '0'; $c <= '9'; $c++) {
21 $this->mask .= $c;
22 } // cast-y, but should be fine
23 // special bytes used by UTF-8
24 for ($i = 0x80; $i <= 0xFF; $i++) {
25 // We don't bother excluding invalid bytes in this range,
26 // because the our restriction of well-formed UTF-8 will
27 // prevent these from ever occurring.
28 $this->mask .= chr($i);
29 }
30
31 /*
32 PHP's internal strcspn implementation is
33 O(length of string * length of mask), making it inefficient
34 for large masks. However, it's still faster than
35 preg_match 8)
36 for (p = s1;;) {
37 spanp = s2;
38 do {
39 if (*spanp == c || p == s1_end) {
40 return p - s1;
41 }
42 } while (spanp++ < (s2_end - 1));
43 c = *++p;
44 }
45 */
46 // possible optimization: invert the mask.
47 }
48
49 /**
50 * @param string $string
51 * @param HTMLPurifier_Config $config
52 * @param HTMLPurifier_Context $context
53 * @return bool|string
54 */
55 public function validate($string, $config, $context)
56 {
57 static $generic_names = array(
58 'serif' => true,
59 'sans-serif' => true,
60 'monospace' => true,
61 'fantasy' => true,
62 'cursive' => true
63 );
64 $allowed_fonts = $config->get('CSS.AllowedFonts');
65
66 // assume that no font names contain commas in them
67 $fonts = explode(',', $string);
68 $final = '';
69 foreach ($fonts as $font) {
70 $font = trim($font);
71 if ($font === '') {
72 continue;
73 }
74 // match a generic name
75 if (isset($generic_names[$font])) {
76 if ($allowed_fonts === null || isset($allowed_fonts[$font])) {
77 $final .= $font . ', ';
78 }
79 continue;
80 }
81 // match a quoted name
82 if ($font[0] === '"' || $font[0] === "'") {
83 $length = strlen($font);
84 if ($length <= 2) {
85 continue;
86 }
87 $quote = $font[0];
88 if ($font[$length - 1] !== $quote) {
89 continue;
90 }
91 $font = substr($font, 1, $length - 2);
92 }
93
94 $font = $this->expandCSSEscape($font);
95
96 // $font is a pure representation of the font name
97
98 if ($allowed_fonts !== null && !isset($allowed_fonts[$font])) {
99 continue;
100 }
101
102 if (ctype_alnum($font) && $font !== '') {
103 // very simple font, allow it in unharmed
104 $final .= $font . ', ';
105 continue;
106 }
107
108 // bugger out on whitespace. form feed (0C) really
109 // shouldn't show up regardless
110 $font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
111
112 // Here, there are various classes of characters which need
113 // to be treated differently:
114 // - Alphanumeric characters are essentially safe. We
115 // handled these above.
116 // - Spaces require quoting, though most parsers will do
117 // the right thing if there aren't any characters that
118 // can be misinterpreted
119 // - Dashes rarely occur, but they fairly unproblematic
120 // for parsing/rendering purposes.
121 // The above characters cover the majority of Western font
122 // names.
123 // - Arbitrary Unicode characters not in ASCII. Because
124 // most parsers give little thought to Unicode, treatment
125 // of these codepoints is basically uniform, even for
126 // punctuation-like codepoints. These characters can
127 // show up in non-Western pages and are supported by most
128 // major browsers, for example: "MS 明朝" is a
129 // legitimate font-name
130 // <http://ja.wikipedia.org/wiki/MS_明朝>. See
131 // the CSS3 spec for more examples:
132 // <http://www.w3.org/TR/2011/WD-css3-fonts-20110324/localizedfamilynames.png>
133 // You can see live samples of these on the Internet:
134 // <http://www.google.co.jp/search?q=font-family+MS+明朝|ゴシック>
135 // However, most of these fonts have ASCII equivalents:
136 // for example, 'MS Mincho', and it's considered
137 // professional to use ASCII font names instead of
138 // Unicode font names. Thanks Takeshi Terada for
139 // providing this information.
140 // The following characters, to my knowledge, have not been
141 // used to name font names.
142 // - Single quote. While theoretically you might find a
143 // font name that has a single quote in its name (serving
144 // as an apostrophe, e.g. Dave's Scribble), I haven't
145 // been able to find any actual examples of this.
146 // Internet Explorer's cssText translation (which I
147 // believe is invoked by innerHTML) normalizes any
148 // quoting to single quotes, and fails to escape single
149 // quotes. (Note that this is not IE's behavior for all
150 // CSS properties, just some sort of special casing for
151 // font-family). So a single quote *cannot* be used
152 // safely in the font-family context if there will be an
153 // innerHTML/cssText translation. Note that Firefox 3.x
154 // does this too.
155 // - Double quote. In IE, these get normalized to
156 // single-quotes, no matter what the encoding. (Fun
157 // fact, in IE8, the 'content' CSS property gained
158 // support, where they special cased to preserve encoded
159 // double quotes, but still translate unadorned double
160 // quotes into single quotes.) So, because their
161 // fixpoint behavior is identical to single quotes, they
162 // cannot be allowed either. Firefox 3.x displays
163 // single-quote style behavior.
164 // - Backslashes are reduced by one (so \\ -> \) every
165 // iteration, so they cannot be used safely. This shows
166 // up in IE7, IE8 and FF3
167 // - Semicolons, commas and backticks are handled properly.
168 // - The rest of the ASCII punctuation is handled properly.
169 // We haven't checked what browsers do to unadorned
170 // versions, but this is not important as long as the
171 // browser doesn't /remove/ surrounding quotes (as IE does
172 // for HTML).
173 //
174 // With these results in hand, we conclude that there are
175 // various levels of safety:
176 // - Paranoid: alphanumeric, spaces and dashes(?)
177 // - International: Paranoid + non-ASCII Unicode
178 // - Edgy: Everything except quotes, backslashes
179 // - NoJS: Standards compliance, e.g. sod IE. Note that
180 // with some judicious character escaping (since certain
181 // types of escaping doesn't work) this is theoretically
182 // OK as long as innerHTML/cssText is not called.
183 // We believe that international is a reasonable default
184 // (that we will implement now), and once we do more
185 // extensive research, we may feel comfortable with dropping
186 // it down to edgy.
187
188 // Edgy: alphanumeric, spaces, dashes, underscores and Unicode. Use of
189 // str(c)spn assumes that the string was already well formed
190 // Unicode (which of course it is).
191 if (strspn($font, $this->mask) !== strlen($font)) {
192 continue;
193 }
194
195 // Historical:
196 // In the absence of innerHTML/cssText, these ugly
197 // transforms don't pose a security risk (as \\ and \"
198 // might--these escapes are not supported by most browsers).
199 // We could try to be clever and use single-quote wrapping
200 // when there is a double quote present, but I have choosen
201 // not to implement that. (NOTE: you can reduce the amount
202 // of escapes by one depending on what quoting style you use)
203 // $font = str_replace('\\', '\\5C ', $font);
204 // $font = str_replace('"', '\\22 ', $font);
205 // $font = str_replace("'", '\\27 ', $font);
206
207 // font possibly with spaces, requires quoting
208 $final .= "'$font', ";
209 }
210 $final = rtrim($final, ', ');
211 if ($final === '') {
212 return false;
213 }
214 return $final;
215 }
216
217}
218
219// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Ident.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Ident.php
new file mode 100644
index 00000000..5f13edfd
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Ident.php
@@ -0,0 +1,32 @@
1<?php
2
3/**
4 * Validates based on {ident} CSS grammar production
5 */
6class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @param string $string
11 * @param HTMLPurifier_Config $config
12 * @param HTMLPurifier_Context $context
13 * @return bool|string
14 */
15 public function validate($string, $config, $context)
16 {
17 $string = trim($string);
18
19 // early abort: '' and '0' (strings that convert to false) are invalid
20 if (!$string) {
21 return false;
22 }
23
24 $pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
25 if (!preg_match($pattern, $string)) {
26 return false;
27 }
28 return $string;
29 }
30}
31
32// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
new file mode 100644
index 00000000..f4848494
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
@@ -0,0 +1,56 @@
1<?php
2
3/**
4 * Decorator which enables !important to be used in CSS values.
5 */
6class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
7{
8 /**
9 * @type HTMLPurifier_AttrDef
10 */
11 public $def;
12 /**
13 * @type bool
14 */
15 public $allow;
16
17 /**
18 * @param HTMLPurifier_AttrDef $def Definition to wrap
19 * @param bool $allow Whether or not to allow !important
20 */
21 public function __construct($def, $allow = false)
22 {
23 $this->def = $def;
24 $this->allow = $allow;
25 }
26
27 /**
28 * Intercepts and removes !important if necessary
29 * @param string $string
30 * @param HTMLPurifier_Config $config
31 * @param HTMLPurifier_Context $context
32 * @return bool|string
33 */
34 public function validate($string, $config, $context)
35 {
36 // test for ! and important tokens
37 $string = trim($string);
38 $is_important = false;
39 // :TODO: optimization: test directly for !important and ! important
40 if (strlen($string) >= 9 && substr($string, -9) === 'important') {
41 $temp = rtrim(substr($string, 0, -9));
42 // use a temp, because we might want to restore important
43 if (strlen($temp) >= 1 && substr($temp, -1) === '!') {
44 $string = rtrim(substr($temp, 0, -1));
45 $is_important = true;
46 }
47 }
48 $string = $this->def->validate($string, $config, $context);
49 if ($this->allow && $is_important) {
50 $string .= ' !important';
51 }
52 return $string;
53 }
54}
55
56// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Length.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Length.php
new file mode 100644
index 00000000..88da41d9
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Length.php
@@ -0,0 +1,77 @@
1<?php
2
3/**
4 * Represents a Length as defined by CSS.
5 */
6class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @type HTMLPurifier_Length|string
11 */
12 protected $min;
13
14 /**
15 * @type HTMLPurifier_Length|string
16 */
17 protected $max;
18
19 /**
20 * @param HTMLPurifier_Length|string $min Minimum length, or null for no bound. String is also acceptable.
21 * @param HTMLPurifier_Length|string $max Maximum length, or null for no bound. String is also acceptable.
22 */
23 public function __construct($min = null, $max = null)
24 {
25 $this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
26 $this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
27 }
28
29 /**
30 * @param string $string
31 * @param HTMLPurifier_Config $config
32 * @param HTMLPurifier_Context $context
33 * @return bool|string
34 */
35 public function validate($string, $config, $context)
36 {
37 $string = $this->parseCDATA($string);
38
39 // Optimizations
40 if ($string === '') {
41 return false;
42 }
43 if ($string === '0') {
44 return '0';
45 }
46 if (strlen($string) === 1) {
47 return false;
48 }
49
50 $length = HTMLPurifier_Length::make($string);
51 if (!$length->isValid()) {
52 return false;
53 }
54
55 if ($this->min) {
56 $c = $length->compareTo($this->min);
57 if ($c === false) {
58 return false;
59 }
60 if ($c < 0) {
61 return false;
62 }
63 }
64 if ($this->max) {
65 $c = $length->compareTo($this->max);
66 if ($c === false) {
67 return false;
68 }
69 if ($c > 0) {
70 return false;
71 }
72 }
73 return $length->toString();
74 }
75}
76
77// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ListStyle.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ListStyle.php
new file mode 100644
index 00000000..b4cce9a9
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/ListStyle.php
@@ -0,0 +1,112 @@
1<?php
2
3/**
4 * Validates shorthand CSS property list-style.
5 * @warning Does not support url tokens that have internal spaces.
6 */
7class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
8{
9
10 /**
11 * Local copy of validators.
12 * @type HTMLPurifier_AttrDef[]
13 * @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
14 */
15 protected $info;
16
17 /**
18 * @param HTMLPurifier_Config $config
19 */
20 public function __construct($config)
21 {
22 $def = $config->getCSSDefinition();
23 $this->info['list-style-type'] = $def->info['list-style-type'];
24 $this->info['list-style-position'] = $def->info['list-style-position'];
25 $this->info['list-style-image'] = $def->info['list-style-image'];
26 }
27
28 /**
29 * @param string $string
30 * @param HTMLPurifier_Config $config
31 * @param HTMLPurifier_Context $context
32 * @return bool|string
33 */
34 public function validate($string, $config, $context)
35 {
36 // regular pre-processing
37 $string = $this->parseCDATA($string);
38 if ($string === '') {
39 return false;
40 }
41
42 // assumes URI doesn't have spaces in it
43 $bits = explode(' ', strtolower($string)); // bits to process
44
45 $caught = array();
46 $caught['type'] = false;
47 $caught['position'] = false;
48 $caught['image'] = false;
49
50 $i = 0; // number of catches
51 $none = false;
52
53 foreach ($bits as $bit) {
54 if ($i >= 3) {
55 return;
56 } // optimization bit
57 if ($bit === '') {
58 continue;
59 }
60 foreach ($caught as $key => $status) {
61 if ($status !== false) {
62 continue;
63 }
64 $r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
65 if ($r === false) {
66 continue;
67 }
68 if ($r === 'none') {
69 if ($none) {
70 continue;
71 } else {
72 $none = true;
73 }
74 if ($key == 'image') {
75 continue;
76 }
77 }
78 $caught[$key] = $r;
79 $i++;
80 break;
81 }
82 }
83
84 if (!$i) {
85 return false;
86 }
87
88 $ret = array();
89
90 // construct type
91 if ($caught['type']) {
92 $ret[] = $caught['type'];
93 }
94
95 // construct image
96 if ($caught['image']) {
97 $ret[] = $caught['image'];
98 }
99
100 // construct position
101 if ($caught['position']) {
102 $ret[] = $caught['position'];
103 }
104
105 if (empty($ret)) {
106 return false;
107 }
108 return implode(' ', $ret);
109 }
110}
111
112// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Multiple.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Multiple.php
new file mode 100644
index 00000000..73d586f2
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Multiple.php
@@ -0,0 +1,71 @@
1<?php
2
3/**
4 * Framework class for strings that involve multiple values.
5 *
6 * Certain CSS properties such as border-width and margin allow multiple
7 * lengths to be specified. This class can take a vanilla border-width
8 * definition and multiply it, usually into a max of four.
9 *
10 * @note Even though the CSS specification isn't clear about it, inherit
11 * can only be used alone: it will never manifest as part of a multi
12 * shorthand declaration. Thus, this class does not allow inherit.
13 */
14class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
15{
16 /**
17 * Instance of component definition to defer validation to.
18 * @type HTMLPurifier_AttrDef
19 * @todo Make protected
20 */
21 public $single;
22
23 /**
24 * Max number of values allowed.
25 * @todo Make protected
26 */
27 public $max;
28
29 /**
30 * @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply
31 * @param int $max Max number of values allowed (usually four)
32 */
33 public function __construct($single, $max = 4)
34 {
35 $this->single = $single;
36 $this->max = $max;
37 }
38
39 /**
40 * @param string $string
41 * @param HTMLPurifier_Config $config
42 * @param HTMLPurifier_Context $context
43 * @return bool|string
44 */
45 public function validate($string, $config, $context)
46 {
47 $string = $this->parseCDATA($string);
48 if ($string === '') {
49 return false;
50 }
51 $parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
52 $length = count($parts);
53 $final = '';
54 for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
55 if (ctype_space($parts[$i])) {
56 continue;
57 }
58 $result = $this->single->validate($parts[$i], $config, $context);
59 if ($result !== false) {
60 $final .= $result . ' ';
61 $num++;
62 }
63 }
64 if ($final === '') {
65 return false;
66 }
67 return rtrim($final);
68 }
69}
70
71// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Number.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Number.php
new file mode 100644
index 00000000..c78f6c9d
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Number.php
@@ -0,0 +1,84 @@
1<?php
2
3/**
4 * Validates a number as defined by the CSS spec.
5 */
6class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * Indicates whether or not only positive values are allowed.
11 * @type bool
12 */
13 protected $non_negative = false;
14
15 /**
16 * @param bool $non_negative indicates whether negatives are forbidden
17 */
18 public function __construct($non_negative = false)
19 {
20 $this->non_negative = $non_negative;
21 }
22
23 /**
24 * @param string $number
25 * @param HTMLPurifier_Config $config
26 * @param HTMLPurifier_Context $context
27 * @return string|bool
28 * @warning Some contexts do not pass $config, $context. These
29 * variables should not be used without checking HTMLPurifier_Length
30 */
31 public function validate($number, $config, $context)
32 {
33 $number = $this->parseCDATA($number);
34
35 if ($number === '') {
36 return false;
37 }
38 if ($number === '0') {
39 return '0';
40 }
41
42 $sign = '';
43 switch ($number[0]) {
44 case '-':
45 if ($this->non_negative) {
46 return false;
47 }
48 $sign = '-';
49 case '+':
50 $number = substr($number, 1);
51 }
52
53 if (ctype_digit($number)) {
54 $number = ltrim($number, '0');
55 return $number ? $sign . $number : '0';
56 }
57
58 // Period is the only non-numeric character allowed
59 if (strpos($number, '.') === false) {
60 return false;
61 }
62
63 list($left, $right) = explode('.', $number, 2);
64
65 if ($left === '' && $right === '') {
66 return false;
67 }
68 if ($left !== '' && !ctype_digit($left)) {
69 return false;
70 }
71
72 $left = ltrim($left, '0');
73 $right = rtrim($right, '0');
74
75 if ($right === '') {
76 return $left ? $sign . $left : '0';
77 } elseif (!ctype_digit($right)) {
78 return false;
79 }
80 return $sign . $left . '.' . $right;
81 }
82}
83
84// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Percentage.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Percentage.php
new file mode 100644
index 00000000..aac1a6f5
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/Percentage.php
@@ -0,0 +1,54 @@
1<?php
2
3/**
4 * Validates a Percentage as defined by the CSS spec.
5 */
6class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * Instance to defer number validation to.
11 * @type HTMLPurifier_AttrDef_CSS_Number
12 */
13 protected $number_def;
14
15 /**
16 * @param bool $non_negative Whether to forbid negative values
17 */
18 public function __construct($non_negative = false)
19 {
20 $this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
21 }
22
23 /**
24 * @param string $string
25 * @param HTMLPurifier_Config $config
26 * @param HTMLPurifier_Context $context
27 * @return bool|string
28 */
29 public function validate($string, $config, $context)
30 {
31 $string = $this->parseCDATA($string);
32
33 if ($string === '') {
34 return false;
35 }
36 $length = strlen($string);
37 if ($length === 1) {
38 return false;
39 }
40 if ($string[$length - 1] !== '%') {
41 return false;
42 }
43
44 $number = substr($string, 0, $length - 1);
45 $number = $this->number_def->validate($number, $config, $context);
46
47 if ($number === false) {
48 return false;
49 }
50 return "$number%";
51 }
52}
53
54// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/TextDecoration.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/TextDecoration.php
new file mode 100644
index 00000000..3992de0e
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/TextDecoration.php
@@ -0,0 +1,46 @@
1<?php
2
3/**
4 * Validates the value for the CSS property text-decoration
5 * @note This class could be generalized into a version that acts sort of
6 * like Enum except you can compound the allowed values.
7 */
8class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
9{
10
11 /**
12 * @param string $string
13 * @param HTMLPurifier_Config $config
14 * @param HTMLPurifier_Context $context
15 * @return bool|string
16 */
17 public function validate($string, $config, $context)
18 {
19 static $allowed_values = array(
20 'line-through' => true,
21 'overline' => true,
22 'underline' => true,
23 );
24
25 $string = strtolower($this->parseCDATA($string));
26
27 if ($string === 'none') {
28 return $string;
29 }
30
31 $parts = explode(' ', $string);
32 $final = '';
33 foreach ($parts as $part) {
34 if (isset($allowed_values[$part])) {
35 $final .= $part . ' ';
36 }
37 }
38 $final = rtrim($final);
39 if ($final === '') {
40 return false;
41 }
42 return $final;
43 }
44}
45
46// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/URI.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/URI.php
new file mode 100644
index 00000000..482b0997
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/CSS/URI.php
@@ -0,0 +1,74 @@
1<?php
2
3/**
4 * Validates a URI in CSS syntax, which uses url('http://example.com')
5 * @note While theoretically speaking a URI in a CSS document could
6 * be non-embedded, as of CSS2 there is no such usage so we're
7 * generalizing it. This may need to be changed in the future.
8 * @warning Since HTMLPurifier_AttrDef_CSS blindly uses semicolons as
9 * the separator, you cannot put a literal semicolon in
10 * in the URI. Try percent encoding it, in that case.
11 */
12class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
13{
14
15 public function __construct()
16 {
17 parent::__construct(true); // always embedded
18 }
19
20 /**
21 * @param string $uri_string
22 * @param HTMLPurifier_Config $config
23 * @param HTMLPurifier_Context $context
24 * @return bool|string
25 */
26 public function validate($uri_string, $config, $context)
27 {
28 // parse the URI out of the string and then pass it onto
29 // the parent object
30
31 $uri_string = $this->parseCDATA($uri_string);
32 if (strpos($uri_string, 'url(') !== 0) {
33 return false;
34 }
35 $uri_string = substr($uri_string, 4);
36 $new_length = strlen($uri_string) - 1;
37 if ($uri_string[$new_length] != ')') {
38 return false;
39 }
40 $uri = trim(substr($uri_string, 0, $new_length));
41
42 if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
43 $quote = $uri[0];
44 $new_length = strlen($uri) - 1;
45 if ($uri[$new_length] !== $quote) {
46 return false;
47 }
48 $uri = substr($uri, 1, $new_length - 1);
49 }
50
51 $uri = $this->expandCSSEscape($uri);
52
53 $result = parent::validate($uri, $config, $context);
54
55 if ($result === false) {
56 return false;
57 }
58
59 // extra sanity check; should have been done by URI
60 $result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
61
62 // suspicious characters are ()'; we're going to percent encode
63 // them for safety.
64 $result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result);
65
66 // there's an extra bug where ampersands lose their escaping on
67 // an innerHTML cycle, so a very unlucky query parameter could
68 // then change the meaning of the URL. Unfortunately, there's
69 // not much we can do about that...
70 return "url(\"$result\")";
71 }
72}
73
74// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Clone.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Clone.php
new file mode 100644
index 00000000..b181d1bc
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Clone.php
@@ -0,0 +1,44 @@
1<?php
2
3/**
4 * Dummy AttrDef that mimics another AttrDef, BUT it generates clones
5 * with make.
6 */
7class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
8{
9 /**
10 * What we're cloning.
11 * @type HTMLPurifier_AttrDef
12 */
13 protected $clone;
14
15 /**
16 * @param HTMLPurifier_AttrDef $clone
17 */
18 public function __construct($clone)
19 {
20 $this->clone = $clone;
21 }
22
23 /**
24 * @param string $v
25 * @param HTMLPurifier_Config $config
26 * @param HTMLPurifier_Context $context
27 * @return bool|string
28 */
29 public function validate($v, $config, $context)
30 {
31 return $this->clone->validate($v, $config, $context);
32 }
33
34 /**
35 * @param string $string
36 * @return HTMLPurifier_AttrDef
37 */
38 public function make($string)
39 {
40 return clone $this->clone;
41 }
42}
43
44// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Enum.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Enum.php
new file mode 100644
index 00000000..b40122b6
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Enum.php
@@ -0,0 +1,73 @@
1<?php
2
3// Enum = Enumerated
4/**
5 * Validates a keyword against a list of valid values.
6 * @warning The case-insensitive compare of this function uses PHP's
7 * built-in strtolower and ctype_lower functions, which may
8 * cause problems with international comparisons
9 */
10class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
11{
12
13 /**
14 * Lookup table of valid values.
15 * @type array
16 * @todo Make protected
17 */
18 public $valid_values = array();
19
20 /**
21 * Bool indicating whether or not enumeration is case sensitive.
22 * @note In general this is always case insensitive.
23 */
24 protected $case_sensitive = false; // values according to W3C spec
25
26 /**
27 * @param array $valid_values List of valid values
28 * @param bool $case_sensitive Whether or not case sensitive
29 */
30 public function __construct($valid_values = array(), $case_sensitive = false)
31 {
32 $this->valid_values = array_flip($valid_values);
33 $this->case_sensitive = $case_sensitive;
34 }
35
36 /**
37 * @param string $string
38 * @param HTMLPurifier_Config $config
39 * @param HTMLPurifier_Context $context
40 * @return bool|string
41 */
42 public function validate($string, $config, $context)
43 {
44 $string = trim($string);
45 if (!$this->case_sensitive) {
46 // we may want to do full case-insensitive libraries
47 $string = ctype_lower($string) ? $string : strtolower($string);
48 }
49 $result = isset($this->valid_values[$string]);
50
51 return $result ? $string : false;
52 }
53
54 /**
55 * @param string $string In form of comma-delimited list of case-insensitive
56 * valid values. Example: "foo,bar,baz". Prepend "s:" to make
57 * case sensitive
58 * @return HTMLPurifier_AttrDef_Enum
59 */
60 public function make($string)
61 {
62 if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
63 $string = substr($string, 2);
64 $sensitive = true;
65 } else {
66 $sensitive = false;
67 }
68 $values = explode(',', $string);
69 return new HTMLPurifier_AttrDef_Enum($values, $sensitive);
70 }
71}
72
73// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Bool.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Bool.php
new file mode 100644
index 00000000..1463c647
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Bool.php
@@ -0,0 +1,51 @@
1<?php
2
3/**
4 * Validates a boolean attribute
5 */
6class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @type bool
11 */
12 protected $name;
13
14 /**
15 * @type bool
16 */
17 public $minimized = true;
18
19 /**
20 * @param bool $name
21 */
22 public function __construct($name = false)
23 {
24 $this->name = $name;
25 }
26
27 /**
28 * @param string $string
29 * @param HTMLPurifier_Config $config
30 * @param HTMLPurifier_Context $context
31 * @return bool|string
32 */
33 public function validate($string, $config, $context)
34 {
35 if (empty($string)) {
36 return false;
37 }
38 return $this->name;
39 }
40
41 /**
42 * @param string $string Name of attribute
43 * @return HTMLPurifier_AttrDef_HTML_Bool
44 */
45 public function make($string)
46 {
47 return new HTMLPurifier_AttrDef_HTML_Bool($string);
48 }
49}
50
51// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Class.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Class.php
new file mode 100644
index 00000000..b874c7e1
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Class.php
@@ -0,0 +1,48 @@
1<?php
2
3/**
4 * Implements special behavior for class attribute (normally NMTOKENS)
5 */
6class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
7{
8 /**
9 * @param string $string
10 * @param HTMLPurifier_Config $config
11 * @param HTMLPurifier_Context $context
12 * @return bool|string
13 */
14 protected function split($string, $config, $context)
15 {
16 // really, this twiddle should be lazy loaded
17 $name = $config->getDefinition('HTML')->doctype->name;
18 if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
19 return parent::split($string, $config, $context);
20 } else {
21 return preg_split('/\s+/', $string);
22 }
23 }
24
25 /**
26 * @param array $tokens
27 * @param HTMLPurifier_Config $config
28 * @param HTMLPurifier_Context $context
29 * @return array
30 */
31 protected function filter($tokens, $config, $context)
32 {
33 $allowed = $config->get('Attr.AllowedClasses');
34 $forbidden = $config->get('Attr.ForbiddenClasses');
35 $ret = array();
36 foreach ($tokens as $token) {
37 if (($allowed === null || isset($allowed[$token])) &&
38 !isset($forbidden[$token]) &&
39 // We need this O(n) check because of PHP's array
40 // implementation that casts -0 to 0.
41 !in_array($token, $ret, true)
42 ) {
43 $ret[] = $token;
44 }
45 }
46 return $ret;
47 }
48}
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Color.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Color.php
new file mode 100644
index 00000000..25c93fc6
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Color.php
@@ -0,0 +1,51 @@
1<?php
2
3/**
4 * Validates a color according to the HTML spec.
5 */
6class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @param string $string
11 * @param HTMLPurifier_Config $config
12 * @param HTMLPurifier_Context $context
13 * @return bool|string
14 */
15 public function validate($string, $config, $context)
16 {
17 static $colors = null;
18 if ($colors === null) {
19 $colors = $config->get('Core.ColorKeywords');
20 }
21
22 $string = trim($string);
23
24 if (empty($string)) {
25 return false;
26 }
27 $lower = strtolower($string);
28 if (isset($colors[$lower])) {
29 return $colors[$lower];
30 }
31 if ($string[0] === '#') {
32 $hex = substr($string, 1);
33 } else {
34 $hex = $string;
35 }
36
37 $length = strlen($hex);
38 if ($length !== 3 && $length !== 6) {
39 return false;
40 }
41 if (!ctype_xdigit($hex)) {
42 return false;
43 }
44 if ($length === 3) {
45 $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
46 }
47 return "#$hex";
48 }
49}
50
51// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php
new file mode 100644
index 00000000..7446b6da
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/FrameTarget.php
@@ -0,0 +1,38 @@
1<?php
2
3/**
4 * Special-case enum attribute definition that lazy loads allowed frame targets
5 */
6class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
7{
8
9 /**
10 * @type array
11 */
12 public $valid_values = false; // uninitialized value
13
14 /**
15 * @type bool
16 */
17 protected $case_sensitive = false;
18
19 public function __construct()
20 {
21 }
22
23 /**
24 * @param string $string
25 * @param HTMLPurifier_Config $config
26 * @param HTMLPurifier_Context $context
27 * @return bool|string
28 */
29 public function validate($string, $config, $context)
30 {
31 if ($this->valid_values === false) {
32 $this->valid_values = $config->get('Attr.AllowedFrameTargets');
33 }
34 return parent::validate($string, $config, $context);
35 }
36}
37
38// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/ID.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/ID.php
new file mode 100644
index 00000000..ccd4a24a
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/ID.php
@@ -0,0 +1,105 @@
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
12class 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 (ctype_alpha($id)) {
76 $result = true;
77 } else {
78 if (!ctype_alpha(@$id[0])) {
79 return false;
80 }
81 // primitive style of regexps, I suppose
82 $trim = trim(
83 $id,
84 'A..Za..z0..9:-._'
85 );
86 $result = ($trim === '');
87 }
88
89 $regexp = $config->get('Attr.IDBlacklistRegexp');
90 if ($regexp && preg_match($regexp, $id)) {
91 return false;
92 }
93
94 if (!$this->selector && $result) {
95 $id_accumulator->add($id);
96 }
97
98 // if no change was made to the ID, return the result
99 // else, return the new id if stripping whitespace made it
100 // valid, or return false.
101 return $result ? $id : false;
102 }
103}
104
105// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Length.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Length.php
new file mode 100644
index 00000000..c8f51886
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Length.php
@@ -0,0 +1,56 @@
1<?php
2
3/**
4 * Validates the HTML type length (not to be confused with CSS's length).
5 *
6 * This accepts integer pixels or percentages as lengths for certain
7 * HTML attributes.
8 */
9
10class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
11{
12
13 /**
14 * @param string $string
15 * @param HTMLPurifier_Config $config
16 * @param HTMLPurifier_Context $context
17 * @return bool|string
18 */
19 public function validate($string, $config, $context)
20 {
21 $string = trim($string);
22 if ($string === '') {
23 return false;
24 }
25
26 $parent_result = parent::validate($string, $config, $context);
27 if ($parent_result !== false) {
28 return $parent_result;
29 }
30
31 $length = strlen($string);
32 $last_char = $string[$length - 1];
33
34 if ($last_char !== '%') {
35 return false;
36 }
37
38 $points = substr($string, 0, $length - 1);
39
40 if (!is_numeric($points)) {
41 return false;
42 }
43
44 $points = (int)$points;
45
46 if ($points < 0) {
47 return '0%';
48 }
49 if ($points > 100) {
50 return '100%';
51 }
52 return ((string)$points) . '%';
53 }
54}
55
56// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php
new file mode 100644
index 00000000..3f56934f
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/LinkTypes.php
@@ -0,0 +1,72 @@
1<?php
2
3/**
4 * Validates a rel/rev link attribute against a directive of allowed values
5 * @note We cannot use Enum because link types allow multiple
6 * values.
7 * @note Assumes link types are ASCII text
8 */
9class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
10{
11
12 /**
13 * Name config attribute to pull.
14 * @type string
15 */
16 protected $name;
17
18 /**
19 * @param string $name
20 */
21 public function __construct($name)
22 {
23 $configLookup = array(
24 'rel' => 'AllowedRel',
25 'rev' => 'AllowedRev'
26 );
27 if (!isset($configLookup[$name])) {
28 trigger_error(
29 'Unrecognized attribute name for link ' .
30 'relationship.',
31 E_USER_ERROR
32 );
33 return;
34 }
35 $this->name = $configLookup[$name];
36 }
37
38 /**
39 * @param string $string
40 * @param HTMLPurifier_Config $config
41 * @param HTMLPurifier_Context $context
42 * @return bool|string
43 */
44 public function validate($string, $config, $context)
45 {
46 $allowed = $config->get('Attr.' . $this->name);
47 if (empty($allowed)) {
48 return false;
49 }
50
51 $string = $this->parseCDATA($string);
52 $parts = explode(' ', $string);
53
54 // lookup to prevent duplicates
55 $ret_lookup = array();
56 foreach ($parts as $part) {
57 $part = strtolower(trim($part));
58 if (!isset($allowed[$part])) {
59 continue;
60 }
61 $ret_lookup[$part] = true;
62 }
63
64 if (empty($ret_lookup)) {
65 return false;
66 }
67 $string = implode(' ', array_keys($ret_lookup));
68 return $string;
69 }
70}
71
72// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/MultiLength.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/MultiLength.php
new file mode 100644
index 00000000..eb713e15
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/MultiLength.php
@@ -0,0 +1,60 @@
1<?php
2
3/**
4 * Validates a MultiLength as defined by the HTML spec.
5 *
6 * A multilength is either a integer (pixel count), a percentage, or
7 * a relative number.
8 */
9class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length
10{
11
12 /**
13 * @param string $string
14 * @param HTMLPurifier_Config $config
15 * @param HTMLPurifier_Context $context
16 * @return bool|string
17 */
18 public function validate($string, $config, $context)
19 {
20 $string = trim($string);
21 if ($string === '') {
22 return false;
23 }
24
25 $parent_result = parent::validate($string, $config, $context);
26 if ($parent_result !== false) {
27 return $parent_result;
28 }
29
30 $length = strlen($string);
31 $last_char = $string[$length - 1];
32
33 if ($last_char !== '*') {
34 return false;
35 }
36
37 $int = substr($string, 0, $length - 1);
38
39 if ($int == '') {
40 return '*';
41 }
42 if (!is_numeric($int)) {
43 return false;
44 }
45
46 $int = (int)$int;
47 if ($int < 0) {
48 return false;
49 }
50 if ($int == 0) {
51 return '0';
52 }
53 if ($int == 1) {
54 return '*';
55 }
56 return ((string)$int) . '*';
57 }
58}
59
60// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php
new file mode 100644
index 00000000..ecb070c3
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Nmtokens.php
@@ -0,0 +1,70 @@
1<?php
2
3/**
4 * Validates contents based on NMTOKENS attribute type.
5 */
6class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @param string $string
11 * @param HTMLPurifier_Config $config
12 * @param HTMLPurifier_Context $context
13 * @return bool|string
14 */
15 public function validate($string, $config, $context)
16 {
17 $string = trim($string);
18
19 // early abort: '' and '0' (strings that convert to false) are invalid
20 if (!$string) {
21 return false;
22 }
23
24 $tokens = $this->split($string, $config, $context);
25 $tokens = $this->filter($tokens, $config, $context);
26 if (empty($tokens)) {
27 return false;
28 }
29 return implode(' ', $tokens);
30 }
31
32 /**
33 * Splits a space separated list of tokens into its constituent parts.
34 * @param string $string
35 * @param HTMLPurifier_Config $config
36 * @param HTMLPurifier_Context $context
37 * @return array
38 */
39 protected function split($string, $config, $context)
40 {
41 // OPTIMIZABLE!
42 // do the preg_match, capture all subpatterns for reformulation
43
44 // we don't support U+00A1 and up codepoints or
45 // escaping because I don't know how to do that with regexps
46 // and plus it would complicate optimization efforts (you never
47 // see that anyway).
48 $pattern = '/(?:(?<=\s)|\A)' . // look behind for space or string start
49 '((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)' .
50 '(?:(?=\s)|\z)/'; // look ahead for space or string end
51 preg_match_all($pattern, $string, $matches);
52 return $matches[1];
53 }
54
55 /**
56 * Template method for removing certain tokens based on arbitrary criteria.
57 * @note If we wanted to be really functional, we'd do an array_filter
58 * with a callback. But... we're not.
59 * @param array $tokens
60 * @param HTMLPurifier_Config $config
61 * @param HTMLPurifier_Context $context
62 * @return array
63 */
64 protected function filter($tokens, $config, $context)
65 {
66 return $tokens;
67 }
68}
69
70// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Pixels.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Pixels.php
new file mode 100644
index 00000000..1a68f238
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/HTML/Pixels.php
@@ -0,0 +1,76 @@
1<?php
2
3/**
4 * Validates an integer representation of pixels according to the HTML spec.
5 */
6class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @type int
11 */
12 protected $max;
13
14 /**
15 * @param int $max
16 */
17 public function __construct($max = null)
18 {
19 $this->max = $max;
20 }
21
22 /**
23 * @param string $string
24 * @param HTMLPurifier_Config $config
25 * @param HTMLPurifier_Context $context
26 * @return bool|string
27 */
28 public function validate($string, $config, $context)
29 {
30 $string = trim($string);
31 if ($string === '0') {
32 return $string;
33 }
34 if ($string === '') {
35 return false;
36 }
37 $length = strlen($string);
38 if (substr($string, $length - 2) == 'px') {
39 $string = substr($string, 0, $length - 2);
40 }
41 if (!is_numeric($string)) {
42 return false;
43 }
44 $int = (int)$string;
45
46 if ($int < 0) {
47 return '0';
48 }
49
50 // upper-bound value, extremely high values can
51 // crash operating systems, see <http://ha.ckers.org/imagecrash.html>
52 // WARNING, above link WILL crash you if you're using Windows
53
54 if ($this->max !== null && $int > $this->max) {
55 return (string)$this->max;
56 }
57 return (string)$int;
58 }
59
60 /**
61 * @param string $string
62 * @return HTMLPurifier_AttrDef
63 */
64 public function make($string)
65 {
66 if ($string === '') {
67 $max = null;
68 } else {
69 $max = (int)$string;
70 }
71 $class = get_class($this);
72 return new $class($max);
73 }
74}
75
76// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Integer.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Integer.php
new file mode 100644
index 00000000..c98376d7
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Integer.php
@@ -0,0 +1,91 @@
1<?php
2
3/**
4 * Validates an integer.
5 * @note While this class was modeled off the CSS definition, no currently
6 * allowed CSS uses this type. The properties that do are: widows,
7 * orphans, z-index, counter-increment, counter-reset. Some of the
8 * HTML attributes, however, find use for a non-negative version of this.
9 */
10class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
11{
12
13 /**
14 * Whether or not negative values are allowed.
15 * @type bool
16 */
17 protected $negative = true;
18
19 /**
20 * Whether or not zero is allowed.
21 * @type bool
22 */
23 protected $zero = true;
24
25 /**
26 * Whether or not positive values are allowed.
27 * @type bool
28 */
29 protected $positive = true;
30
31 /**
32 * @param $negative Bool indicating whether or not negative values are allowed
33 * @param $zero Bool indicating whether or not zero is allowed
34 * @param $positive Bool indicating whether or not positive values are allowed
35 */
36 public function __construct($negative = true, $zero = true, $positive = true)
37 {
38 $this->negative = $negative;
39 $this->zero = $zero;
40 $this->positive = $positive;
41 }
42
43 /**
44 * @param string $integer
45 * @param HTMLPurifier_Config $config
46 * @param HTMLPurifier_Context $context
47 * @return bool|string
48 */
49 public function validate($integer, $config, $context)
50 {
51 $integer = $this->parseCDATA($integer);
52 if ($integer === '') {
53 return false;
54 }
55
56 // we could possibly simply typecast it to integer, but there are
57 // certain fringe cases that must not return an integer.
58
59 // clip leading sign
60 if ($this->negative && $integer[0] === '-') {
61 $digits = substr($integer, 1);
62 if ($digits === '0') {
63 $integer = '0';
64 } // rm minus sign for zero
65 } elseif ($this->positive && $integer[0] === '+') {
66 $digits = $integer = substr($integer, 1); // rm unnecessary plus
67 } else {
68 $digits = $integer;
69 }
70
71 // test if it's numeric
72 if (!ctype_digit($digits)) {
73 return false;
74 }
75
76 // perform scope tests
77 if (!$this->zero && $integer == 0) {
78 return false;
79 }
80 if (!$this->positive && $integer > 0) {
81 return false;
82 }
83 if (!$this->negative && $integer < 0) {
84 return false;
85 }
86
87 return $integer;
88 }
89}
90
91// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Lang.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Lang.php
new file mode 100644
index 00000000..6ad0f799
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Lang.php
@@ -0,0 +1,86 @@
1<?php
2
3/**
4 * Validates the HTML attribute lang, effectively a language code.
5 * @note Built according to RFC 3066, which obsoleted RFC 1766
6 */
7class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
8{
9
10 /**
11 * @param string $string
12 * @param HTMLPurifier_Config $config
13 * @param HTMLPurifier_Context $context
14 * @return bool|string
15 */
16 public function validate($string, $config, $context)
17 {
18 $string = trim($string);
19 if (!$string) {
20 return false;
21 }
22
23 $subtags = explode('-', $string);
24 $num_subtags = count($subtags);
25
26 if ($num_subtags == 0) { // sanity check
27 return false;
28 }
29
30 // process primary subtag : $subtags[0]
31 $length = strlen($subtags[0]);
32 switch ($length) {
33 case 0:
34 return false;
35 case 1:
36 if (!($subtags[0] == 'x' || $subtags[0] == 'i')) {
37 return false;
38 }
39 break;
40 case 2:
41 case 3:
42 if (!ctype_alpha($subtags[0])) {
43 return false;
44 } elseif (!ctype_lower($subtags[0])) {
45 $subtags[0] = strtolower($subtags[0]);
46 }
47 break;
48 default:
49 return false;
50 }
51
52 $new_string = $subtags[0];
53 if ($num_subtags == 1) {
54 return $new_string;
55 }
56
57 // process second subtag : $subtags[1]
58 $length = strlen($subtags[1]);
59 if ($length == 0 || ($length == 1 && $subtags[1] != 'x') || $length > 8 || !ctype_alnum($subtags[1])) {
60 return $new_string;
61 }
62 if (!ctype_lower($subtags[1])) {
63 $subtags[1] = strtolower($subtags[1]);
64 }
65
66 $new_string .= '-' . $subtags[1];
67 if ($num_subtags == 2) {
68 return $new_string;
69 }
70
71 // process all other subtags, index 2 and up
72 for ($i = 2; $i < $num_subtags; $i++) {
73 $length = strlen($subtags[$i]);
74 if ($length == 0 || $length > 8 || !ctype_alnum($subtags[$i])) {
75 return $new_string;
76 }
77 if (!ctype_lower($subtags[$i])) {
78 $subtags[$i] = strtolower($subtags[$i]);
79 }
80 $new_string .= '-' . $subtags[$i];
81 }
82 return $new_string;
83 }
84}
85
86// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Switch.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Switch.php
new file mode 100644
index 00000000..078291f5
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Switch.php
@@ -0,0 +1,53 @@
1<?php
2
3/**
4 * Decorator that, depending on a token, switches between two definitions.
5 */
6class HTMLPurifier_AttrDef_Switch
7{
8
9 /**
10 * @type string
11 */
12 protected $tag;
13
14 /**
15 * @type HTMLPurifier_AttrDef
16 */
17 protected $withTag;
18
19 /**
20 * @type HTMLPurifier_AttrDef
21 */
22 protected $withoutTag;
23
24 /**
25 * @param string $tag Tag name to switch upon
26 * @param HTMLPurifier_AttrDef $with_tag Call if token matches tag
27 * @param HTMLPurifier_AttrDef $without_tag Call if token doesn't match, or there is no token
28 */
29 public function __construct($tag, $with_tag, $without_tag)
30 {
31 $this->tag = $tag;
32 $this->withTag = $with_tag;
33 $this->withoutTag = $without_tag;
34 }
35
36 /**
37 * @param string $string
38 * @param HTMLPurifier_Config $config
39 * @param HTMLPurifier_Context $context
40 * @return bool|string
41 */
42 public function validate($string, $config, $context)
43 {
44 $token = $context->get('CurrentToken', true);
45 if (!$token || $token->name !== $this->tag) {
46 return $this->withoutTag->validate($string, $config, $context);
47 } else {
48 return $this->withTag->validate($string, $config, $context);
49 }
50 }
51}
52
53// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Text.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Text.php
new file mode 100644
index 00000000..9f23bac4
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/Text.php
@@ -0,0 +1,21 @@
1<?php
2
3/**
4 * Validates arbitrary text according to the HTML spec.
5 */
6class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * @param string $string
11 * @param HTMLPurifier_Config $config
12 * @param HTMLPurifier_Context $context
13 * @return bool|string
14 */
15 public function validate($string, $config, $context)
16 {
17 return $this->parseCDATA($string);
18 }
19}
20
21// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI.php
new file mode 100644
index 00000000..a1097cd9
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI.php
@@ -0,0 +1,111 @@
1<?php
2
3/**
4 * Validates a URI as defined by RFC 3986.
5 * @note Scheme-specific mechanics deferred to HTMLPurifier_URIScheme
6 */
7class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
8{
9
10 /**
11 * @type HTMLPurifier_URIParser
12 */
13 protected $parser;
14
15 /**
16 * @type bool
17 */
18 protected $embedsResource;
19
20 /**
21 * @param bool $embeds_resource Does the URI here result in an extra HTTP request?
22 */
23 public function __construct($embeds_resource = false)
24 {
25 $this->parser = new HTMLPurifier_URIParser();
26 $this->embedsResource = (bool)$embeds_resource;
27 }
28
29 /**
30 * @param string $string
31 * @return HTMLPurifier_AttrDef_URI
32 */
33 public function make($string)
34 {
35 $embeds = ($string === 'embedded');
36 return new HTMLPurifier_AttrDef_URI($embeds);
37 }
38
39 /**
40 * @param string $uri
41 * @param HTMLPurifier_Config $config
42 * @param HTMLPurifier_Context $context
43 * @return bool|string
44 */
45 public function validate($uri, $config, $context)
46 {
47 if ($config->get('URI.Disable')) {
48 return false;
49 }
50
51 $uri = $this->parseCDATA($uri);
52
53 // parse the URI
54 $uri = $this->parser->parse($uri);
55 if ($uri === false) {
56 return false;
57 }
58
59 // add embedded flag to context for validators
60 $context->register('EmbeddedURI', $this->embedsResource);
61
62 $ok = false;
63 do {
64
65 // generic validation
66 $result = $uri->validate($config, $context);
67 if (!$result) {
68 break;
69 }
70
71 // chained filtering
72 $uri_def = $config->getDefinition('URI');
73 $result = $uri_def->filter($uri, $config, $context);
74 if (!$result) {
75 break;
76 }
77
78 // scheme-specific validation
79 $scheme_obj = $uri->getSchemeObj($config, $context);
80 if (!$scheme_obj) {
81 break;
82 }
83 if ($this->embedsResource && !$scheme_obj->browsable) {
84 break;
85 }
86 $result = $scheme_obj->validate($uri, $config, $context);
87 if (!$result) {
88 break;
89 }
90
91 // Post chained filtering
92 $result = $uri_def->postFilter($uri, $config, $context);
93 if (!$result) {
94 break;
95 }
96
97 // survived gauntlet
98 $ok = true;
99
100 } while (false);
101
102 $context->destroy('EmbeddedURI');
103 if (!$ok) {
104 return false;
105 }
106 // back to string
107 return $uri->toString();
108 }
109}
110
111// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email.php
new file mode 100644
index 00000000..846d3881
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email.php
@@ -0,0 +1,20 @@
1<?php
2
3abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
4{
5
6 /**
7 * Unpacks a mailbox into its display-name and address
8 * @param string $string
9 * @return mixed
10 */
11 public function unpack($string)
12 {
13 // needs to be implemented
14 }
15
16}
17
18// sub-implementations
19
20// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
new file mode 100644
index 00000000..3b041ce8
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
@@ -0,0 +1,29 @@
1<?php
2
3/**
4 * Primitive email validation class based on the regexp found at
5 * http://www.regular-expressions.info/email.html
6 */
7class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_URI_Email
8{
9
10 /**
11 * @param string $string
12 * @param HTMLPurifier_Config $config
13 * @param HTMLPurifier_Context $context
14 * @return bool|string
15 */
16 public function validate($string, $config, $context)
17 {
18 // no support for named mailboxes i.e. "Bob <bob@example.com>"
19 // that needs more percent encoding to be done
20 if ($string == '') {
21 return false;
22 }
23 $string = trim($string);
24 $result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string);
25 return $result ? $string : false;
26 }
27}
28
29// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Host.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Host.php
new file mode 100644
index 00000000..01457785
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/Host.php
@@ -0,0 +1,128 @@
1<?php
2
3/**
4 * Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
5 */
6class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
7{
8
9 /**
10 * IPv4 sub-validator.
11 * @type HTMLPurifier_AttrDef_URI_IPv4
12 */
13 protected $ipv4;
14
15 /**
16 * IPv6 sub-validator.
17 * @type HTMLPurifier_AttrDef_URI_IPv6
18 */
19 protected $ipv6;
20
21 public function __construct()
22 {
23 $this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
24 $this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
25 }
26
27 /**
28 * @param string $string
29 * @param HTMLPurifier_Config $config
30 * @param HTMLPurifier_Context $context
31 * @return bool|string
32 */
33 public function validate($string, $config, $context)
34 {
35 $length = strlen($string);
36 // empty hostname is OK; it's usually semantically equivalent:
37 // the default host as defined by a URI scheme is used:
38 //
39 // If the URI scheme defines a default for host, then that
40 // default applies when the host subcomponent is undefined
41 // or when the registered name is empty (zero length).
42 if ($string === '') {
43 return '';
44 }
45 if ($length > 1 && $string[0] === '[' && $string[$length - 1] === ']') {
46 //IPv6
47 $ip = substr($string, 1, $length - 2);
48 $valid = $this->ipv6->validate($ip, $config, $context);
49 if ($valid === false) {
50 return false;
51 }
52 return '[' . $valid . ']';
53 }
54
55 // need to do checks on unusual encodings too
56 $ipv4 = $this->ipv4->validate($string, $config, $context);
57 if ($ipv4 !== false) {
58 return $ipv4;
59 }
60
61 // A regular domain name.
62
63 // This doesn't match I18N domain names, but we don't have proper IRI support,
64 // so force users to insert Punycode.
65
66 // There is not a good sense in which underscores should be
67 // allowed, since it's technically not! (And if you go as
68 // far to allow everything as specified by the DNS spec...
69 // well, that's literally everything, modulo some space limits
70 // for the components and the overall name (which, by the way,
71 // we are NOT checking!). So we (arbitrarily) decide this:
72 // let's allow underscores wherever we would have allowed
73 // hyphens, if they are enabled. This is a pretty good match
74 // for browser behavior, for example, a large number of browsers
75 // cannot handle foo_.example.com, but foo_bar.example.com is
76 // fairly well supported.
77 $underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : '';
78
79 // The productions describing this are:
80 $a = '[a-z]'; // alpha
81 $an = '[a-z0-9]'; // alphanum
82 $and = "[a-z0-9-$underscore]"; // alphanum | "-"
83 // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
84 $domainlabel = "$an($and*$an)?";
85 // toplabel = alpha | alpha *( alphanum | "-" ) alphanum
86 $toplabel = "$a($and*$an)?";
87 // hostname = *( domainlabel "." ) toplabel [ "." ]
88 if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
89 return $string;
90 }
91
92 // If we have Net_IDNA2 support, we can support IRIs by
93 // punycoding them. (This is the most portable thing to do,
94 // since otherwise we have to assume browsers support
95
96 if ($config->get('Core.EnableIDNA')) {
97 $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
98 // we need to encode each period separately
99 $parts = explode('.', $string);
100 try {
101 $new_parts = array();
102 foreach ($parts as $part) {
103 $encodable = false;
104 for ($i = 0, $c = strlen($part); $i < $c; $i++) {
105 if (ord($part[$i]) > 0x7a) {
106 $encodable = true;
107 break;
108 }
109 }
110 if (!$encodable) {
111 $new_parts[] = $part;
112 } else {
113 $new_parts[] = $idna->encode($part);
114 }
115 }
116 $string = implode('.', $new_parts);
117 if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
118 return $string;
119 }
120 } catch (Exception $e) {
121 // XXX error reporting
122 }
123 }
124 return false;
125 }
126}
127
128// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv4.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv4.php
new file mode 100644
index 00000000..bbc8a77e
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv4.php
@@ -0,0 +1,45 @@
1<?php
2
3/**
4 * Validates an IPv4 address
5 * @author Feyd @ forums.devnetwork.net (public domain)
6 */
7class HTMLPurifier_AttrDef_URI_IPv4 extends HTMLPurifier_AttrDef
8{
9
10 /**
11 * IPv4 regex, protected so that IPv6 can reuse it.
12 * @type string
13 */
14 protected $ip4;
15
16 /**
17 * @param string $aIP
18 * @param HTMLPurifier_Config $config
19 * @param HTMLPurifier_Context $context
20 * @return bool|string
21 */
22 public function validate($aIP, $config, $context)
23 {
24 if (!$this->ip4) {
25 $this->_loadRegex();
26 }
27
28 if (preg_match('#^' . $this->ip4 . '$#s', $aIP)) {
29 return $aIP;
30 }
31 return false;
32 }
33
34 /**
35 * Lazy load function to prevent regex from being stuffed in
36 * cache.
37 */
38 protected function _loadRegex()
39 {
40 $oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255
41 $this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})";
42 }
43}
44
45// vim: et sw=4 sts=4
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv6.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv6.php
new file mode 100644
index 00000000..67f148bd
--- /dev/null
+++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/AttrDef/URI/IPv6.php
@@ -0,0 +1,89 @@
1<?php
2
3/**
4 * Validates an IPv6 address.
5 * @author Feyd @ forums.devnetwork.net (public domain)
6 * @note This function requires brackets to have been removed from address
7 * in URI.
8 */
9class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4
10{
11
12 /**
13 * @param string $aIP
14 * @param HTMLPurifier_Config $config
15 * @param HTMLPurifier_Context $context
16 * @return bool|string
17 */
18 public function validate($aIP, $config, $context)
19 {
20 if (!$this->ip4) {
21 $this->_loadRegex();
22 }
23
24 $original = $aIP;
25
26 $hex = '[0-9a-fA-F]';
27 $blk = '(?:' . $hex . '{1,4})';
28 $pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128
29
30 // prefix check
31 if (strpos($aIP, '/') !== false) {
32 if (preg_match('#' . $pre . '$#s', $aIP, $find)) {
33 $aIP = substr($aIP, 0, 0 - strlen($find[0]));
34 unset($find);
35 } else {
36 return false;
37 }
38 }
39
40 // IPv4-compatiblity check
41 if (preg_match('#(?<=:' . ')' . $this->ip4 . '$#s', $aIP, $find)) {
42 $aIP = substr($aIP, 0, 0 - strlen($find[0]));
43 $ip = explode('.', $find[0]);
44 $ip = array_map('dechex', $ip);
45 $aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
46 unset($find, $ip);
47 }
48
49 // compression check
50 $aIP = explode('::', $aIP);
51 $c = count($aIP);
52 if ($c > 2) {
53 return false;
54 } elseif ($c == 2) {
55 list($first, $second) = $aIP;
56 $first = explode(':', $first);
57 $second = explode(':', $second);
58
59 if (count($first) + count($second) > 8) {
60 return false;
61 }
62
63 while (count($first) < 8) {
64 array_push($first, '0');
65 }
66
67 array_splice($first, 8 - count($second), 8, $second);
68 $aIP = $first;
69 unset($first, $second);
70 } else {
71 $aIP = explode(':', $aIP[0]);
72 }
73 $c = count($aIP);
74
75 if ($c != 8) {
76 return false;
77 }
78
79 // All the pieces should be 16-bit hex strings. Are they?
80 foreach ($aIP as $piece) {
81 if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece))) {
82 return false;
83 }
84 }
85 return $original;
86 }
87}
88
89// vim: et sw=4 sts=4