]> granicus.if.org Git - php/commitdiff
This commit was manufactured by cvs2svn to create branch 'PHP_5_2'.
authorSVN Migration <svn@php.net>
Wed, 5 Jul 2006 10:12:43 +0000 (10:12 +0000)
committerSVN Migration <svn@php.net>
Wed, 5 Jul 2006 10:12:43 +0000 (10:12 +0000)
24 files changed:
ext/filter/docs/filter.txt [new file with mode: 0644]
ext/filter/docs/input_get_args.php [new file with mode: 0644]
ext/filter/filter.c [new file with mode: 0644]
ext/filter/filter_private.h [new file with mode: 0644]
ext/filter/logical_filters.c [new file with mode: 0644]
ext/filter/package.xml [new file with mode: 0644]
ext/filter/package2.xml [new file with mode: 0644]
ext/filter/php_filter.h [new file with mode: 0644]
ext/filter/tests/010.phpt [new file with mode: 0644]
ext/filter/tests/013.phpt [new file with mode: 0644]
ext/filter/tests/015.phpt [new file with mode: 0644]
ext/filter/tests/016.phpt [new file with mode: 0644]
ext/filter/tests/017.phpt [new file with mode: 0644]
ext/filter/tests/018.phpt [new file with mode: 0644]
ext/filter/tests/019.phpt [new file with mode: 0644]
ext/filter/tests/030.phpt [new file with mode: 0644]
ext/filter/tests/031.phpt [new file with mode: 0644]
ext/filter/tests/032.phpt [new file with mode: 0644]
ext/filter/tests/033.phpt [new file with mode: 0644]
ext/filter/tests/033_run.php [new file with mode: 0644]
ext/filter/tests/bug7586.phpt [new file with mode: 0644]
ext/filter/tests/bug7715.phpt [new file with mode: 0644]
ext/filter/tests/bug7733.phpt [new file with mode: 0644]
sapi/apache2filter/config.w32 [new file with mode: 0755]

diff --git a/ext/filter/docs/filter.txt b/ext/filter/docs/filter.txt
new file mode 100644 (file)
index 0000000..48aae0c
--- /dev/null
@@ -0,0 +1,331 @@
+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 &amp;
+
+                                           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 &amp;
+                 
+                                           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
+
diff --git a/ext/filter/docs/input_get_args.php b/ext/filter/docs/input_get_args.php
new file mode 100644 (file)
index 0000000..b580524
--- /dev/null
@@ -0,0 +1,41 @@
+<?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);
+
diff --git a/ext/filter/filter.c b/ext/filter/filter.c
new file mode 100644 (file)
index 0000000..da4bb04
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+  +----------------------------------------------------------------------+
+  | 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
+ */
diff --git a/ext/filter/filter_private.h b/ext/filter/filter_private.h
new file mode 100644 (file)
index 0000000..ea44775
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+  +----------------------------------------------------------------------+
+  | 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
+ */
diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c
new file mode 100644 (file)
index 0000000..f68d517
--- /dev/null
@@ -0,0 +1,842 @@
+/*
+  +----------------------------------------------------------------------+
+  | 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
+ */
diff --git a/ext/filter/package.xml b/ext/filter/package.xml
new file mode 100644 (file)
index 0000000..cca5fd6
--- /dev/null
@@ -0,0 +1,98 @@
+<?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
+-->
diff --git a/ext/filter/package2.xml b/ext/filter/package2.xml
new file mode 100644 (file)
index 0000000..ffe3d7d
--- /dev/null
@@ -0,0 +1,127 @@
+<?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>
diff --git a/ext/filter/php_filter.h b/ext/filter/php_filter.h
new file mode 100644 (file)
index 0000000..4c2b938
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+  +----------------------------------------------------------------------+
+  | 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:
+ */
diff --git a/ext/filter/tests/010.phpt b/ext/filter/tests/010.phpt
new file mode 100644 (file)
index 0000000..eaded25
--- /dev/null
@@ -0,0 +1,60 @@
+--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
diff --git a/ext/filter/tests/013.phpt b/ext/filter/tests/013.phpt
new file mode 100644 (file)
index 0000000..728a29c
--- /dev/null
@@ -0,0 +1,72 @@
+--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
diff --git a/ext/filter/tests/015.phpt b/ext/filter/tests/015.phpt
new file mode 100644 (file)
index 0000000..c46b7d1
--- /dev/null
@@ -0,0 +1,72 @@
+--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
diff --git a/ext/filter/tests/016.phpt b/ext/filter/tests/016.phpt
new file mode 100644 (file)
index 0000000..5043567
--- /dev/null
@@ -0,0 +1,32 @@
+--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
diff --git a/ext/filter/tests/017.phpt b/ext/filter/tests/017.phpt
new file mode 100644 (file)
index 0000000..18c3235
--- /dev/null
@@ -0,0 +1,24 @@
+--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
diff --git a/ext/filter/tests/018.phpt b/ext/filter/tests/018.phpt
new file mode 100644 (file)
index 0000000..0f5c1a4
--- /dev/null
@@ -0,0 +1,50 @@
+--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
diff --git a/ext/filter/tests/019.phpt b/ext/filter/tests/019.phpt
new file mode 100644 (file)
index 0000000..7c22e10
--- /dev/null
@@ -0,0 +1,20 @@
+--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
diff --git a/ext/filter/tests/030.phpt b/ext/filter/tests/030.phpt
new file mode 100644 (file)
index 0000000..ff4ea39
--- /dev/null
@@ -0,0 +1,35 @@
+--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
diff --git a/ext/filter/tests/031.phpt b/ext/filter/tests/031.phpt
new file mode 100644 (file)
index 0000000..a743291
--- /dev/null
@@ -0,0 +1,54 @@
+--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)
diff --git a/ext/filter/tests/032.phpt b/ext/filter/tests/032.phpt
new file mode 100644 (file)
index 0000000..a7f8a7c
--- /dev/null
@@ -0,0 +1,55 @@
+--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)
+  }
+}
diff --git a/ext/filter/tests/033.phpt b/ext/filter/tests/033.phpt
new file mode 100644 (file)
index 0000000..c6ec133
--- /dev/null
@@ -0,0 +1,25 @@
+--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&#39;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&#60;&#62;()  O&#39;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        하퍼  
diff --git a/ext/filter/tests/033_run.php b/ext/filter/tests/033_run.php
new file mode 100644 (file)
index 0000000..229e7ba
--- /dev/null
@@ -0,0 +1,23 @@
+<?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]);
+}
+?>
diff --git a/ext/filter/tests/bug7586.phpt b/ext/filter/tests/bug7586.phpt
new file mode 100644 (file)
index 0000000..af4be33
--- /dev/null
@@ -0,0 +1,53 @@
+--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)
+  }
+}
diff --git a/ext/filter/tests/bug7715.phpt b/ext/filter/tests/bug7715.phpt
new file mode 100644 (file)
index 0000000..9e1206f
--- /dev/null
@@ -0,0 +1,27 @@
+--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)
diff --git a/ext/filter/tests/bug7733.phpt b/ext/filter/tests/bug7733.phpt
new file mode 100644 (file)
index 0000000..f849712
--- /dev/null
@@ -0,0 +1,27 @@
+--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)
+}
diff --git a/sapi/apache2filter/config.w32 b/sapi/apache2filter/config.w32
new file mode 100755 (executable)
index 0000000..9eeccbb
--- /dev/null
@@ -0,0 +1,35 @@
+// 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");
+       }
+}