--- /dev/null
+Input Filter Extension
+~~~~~~~~~~~~~~~~~~~~~~
+
+Introduction
+============
+We all know that you should always check input variables, but PHP does not
+offer really good functionality for doing this in a safe way. The Input Filter
+extension is meant to address this issue by implementing a set of filters and
+mechanisms that users can use to safely access their input data.
+
+
+Change Log
+==========
+2005-10-27
+ * Updated filter_data prototype
+ * Added filter constants
+ * Fixed minor problems
+ * Changes by David Tulloh
+
+2005-10-05
+ * Changed "input_filter.paranoid_admin_default_filter" to
+ "filter.default".
+ * Updated API prototypes to reflect implementation.
+ * Added 'on' and 'off' to the boolean filter.
+ * Removed min_range and max_range flags from the float filter.
+ * Added validate_url, validate_email and validate_ip filters.
+ * Updated allows flags for all filters.
+
+2005-08-15
+ * Unmade *source* a bitmask, it doesn't make sense to do.
+ * Changed return value of filters which got invalid data from 'false' to
+ 'null.
+ * Failed filters do not throw an E_NOTICE any longer.
+ * Added a magic_quotes sanitizing filter.
+
+
+General Considerations
+======================
+* If the filter's expected input data mask does not match the provided data
+ for logical filters the filter function returns "false". If the data was
+ not found, "null" is returned.
+* Character filters always return a string.
+* With the input filter extension enabled, and the
+ input_filter.paranoid_admin_default_filter is set to something != 'raw',
+ then all entries in the affected super globals will be passed through the
+ configured filter. The 'callback' filter can not be used here, as that
+ requieres a PHP script to be running already.
+* As the input filter acts on input data before the magic quotes function
+ mangles data, all access through the filter() function will not have any
+ quotes or slashes added - it will be the pure data as send by the browser.
+* All flags mentioned here should be prepended with `FILTER_FLAG_` when used
+ with PHP.
+
+
+API
+===
+mixed *input_get* (int *source*, string *name*, [, int *filter* [, mixed *filter_options*, [ string *characterset* ] ]);
+ Returns the filtered variable *$name* from source *$source*. It uses the
+ filter as specified in *$filter* with a constant, and additional options
+ to the filter through *$filter_options*.
+
+mixed *input_get_args* (array *definitions*, int *source*, [, array *data*]);
+ Returns an array with all filtered variables defined in 'definition'.
+ The keys are used as the name of the argument. The value can be either
+ an integer (flags) or an array of options. This array can contain
+ the 'filter' type, the 'flags', the 'otptions' or the 'charset'
+
+bool *input_has_variable (int *source*, string *name*);
+ Returns *true* if the variable with the name *name* exists in *source*, or
+ *false* otherwise.
+
+array *input_filters_list* ();
+ Returns a list with all supported filter names.
+
+mixed *filter_data* (mixed *variable*, int *filter* [, mixed *filter_options*, [ string *characterset* ] ]);
+ Filters the user supplied variable *$variable* in the same manner as
+ *input_get*.
+
+*$source*:
+
+* INPUT_POST 0
+* INPUT_GET 1
+* INPUT_COOKIE 2
+* INPUT_ENV 4
+* INPUT_SERVER 5 (not implemented yet)
+* INPUT_SESSION 6 (not implemented yet)
+
+
+General flags
+=============
+
+* FILTER_FLAG_SCALAR
+* FILTER_FLAG_ARRAY
+
+These two constants define whether to allow arrays in the source values. The
+default value is SCALAR for input_get_args and ARRAY for the other functions
+(< 0.9.5). These constants also insure that the function returns the correct
+type, if you ask for an array, you will get an array even if the source is
+only one value. However, if you ask for a scalar and the source is an array,
+the result will be FALSE (invalid).
+
+
+Logical Filters
+===============
+
+These filters check whether passed data was valid, and do never mangle input
+variables, but ofcourse they can deny the whole input variable getting to the
+application by returning false.
+
+The constants should be prepended by `FILTER_VALIDATE_` when used with php.
+
+================ ========== =========== ==================================================
+Name Constant Return Type Description
+================ ========== =========== ==================================================
+int INT integer Returns the input variable as an integer
+
+ $filter_options - an array with the optional
+ elements:
+
+ * min_range: Minimal number that is allowed
+ (inclusive)
+ * max_range: Maximum number that is allowed
+ (inclusive)
+ * flags: A bitmask supporting the following flags:
+
+ - ALLOW_OCTAL: allow octal numbers with the format
+ 0nn as input too.
+ - ALLOW_HEX: allow hexadecimal numbers with the
+ format 0xnn or 0Xnn too.
+
+boolean BOOLEAN boolean Returns *true* for '1', 'on' and 'true' and *false*
+ for '0', 'off' and 'false'
+
+float FLOAT float Returns the input variable as a floating point value
+
+validate_regexp REGEXP string Matches the input value as a string against the
+ regular expression. If there is a match then the
+ string is returned, otherwise the filter returns
+ *null*.
+ Remarks: Only available if pcre has been compiled
+ into PHP.
+
+validate_url URL string Validates an URL's format.
+
+ $filter_options - an bitmask that supports the
+ following flags:
+
+ * SCHEME_REQUIRED: The 'schema' part of the URL
+ needs to in the passed URL.
+ * HOST_REQUIRED: The 'host' part of the URL
+ needs to in the passed URL.
+ * PATH_REQUIRED: The 'path' part of the URL
+ needs to in the passed URL.
+ * QUERY_REQUIRED: The 'query' part of the URL
+ needs to in the passed URL.
+
+validate_email EMAIL string Validates the passed string against a reasonably
+ good regular expression for validating an email
+ address.
+
+validate_ip IP string Validates a string representing an IP address.
+
+ $filter_options - an bitmask that supports the
+ following flags:
+
+ * IPV4: Allows IPv4 addresses.
+ * IPV6: Allows IPv6 addresses.
+ * NO_RES_RANGE: Disallows addresses in reversed
+ ranges (IPv4 only)
+ * NO_PRIV_RANGE: Disallows addresses in private
+ ranges (IPv4 only)
+================ ========== =========== ==================================================
+
+
+Sanitizing Filters
+==================
+
+These filters remove data, or change data depending on the filter, and the
+set rules for this specific filter. Instead of taking an *options* array, they
+use this parameter for flags for the specific filter.
+
+The constants should be prepended by `FILTER_SANITIZE_` when used with php.
+
+============= ================ =========== =====================================================
+Name Constant Return Type Description
+============= ================ =========== =====================================================
+string STRING string Returns the input variable as a string after it has
+ been stripped of XML/HTML tags and other evil things
+ that can cause XSS problems.
+
+ $filter_options - an bitmask that supports the
+ following flags:
+
+ * NO_ENCODE_QUOTES: Prevents single and double
+ quotes from being encoded as numerical HTML
+ entities.
+ * STRIP_LOW: excludes all characters < 0x20 from the
+ allowed character list
+ * STRIP_HIGH: excludes all characters >= 0x80 from
+ the allowed character list
+ * ENCODE_LOW: allows characters < 0x20 but encodes
+ them as numerical HTML entities
+ * ENCODE_HIGH: allows characters >= 0x80 but encodes
+ them as numerical HTML entities
+ * ENCODE_AMP: encodes & as &
+
+ The flags STRIP_LOW and ENCODE_LOW are mutual
+ exclusive, and so are STRIP_HIGH and ENCODE_HIGH. In
+ the case they clash, the characters will be
+ stripped.
+
+stripped STRIPPED string Alias for 'string'.
+
+encoded ENCODED string Encodes all characters outside the range
+ "a-zA-Z0-9-._" as URL encoded values.
+
+ $filter_options - an bitmask that supports the
+ following flags:
+
+ * STRIP_LOW: excludes all characters < 0x20 from the
+ allowed character list
+ * STRIP_HIGH: excludes all characters >= 0x80 from
+ the allowed character list
+ * ENCODE_LOW: allows characters < 0x20 but encodes
+ them as numerical HTML entities
+ * ENCODE_HIGH: allows characters >= 0x80 but encodes
+ them as numerical HTML entities
+
+special_chars SPECIAL_CHARS string Encodes the 'special' characters ' " < > &, \0 and
+ everything below 0x20 as numerical HTML entities.
+
+ $filter_options - an bitmask that supports the
+ following flags:
+
+ * STRIP_LOW: excludes all characters < 0x20 from the
+ allowed character list. If this is not set, then
+ those characters are encoded as numerical HTML
+ entities
+ * STRIP_HIGH: excludes all characters >= 0x80 from
+ the allowed character list
+ * ENCODE_HIGH: allows characters >= 0x80 but encodes
+ them as numerical HTML entities
+
+unsafe_raw UNSAFE_RAW string Returns the input variable as a string without
+ XML/HTML being stripped from the input value.
+
+ $filter_options - an bitmask that supports the
+ following flags:
+
+ * STRIP_LOW: excludes all characters < 0x20 from the
+ allowed character list
+ * STRIP_HIGH: excludes all characters >= 0x80 from
+ the allowed character list
+ * ENCODE_LOW: allows characters < 0x20 but encodes
+ them as numerical HTML entities
+ * ENCODE_HIGH: allows characters >= 0x80 but encodes
+ them as numerical HTML entities
+ * ENCODE_AMP: encodes & as &
+
+ The flags STRIP_LOW and ENCODE_LOW are mutual
+ exclusive, and so are STRIP_HIGH and ENCODE_HIGH. In
+ the case they clash, the characters will be
+ stripped.
+
+email EMAIL string Removes all characters that can not be part of a
+ correctly formed e-mail address (exception are
+ comments in the email address) (a-z A-Z 0-9 " ! # $
+ % & ' * + - / = ? ^ _ ` { | } ~ @ . [ ]). This
+ filter does `not` validate if the e-mail address has
+ the correct format, use the validate_email filter
+ for that.
+
+url URL string Removes all characters that can not be part of a
+ correctly formed URI. (a-z A-Z 0-9 $ - _ . + ! * ' (
+ ) , { } | \ ^ ~ [ ] ` < > # % " ; / ? : @ & =) This
+ filter does `not` validate if a URI has the correct
+ format, use the validate_url filter for that.
+
+number_int NUMBER_INT int Removes all characters that are [^0-9+-].
+
+number_float NUMBER_FLOAT float Removes all characters that are [^0-9+-].
+
+ $filter_options - an bitmask that supports the
+ following flags:
+
+ * ALLOW_FRACTION: adds "." to the characters that
+ are not stripped.
+ * ALLOW_THOUSAND: adds "," to the characters that
+ are not stripped.
+ * ALLOW_SCIENTIFIC: adds "eE" to the characters that
+ are not stripped.
+
+magic_quotes MAGIC_QUOTES string BC filter for people who like magic quotes.
+============= ================ =========== =====================================================
+
+
+Callback Filter
+===============
+
+This filter will callback to the specified callback function as specified with
+the *filter_options* parameter. All variants of callback functions are
+supported:
+
+* function with *'functionname'*
+* static method with *array('classname', 'methodname')*
+* dynamic method with *array(&$this, 'methodname')*
+
+The constants should be prepended by `FILTER_` when used with php.
+
+============= =========== =========== =====================================================
+Name Constant Return Type Description
+============= =========== =========== =====================================================
+callback CALLBACK mixed Calls the callback function/method with the input
+ variable's value by reference which can do filtering
+ and modifying of the input value. If the callback
+ function returns "false" then the input value is
+ supposed to be incorrect and the returned value will
+ be 'false' (and an E_NOTICE will be raised).
+============= =========== =========== =====================================================
+
+The callback function's prototype is:
+
+boolean callback(&$value, $characterset);
+ With *$value* being a reference to the input variable and *$characterset*
+ containing the same value as this parameter's value in the call to
+ *input_get()* or *input_get_array()*. If the *$characterset* parameter was
+ not passed, it defaults to *'null'*.
+
+Version: $Id$
+.. vim: et syn=rst tw=78
+
--- /dev/null
+<?php
+error_reporting(E_ALL|E_STRICT);
+$data = array(
+ 'product_id' => 'product id<script>',
+ 'component' => '10',
+ 'versions' => '1.2.33',
+ 'testscalar' => array('2','23','10','12'),
+ 'testarray' => '2',
+);
+
+$args = array(
+ 'product_id' => FILTER_SANITIZE_ENCODED,
+ 'component' => array('filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FLAG_ARRAY,
+ 'options' => array("min_range"=>1, "max_range"=>10)
+ ),
+
+ /* equivalent of => FILTER_SANITIZE_ENCODED as SCALAR is
+ * the default mode
+ */
+ 'versions' => array(
+ 'filter' => FILTER_SANITIZE_ENCODED,
+ 'flags' => FILTER_FLAG_SCALAR,
+ ),
+ 'doesnotexist' => FILTER_VALIDATE_INT,
+ 'testscalar' => FILTER_VALIDATE_INT,
+ 'testarray' => array(
+ 'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FLAG_ARRAY,
+ )
+
+);
+
+/*
+The other INPUT_* can be used as well.
+$myinputs = input_get_args($args, INPUT_POST);
+*/
+$myinputs = input_get_args($args, INPUT_DATA, $data);
+
+var_dump($myinputs);
+
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@php.net> |
+ | Derick Rethans <derick@php.net> |
+ | Pierre-A. Joye <pierre@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php_filter.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(filter)
+
+#include "filter_private.h"
+
+typedef struct filter_list_entry {
+ char *name;
+ int id;
+ void (*function)(PHP_INPUT_FILTER_PARAM_DECL);
+} filter_list_entry;
+
+/* {{{ filter_list */
+filter_list_entry filter_list[] = {
+ { "int", FILTER_VALIDATE_INT, php_filter_int },
+ { "boolean", FILTER_VALIDATE_BOOLEAN, php_filter_boolean },
+ { "float", FILTER_VALIDATE_FLOAT, php_filter_float },
+
+ { "validate_regexp", FILTER_VALIDATE_REGEXP, php_filter_validate_regexp },
+ { "validate_url", FILTER_VALIDATE_URL, php_filter_validate_url },
+ { "validate_email", FILTER_VALIDATE_EMAIL, php_filter_validate_email },
+ { "validate_ip", FILTER_VALIDATE_IP, php_filter_validate_ip },
+
+ { "string", FILTER_SANITIZE_STRING, php_filter_string },
+ { "stripped", FILTER_SANITIZE_STRING, php_filter_string },
+ { "encoded", FILTER_SANITIZE_ENCODED, php_filter_encoded },
+ { "special_chars", FILTER_SANITIZE_SPECIAL_CHARS, php_filter_special_chars },
+ { "unsafe_raw", FILTER_UNSAFE_RAW, php_filter_unsafe_raw },
+ { "email", FILTER_SANITIZE_EMAIL, php_filter_email },
+ { "url", FILTER_SANITIZE_URL, php_filter_url },
+ { "number_int", FILTER_SANITIZE_NUMBER_INT, php_filter_number_int },
+ { "number_float", FILTER_SANITIZE_NUMBER_FLOAT, php_filter_number_float },
+ { "magic_quotes", FILTER_SANITIZE_MAGIC_QUOTES, php_filter_magic_quotes },
+
+ { "callback", FILTER_CALLBACK, php_filter_callback },
+};
+/* }}} */
+
+#ifndef PARSE_ENV
+#define PARSE_ENV 4
+#endif
+
+#ifndef PARSE_SERVER
+#define PARSE_SERVER 5
+#endif
+
+#ifndef PARSE_SESSION
+#define PARSE_SESSION 6
+#endif
+
+#ifndef PARSE_DATA
+#define PARSE_DATA 7
+#endif
+
+static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC);
+
+/* {{{ filter_functions[]
+ */
+zend_function_entry filter_functions[] = {
+ PHP_FE(input_get, NULL)
+ PHP_FE(input_get_args, NULL)
+ PHP_FE(input_filters_list, NULL)
+ PHP_FE(input_has_variable, NULL)
+ PHP_FE(input_name_to_filter, NULL)
+ PHP_FE(filter_data, NULL)
+ {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ filter_module_entry
+ */
+zend_module_entry filter_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+#endif
+ "filter",
+ filter_functions,
+ PHP_MINIT(filter),
+ PHP_MSHUTDOWN(filter),
+ NULL,
+ PHP_RSHUTDOWN(filter),
+ PHP_MINFO(filter),
+ "0.9.5-dev",
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_FILTER
+ZEND_GET_MODULE(filter)
+#endif
+
+static PHP_INI_MH(UpdateDefaultFilter) /* {{{ */
+{
+ int i, size = sizeof(filter_list) / sizeof(filter_list_entry);
+
+ for (i = 0; i < size; ++i) {
+ if ((strcasecmp(new_value, filter_list[i].name) == 0)) {
+ IF_G(default_filter) = filter_list[i].id;
+ return SUCCESS;
+ }
+ }
+ /* Fallback to "string" filter */
+ IF_G(default_filter) = FILTER_DEFAULT;
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_INI
+ */
+static PHP_INI_MH(OnUpdateFlags)
+{
+ if (!new_value) {
+ IF_G(default_filter_flags) = FILTER_FLAG_NO_ENCODE_QUOTES;
+ } else {
+ IF_G(default_filter_flags) = atoi(new_value);
+ }
+ return SUCCESS;
+}
+
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("filter.default", "unsafe_raw", PHP_INI_SYSTEM|PHP_INI_PERDIR, UpdateDefaultFilter, default_filter, zend_filter_globals, filter_globals)
+ PHP_INI_ENTRY("filter.default_flags", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateFlags)
+PHP_INI_END()
+/* }}} */
+
+static void php_filter_init_globals(zend_filter_globals *filter_globals) /* {{{ */
+{
+ filter_globals->post_array = NULL;
+ filter_globals->get_array = NULL;
+ filter_globals->cookie_array = NULL;
+ filter_globals->env_array = NULL;
+ filter_globals->server_array = NULL;
+ filter_globals->session_array = NULL;
+ filter_globals->default_filter = FILTER_DEFAULT;
+}
+/* }}} */
+
+#define PARSE_REQUEST 99
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(filter)
+{
+ ZEND_INIT_MODULE_GLOBALS(filter, php_filter_init_globals, NULL);
+
+ REGISTER_INI_ENTRIES();
+
+ REGISTER_LONG_CONSTANT("INPUT_POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("INPUT_GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("INPUT_COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("INPUT_ENV", PARSE_ENV, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("INPUT_SERVER", PARSE_SERVER, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("INPUT_SESSION", PARSE_SESSION, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("INPUT_DATA", PARSE_DATA, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_NONE", FILTER_FLAG_NONE, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_SCALAR", FILTER_FLAG_SCALAR, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ARRAY", FILTER_FLAG_ARRAY, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_VALIDATE_INT", FILTER_VALIDATE_INT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_VALIDATE_BOOLEAN", FILTER_VALIDATE_BOOLEAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_VALIDATE_FLOAT", FILTER_VALIDATE_FLOAT, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_VALIDATE_REGEXP", FILTER_VALIDATE_REGEXP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_VALIDATE_URL", FILTER_VALIDATE_URL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_VALIDATE_EMAIL", FILTER_VALIDATE_EMAIL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_VALIDATE_IP", FILTER_VALIDATE_IP, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_DEFAULT", FILTER_DEFAULT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_UNSAFE_RAW", FILTER_UNSAFE_RAW, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_STRING", FILTER_SANITIZE_STRING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_STRIPPED", FILTER_SANITIZE_STRING, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_ENCODED", FILTER_SANITIZE_ENCODED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_SPECIAL_CHARS", FILTER_SANITIZE_SPECIAL_CHARS, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_EMAIL", FILTER_SANITIZE_EMAIL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_URL", FILTER_SANITIZE_URL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_NUMBER_INT", FILTER_SANITIZE_NUMBER_INT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_NUMBER_FLOAT", FILTER_SANITIZE_NUMBER_FLOAT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_SANITIZE_MAGIC_QUOTES", FILTER_SANITIZE_MAGIC_QUOTES, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_CALLBACK", FILTER_CALLBACK, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ALLOW_OCTAL", FILTER_FLAG_ALLOW_OCTAL, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ALLOW_HEX", FILTER_FLAG_ALLOW_HEX, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_STRIP_LOW", FILTER_FLAG_STRIP_LOW, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_STRIP_HIGH", FILTER_FLAG_STRIP_HIGH, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ENCODE_LOW", FILTER_FLAG_ENCODE_LOW, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ENCODE_HIGH", FILTER_FLAG_ENCODE_HIGH, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ENCODE_AMP", FILTER_FLAG_ENCODE_AMP, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_ENCODE_QUOTES", FILTER_FLAG_NO_ENCODE_QUOTES, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_EMPTY_STRING_NULL", FILTER_FLAG_EMPTY_STRING_NULL, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ALLOW_FRACTION", FILTER_FLAG_ALLOW_FRACTION, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ALLOW_THOUSAND", FILTER_FLAG_ALLOW_THOUSAND, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_ALLOW_SCIENTIFIC", FILTER_FLAG_ALLOW_SCIENTIFIC, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_SCHEME_REQUIRED", FILTER_FLAG_SCHEME_REQUIRED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_HOST_REQUIRED", FILTER_FLAG_HOST_REQUIRED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_PATH_REQUIRED", FILTER_FLAG_PATH_REQUIRED, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_QUERY_REQUIRED", FILTER_FLAG_QUERY_REQUIRED, CONST_CS | CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_IPV4", FILTER_FLAG_IPV4, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_IPV6", FILTER_FLAG_IPV6, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_RES_RANGE", FILTER_FLAG_NO_RES_RANGE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_PRIV_RANGE", FILTER_FLAG_NO_PRIV_RANGE, CONST_CS | CONST_PERSISTENT);
+
+ sapi_register_input_filter(php_sapi_filter);
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(filter)
+{
+ UNREGISTER_INI_ENTRIES();
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_RSHUTDOWN_FUNCTION
+ */
+#define VAR_ARRAY_COPY_DTOR(a) \
+ if (IF_G(a)) { \
+ zval_ptr_dtor(&IF_G(a)); \
+ IF_G(a) = NULL; \
+ }
+PHP_RSHUTDOWN_FUNCTION(filter)
+{
+ VAR_ARRAY_COPY_DTOR(get_array)
+ VAR_ARRAY_COPY_DTOR(post_array)
+ VAR_ARRAY_COPY_DTOR(cookie_array)
+ VAR_ARRAY_COPY_DTOR(server_array)
+ VAR_ARRAY_COPY_DTOR(env_array)
+ VAR_ARRAY_COPY_DTOR(session_array)
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(filter)
+{
+ php_info_print_table_start();
+ php_info_print_table_row( 2, "Input Validation and Filtering", "enabled" );
+ php_info_print_table_row( 2, "Revision", "$Revision$");
+ php_info_print_table_end();
+
+ DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+
+static filter_list_entry php_find_filter(long id) /* {{{ */
+{
+ int i, size = sizeof(filter_list) / sizeof(filter_list_entry);
+
+ for (i = 0; i < size; ++i) {
+ if (filter_list[i].id == id) {
+ return filter_list[i];
+ }
+ }
+ /* Fallback to "string" filter */
+ for (i = 0; i < size; ++i) {
+ if (filter_list[i].id == FILTER_DEFAULT) {
+ return filter_list[i];
+ }
+ }
+ /* To shut up GCC */
+ return filter_list[0];
+}
+/* }}} */
+
+static void php_zval_filter(zval *value, long filter, long flags, zval *options, char* charset TSRMLS_DC) /* {{{ */
+{
+ filter_list_entry filter_func;
+
+ filter_func = php_find_filter(filter);
+
+ if (!filter_func.id) {
+ /* Find default filter */
+ filter_func = php_find_filter(FILTER_DEFAULT);
+ }
+
+ /* Here be strings */
+ convert_to_string(value);
+
+ filter_func.function(value, flags, options, charset TSRMLS_CC);
+}
+/* }}} */
+
+static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC) /* {{{ */
+{
+ zval new_var, raw_var;
+ zval *array_ptr = NULL, *orig_array_ptr = NULL;
+ char *orig_var;
+ int retval = 0;
+
+ assert(*val != NULL);
+
+#define PARSE_CASE(s,a,t) \
+ case s: \
+ if (!IF_G(a)) { \
+ ALLOC_ZVAL(array_ptr); \
+ array_init(array_ptr); \
+ INIT_PZVAL(array_ptr); \
+ IF_G(a) = array_ptr; \
+ } else { \
+ array_ptr = IF_G(a); \
+ } \
+ orig_array_ptr = PG(http_globals)[t]; \
+ break;
+
+ switch (arg) {
+ PARSE_CASE(PARSE_POST, post_array, TRACK_VARS_POST)
+ PARSE_CASE(PARSE_GET, get_array, TRACK_VARS_GET)
+ PARSE_CASE(PARSE_COOKIE, cookie_array, TRACK_VARS_COOKIE)
+ PARSE_CASE(PARSE_SERVER, server_array, TRACK_VARS_SERVER)
+ PARSE_CASE(PARSE_ENV, env_array, TRACK_VARS_ENV)
+
+ case PARSE_STRING: /* PARSE_STRING is used by parse_str() function */
+ retval = 1;
+ break;
+ }
+
+ if (array_ptr) {
+ /* Make a copy of the variable name, as php_register_variable_ex seems to
+ * modify it */
+ orig_var = estrdup(var);
+
+ /* Store the RAW variable internally */
+ /* FIXME: Should not use php_register_variable_ex as that also registers
+ * globals when register_globals is turned on */
+ Z_STRLEN(raw_var) = val_len;
+ Z_STRVAL(raw_var) = estrndup(*val, val_len + 1);
+ Z_TYPE(raw_var) = IS_STRING;
+
+ php_register_variable_ex(var, &raw_var, array_ptr TSRMLS_CC);
+ }
+
+ /* Register mangled variable */
+ /* FIXME: Should not use php_register_variable_ex as that also registers
+ * globals when register_globals is turned on */
+ Z_STRLEN(new_var) = val_len;
+ Z_STRVAL(new_var) = estrndup(*val, val_len + 1);
+ Z_TYPE(new_var) = IS_STRING;
+
+ if (val_len) {
+ if (! (IF_G(default_filter) == FILTER_UNSAFE_RAW)) {
+ php_zval_filter(&new_var, IF_G(default_filter), IF_G(default_filter_flags), NULL, NULL/*charset*/ TSRMLS_CC);
+ }
+ }
+
+ if (orig_array_ptr) {
+ php_register_variable_ex(orig_var, &new_var, orig_array_ptr TSRMLS_CC);
+ }
+ if (array_ptr) {
+ efree(orig_var);
+ }
+
+ if (retval) {
+ if (new_val_len) {
+ *new_val_len = Z_STRLEN(new_var);
+ }
+ efree(*val);
+ if (Z_STRLEN(new_var)) {
+ *val = estrndup(Z_STRVAL(new_var), Z_STRLEN(new_var) + 1);
+ zval_dtor(&new_var);
+ } else {
+ *val = estrdup("");
+ }
+ }
+
+ return retval;
+}
+/* }}} */
+
+static void php_zval_filter_recursive(zval *value, long filter, long flags, zval *options, char *charset TSRMLS_DC) /* {{{ */
+{
+ zval **element;
+ HashPosition pos;
+
+ if (Z_TYPE_P(value) == IS_ARRAY) {
+ for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(value), &pos);
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(value), (void **) &element, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(Z_ARRVAL_P(value), &pos)) {
+ php_zval_filter_recursive(*element, filter, flags, options, charset TSRMLS_CC);
+ }
+ } else {
+ php_zval_filter(value, filter, flags, options, charset TSRMLS_CC);
+ }
+}
+/* }}} */
+
+static zval * php_filter_get_storage(long arg TSRMLS_DC) /* {{{ */
+{
+ zval * array_ptr = NULL;
+ zend_bool jit_initialization = (PG(auto_globals_jit) && !PG(register_globals) && !PG(register_long_arrays));
+ switch (arg) {
+ case PARSE_GET:
+ array_ptr = IF_G(get_array);
+ break;
+ case PARSE_POST:
+ array_ptr = IF_G(post_array);
+ break;
+ case PARSE_COOKIE:
+ array_ptr = IF_G(cookie_array);
+ break;
+ case PARSE_SERVER:
+ if(jit_initialization) zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
+ array_ptr = IF_G(server_array);
+ break;
+ case PARSE_ENV:
+ if(jit_initialization) zend_is_auto_global("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
+ array_ptr = IF_G(env_array);
+ break;
+ }
+
+ return array_ptr;
+}
+/* }}} */
+
+/* {{{ proto mixed input_has_variable(constant type, string variable_name)
+ * Returns true if the variable with the name 'name' exists in source.
+ */
+PHP_FUNCTION(input_has_variable)
+{
+ long arg;
+ char *var;
+ int var_len;
+ zval **tmp;
+ zval *array_ptr = NULL;
+ HashTable *hash_ptr;
+ int found = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
+ return;
+ }
+
+ array_ptr = php_filter_get_storage(arg TSRMLS_CC);
+
+ if (!array_ptr) {
+ RETURN_FALSE;
+ }
+
+ if (!found) {
+ hash_ptr = HASH_OF(array_ptr);
+
+ if (hash_ptr && zend_hash_find(hash_ptr, var, var_len + 1, (void **)&tmp) == SUCCESS) {
+ RETURN_TRUE;
+ }
+ }
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto mixed input_get(constant type, string variable_name [, int filter [, mixed flags [, string charset]]])
+ * Returns the filtered variable 'name'* from source `type`.
+ */
+PHP_FUNCTION(input_get)
+{
+ long arg, filter = FILTER_DEFAULT;
+ char *var, *charset = NULL;
+ int var_len, charset_len;
+ zval *flags = NULL;
+ zval **tmp;
+ zval *array_ptr = NULL, *array_ptr2 = NULL, *array_ptr3 = NULL;
+ HashTable *hash_ptr;
+ int found = 0;
+ long filter_flags = 0;
+ zval *options = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|lzs", &arg, &var, &var_len, &filter, &flags, &charset, &charset_len) == FAILURE) {
+ return;
+ }
+
+ if (flags) {
+ switch (Z_TYPE_P(flags)) {
+ case IS_ARRAY:
+ options = flags;
+ break;
+
+ case IS_STRING:
+ case IS_BOOL:
+ case IS_LONG:
+ convert_to_long(flags);
+ filter_flags = Z_LVAL_P(flags);
+ options = NULL;
+ break;
+ }
+ }
+
+ switch(arg) {
+ case PARSE_GET:
+ case PARSE_POST:
+ case PARSE_COOKIE:
+ case PARSE_SERVER:
+ case PARSE_ENV:
+ array_ptr = php_filter_get_storage(arg TSRMLS_CC);
+ break;
+
+ case PARSE_SESSION:
+ /* FIXME: Implement session source */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "INPUT_SESSION not implemented");
+ break;
+
+ case PARSE_REQUEST:
+ /* FIXME: Implement request source */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "INPUT_REQUEST not implemented");
+ return;
+ if (PG(variables_order)) {
+ zval **a_ptr = &array_ptr;
+ char *p, *variables_order = PG(variables_order);
+
+ for (p = variables_order; p && *p; p++) {
+ switch (*p) {
+ case 'p':
+ case 'P':
+ if (IF_G(default_filter) != FILTER_UNSAFE_RAW) {
+ *a_ptr = IF_G(post_array);
+ } else {
+ *a_ptr = PG(http_globals)[TRACK_VARS_POST];
+ }
+ break;
+ case 'g':
+ case 'G':
+ if (IF_G(default_filter) != FILTER_UNSAFE_RAW) {
+ *a_ptr = IF_G(get_array);
+ } else {
+ *a_ptr = PG(http_globals)[TRACK_VARS_GET];
+ }
+ break;
+ case 'c':
+ case 'C':
+ if (IF_G(default_filter) != FILTER_UNSAFE_RAW) {
+ *a_ptr = IF_G(cookie_array);
+ } else {
+ *a_ptr = PG(http_globals)[TRACK_VARS_COOKIE];
+ }
+ break;
+ }
+ if (array_ptr && !array_ptr2) {
+ a_ptr = &array_ptr2;
+ continue;
+ }
+ if (array_ptr2 && !array_ptr3) {
+ a_ptr = &array_ptr3;
+ }
+ }
+ } else {
+ array_ptr = php_filter_get_storage(PARSE_GET TSRMLS_CC);
+ }
+ }
+
+ if (!array_ptr) {
+ RETURN_FALSE;
+ }
+
+ if (array_ptr3) {
+ hash_ptr = HASH_OF(array_ptr3);
+ if (hash_ptr && zend_hash_find(hash_ptr, var, var_len + 1, (void **)&tmp) == SUCCESS) {
+ *return_value = **tmp;
+ found = 1;
+ }
+ }
+
+ if (array_ptr2 && !found) {
+ hash_ptr = HASH_OF(array_ptr2);
+ if (hash_ptr && zend_hash_find(hash_ptr, var, var_len + 1, (void **)&tmp) == SUCCESS) {
+ *return_value = **tmp;
+ found = 1;
+ }
+ }
+
+ if (!found) {
+ hash_ptr = HASH_OF(array_ptr);
+
+ if (hash_ptr && zend_hash_find(hash_ptr, var, var_len + 1, (void **)&tmp) == SUCCESS) {
+ *return_value = **tmp;
+ found = 1;
+ }
+ }
+
+ if (found) {
+ zval_copy_ctor(return_value); /* Watch out for empty strings */
+ php_zval_filter_recursive(return_value, filter, filter_flags, options, charset TSRMLS_CC);
+ } else {
+ RETURN_NULL();
+ }
+}
+/* }}} */
+
+/* {{{ proto mixed input_get_args(array definition, constant type [, array data])
+ * Returns an array with all arguments defined in 'definition'.
+ */
+PHP_FUNCTION(input_get_args)
+{
+ long filter = FILTER_DEFAULT;
+ char *charset = NULL;
+ zval **tmp, ** option;
+ int filter_flags = FILTER_FLAG_SCALAR;
+ zval *options = NULL, *temparray = NULL;
+
+ zval *args_array, *values = NULL;
+ HashTable *args_hash;
+ HashPosition pos;
+
+ HashTable * g_hash;
+
+ long args_from = 0;
+ long elm_count;
+ char *key;
+ unsigned int key_len;
+ unsigned long index;
+
+ /* pointers to the zval array GET, POST,... */
+ zval *array_ptr = NULL;
+ zval **element;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|a", &args_array, &args_from, &values) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ args_hash = HASH_OF(args_array);
+ elm_count = zend_hash_num_elements(args_hash);
+
+ if (elm_count < 1) {
+ RETURN_NULL();
+ }
+
+ switch (args_from) {
+ case PARSE_GET:
+ case PARSE_POST:
+ case PARSE_COOKIE:
+ case PARSE_SERVER:
+ case PARSE_ENV:
+ array_ptr = php_filter_get_storage(args_from TSRMLS_CC);
+ break;
+
+ case PARSE_DATA:
+ array_ptr = values;
+ break;
+
+ case PARSE_SESSION:
+ /* FIXME: Implement session source */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "INPUT_SESSION not implemented");
+ break;
+
+ case PARSE_REQUEST:
+ /* FIXME: Implement session source */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "INPUT_REQUEST not implemented");
+ return;
+ break;
+
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown INPUT method");
+ return;
+ break;
+ }
+
+ if (!array_ptr) {
+ RETURN_FALSE;
+ } else {
+ g_hash = HASH_OF(array_ptr);
+ zend_hash_internal_pointer_reset_ex(g_hash, &pos);
+ array_init(return_value);
+ }
+
+ for (zend_hash_internal_pointer_reset_ex(args_hash, &pos);
+ zend_hash_get_current_data_ex(args_hash, (void **) &element, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(args_hash, &pos)) {
+
+ if (zend_hash_get_current_key_ex(args_hash, &key, &key_len, &index, 0, &pos) != HASH_KEY_IS_STRING) {
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+
+ if (g_hash && zend_hash_find(g_hash, key, key_len, (void **)&tmp) == SUCCESS) {
+ if (Z_TYPE_PP(element) != IS_ARRAY) {
+ convert_to_long(*element);
+ filter = Z_LVAL_PP(element);
+ filter_flags = FILTER_FLAG_SCALAR;
+
+ if ((filter_flags & FILTER_FLAG_SCALAR) && Z_TYPE_PP(tmp) == IS_ARRAY) {
+ /* asked for scalar and found an array do not test further */
+ add_assoc_bool(return_value, key, 0);
+ continue;
+ }
+
+ } else {
+ if (zend_hash_find(HASH_OF(*element), "filter", sizeof("filter"), (void **)&option) == SUCCESS) {
+ convert_to_long(*option);
+ filter = Z_LVAL_PP(option);
+ }
+
+ if (zend_hash_find(HASH_OF(*element), "options", sizeof("options"), (void **)&option) == SUCCESS) {
+ if (Z_TYPE_PP(option) == IS_ARRAY) {
+ options = *option;
+ }
+ } else {
+ options = NULL;
+ }
+
+ if (zend_hash_find(HASH_OF(*element), "flags", sizeof("flags"), (void **)&option) == SUCCESS) {
+
+ switch (Z_TYPE_PP(option)) {
+ case IS_ARRAY:
+ break;
+ default:
+ convert_to_long(*option);
+ filter_flags = Z_LVAL_PP(option);
+ break;
+ }
+ } else {
+ filter_flags = FILTER_FLAG_SCALAR;
+ }
+
+ if ((filter_flags & FILTER_FLAG_SCALAR) && Z_TYPE_PP(tmp) == IS_ARRAY) {
+ /* asked for scalar and found an array do not test further */
+ add_assoc_bool(return_value, key, 0);
+ continue;
+ }
+
+ if (zend_hash_find(HASH_OF(*element), "charset", sizeof("charset"), (void **)&option) == SUCCESS) {
+ convert_to_string(*option);
+ charset = Z_STRVAL_PP(option);
+ }
+ }
+
+ if (filter_flags & FILTER_FLAG_ARRAY) {
+ php_zval_filter_recursive(*tmp, filter, filter_flags, options, charset TSRMLS_CC);
+
+ /* ARRAY always returns an array */
+ if (Z_TYPE_PP(tmp) != IS_ARRAY) {
+ ALLOC_INIT_ZVAL(temparray);
+ array_init(temparray);
+ add_next_index_zval(temparray, *tmp);
+ *tmp = temparray;
+ }
+ } else {
+ php_zval_filter(*tmp, filter, filter_flags, options, charset TSRMLS_CC);
+ }
+
+ add_assoc_zval(return_value, key, *tmp);
+ } else {
+ add_assoc_null(return_value, key);
+ }
+ filter = FILTER_DEFAULT;
+ filter_flags = FILTER_FLAG_SCALAR;
+ }
+}
+/* }}} */
+
+/* {{{ proto input_filters_list()
+ * Returns a list of all supported filters */
+PHP_FUNCTION(input_filters_list)
+{
+ int i, size = sizeof(filter_list) / sizeof(filter_list_entry);
+
+ array_init(return_value);
+ for (i = 0; i < size; ++i) {
+ add_next_index_string(return_value, filter_list[i].name, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto input_name_to_filter(string filtername)
+ * Returns the filter ID belonging to a named filter */
+PHP_FUNCTION(input_name_to_filter)
+{
+ int i, filter_len;
+ int size = sizeof(filter_list) / sizeof(filter_list_entry);
+ char *filter;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filter, &filter_len) == FAILURE) {
+ return;
+ }
+
+ for (i = 0; i < size; ++i) {
+ if (strcmp(filter_list[i].name, filter) == 0) {
+ RETURN_LONG(filter_list[i].id);
+ }
+ }
+ RETURN_NULL();
+}
+/* }}} */
+
+/* {{{ proto filter_data(mixed variable, int filter [, mixed filter_options [, string charset ]])
+ * Returns the filterd variable (scalar or array can be used).
+ */
+PHP_FUNCTION(filter_data)
+{
+ long filter = FILTER_DEFAULT;
+ char *charset = NULL;
+ int charset_len;
+ zval *var, *flags = NULL;
+ int filter_flags = 0;
+ zval *options = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/l|zs", &var, &filter, &flags, &charset, &charset_len) == FAILURE) {
+ return;
+ }
+
+ if (filter != FILTER_CALLBACK) {
+ if (flags) {
+ switch (Z_TYPE_P(flags)) {
+ case IS_ARRAY:
+ options = flags;
+ break;
+
+ case IS_STRING:
+ case IS_BOOL:
+ case IS_LONG:
+ convert_to_long(flags);
+ filter_flags = Z_LVAL_P(flags);
+ options = NULL;
+ break;
+ }
+ }
+ } else {
+ if (flags) {
+ switch (Z_TYPE_P(flags)) {
+ case IS_ARRAY:
+ case IS_STRING:
+ options = flags;
+ break;
+
+ default:
+ convert_to_string(flags);
+ options = flags;
+ break;
+ }
+ }
+ }
+ php_zval_filter_recursive(var, filter, filter_flags, options, charset TSRMLS_CC);
+ RETURN_ZVAL(var, 1, 0);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <derick@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef FILTER_PRIVATE_H
+#define FILTER_PRIVATE_H
+
+#define FILTER_FLAG_NONE 0x0000
+
+#define FILTER_FLAG_ARRAY 0x1000000
+#define FILTER_FLAG_SCALAR 0x2000000
+
+#define FILTER_FLAG_ALLOW_OCTAL 0x0001
+#define FILTER_FLAG_ALLOW_HEX 0x0002
+
+#define FILTER_FLAG_STRIP_LOW 0x0004
+#define FILTER_FLAG_STRIP_HIGH 0x0008
+#define FILTER_FLAG_ENCODE_LOW 0x0010
+#define FILTER_FLAG_ENCODE_HIGH 0x0020
+#define FILTER_FLAG_ENCODE_AMP 0x0040
+#define FILTER_FLAG_NO_ENCODE_QUOTES 0x0080
+#define FILTER_FLAG_EMPTY_STRING_NULL 0x0100
+
+#define FILTER_FLAG_ALLOW_FRACTION 0x1000
+#define FILTER_FLAG_ALLOW_THOUSAND 0x2000
+#define FILTER_FLAG_ALLOW_SCIENTIFIC 0x4000
+
+#define FILTER_FLAG_SCHEME_REQUIRED 0x010000
+#define FILTER_FLAG_HOST_REQUIRED 0x020000
+#define FILTER_FLAG_PATH_REQUIRED 0x040000
+#define FILTER_FLAG_QUERY_REQUIRED 0x080000
+
+#define FILTER_FLAG_IPV4 0x100000
+#define FILTER_FLAG_IPV6 0x200000
+#define FILTER_FLAG_NO_RES_RANGE 0x400000
+#define FILTER_FLAG_NO_PRIV_RANGE 0x800000
+
+#define FILTER_VALIDATE_INT 0x0101
+#define FILTER_VALIDATE_BOOLEAN 0x0102
+#define FILTER_VALIDATE_FLOAT 0x0103
+
+#define FILTER_VALIDATE_REGEXP 0x0110
+#define FILTER_VALIDATE_URL 0x0111
+#define FILTER_VALIDATE_EMAIL 0x0112
+#define FILTER_VALIDATE_IP 0x0113
+
+#define FILTER_VALIDATE_ALL 0x0100
+
+#define FILTER_DEFAULT 0x0204
+#define FILTER_UNSAFE_RAW 0x0204
+
+#define FILTER_SANITIZE_STRING 0x0201
+#define FILTER_SANITIZE_ENCODED 0x0202
+#define FILTER_SANITIZE_SPECIAL_CHARS 0x0203
+#define FILTER_SANITIZE_EMAIL 0x0205
+#define FILTER_SANITIZE_URL 0x0206
+#define FILTER_SANITIZE_NUMBER_INT 0x0207
+#define FILTER_SANITIZE_NUMBER_FLOAT 0x0208
+#define FILTER_SANITIZE_MAGIC_QUOTES 0x0209
+
+#define FILTER_SANITIZE_ALL 0x0200
+
+#define FILTER_CALLBACK 0x0400
+
+#endif /* FILTER_PRIVATE_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Derick Rethans <derick@php.net> |
+ | Pierre-A. Joye <pierre@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "php_filter.h"
+#include "filter_private.h"
+#include "ext/standard/url.h"
+#include "ext/pcre/php_pcre.h"
+
+/* {{{ FETCH_LONG_OPTION(var_name, option_name) */
+#define FETCH_LONG_OPTION(var_name, option_name) \
+ var_name = 0; \
+ var_name##_set = 0; \
+ if (option_array) { \
+ if (zend_hash_find(HASH_OF(option_array), option_name, sizeof(option_name), (void **) &option_val) == SUCCESS) { \
+ convert_to_long(*option_val); \
+ var_name = Z_LVAL_PP(option_val); \
+ var_name##_set = 1; \
+ } \
+ }
+/* }}} */
+
+/* {{{ FETCH_STRING_OPTION(var_name, option_name) */
+#define FETCH_STRING_OPTION(var_name, option_name) \
+ var_name = NULL; \
+ var_name##_set = 0; \
+ if (option_array) { \
+ if (zend_hash_find(HASH_OF(option_array), option_name, sizeof(option_name), (void **) &option_val) == SUCCESS) { \
+ convert_to_string(*option_val); \
+ var_name = Z_STRVAL_PP(option_val); \
+ var_name##_set = 1; \
+ var_name##_len = Z_STRLEN_PP(option_val); \
+ } \
+ }
+/* }}} */
+
+#define TYPE_INT 1
+#define TYPE_HEX 2
+#define TYPE_OCTAL 3
+#define FORMAT_IPV4 4
+#define FORMAT_IPV6 6
+
+void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+{
+ zval **option_val;
+ long min_range, max_range, option_flags;
+ int min_range_set, max_range_set, option_flags_set;
+ int allow_octal = 0, allow_hex = 0;
+ int len;
+ long ctx_type, ctx_value, ctx_multiply;
+ char *p, *start, *end;
+
+ /* Parse options */
+ FETCH_LONG_OPTION(min_range, "min_range");
+ FETCH_LONG_OPTION(max_range, "max_range");
+ FETCH_LONG_OPTION(option_flags, "flags");
+
+ if (option_flags_set && (option_flags & FILTER_FLAG_ALLOW_OCTAL)) {
+ allow_octal = 1;
+ }
+
+ if (option_flags_set && (option_flags & FILTER_FLAG_ALLOW_HEX)) {
+ allow_hex = 1;
+ }
+
+ len = Z_STRLEN_P(value);
+
+ if (len == 0) {
+ if (min_range_set && (0 < min_range)) {
+ goto stateE;
+ }
+ if (max_range_set && (0 > max_range)) {
+ goto stateE;
+ }
+ zval_dtor(value);
+ Z_TYPE_P(value) = IS_LONG;
+ Z_LVAL_P(value) = 0;
+ return;
+ }
+
+ /* Start the validating loop */
+ p = Z_STRVAL_P(value);
+ ctx_type = TYPE_INT;
+ ctx_value = 0;
+ ctx_multiply = 1;
+
+ /* fast(er) trim */
+ while (*p == ' ') {
+ p++;
+ len--;
+ }
+ start = p;
+
+ end = p + len - 1;
+ if (*end == ' ') {
+ unsigned int i;
+ for (i = len - 1; i >= 0; i--) {
+ if (p[i] != ' ') {
+ break;
+ }
+ }
+ i++;
+ p[i] = '\0';
+ }
+
+ /* state 0 */
+ if (*p == '-' || *p == '+') {
+ ctx_multiply = *p == '-' ? -1 : 1; p++;
+ }
+ goto stateOH1;
+
+stateI1: /* state "integer 1" */
+ if (*p >= '1' && *p <= '9') {
+ ctx_value += ((*p) - '0'); p++; goto stateI2;
+ } else {
+ goto stateE;
+ }
+
+stateI2: /* state "integer 2" */
+ if (*p >= '0' && *p <= '9') {
+ ctx_value *= 10; ctx_value += ((*p) - '0'); p++; goto stateI2;
+ } else {
+ goto stateT;
+ }
+
+stateOH1: /* state "octal or hex" */
+ if (*p != '0') {
+ goto stateI1;
+ }
+ p++;
+ if (*p == 'x' || *p == 'X') {
+ if (allow_hex) {
+ p++;
+ goto stateH1;
+ } else {
+ goto stateE;
+ }
+ } else if (*p >= '0' && *p <= '7') {
+ if (!allow_octal) {
+ goto stateE;
+ }
+ ctx_value = ((*p) - '0'); p++; goto stateO1;
+ }
+ goto stateT; /* lone 0 */
+
+stateO1: /* state "octal 1" */
+ ctx_type = TYPE_OCTAL;
+ if (*p >= '0' && *p <= '7') {
+ ctx_value *= 8; ctx_value += ((*p) - '0'); p++; goto stateO1;
+ } else {
+ goto stateT;
+ }
+
+stateH1: /* state "hex 1" */
+ ctx_type = TYPE_HEX;
+ if ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F')) {
+ ctx_value *= 16;
+ if (*p >= '0' && *p <= '9') {
+ ctx_value += ((*p) - '0');
+ }
+ if (*p >= 'a' && *p <= 'f') {
+ ctx_value += 10 + ((*p) - 'a');
+ }
+ if (*p >= 'A' && *p <= 'F') {
+ ctx_value += 10 + ((*p) - 'A');
+ }
+ p++;
+ goto stateH1;
+ } else {
+ goto stateT;
+ }
+
+stateT: /* state "tail" */
+ if (*p != '\0') {
+ goto stateE;
+ } else {
+ goto stateR;
+ }
+
+stateR: /* state 'return' */
+ ctx_value *= ctx_multiply;
+ if (min_range_set && (ctx_value < min_range)) {
+ goto stateE;
+ }
+ if (max_range_set && (ctx_value > max_range)) {
+ goto stateE;
+ }
+ zval_dtor(value);
+ Z_TYPE_P(value) = IS_LONG;
+ Z_LVAL_P(value) = ctx_value;
+ return;
+
+ /* state "error" */
+stateE:
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+}
+/* }}} */
+
+void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+{
+ /* returns true for "1", "true", "on" and "yes"
+ * returns false for "0", "false", "off", "no", and ""
+ * null otherwise. */
+ if ((strncasecmp(Z_STRVAL_P(value), "true", sizeof("true")) == 0) ||
+ (strncasecmp(Z_STRVAL_P(value), "yes", sizeof("yes")) == 0) ||
+ (strncasecmp(Z_STRVAL_P(value), "on", sizeof("on")) == 0) ||
+ (strncmp(Z_STRVAL_P(value), "1", sizeof("1")) == 0))
+ {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 1);
+ } else if ((strncasecmp(Z_STRVAL_P(value), "false", sizeof("false")) == 0) ||
+ (strncasecmp(Z_STRVAL_P(value), "off", sizeof("off")) == 0) ||
+ (strncasecmp(Z_STRVAL_P(value), "no", sizeof("no")) == 0) ||
+ (strncmp(Z_STRVAL_P(value), "0", sizeof("0")) == 0) ||
+ Z_STRLEN_P(value) == 0)
+ {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ } else {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+}
+/* }}} */
+
+void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+{
+ int len;
+ char *str, *start, *end;
+
+ zval **option_val;
+ char *decimal;
+ char dec_sep;
+
+ const char default_decimal[] = ".";
+ int decimal_set, decimal_len;
+
+ char tsd_sep[3] = "',.";
+
+ long options_flag;
+ int options_flag_set;
+
+ int sign = 1;
+
+ double ret_val;
+ double factor;
+
+ int exp_value = 0, exp_multiply = 1;
+
+ len = Z_STRLEN_P(value);
+
+ if (len < 1) {
+ zval_dtor(value);
+ Z_TYPE_P(value) = IS_DOUBLE;
+ Z_DVAL_P(value) = 0;
+ return;
+ }
+
+ str = Z_STRVAL_P(value);
+ start = str;
+
+ if (len == 1) {
+ if (*str >= '0' && *str <= '9') {
+ ret_val = (double)*str - '0';
+ } else if (*str == 'E' || *str == 'e') {
+ ret_val = 0;
+ }
+ zval_dtor(value);
+ Z_TYPE_P(value) = IS_DOUBLE;
+ Z_DVAL_P(value) = ret_val;
+ return;
+ }
+
+ FETCH_STRING_OPTION(decimal, "decimal");
+ FETCH_LONG_OPTION(options_flag, "flags");
+
+ if (decimal_set) {
+ if (decimal_len > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "decimal separator must be one char");
+ } else {
+ dec_sep = *decimal;
+ }
+ } else {
+ dec_sep = *default_decimal;
+ }
+
+ /* fast(er) trim */
+ while (*str == ' ') {
+ str++;
+ len--;
+ }
+ start = str;
+
+ end = str + len - 1;
+ if (*end == ' ') {
+ int i;
+ for (i = len - 1; i >= 0; i--) {
+ if (str[i] != ' ') {
+ break;
+ }
+ }
+ i++;
+ str[i] = '\0';
+ }
+
+ if (*str == '-') {
+ sign = -1;
+ str++;
+ start = str;
+ } else if (*str == '+') {
+ sign = 1;
+ str++;
+ start = str;
+ }
+
+ ret_val = 0.0;
+
+ if (*str == '0') {
+ /* leading zeros */
+ while (*(str++) == '0');
+ }
+
+ if (*str == dec_sep) {
+ str++;
+ goto stateDot;
+ }
+
+ ret_val = 0;
+
+ if (str != start) {
+ str--;
+ }
+
+ while (*str && *str != dec_sep) {
+ if ((options_flag & FILTER_FLAG_ALLOW_THOUSAND) && (*str == tsd_sep[0] || *str == tsd_sep[1] || *str == tsd_sep[2])) {
+ str++;
+ continue;
+ }
+
+ if (*str == 'e' || *str == 'E') {
+ goto stateExp;
+ }
+
+ if (*str < '0' || *str > '9') {
+ goto stateError;
+ }
+
+ ret_val *=10; ret_val += (*str - '0');
+ str++;
+ }
+ if (!(*str)) {
+ goto stateT;
+ }
+ str++;
+
+stateDot:
+ factor = 0.1;
+ while (*str) {
+ if (*str == 'e' || *str == 'E') {
+ goto stateExp;
+ }
+
+ if (*str < '0' || *str > '9') {
+ goto stateError;
+ }
+
+ ret_val += factor * (*str - '0');
+ factor /= 10;
+ str++;
+ }
+ if (!(*str)) {
+ goto stateT;
+ }
+
+stateExp:
+ str++;
+ switch (*str) {
+ case '-':
+ exp_multiply = -1;
+ str++;
+ break;
+ case '+':
+ exp_multiply = 1;
+ str++;
+ }
+
+ while (*str) {
+ if (*str < '0' || *str > '9') {
+ goto stateError;
+ }
+ exp_value *= 10;
+ exp_value += ((*str) - '0');
+ str++;
+ }
+
+stateT:
+ if (exp_value) {
+ exp_value *= exp_multiply;
+ ret_val *= pow(10, exp_value);
+ }
+
+ zval_dtor(value);
+ Z_TYPE_P(value) = IS_DOUBLE;
+ Z_DVAL_P(value) = sign * ret_val;
+ return;
+
+stateError:
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+}
+/* }}} */
+
+void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+{
+ zval **option_val;
+ char *regexp;
+ int regexp_len;
+ long option_flags;
+ int regexp_set, option_flags_set;
+
+ pcre *re = NULL;
+ pcre_extra *pcre_extra = NULL;
+ int preg_options = 0;
+
+ int ovector[3];
+ int matches;
+
+ /* Parse options */
+ FETCH_STRING_OPTION(regexp, "regexp");
+ FETCH_LONG_OPTION(option_flags, "flags");
+
+ if (!regexp_set) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'regexp' option missing");
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+
+ re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
+ if (!re) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+ matches = pcre_exec(re, NULL, Z_STRVAL_P(value), Z_STRLEN_P(value), 0, 0, ovector, 3);
+
+ /* 0 means that the vector is too small to hold all the captured substring offsets */
+ if (matches < 0) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+}
+/* }}} */
+
+void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+{
+ php_url *url;
+
+ /* Use parse_url - if it returns false, we return NULL */
+ url = php_url_parse_ex(Z_STRVAL_P(value), Z_STRLEN_P(value));
+
+ if (url == NULL) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+
+ if ((flags & FILTER_FLAG_SCHEME_REQUIRED) && url->scheme == NULL) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+ if ((flags & FILTER_FLAG_HOST_REQUIRED) && url->host == NULL) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+ if ((flags & FILTER_FLAG_PATH_REQUIRED) && url->path == NULL) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+ if ((flags & FILTER_FLAG_QUERY_REQUIRED) && url->query == NULL) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+ php_url_free(url);
+}
+/* }}} */
+
+void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+{
+ /* From http://cvs.php.net/co.php/pear/HTML_QuickForm/QuickForm/Rule/Email.php?r=1.4 */
+ const char *regexp = "/^((\\\"[^\\\"\\f\\n\\r\\t\\v\\b]+\\\")|([\\w\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\^\\`\\|\\{\\}]+(\\.[\\w\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\^\\`\\|\\{\\}]+)*))@((\\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\\-])+\\.)+[A-Za-z\\-]+))$/";
+
+ pcre *re = NULL;
+ pcre_extra *pcre_extra = NULL;
+ int preg_options = 0;
+ int ovector[150]; /* Needs to be a multiple of 3 */
+ int matches;
+
+
+ re = pcre_get_compiled_regex((char *)regexp, &pcre_extra, &preg_options TSRMLS_CC);
+ if (!re) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+ matches = pcre_exec(re, NULL, Z_STRVAL_P(value), Z_STRLEN_P(value), 0, 0, ovector, 3);
+
+ /* 0 means that the vector is too small to hold all the captured substring offsets */
+ if (matches < 0) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ }
+
+}
+/* }}} */
+
+static int _php_filter_validate_ipv4_count_dots(char *str) /* {{{ */
+{
+ char *s1, *s2, *s3, *s4;
+
+ s1 = strchr(str, '.');
+ if (!s1)
+ return 0;
+ s2 = strchr(s1 + 1, '.');
+ if (!s2)
+ return 1;
+ s3 = strchr(s2 + 1, '.');
+ if (!s3)
+ return 2;
+ s4 = strchr(s3 + 1, '.');
+ if (!s4)
+ return 3;
+ return 4; /* too many */
+}
+/* }}} */
+
+static int _php_filter_validate_ipv4_get_nr(char **str) /* {{{ */
+{
+ char *begin, *end, *ptr, *tmp_str;
+ int tmp_nr = -1;
+
+ begin = ptr = *str;
+ while ((*ptr >= '0') && (*ptr <= '9')) {
+ ++ptr;
+ }
+ end = ptr;
+ *str = end + 1;
+
+ if (end == begin) {
+ return -1;
+ }
+
+ tmp_str = calloc(1, end - begin + 1);
+ memcpy(tmp_str, begin, end - begin);
+ tmp_nr = strtol(tmp_str, NULL, 10);
+ free(tmp_str);
+
+ if (tmp_nr < 0 || tmp_nr > 255) {
+ tmp_nr = -1;
+ }
+ return tmp_nr;
+}
+/* }}} */
+
+static int _php_filter_validate_ipv4(char *str, int *ip TSRMLS_DC) /* {{{ */
+{
+ char *p;
+ int x;
+
+ if (_php_filter_validate_ipv4_count_dots(str) != 3) {
+ return 0;
+ }
+
+ p = str;
+ for (x = 0; x < 4; ++x) {
+ ip[x] = _php_filter_validate_ipv4_get_nr(&p);
+ if (ip[x] == -1) {
+ return 0;
+ }
+ }
+ return 1;
+}
+/* }}} */
+
+#define IS_HEX(s) if (!((s >= '0' && s <= '9') || (s >= 'a' && s <= 'f') ||(s >= 'A' && s <= 'F'))) { \
+ return 0; \
+}
+
+#define IPV6_LOOP_IN(str) \
+ if (*str == ':') { \
+ if (hexcode_found > 4) { \
+ return -134; \
+ } \
+ hexcode_found = 0; \
+ col_fnd++; \
+ } else { \
+ IS_HEX(*str); \
+ hexcode_found++; \
+ }
+
+static int _php_filter_validate_ipv6_(char *str TSRMLS_DC) /* {{{ */
+{
+ int hexcode_found = 0;
+ int compressed_2end = 0;
+ int col_fnd = 0;
+ char *start = str;
+ char *compressed = NULL, *t = str;
+ char *s2 = NULL, *ipv4=NULL;
+ int ip4elm[4];
+
+ if (!strchr(str, ':')) {
+ return 0;
+ }
+
+ /* Check for compressed expression. only one is allowed */
+ compressed = strstr(str, "::");
+ if (compressed) {
+ s2 = strstr(compressed+1, "::");
+ if (s2) {
+ return 0;
+ }
+ }
+
+ /* check for bundled IPv4 */
+ ipv4 = strchr(str, '.');
+
+ if (ipv4) {
+ while (*ipv4 != ':' && ipv4 >= start) {
+ ipv4--;
+ }
+
+ /* ::w.x.y.z */
+ if (compressed && ipv4 == (compressed + 1)) {
+ compressed_2end = 1;
+ }
+ ipv4++;
+
+ if (!_php_filter_validate_ipv4(ipv4, ip4elm TSRMLS_CC)) {
+ return 0;
+ }
+
+ if (compressed_2end) {
+ return 1;
+ }
+ }
+
+ if (!compressed) {
+ char *end;
+ if (ipv4) {
+ end = ipv4 - 1;
+ } else {
+ end = str + strlen(start);
+ }
+
+ while (*str && str <= end) {
+ IPV6_LOOP_IN(str);
+ str++;
+ }
+
+ if (!ipv4) {
+ if (col_fnd != 7) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ if (col_fnd != 6) {
+ return -1230;
+ } else {
+ return 1;
+ }
+ }
+ } else {
+ if (!ipv4) {
+ t = compressed - 1;
+ while (t >= start) {
+ IPV6_LOOP_IN(t);
+ t--;
+ }
+
+ if (hexcode_found > 4) {
+ return 0;
+ }
+
+ t = compressed + 2;
+ hexcode_found = 0;
+ while (*t) {
+ IPV6_LOOP_IN(t);
+ t++;
+ }
+
+ if (hexcode_found > 4) {
+ return 0;
+ }
+
+ if (col_fnd > 6) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ /* ipv4 part always at the end */
+ t = ipv4 - 1;
+ while (t >= (compressed + 2)) {
+ IPV6_LOOP_IN(t);
+ t--;
+ }
+
+ if (hexcode_found > 4) {
+ return 0;
+ }
+
+ hexcode_found = 0;
+ t = compressed - 1;
+ while (t >= start) {
+ IPV6_LOOP_IN(t);
+ t--;
+ }
+ if (hexcode_found > 4) {
+ return 0;
+ }
+
+ if (col_fnd > 6) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+/* }}} */
+
+void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
+{
+ /* validates an ipv4 or ipv6 IP, based on the flag (4, 6, or both) add a
+ * flag to throw out reserved ranges; multicast ranges... etc. If both
+ * allow_ipv4 and allow_ipv6 flags flag are used, then the first dot or
+ * colon determine the format */
+
+ char *str = NULL;
+ int ip[4];
+ int mode;
+
+ str = Z_STRVAL_P(value);
+
+ if (strchr(str, ':')) {
+ mode = FORMAT_IPV6;
+ } else if (strchr(str, '.')) {
+ mode = FORMAT_IPV4;
+ } else {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+
+ if (flags & (FILTER_FLAG_IPV4 || FILTER_FLAG_IPV6)) {
+ /* Both formats are cool */
+ } else if ((flags & FILTER_FLAG_IPV4) && mode == FORMAT_IPV6) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ } else if ((flags & FILTER_FLAG_IPV6) && mode == FORMAT_IPV4) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+
+ switch (mode) {
+ case FORMAT_IPV4:
+ if (!_php_filter_validate_ipv4(str, ip TSRMLS_CC)) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+
+ /* Check flags */
+ if (flags & FILTER_FLAG_NO_PRIV_RANGE) {
+ if (
+ (ip[0] == 10) ||
+ (ip[0] == 172 && (ip[1] >= 16 && ip[1] <= 31)) ||
+ (ip[0] == 192 && ip[1] == 168)
+ ) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+ }
+
+ if (flags & FILTER_FLAG_NO_RES_RANGE) {
+ if (
+ (ip[0] == 0) ||
+ (ip[0] == 169 && ip[1] == 254) ||
+ (ip[0] == 192 && ip[1] == 0 && ip[2] == 2) ||
+ (ip[0] >= 224 && ip[0] <= 255)
+ ) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+ }
+ break;
+
+ case FORMAT_IPV6:
+ {
+ int res = 0;
+ res = _php_filter_validate_ipv6_(str TSRMLS_CC);
+ if (res < 1) {
+ zval_dtor(value);
+ ZVAL_BOOL(value, 0);
+ return;
+ }
+ }
+ break;
+ }
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE package SYSTEM "../pear/package.dtd">
+<package>
+ <name>filter</name>
+ <summary>Extension for safely dealing with input parameters</summary>
+ <maintainers>
+ <maintainer>
+ <user>derick</user>
+ <name>Derick Rethans</name>
+ <email>derick@php.net</email>
+ <role>lead</role>
+ </maintainer>
+ <maintainer>
+ <user>rasmus</user>
+ <name>Rasmus Lerdorf</name>
+ <email>rasmus@php.net</email>
+ <role>lead</role>
+ </maintainer>
+ </maintainers>
+ <description>
+The Input Filter extension is meant to address this issue by implementing a set
+of filters and mechanisms that users can use to safely access their input data.
+ </description>
+ <license>PHP</license>
+ <release>
+ <state>beta</state>
+ <version>0.10.0</version>
+ <date>2006-05-14</date>
+ <notes>- Fixed PECL bug #6136, ini_set should not be able to change the filter.default (Pierre)
+- Fixed PECL bug #6639: uppercase hexadecimal digits are not supported
+- Fixed PECL bug #7733, Float exponential weird result (Pierre)
+- Fixed PECL bug #7715, Input_get float error (Pierre)
+- Implemented PECL req #6641: negative values for hexadecimal and octal numbers are not supported.
+- Added support for php pcre expressions (Pierre)
+- Fixed Possible leak in internal sapi_filter (Pierre)
+- Added input_get_args, fetches all input in one call (Pierre)
+- Added FILTER_FLAG_SCALAR and FILTER_FLAG_ARRAY , allows or not array values (Pierre)
+- Basic IPv6 (no option yet, only the syntax is verified) (Pierre)
+- Add support for custom decimal separator (Pierre)
+- INT and Float filters trim the values before the validations (spaces only) (Pierre)
+- input_get and input_get_args returns now FALSE when the validation failed
+ and NULL when the variable has not been found (Pierre)
+- Added JIT support
+ </notes>
+ <filelist>
+ <file role="src" name="config.m4"/>
+ <file role="src" name="config.w32"/>
+ <file role="src" name="filter.c"/>
+ <file role="src" name="filter_private.h"/>
+ <file role="src" name="callback_filter.c"/>
+ <file role="src" name="logical_filters.c"/>
+ <file role="src" name="sanitizing_filters.c"/>
+ <file role="src" name="php_filter.h"/>
+ <file role="doc" name="CREDITS"/>
+ <dir name="tests">
+ <file role="test" name="001.phpt"/>
+ <file role="test" name="002.phpt"/>
+ <file role="test" name="003.phpt"/>
+ <file role="test" name="004.phpt"/>
+ <file role="test" name="005.phpt"/>
+ <file role="test" name="006.phpt"/>
+ <file role="test" name="007.phpt"/>
+ <file role="test" name="008.phpt"/>
+ <file role="test" name="009.phpt"/>
+ <file role="test" name="010.phpt"/>
+ <file role="test" name="011.phpt"/>
+ <file role="test" name="012.phpt"/>
+ <file role="test" name="013.phpt"/>
+ <file role="test" name="014.phpt"/>
+ <file role="test" name="015.phpt"/>
+ <file role="test" name="016.phpt"/>
+ <file role="test" name="017.phpt"/>
+ <file role="test" name="018.phpt"/>
+ <file role="test" name="019.phpt"/>
+ <file role="test" name="020.phpt"/>
+ <file role="test" name="021.phpt"/>
+ <file role="test" name="022.phpt"/>
+ <file role="test" name="023.phpt"/>
+ <file role="test" name="024.phpt"/>
+ <file role="test" name="025.phpt"/>
+ <file role="test" name="026.phpt"/>
+ <file role="test" name="027.phpt"/>
+ <file role="test" name="028.phpt"/>
+ <file role="test" name="029.phpt"/>
+ <file role="test" name="030.phpt"/>
+ <file role="test" name="031.phpt"/>
+ <file role="test" name="032.phpt"/>
+ <file role="test" name="bug7586.phpt"/>
+ </dir>
+ </filelist>
+ <deps>
+ <dep type="php" rel="ge" version="5.0.0"/>
+ </deps>
+ </release>
+</package>
+<!--
+vim:et:ts=1:sw=1
+-->
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" packagerversion="1.4.6" version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+ <name>filter</name>
+ <channel>pecl.php.net</channel>
+ <summary>Extension for safely dealing with input parameters</summary>
+ <description>The Input Filter extension is meant to address this issue by implementing a set
+of filters and mechanisms that users can use to safely access their input data.
+
+ </description>
+ <lead>
+ <name>Derick Rethans</name>
+ <user>derick</user>
+ <email>derick@php.net</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>Rasmus Lerdorf</name>
+ <user>rasmus</user>
+ <email>rasmus@php.net</email>
+ <active>yes</active>
+ </lead>
+ <date>2006-05-14</date>
+ <time>10:04:15</time>
+ <version>
+ <release>0.10.0</release>
+ <api>0.10.0</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>- Fixed PECL bug #6136, ini_set should not be able to change the filter.default (Pierre)
+- Fixed PECL bug #6639: uppercase hexadecimal digits are not supported
+- Fixed PECL bug #7733, Float exponential weird result (Pierre)
+- Fixed PECL bug #7715, Input_get float error (Pierre)
+- Implemented PECL req #6641: negative values for hexadecimal and octal numbers are not supported.
+- Added support for php pcre expressions (Pierre)
+- Fixed Possible leak in internal sapi_filter (Pierre)
+- Added input_get_args, fetches all input in one call (Pierre)
+- Added FILTER_FLAG_SCALAR and FILTER_FLAG_ARRAY , allows or not array values (Pierre)
+- Basic IPv6 (no option yet, only the syntax is verified) (Pierre)
+- Add support for custom decimal separator (Pierre)
+- INT and Float filters trim the values before the validations (spaces only) (Pierre)
+- input_get and input_get_args returns now FALSE when the validation failed
+ and NULL when the variable has not been found (Pierre)
+- Added JIT support
+ </notes>
+ <contents>
+ <dir name="/">
+ <file name="callback_filter.c" role="src"/>
+ <file name="config.m4" role="src"/>
+ <file name="config.w32" role="src"/>
+ <file name="CREDITS" role="doc"/>
+ <file name="filter.c" role="src"/>
+ <file name="filter_private.h" role="src"/>
+ <file name="logical_filters.c" role="src"/>
+ <file name="php_filter.h" role="src"/>
+ <file name="sanitizing_filters.c" role="src"/>
+ <dir name="tests">
+ <file role="test" name="001.phpt"/>
+ <file role="test" name="002.phpt"/>
+ <file role="test" name="003.phpt"/>
+ <file role="test" name="004.phpt"/>
+ <file role="test" name="005.phpt"/>
+ <file role="test" name="006.phpt"/>
+ <file role="test" name="007.phpt"/>
+ <file role="test" name="008.phpt"/>
+ <file role="test" name="009.phpt"/>
+ <file role="test" name="010.phpt"/>
+ <file role="test" name="011.phpt"/>
+ <file role="test" name="012.phpt"/>
+ <file role="test" name="013.phpt"/>
+ <file role="test" name="014.phpt"/>
+ <file role="test" name="015.phpt"/>
+ <file role="test" name="016.phpt"/>
+ <file role="test" name="017.phpt"/>
+ <file role="test" name="018.phpt"/>
+ <file role="test" name="019.phpt"/>
+ <file role="test" name="020.phpt"/>
+ <file role="test" name="021.phpt"/>
+ <file role="test" name="022.phpt"/>
+ <file role="test" name="023.phpt"/>
+ <file role="test" name="024.phpt"/>
+ <file role="test" name="025.phpt"/>
+ <file role="test" name="026.phpt"/>
+ <file role="test" name="027.phpt"/>
+ <file role="test" name="028.phpt"/>
+ <file role="test" name="029.phpt"/>
+ <file role="test" name="030.phpt"/>
+ <file role="test" name="031.phpt"/>
+ <file role="test" name="032.phpt"/>
+ <file role="test" name="bug7586.phpt"/>
+ </dir>
+ </dir>
+<!-- / -->
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.0.0</min>
+ </php>
+ <pearinstaller>
+ <min>1.4.0b1</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <providesextension>filter</providesextension>
+ <extsrcrelease/>
+ <changelog>
+ <release>
+ <date>2006-01-23</date>
+ <time>10:04:15</time>
+ <version>
+ <release>0.9.4</release>
+ <api>0.9.4</api>
+ </version>
+ <stability>
+ <release>beta</release>
+ <api>beta</api>
+ </stability>
+ <notes>- Reimplement php_filter_callback() as exception-safe and without memleaks
+- Renamed all constants.
+- Fixed PECL bug #6124: Crash on HTML tags when using FS_STRING</notes>
+ </release>
+ </changelog>
+</package>
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@php.net> |
+ | Derick Rethans <derick@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_FILTER_H
+#define PHP_FILTER_H
+
+#include "SAPI.h"
+#include "zend_API.h"
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "ext/standard/php_string.h"
+#include "php_variables.h"
+
+extern zend_module_entry filter_module_entry;
+#define phpext_filter_ptr &filter_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_FILTER_API __declspec(dllexport)
+#else
+#define PHP_FILTER_API
+#endif
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+PHP_MINIT_FUNCTION(filter);
+PHP_MSHUTDOWN_FUNCTION(filter);
+PHP_RINIT_FUNCTION(filter);
+PHP_RSHUTDOWN_FUNCTION(filter);
+PHP_MINFO_FUNCTION(filter);
+
+PHP_FUNCTION(input_get);
+PHP_FUNCTION(input_get_args);
+PHP_FUNCTION(input_filters_list);
+PHP_FUNCTION(input_has_variable);
+PHP_FUNCTION(input_name_to_filter);
+PHP_FUNCTION(filter_data);
+
+ZEND_BEGIN_MODULE_GLOBALS(filter)
+ zval *post_array;
+ zval *get_array;
+ zval *cookie_array;
+ zval *env_array;
+ zval *server_array;
+ zval *session_array;
+ long default_filter;
+ long default_filter_flags;
+ZEND_END_MODULE_GLOBALS(filter)
+
+#ifdef ZTS
+#define IF_G(v) TSRMG(filter_globals_id, zend_filter_globals *, v)
+#else
+#define IF_G(v) (filter_globals.v)
+#endif
+
+
+#define PHP_INPUT_FILTER_PARAM_DECL zval *value, long flags, zval *option_array, char *charset TSRMLS_DC
+void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL);
+
+void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_url(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL);
+void php_filter_magic_quotes(PHP_INPUT_FILTER_PARAM_DECL);
+
+void php_filter_callback(PHP_INPUT_FILTER_PARAM_DECL);
+
+#endif /* FILTER_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
--- /dev/null
+--TEST--
+filter_data()
+--FILE--
+<?php
+
+var_dump(filter_data(array(1,"1","", "-23234", "text", "asdf234asdfgs", array()), FILTER_VALIDATE_INT));
+var_dump(filter_data(array(1.2,"1.7","", "-23234.123", "text", "asdf234.2asdfgs", array()), FILTER_VALIDATE_FLOAT));
+var_dump(filter_data(1, array()));
+var_dump(filter_data(1, FILTER_SANITIZE_STRING, 1));
+var_dump(filter_data(1, FILTER_SANITIZE_STRING, 0));
+var_dump(filter_data(1, FILTER_SANITIZE_STRING, array()));
+var_dump(filter_data(1, -1, array(123)));
+var_dump(filter_data(1, 0, array()));
+
+echo "Done\n";
+?>
+--EXPECTF--
+array(7) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(1)
+ [2]=>
+ int(0)
+ [3]=>
+ int(-23234)
+ [4]=>
+ bool(false)
+ [5]=>
+ bool(false)
+ [6]=>
+ array(0) {
+ }
+}
+array(7) {
+ [0]=>
+ float(1.2)
+ [1]=>
+ float(1.7)
+ [2]=>
+ float(0)
+ [3]=>
+ float(-23234.123)
+ [4]=>
+ bool(false)
+ [5]=>
+ bool(false)
+ [6]=>
+ array(0) {
+ }
+}
+
+Warning: filter_data() expects parameter 2 to be long, array given in %s on line %d
+NULL
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+string(1) "1"
+Done
--- /dev/null
+--TEST--
+filter_data() and flags
+--FILE--
+<?php
+var_dump(filter_data(" 234", FILTER_VALIDATE_INT));
+var_dump(filter_data("234 ", FILTER_VALIDATE_INT));
+var_dump(filter_data(" 234 ", FILTER_VALIDATE_INT));
+var_dump(filter_data("0xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("0Xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("0xFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("0XFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("07", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
+var_dump(filter_data("0xff0000", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("0666", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
+var_dump(filter_data("08", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
+var_dump(filter_data("00", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
+var_dump(filter_data("000", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
+
+var_dump(filter_data("-0xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("-0Xff", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("-0xFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("-0XFF", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("-07", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
+var_dump(filter_data("-0xff0000", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_HEX)));
+var_dump(filter_data("-0666", FILTER_VALIDATE_INT, array("flags"=>FILTER_FLAG_ALLOW_OCTAL)));
+
+var_dump(filter_data("6", FILTER_VALIDATE_INT, array("min_range"=>1, "max_range"=>7)));
+var_dump(filter_data("6", FILTER_VALIDATE_INT, array("min_range"=>0, "max_range"=>5)));
+var_dump(filter_data(-1, FILTER_VALIDATE_INT, array("min_range"=>1, "max_range"=>7)));
+var_dump(filter_data(-1, FILTER_VALIDATE_INT, array("min_range"=>-4, "max_range"=>7)));
+
+var_dump(filter_data("", FILTER_VALIDATE_INT, array("min_range"=>-4, "max_range"=>7)));
+var_dump(filter_data("", FILTER_VALIDATE_INT, array("min_range"=>2, "max_range"=>7)));
+var_dump(filter_data("", FILTER_VALIDATE_INT, array("min_range"=>-5, "max_range"=>-3)));
+var_dump(filter_data(345, FILTER_VALIDATE_INT, array("min_range"=>500, "max_range"=>100)));
+var_dump(filter_data("0ff", FILTER_VALIDATE_INT));
+var_dump(filter_data("010", FILTER_VALIDATE_INT));
+
+echo "Done\n";
+?>
+--EXPECT--
+int(234)
+int(234)
+int(234)
+int(255)
+int(255)
+int(255)
+int(255)
+int(7)
+int(16711680)
+int(438)
+bool(false)
+int(0)
+int(0)
+int(-255)
+int(-255)
+int(-255)
+int(-255)
+int(-7)
+int(-16711680)
+int(-438)
+int(6)
+bool(false)
+bool(false)
+int(-1)
+int(0)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+Done
--- /dev/null
+--TEST--
+filter_data() and FILTER_VALIDATE_URL
+--FILE--
+<?php
+
+$values = Array(
+'http://example.com/index.html',
+'http://www.example.com/index.php',
+'http://www.example/img/test.png',
+'http://www.example/img/dir/',
+'http://www.example/img/dir',
+'http//www.example/wrong/url/',
+'http:/www.example',
+'file:///tmp/test.c',
+'ftp://ftp.example.com/tmp/',
+'/tmp/test.c',
+'/',
+'http://',
+'http:/',
+'http:',
+'http',
+'',
+-1,
+array(),
+);
+foreach ($values as $value) {
+ var_dump(filter_data($value, FILTER_VALIDATE_URL));
+}
+
+
+var_dump(filter_data("qwe", FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
+var_dump(filter_data("http://qwe", FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
+var_dump(filter_data("http://", FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
+var_dump(filter_data("/tmp/test", FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
+var_dump(filter_data("http://www.example.com", FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
+var_dump(filter_data("http://www.example.com", FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
+var_dump(filter_data("http://www.example.com/path/at/the/server/", FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
+var_dump(filter_data("http://www.example.com/index.html", FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));
+var_dump(filter_data("http://www.example.com/index.php?a=b&c=d", FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));
+
+echo "Done\n";
+?>
+--EXPECTF--
+string(29) "http://example.com/index.html"
+string(32) "http://www.example.com/index.php"
+string(31) "http://www.example/img/test.png"
+string(27) "http://www.example/img/dir/"
+string(26) "http://www.example/img/dir"
+string(28) "http//www.example/wrong/url/"
+string(17) "http:/www.example"
+string(18) "file:///tmp/test.c"
+string(26) "ftp://ftp.example.com/tmp/"
+string(11) "/tmp/test.c"
+string(1) "/"
+bool(false)
+string(6) "http:/"
+string(5) "http:"
+string(4) "http"
+string(0) ""
+string(2) "-1"
+array(0) {
+}
+bool(false)
+string(10) "http://qwe"
+bool(false)
+bool(false)
+string(22) "http://www.example.com"
+bool(false)
+string(42) "http://www.example.com/path/at/the/server/"
+bool(false)
+string(40) "http://www.example.com/index.php?a=b&c=d"
+Done
--- /dev/null
+--TEST--
+filter_data() and FILTER_VALIDATE_EMAIL
+--FILE--
+<?php
+$values = Array(
+'a@b.c',
+'abuse@example.com',
+'test!.!@#$%^&*@example.com',
+'test@@#$%^&*())).com',
+'test@.com',
+'test@com',
+'@',
+'[]()/@example.com',
+'QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET',
+);
+foreach ($values as $value) {
+ var_dump(filter_data($value, FILTER_VALIDATE_EMAIL));
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+string(5) "a@b.c"
+string(17) "abuse@example.com"
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+string(57) "QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET"
+Done
--- /dev/null
+--TEST--
+filter_data() and FILTER_VALIDATE_REGEXP
+--FILE--
+<?php
+
+var_dump(filter_data("data", FILTER_VALIDATE_REGEXP, array("regexp"=>'/.*/')));
+var_dump(filter_data("data", FILTER_VALIDATE_REGEXP, array("regexp"=>'/^b(.*)/')));
+var_dump(filter_data("data", FILTER_VALIDATE_REGEXP, array("regexp"=>'/^d(.*)/')));
+var_dump(filter_data("data", FILTER_VALIDATE_REGEXP, array("regexp"=>'/blah/')));
+var_dump(filter_data("data", FILTER_VALIDATE_REGEXP, array("regexp"=>'/\[/')));
+var_dump(filter_data("data", FILTER_VALIDATE_REGEXP));
+
+echo "Done\n";
+?>
+--EXPECTF--
+string(4) "data"
+bool(false)
+string(4) "data"
+bool(false)
+bool(false)
+
+Warning: filter_data(): 'regexp' option missing in %s on line %d
+bool(false)
+Done
--- /dev/null
+--TEST--
+filter_data() and FILTER_VALIDATE_IP
+--FILE--
+<?php
+var_dump(filter_data("192.168.0.1", FILTER_VALIDATE_IP));
+var_dump(filter_data("192.168.0.1.1", FILTER_VALIDATE_IP));
+var_dump(filter_data("::1", FILTER_VALIDATE_IP));
+var_dump(filter_data("fe00::0", FILTER_VALIDATE_IP));
+var_dump(filter_data("::123456", FILTER_VALIDATE_IP));
+var_dump(filter_data("::1::b", FILTER_VALIDATE_IP));
+var_dump(filter_data("127.0.0.1", FILTER_VALIDATE_IP));
+var_dump(filter_data("192.168.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));
+var_dump(filter_data("192.0.34.166", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));
+var_dump(filter_data("127.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
+var_dump(filter_data("192.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
+var_dump(filter_data("192.0.34.166", FILTER_VALIDATE_IP));
+var_dump(filter_data("256.1237.123.1", FILTER_VALIDATE_IP));
+var_dump(filter_data("255.255.255.255", FILTER_VALIDATE_IP));
+var_dump(filter_data("255.255.255.255", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
+var_dump(filter_data("", FILTER_VALIDATE_IP));
+var_dump(filter_data(-1, FILTER_VALIDATE_IP));
+var_dump(filter_data("::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4));
+var_dump(filter_data("127.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
+var_dump(filter_data("::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
+var_dump(filter_data("127.0.0.1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV4));
+echo "Done\n";
+?>
+--EXPECT--
+string(11) "192.168.0.1"
+bool(false)
+string(3) "::1"
+string(7) "fe00::0"
+bool(false)
+bool(false)
+string(9) "127.0.0.1"
+bool(false)
+string(12) "192.0.34.166"
+string(9) "127.0.0.1"
+string(9) "192.0.0.1"
+string(12) "192.0.34.166"
+bool(false)
+string(15) "255.255.255.255"
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+string(3) "::1"
+string(9) "127.0.0.1"
+Done
--- /dev/null
+--TEST--
+filter_data() & FILTER_VALIDATE_IP and weird data
+--FILE--
+<?php
+
+var_dump(filter_data("....", FILTER_VALIDATE_IP));
+var_dump(filter_data("...", FILTER_VALIDATE_IP));
+var_dump(filter_data("..", FILTER_VALIDATE_IP));
+var_dump(filter_data(".", FILTER_VALIDATE_IP));
+var_dump(filter_data("1.1.1.1", FILTER_VALIDATE_IP));
+
+echo "Done\n";
+?>
+--EXPECTF--
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+string(7) "1.1.1.1"
+Done
--- /dev/null
+--TEST--
+filter_data() and IPv6
+--FILE--
+<?php
+$ipv6_test = array(
+ "::127.0.0.1" => true,
+ "FF01::101:127.0.1" => false,
+ "FF01:0:0:0:101:127.0.1.1" => false,
+ "FF01:0:0:0:237:101:127.0.1.1" => true,
+ "FF01::101" => true,
+ "A1080::8:800:200C:417A" => false,
+ "1080::8:Z00:200C:417A" => false,
+ "FF01::101::1" => false,
+ "1080::8:800:200C:417A" => true,
+ "1080:0:0:0:8:800:200C:417A" => true,
+ "2001:ec8:1:1:1:1:1:1" => true,
+ "ffff::FFFF:129.144.52.38" => true,
+ "::ffff:1.2.3.4" => true,
+ "0:0:0:0:0:FFFF:129.144.52.38" => true,
+ "0:0:0:0:0:0:13.1.68.3" => true,
+ "::13.1.68.3" => true,
+ "::FFFF:129.144.52.38" => true
+);
+foreach ($ipv6_test as $ip => $exp) {
+ $out = filter_data($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
+ $out = (int) ($out === false ? 0 : 1);
+ if ($exp != $out) {
+ echo "$ip failed\n";
+ }
+}
+
+echo "Ok\n";
+?>
+--EXPECT--
+Ok
--- /dev/null
+--TEST--
+filter_data() and FLOAT
+--FILE--
+<?php
+
+$floats = array(
+'1.234 ',
+' 1.234',
+'1.234' ,
+'1.2e3',
+'7E3',
+'7E3 ',
+' 7E3 ',
+' 7E-3 '
+);
+
+foreach ($floats as $float) {
+ $out = filter_data($float, FILTER_VALIDATE_FLOAT);
+ var_dump($out);
+}
+
+$floats = array(
+'1.234 ' => ',',
+'1,234' => ',',
+' 1.234' => '.',
+'1.234' => '..',
+'1.2e3' => ','
+);
+
+echo "\ncustom decimal:\n";
+foreach ($floats as $float => $dec) {
+ $out = filter_data($float, FILTER_VALIDATE_FLOAT, array('decimal' => $dec));
+ var_dump($out);
+}
+
+?>
+--EXPECTF--
+float(1.234)
+float(1.234)
+float(1.234)
+float(1200)
+float(7000)
+float(7000)
+float(7000)
+float(0.007)
+
+custom decimal:
+bool(false)
+float(1.234)
+float(1.234)
+
+Warning: filter_data(): decimal separator must be one char in %s on line %d
+bool(false)
+bool(false)
--- /dev/null
+--TEST--
+input_get_args()
+--FILE--
+<?php
+$data = array(
+ 'product_id' => 'libgd<script>',
+ 'component' => '10dhsajkkdhk <do>',
+ 'versions' => '2.0.33',
+ 'testscalar' => array('2','23','10','12'),
+ 'testarray' => '2',
+);
+
+$args = array(
+ 'product_id' => FILTER_SANITIZE_ENCODED,
+ 'component' => array(//'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FLAG_ARRAY,
+ 'options' => array("min_range"=>1, "max_range"=>10)
+ ),
+ 'versions' => array(
+ 'filter' => FILTER_SANITIZE_ENCODED,
+ 'flags' => FILTER_FLAG_SCALAR,
+ ),
+ 'doesnotexist' => FILTER_VALIDATE_INT,
+ 'testscalar' => FILTER_VALIDATE_INT,
+ 'testarray' => array(
+ 'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FLAG_ARRAY,
+ )
+
+);
+
+$myinputs = input_get_args($args, INPUT_DATA, $data);
+var_dump($myinputs);
+?>
+--EXPECT--
+array(6) {
+ ["product_id"]=>
+ string(17) "libgd%3Cscript%3E"
+ ["component"]=>
+ array(1) {
+ [0]=>
+ string(17) "10dhsajkkdhk <do>"
+ }
+ ["versions"]=>
+ string(6) "2.0.33"
+ ["doesnotexist"]=>
+ NULL
+ ["testscalar"]=>
+ bool(false)
+ ["testarray"]=>
+ array(1) {
+ [0]=>
+ int(2)
+ }
+}
--- /dev/null
+--TEST--
+Test all filters returned by input_filters_list()
+--FILE--
+<?php
+include dirname(__FILE__) . '/033_run.php';
+?>
+--EXPECT--
+int 1 123
+boolean 1
+float 1
+validate_regexp O'Henry
+validate_url http://a.b.c
+validate_email foo@bar.com
+validate_ip 1.2.3.4
+string PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc() O'Henry 하퍼
+stripped PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc() OHenry 하퍼
+encoded PHP 1 foo%40bar.com http%3A%2F%2Fa.b.c 1.2.3.4 123 123abc%3C%3E%28%29 O%27Henry %ED%95%98%ED%8D%BC
+special_chars PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O'Henry 하퍼
+unsafe_raw PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O'Henry 하퍼
+email PHP 1 foo@bar.com http//a.b.c 1.2.3.4 123 123abc O'Henry
+url PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O'Henry
+number_int 1 1234 123 123
+number_float 1 1.2.3.4 123 123
+magic_quotes PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O\'Henry 하퍼
+callback PHP 1 FOO@BAR.COM HTTP://A.B.C 1.2.3.4 123 123ABC<>() O'HENRY 하퍼
--- /dev/null
+<?php
+function test($data) {
+ return strtoupper($data);
+}
+$data = array("PHP","1","foo@bar.com","http://a.b.c","1.2.3.4","123","123abc<>()","O'Henry", "하퍼");
+foreach(input_filters_list() as $filter) {
+ if($filter=="validate_regexp") {
+ foreach($data as $k=>$d) $result[$k] = filter_data($d,input_name_to_filter($filter),array("regexp"=>'/^O.*/'));
+ } else {
+ foreach($data as $k=>$d) $result[$k] = filter_data($d,input_name_to_filter($filter),"test");
+ }
+ printf("%-20s",$filter);
+ printf("%-5s",$result[0]);
+ printf("%-3s",$result[1]);
+ printf("%-15s",$result[2]);
+ printf("%-20s",$result[3]);
+ printf("%-10s",$result[4]);
+ printf("%-5s",$result[5]);
+ printf("%-20s",$result[6]);
+ printf("%-15s",$result[7]);
+ printf("%-10s\n",$result[8]);
+}
+?>
--- /dev/null
+--TEST--
+input_get_args() filter not reseted between elements
+--FILE--
+<?php
+$data = array(
+ 'product_id' => 'libgd<script>',
+ 'component' => '10dhsajkkdhk <do>',
+ 'versions' => '2.0.33',
+ 'testscalar' => array('2','23','10','12'),
+ 'testarray' => '2',
+);
+
+$args = array(
+ 'product_id' => FILTER_SANITIZE_ENCODED,
+ 'component' => array('flags' => FILTER_FLAG_ARRAY,
+ 'options' => array("min_range"=>1, "max_range"=>10)
+ ),
+ 'versions' => array(
+ 'filter' => FILTER_SANITIZE_ENCODED,
+ 'flags' => FILTER_FLAG_SCALAR,
+ ),
+ 'doesnotexist' => FILTER_VALIDATE_INT,
+ 'testscalar' => FILTER_VALIDATE_INT,
+ 'testarray' => array(
+ 'filter' => FILTER_VALIDATE_INT,
+ 'flags' => FILTER_FLAG_ARRAY,
+ )
+
+);
+$out = input_get_args($args, INPUT_DATA, $data);
+var_dump($out);
+?>
+--EXPECTF--
+array(6) {
+ ["product_id"]=>
+ string(17) "libgd%3Cscript%3E"
+ ["component"]=>
+ array(1) {
+ [0]=>
+ string(17) "%s"
+ }
+ ["versions"]=>
+ string(6) "2.0.33"
+ ["doesnotexist"]=>
+ NULL
+ ["testscalar"]=>
+ bool(false)
+ ["testarray"]=>
+ array(1) {
+ [0]=>
+ int(2)
+ }
+}
--- /dev/null
+--TEST--
+bug 7715, floats value with integer or incomplete input
+--FILE--
+<?php
+$data = array(
+ '.23',
+ '-42',
+ '+42',
+ '.4',
+ '-.4',
+ '1000000000000',
+ '-1000000000000'
+);
+foreach ($data as $val) {
+ $res = filter_data($val, FILTER_VALIDATE_FLOAT);
+ var_dump($res);
+}
+echo "\n";
+?>
+--EXPECTF--
+float(0.23)
+float(-42)
+float(42)
+float(0.4)
+float(-0.4)
+float(1.0E+12)
+float(-1.0E+12)
--- /dev/null
+--TEST--
+input_get_args() filter not reseted between elements
+--FILE--
+<?php
+$data = array(
+ 'E2',
+ '10E',
+ '2E-',
+ 'E-2',
+ '+E2'
+ );
+$out = filter_data($data, FILTER_VALIDATE_FLOAT);
+var_dump($out);
+?>
+--EXPECTF--
+array(5) {
+ [0]=>
+ float(0)
+ [1]=>
+ float(10)
+ [2]=>
+ float(2)
+ [3]=>
+ float(0)
+ [4]=>
+ float(0)
+}
--- /dev/null
+// vim:ft=javascript
+// $Id$
+
+ARG_ENABLE('apache2filter', 'Build Apache 2.x filter', 'no');
+
+if (PHP_APACHE2FILTER != "no") {
+ if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2FILTER", PHP_PHP_BUILD + "\\apache2\\include") &&
+ CHECK_LIB("libhttpd.lib", "apache2filter", PHP_PHP_BUILD + "\\apache2\\lib") &&
+ CHECK_LIB("libapr.lib", "apache2filter", PHP_PHP_BUILD + "\\apache2\\lib") &&
+ CHECK_LIB("libaprutil.lib", "apache2filter", PHP_PHP_BUILD + "\\apache2\\lib")
+ ) {
+ SAPI('apache2filter', 'sapi_apache2.c apache_config.c php_functions.c',
+ 'php' + PHP_VERSION + 'apache2_filter.dll',
+ '/D PHP_APACHE2_EXPORTS /I win32');
+ } else {
+ WARNING("Could not find apache2 filter libraries/headers");
+ }
+}
+
+ARG_ENABLE('apache2-2filter', 'Build Apache 2.2.x filter', 'no');
+
+if (PHP_APACHE2_2FILTER != "no") {
+ if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2_2FILTER", PHP_PHP_BUILD + "\\include\\apache2_2") &&
+ CHECK_LIB("libhttpd.lib", "apache2_2filter", PHP_PHP_BUILD + "\\lib\\apache2_2") &&
+ CHECK_LIB("libapr-1.lib", "apache2_2filter", PHP_PHP_BUILD + "\\lib\\apache2_2") &&
+ CHECK_LIB("libaprutil-1.lib", "apache2_2filter", PHP_PHP_BUILD + "\\lib\\apache2_2")
+ ) {
+ SAPI('apache2_2filter', 'sapi_apache2.c apache_config.c php_functions.c',
+ 'php' + PHP_VERSION + 'apache2_2_filter.dll',
+ '/D PHP_APACHE2_EXPORTS /I win32',
+ 'sapi\\apache2_2filter');
+ } else {
+ WARNING("Could not find apache2.2 filter libraries/headers");
+ }
+}