Skip to content

Commit

Permalink
MDL-41451 - Large forms are truncated by max_input_vars
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pauln committed Sep 6, 2013
1 parent b69ec28 commit 85b82a9
Showing 1 changed file with 34 additions and 2 deletions.
36 changes: 34 additions & 2 deletions lib/formslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,10 @@ function _process_submission($method) {
$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
Expand All @@ -283,6 +283,38 @@ function _process_submission($method) {
$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.
Expand Down

0 comments on commit 85b82a9

Please sign in to comment.