diff --git a/wire/config.php b/wire/config.php index db905542..04d5ba5f 100644 --- a/wire/config.php +++ b/wire/config.php @@ -1031,6 +1031,26 @@ $config->wireInputOrder = 'get post'; */ $config->wireInputLazy = false; +/** + * Maximum depth for input variables accessed from $input + * + * A value of 1 (or less) means only single dimensional arrays are allowed. For instance, `$a['foo']` + * would be allowed (since it is one dimension), but `$a['foo']['bar']` would not because it is + * multi-dimensional to a depth of 2. + * + * A value of 2 or higher enables multi-dimensional arrays to that depth. For instance, a value of 2 + * would allow `$a['foo']['bar']` and a value of 3 or higher would enable `$a['foo']['bar']['baz']`. + * + * Note: if your use case requires multi-dimensional input arrays and you do not have control over + * this setting (like if you are a 3rd party module author), or are using a version of PW prior to + * 3.0.178 you can always still access multi-dimensional arrays directly from `$_GET` or `$_POST`. + * + * @var int + * @since 3.0.178 + * + */ +$config->wireInputArrayDepth = 1; + /** * Options for setting cookies from $input->cookie()->set(...) * diff --git a/wire/core/Config.php b/wire/core/Config.php index 825bfd78..6c4710c7 100644 --- a/wire/core/Config.php +++ b/wire/core/Config.php @@ -92,6 +92,7 @@ * @property int $maxUrlDepth Maximum URL/path slashes (depth) for request URLs. (Min=10, Max=60) #pw-group-URLs * @property string $wireInputOrder Order that variables with the $input API var are handled when you access $input->var. #pw-group-HTTP-and-input * @property bool $wireInputLazy Specify true for $input API var to load input data in a lazy fashion and potentially use less memory. Default is false. #pw-group-HTTP-and-input + * @property int $wireInputArrayDepth Maximum multi-dimensional array depth for input variables accessed from $input or 1 to only allow single dimension arrays. (3.0.178+). #pw-group-HTTP-and-input * @property array $cookieOptions Options for setting cookies from $input->cookie #pw-group-HTTP-and-input * * @property bool $advanced Special mode for ProcessWire system development. Not recommended for regular site development or production use. #pw-group-system diff --git a/wire/core/WireInputData.php b/wire/core/WireInputData.php index d3410b5e..71db5a6f 100644 --- a/wire/core/WireInputData.php +++ b/wire/core/WireInputData.php @@ -330,19 +330,43 @@ class WireInputData extends Wire implements \ArrayAccess, \IteratorAggregate, \C /** * Clean an array of data * - * Removes multi-dimensional arrays and slashes (if applicable) + * Support multi-dimensional arrays consistent with `$config->wireInputArrayDepth` + * setting (3.0.178+) and remove slashes if applicable/necessary. * * @param array $a * @return array * */ protected function cleanArray(array $a) { + static $depth = 1; + + $maxDepth = (int) $this->wire()->config->wireInputArrayDepth; + if($maxDepth < 1) $maxDepth = 1; + $clean = array(); + foreach($a as $key => $value) { - if(is_array($value)) continue; // we only allow one dimensional arrays - if(is_string($value) && $this->stripSlashes) $value = stripslashes($value); - $clean[$key] = $value; + if(is_array($value)) { + if($depth >= $maxDepth) { + // max dimension reached + $value = null; + } else { + // allow another dimension + $depth++; + $value = $this->cleanArray($value); + $depth--; + // empty arrays not possible in input vars past 1st dimension + if(!count($value)) $value = null; + } + } else if(is_string($value)) { + if($this->stripSlashes) $value = stripslashes($value); + } + + if($value !== null) { + $clean[$key] = $value; + } } + return $clean; }