2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2014 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Derick Rethans <derick@php.net> |
16 +----------------------------------------------------------------------+
21 #include "php_filter.h"
22 #include "filter_private.h"
23 #include "ext/standard/php_smart_str.h"
26 typedef unsigned long filter_map
[256];
29 /* {{{ HELPER FUNCTIONS */
30 static void php_filter_encode_html(zval
*value
, const unsigned char *chars
)
33 int len
= Z_STRLEN_P(value
);
34 unsigned char *s
= (unsigned char *)Z_STRVAL_P(value
);
35 unsigned char *e
= s
+ len
;
37 if (Z_STRLEN_P(value
) == 0) {
43 smart_str_appendl(&str
, "&#", 2);
44 smart_str_append_unsigned(&str
, (unsigned long)*s
);
45 smart_str_appendc(&str
, ';');
47 /* XXX: this needs to be optimized to work with blocks of 'safe' chars */
48 smart_str_appendc(&str
, *s
);
54 str_efree(Z_STRVAL_P(value
));
55 Z_STRVAL_P(value
) = str
.c
;
56 Z_STRLEN_P(value
) = str
.len
;
59 static const unsigned char hexchars
[] = "0123456789ABCDEF";
61 #define LOWALPHA "abcdefghijklmnopqrstuvwxyz"
62 #define HIALPHA "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
63 #define DIGIT "0123456789"
65 #define DEFAULT_URL_ENCODE LOWALPHA HIALPHA DIGIT "-._"
67 static void php_filter_encode_url(zval
*value
, const unsigned char* chars
, const int char_len
, int high
, int low
, int encode_nul
)
69 unsigned char *str
, *p
;
70 unsigned char tmp
[256];
71 unsigned char *s
= (unsigned char *)chars
;
72 unsigned char *e
= s
+ char_len
;
74 memset(tmp
, 1, sizeof(tmp
)-1);
79 /* XXX: This is not needed since these chars in the allowed list never include the high/low/null value
84 memset(tmp + 127, 1, sizeof(tmp) - 127);
90 p
= str
= (unsigned char *) safe_emalloc(3, Z_STRLEN_P(value
), 1);
91 s
= (unsigned char *)Z_STRVAL_P(value
);
92 e
= s
+ Z_STRLEN_P(value
);
97 *p
++ = hexchars
[(unsigned char) *s
>> 4];
98 *p
++ = hexchars
[(unsigned char) *s
& 15];
105 str_efree(Z_STRVAL_P(value
));
106 Z_STRVAL_P(value
) = (char *)str
;
107 Z_STRLEN_P(value
) = p
- str
;
110 static void php_filter_strip(zval
*value
, long flags
)
112 unsigned char *buf
, *str
;
115 /* Optimization for if no strip flags are set */
116 if (! ((flags
& FILTER_FLAG_STRIP_LOW
) || (flags
& FILTER_FLAG_STRIP_HIGH
)) ) {
120 str
= (unsigned char *)Z_STRVAL_P(value
);
121 buf
= safe_emalloc(1, Z_STRLEN_P(value
) + 1, 1);
123 for (i
= 0; i
< Z_STRLEN_P(value
); i
++) {
124 if ((str
[i
] > 127) && (flags
& FILTER_FLAG_STRIP_HIGH
)) {
125 } else if ((str
[i
] < 32) && (flags
& FILTER_FLAG_STRIP_LOW
)) {
126 } else if ((str
[i
] == '`') && (flags
& FILTER_FLAG_STRIP_BACKTICK
)) {
132 /* update zval string data */
134 str_efree(Z_STRVAL_P(value
));
135 Z_STRVAL_P(value
) = (char *)buf
;
136 Z_STRLEN_P(value
) = c
;
140 /* {{{ FILTER MAP HELPERS */
141 static void filter_map_init(filter_map
*map
)
143 memset(map
, 0, sizeof(filter_map
));
146 static void filter_map_update(filter_map
*map
, int flag
, const unsigned char *allowed_list
)
150 l
= strlen((const char*)allowed_list
);
151 for (i
= 0; i
< l
; ++i
) {
152 (*map
)[allowed_list
[i
]] = flag
;
156 static void filter_map_apply(zval
*value
, filter_map
*map
)
158 unsigned char *buf
, *str
;
161 str
= (unsigned char *)Z_STRVAL_P(value
);
162 buf
= safe_emalloc(1, Z_STRLEN_P(value
) + 1, 1);
164 for (i
= 0; i
< Z_STRLEN_P(value
); i
++) {
165 if ((*map
)[str
[i
]]) {
170 /* update zval string data */
172 str_efree(Z_STRVAL_P(value
));
173 Z_STRVAL_P(value
) = (char *)buf
;
174 Z_STRLEN_P(value
) = c
;
178 /* {{{ php_filter_string */
179 void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL
)
182 unsigned char enc
[256] = {0};
184 /* strip high/strip low ( see flags )*/
185 php_filter_strip(value
, flags
);
187 if (!(flags
& FILTER_FLAG_NO_ENCODE_QUOTES
)) {
188 enc
['\''] = enc
['"'] = 1;
190 if (flags
& FILTER_FLAG_ENCODE_AMP
) {
193 if (flags
& FILTER_FLAG_ENCODE_LOW
) {
196 if (flags
& FILTER_FLAG_ENCODE_HIGH
) {
197 memset(enc
+ 127, 1, sizeof(enc
) - 127);
200 php_filter_encode_html(value
, enc
);
202 /* strip tags, implicitly also removes \0 chars */
203 new_len
= php_strip_tags_ex(Z_STRVAL_P(value
), Z_STRLEN_P(value
), NULL
, NULL
, 0, 1);
204 Z_STRLEN_P(value
) = new_len
;
208 if (flags
& FILTER_FLAG_EMPTY_STRING_NULL
) {
211 ZVAL_EMPTY_STRING(value
);
218 /* {{{ php_filter_encoded */
219 void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL
)
221 /* apply strip_high and strip_low filters */
222 php_filter_strip(value
, flags
);
224 php_filter_encode_url(value
, (unsigned char *)DEFAULT_URL_ENCODE
, sizeof(DEFAULT_URL_ENCODE
)-1, flags
& FILTER_FLAG_ENCODE_HIGH
, flags
& FILTER_FLAG_ENCODE_LOW
, 1);
228 /* {{{ php_filter_special_chars */
229 void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL
)
231 unsigned char enc
[256] = {0};
233 php_filter_strip(value
, flags
);
235 /* encodes ' " < > & \0 to numerical entities */
236 enc
['\''] = enc
['"'] = enc
['<'] = enc
['>'] = enc
['&'] = enc
[0] = 1;
238 /* if strip low is not set, then we encode them as &#xx; */
241 if (flags
& FILTER_FLAG_ENCODE_HIGH
) {
242 memset(enc
+ 127, 1, sizeof(enc
) - 127);
245 php_filter_encode_html(value
, enc
);
249 /* {{{ php_filter_full_special_chars */
250 void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL
)
256 if (!(flags
& FILTER_FLAG_NO_ENCODE_QUOTES
)) {
259 quotes
= ENT_NOQUOTES
;
261 buf
= php_escape_html_entities_ex(Z_STRVAL_P(value
), Z_STRLEN_P(value
), &len
, 1, quotes
, SG(default_charset
), 0 TSRMLS_CC
);
262 str_efree(Z_STRVAL_P(value
));
263 Z_STRVAL_P(value
) = buf
;
264 Z_STRLEN_P(value
) = len
;
268 /* {{{ php_filter_unsafe_raw */
269 void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL
)
271 /* Only if no flags are set (optimization) */
272 if (flags
!= 0 && Z_STRLEN_P(value
) > 0) {
273 unsigned char enc
[256] = {0};
275 php_filter_strip(value
, flags
);
277 if (flags
& FILTER_FLAG_ENCODE_AMP
) {
280 if (flags
& FILTER_FLAG_ENCODE_LOW
) {
283 if (flags
& FILTER_FLAG_ENCODE_HIGH
) {
284 memset(enc
+ 127, 1, sizeof(enc
) - 127);
287 php_filter_encode_html(value
, enc
);
288 } else if (flags
& FILTER_FLAG_EMPTY_STRING_NULL
&& Z_STRLEN_P(value
) == 0) {
297 /* {{{ php_filter_email */
299 #define EXTRA "!*'(),"
300 #define NATIONAL "{}|\\^~[]`"
301 #define PUNCTUATION "<>#%\""
302 #define RESERVED ";/?:@&="
304 void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL
)
306 /* Check section 6 of rfc 822 http://www.faqs.org/rfcs/rfc822.html */
307 const unsigned char allowed_list
[] = LOWALPHA HIALPHA DIGIT
"!#$%&'*+-=?^_`{|}~@.[]";
310 filter_map_init(&map
);
311 filter_map_update(&map
, 1, allowed_list
);
312 filter_map_apply(value
, &map
);
316 /* {{{ php_filter_url */
317 void php_filter_url(PHP_INPUT_FILTER_PARAM_DECL
)
319 /* Strip all chars not part of section 5 of
320 * http://www.faqs.org/rfcs/rfc1738.html */
321 const unsigned char allowed_list
[] = LOWALPHA HIALPHA DIGIT SAFE EXTRA NATIONAL PUNCTUATION RESERVED
;
324 filter_map_init(&map
);
325 filter_map_update(&map
, 1, allowed_list
);
326 filter_map_apply(value
, &map
);
330 /* {{{ php_filter_number_int */
331 void php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL
)
333 /* strip everything [^0-9+-] */
334 const unsigned char allowed_list
[] = "+-" DIGIT
;
337 filter_map_init(&map
);
338 filter_map_update(&map
, 1, allowed_list
);
339 filter_map_apply(value
, &map
);
343 /* {{{ php_filter_number_float */
344 void php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL
)
346 /* strip everything [^0-9+-] */
347 const unsigned char allowed_list
[] = "+-" DIGIT
;
350 filter_map_init(&map
);
351 filter_map_update(&map
, 1, allowed_list
);
353 /* depending on flags, strip '.', 'e', ",", "'" */
354 if (flags
& FILTER_FLAG_ALLOW_FRACTION
) {
355 filter_map_update(&map
, 2, (const unsigned char *) ".");
357 if (flags
& FILTER_FLAG_ALLOW_THOUSAND
) {
358 filter_map_update(&map
, 3, (const unsigned char *) ",");
360 if (flags
& FILTER_FLAG_ALLOW_SCIENTIFIC
) {
361 filter_map_update(&map
, 4, (const unsigned char *) "eE");
363 filter_map_apply(value
, &map
);
367 /* {{{ php_filter_magic_quotes */
368 void php_filter_magic_quotes(PHP_INPUT_FILTER_PARAM_DECL
)
373 /* just call php_addslashes quotes */
374 buf
= php_addslashes(Z_STRVAL_P(value
), Z_STRLEN_P(value
), &len
, 0 TSRMLS_CC
);
376 str_efree(Z_STRVAL_P(value
));
377 Z_STRVAL_P(value
) = buf
;
378 Z_STRLEN_P(value
) = len
;
387 * vim600: noet sw=4 ts=4 fdm=marker
388 * vim<600: noet sw=4 ts=4