1
- function filter_var ( v , filter , options ) {
1
+ function filter_var ( input , filter , options ) {
2
2
// http://kevin.vanzonneveld.net
3
3
// + original by: Brett Zamir (http://brett-zamir.me)
4
+ // + improved by: Rafał Kukawski (http://kukawski.pl)
5
+ // - depends on: addslashes
6
+ // - depends on: htmlspecialchars
7
+ // - depends on: strip_tags
4
8
// * example 1: filter_var('true', 'FILTER_VALIDATE_BOOLEAN');
5
9
// * returns 1: true
6
10
7
- var OPTS = {
8
- FILTER_VALIDATE_BOOLEAN : 1 ,
9
-
10
- } ,
11
- FLAGS = {
12
- FILTER_NULL_ON_FAILURE : 1 ,
13
- } ,
14
- getOption = function ( option , OPTIONS ) {
15
- var optionNames = 0 , fl = 0 ;
16
- if ( typeof option === 'number' ) { // Allow for a single string or an array of string option
17
- optionNames = option ;
11
+ function is ( val , type ) {
12
+ if ( val == null ) {
13
+ return type === "null" ;
14
+ }
15
+
16
+ if ( type === "primitive" ) {
17
+ return val !== Object ( val ) ;
18
+ }
19
+
20
+ var actual = typeof val ;
21
+
22
+ if ( actual === "object" ) {
23
+ return {
24
+ "[object Array]" : "array" ,
25
+ "[object RegExp]" : "regex"
26
+ } [ Object . prototype . toString . call ( val ) ] || "object" ;
27
+ }
28
+
29
+ if ( actual === "number" ) {
30
+ if ( isNaN ( val ) ) {
31
+ return type === "nan" ;
32
+ }
33
+
34
+ if ( ! isFinite ( val ) ) {
35
+ return "inf" ;
36
+ }
37
+ }
38
+
39
+ return type === actual ;
40
+ }
41
+
42
+ function str2regex ( str ) { }
43
+
44
+ function isPrimitive ( val ) {
45
+ return val !== Object ( val ) ;
46
+ }
47
+
48
+ var supportedFilters = {
49
+ FILTER_VALIDATE_INT : 257 ,
50
+ FILTER_VALIDATE_BOOLEAN : 258 ,
51
+ FILTER_VALIDATE_FLOAT : 259 ,
52
+ FILTER_VALIDATE_REGEXP : 272 ,
53
+ FILTER_VALIDATE_URL : 273 ,
54
+ FILTER_VALIDATE_EMAIL : 274 ,
55
+ FILTER_VALIDATE_IP : 275 ,
56
+
57
+ FILTER_SANITIZE_STRING : 513 ,
58
+ FILTER_SANITIZE_STRIPPED : 513 ,
59
+ FILTER_SANITIZE_ENCODED : 514 ,
60
+ FILTER_SANITIZE_SPECIAL_CHARS : 515 ,
61
+ FILTER_UNSAFE_RAW : 516 ,
62
+ FILTER_DEFAULT : 516 ,
63
+ FILTER_SANITIZE_EMAIL : 517 ,
64
+ FILTER_SANITIZE_URL : 518 ,
65
+ FILTER_SANITIZE_NUMBER_INT : 519 ,
66
+ FILTER_SANITIZE_NUMBER_FLOAT : 520 ,
67
+ FILTER_SANITIZE_MAGIC_QUOTES : 521 ,
68
+ // TODO: doesn't exist on my server. Add constant value
69
+ FILTER_SANITIZE_FULL_SPECIAL_CHARS : - 1 ,
70
+ FILTER_CALLBACK : 1024
71
+ } ;
72
+
73
+ var supportedFlags = {
74
+ FILTER_FLAG_ALLOW_OCTAL : 1 ,
75
+ FILTER_FLAG_ALLOW_HEX : 2 ,
76
+ FILTER_FLAG_STRIP_LOW : 4 ,
77
+ FILTER_FLAG_STRIP_HIGH : 8 ,
78
+ FILTER_FLAG_ENCODE_LOW : 16 ,
79
+ FILTER_FLAG_ENCODE_HIGH : 32 ,
80
+ FILTER_FLAG_ENCODE_AMP : 64 ,
81
+ FILTER_FLAG_NO_ENCODE_QUOTES : 128 ,
82
+ FILTER_FLAG_ALLOW_FRACTION : 4096 ,
83
+ FILTER_FLAG_ALLOW_THOUSAND : 8192 ,
84
+ FILTER_FLAG_ALLOW_SCIENTIFIC : 16384 ,
85
+ FILTER_FLAG_PATH_REQUIRED : 262144 ,
86
+ FILTER_FLAG_QUERY_REQUIRED : 524288 ,
87
+ FILTER_FLAG_IPV4 : 1048576 ,
88
+ FILTER_FLAG_IPV6 : 2097152 ,
89
+ FILTER_FLAG_NO_RES_RANGE : 4194304 ,
90
+ FILTER_FLAG_NO_PRIV_RANGE : 8388608 ,
91
+ FILTER_NULL_ON_FAILURE : 134217728
92
+ } ;
93
+
94
+ if ( is ( filter , "null" ) ) {
95
+ filter = supportedFilters . FILTER_DEFAULT ;
96
+ } else if ( is ( filter , "string" ) ) {
97
+ filter = supportedFilters [ filter ] ;
98
+ }
99
+
100
+ var flags = 0 ;
101
+ if ( is ( options , "number" ) ) {
102
+ flags = options ;
103
+ } else if ( is ( options , "string" ) ) {
104
+ flags = supportedFlags [ options ] || 0 ;
105
+ } else if ( is ( options , "object" ) && is ( options . flags , "number" ) ) {
106
+ flags = options . flags ;
107
+ }
108
+
109
+ var opts = { } ;
110
+
111
+ if ( is ( options , "object" ) ) {
112
+ opts = options . options || { } ;
113
+ }
114
+
115
+ // it looks like the FILTER_NULL_ON_FAILURE is used across all filters, not only FILTER_VALIDATE_BOOLEAN
116
+ // thus the failure var
117
+ var failure = ( flags & supportedFlags . FILTER_NULL_ON_FAILURE ) ? null : false ;
118
+
119
+ if ( ! is ( filter , "number" ) ) {
120
+ // no numeric filter, return
121
+ return failure ;
122
+ }
123
+
124
+ // Shortcut for non-primitive values. All are failures
125
+ if ( ! isPrimitive ( input ) ) {
126
+ return failure ;
127
+ }
128
+
129
+ // if input is string, trim whitespace TODO: make a dependency on trim()?
130
+ var data = is ( input , "string" ) ? input . replace ( / ( ^ \s + ) | ( \s + $ ) / g, '' ) : input ;
131
+
132
+ switch ( filter ) {
133
+ case supportedFilters . FILTER_VALIDATE_BOOLEAN :
134
+ return / ^ (?: 1 | t r u e | y e s | o n ) $ / i. test ( data ) || ( / ^ (?: 0 | f a l s e | n o | o f f ) $ / i. test ( data ) ? false : failure ) ;
135
+
136
+ case supportedFilters . FILTER_VALIDATE_INT :
137
+ var numValue = + data ;
138
+
139
+ if ( ! / ^ (?: 0 | [ + \- ] ? [ 1 - 9 ] \d * ) $ / . test ( data ) ) {
140
+ if ( ( flags & supportedFlags . FILTER_FLAG_ALLOW_HEX ) && / ^ 0 x [ \d a - f ] + $ / i. test ( data ) ) {
141
+ numValue = parseInt ( data , 16 ) ;
142
+ } else if ( ( flags & supportedFlags . FILTER_FLAG_ALLOW_OCTAL ) && / ^ 0 [ 0 - 7 ] + $ / . test ( data ) ) {
143
+ numValue = parseInt ( data , 8 ) ;
18
144
} else {
19
- option = [ ] . concat ( option ) ;
20
- for ( i = 0 , fl = option . length ; i < fl ; i ++ ) {
21
- if ( OPTIONS [ option [ i ] ] ) {
22
- optionNames = optionNames | OPTIONS [ option [ i ] ] ;
23
- }
145
+ return failure ;
146
+ }
147
+ }
148
+
149
+ var minValue = is ( opts . min_range , "number" ) ? opts . min_range : - Infinity ;
150
+ var maxValue = is ( opts . max_range , "number" ) ? opts . max_range : Infinity ;
151
+
152
+ if ( ! is ( numValue , "number" ) || numValue % 1 || numValue < minValue || numValue > maxValue ) {
153
+ return failure ;
154
+ }
155
+
156
+ return numValue ;
157
+
158
+ case supportedFilters . FILTER_VALIDATE_REGEXP :
159
+ if ( is ( options . regexp , "regex" ) ) {
160
+ // FIXME: we are passing pre-processed input data (trimmed data).
161
+ // check whether PHP also passess trimmed input
162
+ var matches = options . regexp ( data )
163
+ return matches ? matches [ 0 ] : failure ;
164
+ }
165
+ // TODO: support passing regexes as strings "#regex#is"
166
+ case supportedFilters . FILTER_VALIDATE_IP :
167
+ var ipv4 = / ^ ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | [ 0 1 ] ? \d ? \d ) \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | [ 0 1 ] ? \d ? \d ) \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | [ 0 1 ] ? \d ? \d ) \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | [ 0 1 ] ? \d ? \d ) $ /
168
+ var ipv4privrange = / ^ (?: 0 ? 1 0 | 1 7 2 \. 0 ? (?: 1 [ 6 - 9 ] | 2 \d | 3 [ 0 1 ] ) | 1 9 2 \. 1 6 8 ) \. / ;
169
+ var ipv4resrange = / ^ (?: 0 ? 0 ? 0 \. | 1 2 7 \. 0 ? 0 ? 0 \. 0 ? 0 ? 0 \. 0 ? 0 ? 1 | 1 2 8 \. 0 ? 0 ? 0 \. | 1 6 9 \. 2 5 4 \. | 1 9 1 \. 2 5 5 \. | 1 9 2 \. 0 ? 0 ? 0 \. 0 ? 0 ? 2 \. | 2 5 [ 0 - 5 ] \. | 2 [ 3 4 ] \d \. | 2 2 [ 4 - 9 ] \. ) / ;
170
+ // IPv6 regex taken from here: http://forums.intermapper.com/viewtopic.php?t=452
171
+ var ipv6 = / ^ ( ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 7 } ( [ 0 - 9 A - F a - f ] { 1 , 4 } | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 6 } ( : [ 0 - 9 A - F a - f ] { 1 , 4 } | ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 5 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 2 } ) | : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 4 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 3 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) ? : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 3 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 4 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 2 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 2 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 5 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 3 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( ( [ 0 - 9 A - F a - f ] { 1 , 4 } : ) { 1 } ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 6 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 4 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) | ( : ( ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 1 , 7 } ) | ( ( : [ 0 - 9 A - F a - f ] { 1 , 4 } ) { 0 , 5 } : ( ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ( \. ( 2 5 [ 0 - 5 ] | 2 [ 0 - 4 ] \d | 1 \d \d | [ 1 - 9 ] ? \d ) ) { 3 } ) ) | : ) ) ) ( % .+ ) ? $ / ;
172
+
173
+ var mode = ( supportedFlags . FILTER_FLAG_IPV4 | supportedFlags . FILTER_FLAG_IPV6 ) ;
174
+
175
+ if ( flags !== 0 ) {
176
+ mode &= flags ;
177
+ }
178
+
179
+ if ( mode & supportedFlags . FILTER_FLAG_IPV4 ) {
180
+ var ip = ipv4 . test ( input ) ;
181
+
182
+ if ( ip ) {
183
+ if ( ( flags & supportedFlags . FILTER_FLAG_NO_PRIV_RANGE ) && privrange . test ( data ) ) {
184
+ return failure ;
185
+ }
186
+
187
+ if ( ( flags & supportedFlags . FILTER_FLAG_NO_RES_RANGE ) && resrange . test ( data ) ) {
188
+ return failure ;
24
189
}
190
+
191
+ return input ;
192
+ }
193
+ }
194
+
195
+ if ( mode & supportedFlags . FILTER_FLAG_IPV6 ) {
196
+ var ip = ipv6 . test ( input ) ;
197
+
198
+ if ( ip ) {
199
+ // TODO: check ipv6 ranges
200
+ return input ;
25
201
}
26
- return optionNames ;
27
- } ;
28
- filter = getOption ( filter , OPTS ) ;
29
- options = getOption ( options , FLAGS ) ;
30
-
31
- if ( filter & OPTS . option_VALIDATE_BOOLEAN ) {
32
- return ( / ^ (?: 1 | t r u e | o n | y e s ) $ / ) . test ( v ) ||
33
- (
34
- ( ( options & FLAGS . option_NULL_ON_FAILURE ) &&
35
- ! ( / ^ (?: 0 | f a l s e | o f f | n o ) ? $ / ) . test ( v ) ) ? null : false
36
- ) ;
37
- }
38
-
202
+ }
203
+
204
+ return failure ;
205
+
206
+ case supportedFilters . FILTER_CALLBACK :
207
+ var fn = opts ;
208
+
209
+ if ( is ( fn , "string" ) ) {
210
+ fn = this . window [ fn ] ;
211
+ }
212
+
213
+ if ( is ( fn , "function" ) ) {
214
+ return fn ( input ) ;
215
+ }
216
+
217
+ return failure ;
218
+
219
+ case supportedFilters . FILTER_SANITIZE_NUMBER_INT :
220
+ return ( "" + input ) . replace ( / [ ^ \d + \- ] / g, "" ) ;
221
+
222
+ case supportedFilters . FILTER_SANITIZE_NUMBER_FLOAT :
223
+ return ( '' + input ) . replace ( / [ ^ \d e E . , + \- ] / g, '' ) . replace ( / [ e E . , ] / g,
224
+ function ( m ) {
225
+ return {
226
+ '.' : ( filter & supportedFilters . FILTER_FLAG_ALLOW_FRACTION ) ? '.' : '' ,
227
+ ',' : ( filter & supportedFilters . FILTER_FLAG_ALLOW_THOUSAND ) ? ',' : '' ,
228
+ 'e' : ( filter & supportedFilters . FILTER_FLAG_ALLOW_SCIENTIFIC ) ? 'e' : '' ,
229
+ 'E' : ( filter & supportedFilters . FILTER_FLAG_ALLOW_SCIENTIFIC ) ? 'e' : ''
230
+ } [ m ] ;
231
+ } ) ;
232
+
233
+ /*case supportedFilters.FILTER_SANITIZE_MAGIC_QUOTES:
234
+ return this.addslashes(input); // ('' + input).replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0')*/
235
+
236
+ case supportedFilters . FILTER_SANITIZE_URL :
237
+ return ( "" + data ) . replace ( / [ ^ a - z A - Z \d $ \- _ . + ! * ' ( ) , { } | \\ \^ ~ \[ \] ` < > # % " ; \/ ? : @ & = ] / g, '' ) ;
238
+
239
+ case supportedFilters . FILTER_SANITIZE_EMAIL :
240
+ return ( "" + data ) . replace ( / [ ^ a - z A - Z \d ! # $ % & ' * + \- \/ = ? \^ _ ` { | } ~ @ . \[ \] ] / g, '' ) ;
241
+
242
+ case supportedFilters . FILTER_DEFAULT :
243
+ // is alias of FILTER_UNSAFE_RAW
244
+ // fall-through
245
+ case supportedFilters . FILTER_UNSAFE_RAW :
246
+ data = input + "" ;
247
+
248
+ if ( flags & supportedFlags . FILTER_FLAG_ENCODE_AMP ) {
249
+ data = data . replace ( / & / g, "&" ) ;
250
+ }
251
+
252
+ if ( ( supportedFlags . FILTER_FLAG_ENCODE_LOW |
253
+ supportedFlags . FILTER_FLAG_STRIP_LOW |
254
+ supportedFlags . FILTER_FLAG_ENCODE_HIGH |
255
+ supportedFlags . FILTER_FLAG_STRIP_HIGH ) &
256
+ flags ) {
257
+
258
+ data = data . replace ( / [ \s \S ] / g,
259
+ function ( c ) {
260
+ var charCode = c . charCodeAt ( 0 ) ;
261
+
262
+ if ( charCode < 32 ) {
263
+ return ( flags & supportedFlags . FILTER_FLAG_STRIP_LOW ) ? "" :
264
+ ( flags & supportedFlags . FILTER_FLAG_ENCODE_LOW ) ? "&#" + charCode : c ;
265
+ } else if ( charCode > 127 ) {
266
+ return ( flags & supportedFlags . FILTER_FLAG_STRIP_HIGH ) ? "" : ( flags & supportedFlags . FILTER_FLAG_ENCODE_HIGH ) ? "&#" + charCode : c ;
267
+ }
268
+
269
+ return c ;
270
+ } ) ;
271
+ }
272
+
273
+ return data ;
274
+ default :
275
+ return false ;
276
+ }
277
+
278
+ return false ;
39
279
}
0 commit comments