MDL-41451 - Large forms are truncated by max_input_vars

By parsing php://input in chunks, we can bypass max_input_vars for
forms which do not use the "multipart/form-data" enctype.  This can
be (and is) safely skipped if there are fewer than max_input_vars
fields submitted as part of $_POST.
This commit is contained in:
Paul Nicholls
2013-09-06 14:57:03 +12:00
parent e78a2d0e44
commit 52b617673c
+34 -2
View File
@@ -261,10 +261,10 @@ abstract class moodleform {
$submission = array();
if ($method == 'post') {
if (!empty($_POST)) {
$submission = $_POST;
$submission = $this->_get_post_params();
}
} else {
$submission = array_merge_recursive($_GET, $_POST); // emulate handling of parameters in xxxx_param()
$submission = array_merge_recursive($_GET, $this->_get_post_params()); // Emulate handling of parameters in xxxx_param().
}
// following trick is needed to enable proper sesskey checks when using GET forms
@@ -282,6 +282,38 @@ abstract class moodleform {
$this->_form->updateSubmission($submission, $files);
}
/**
* Internal method. Gets all POST variables, bypassing max_input_vars limit if needed.
*
* @return array All POST variables as an array, in the same format as $_POST.
*/
protected function _get_post_params() {
$enctype = $this->_form->getAttribute('enctype');
$max = (int)ini_get('max_input_vars');
if (empty($max) || count($_POST, COUNT_RECURSIVE) < $max || (!empty($enctype) && $enctype == 'multipart/form-data')) {
return $_POST;
}
// Large POST request with enctype supported by php://input.
// Parse php://input in chunks to bypass max_input_vars limit, which also applies to parse_str().
$allvalues = array();
$values = array();
$str = file_get_contents("php://input");
$delim = '&';
$chunks = array_map(function($p) use ($delim) {
return implode($delim, $p);
}, array_chunk(explode($delim, $str), $max));
foreach ($chunks as $chunk) {
parse_str($chunk, $values);
$allvalues = array_merge_recursive($allvalues, $values);
}
return $allvalues;
}
/**
* Internal method. Validates all old-style deprecated uploaded files.
* The new way is to upload files via repository api.