Skip to content

Commit

Permalink
Merge branch 'MDL-54110_30_STABLE' of https://github.com/marxjohnson/…
Browse files Browse the repository at this point in the history
…moodle into MOODLE_30_STABLE
  • Loading branch information
andrewnicols committed May 11, 2016
2 parents 8e25eba + a674b36 commit 539c1cf
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 29 deletions.
70 changes: 43 additions & 27 deletions lib/moodlelib.php
Expand Up @@ -6079,53 +6079,67 @@ function valid_uploaded_file($newfile) {
/**
* Returns the maximum size for uploading files.
*
* There are seven possible upload limits:
* 1. in Apache using LimitRequestBody (no way of checking or changing this)
* 2. in php.ini for 'upload_max_filesize' (can not be changed inside PHP)
* 3. in .htaccess for 'upload_max_filesize' (can not be changed inside PHP)
* 4. in php.ini for 'post_max_size' (can not be changed inside PHP)
* 5. by the Moodle admin in $CFG->maxbytes
* 6. by the teacher in the current course $course->maxbytes
* 7. by the teacher for the current module, eg $assignment->maxbytes
* There are eight possible upload limits:
* 1. No limit, if the upload isn't using a post request and the user has permission to ignore limits.
* 2. in Apache using LimitRequestBody (no way of checking or changing this)
* 3. in php.ini for 'upload_max_filesize' (can not be changed inside PHP)
* 4. in .htaccess for 'upload_max_filesize' (can not be changed inside PHP)
* 5. in php.ini for 'post_max_size' (can not be changed inside PHP)
* 6. by the Moodle admin in $CFG->maxbytes
* 7. by the teacher in the current course $course->maxbytes
* 8. by the teacher for the current module, eg $assignment->maxbytes
*
* These last two are passed to this function as arguments (in bytes).
* Anything defined as 0 is ignored.
* The smallest of all the non-zero numbers is returned.
*
* The php.ini settings are only used if $usespost is true. This allows repositories that do not use post requests, such as
* repository_filesystem, to copy in files that are larger than post_max_size if the user has permission.
*
* @todo Finish documenting this function
*
* @param int $sitebytes Set maximum size
* @param int $coursebytes Current course $course->maxbytes (in bytes)
* @param int $modulebytes Current module ->maxbytes (in bytes)
* @param bool $usespost Does the upload we're getting the max size for use a post request?
* @return int The maximum size for uploading files.
*/
function get_max_upload_file_size($sitebytes=0, $coursebytes=0, $modulebytes=0) {
function get_max_upload_file_size($sitebytes=0, $coursebytes=0, $modulebytes=0, $usespost = true) {

if (! $filesize = ini_get('upload_max_filesize')) {
$filesize = '5M';
}
$minimumsize = get_real_size($filesize);
$sizes = array();

if ($usespost) {
if (! $filesize = ini_get('upload_max_filesize')) {
$filesize = '5M';
}
$sizes[] = get_real_size($filesize);

if ($postsize = ini_get('post_max_size')) {
$postsize = get_real_size($postsize);
if ($postsize < $minimumsize) {
$minimumsize = $postsize;
if ($postsize = ini_get('post_max_size')) {
$sizes[] = get_real_size($postsize);
}

if ($sitebytes > 0) {
$sizes[] = $sitebytes;
}
} else {
if ($sitebytes != 0) { // It's for possible that $sitebytes == USER_CAN_IGNORE_FILE_SIZE_LIMITS (-1).
$sizes[] = $sitebytes;
}
}

if (($sitebytes > 0) and ($sitebytes < $minimumsize)) {
$minimumsize = $sitebytes;
if ($coursebytes > 0) {
$sizes[] = $coursebytes;
}

if (($coursebytes > 0) and ($coursebytes < $minimumsize)) {
$minimumsize = $coursebytes;
if ($modulebytes > 0) {
$sizes[] = $modulebytes;
}

if (($modulebytes > 0) and ($modulebytes < $minimumsize)) {
$minimumsize = $modulebytes;
if (empty($sizes)) {
throw new coding_exception('You must specify at least one filesize limit.');
}

return $minimumsize;
return min($sizes);
}

/**
Expand All @@ -6138,20 +6152,22 @@ function get_max_upload_file_size($sitebytes=0, $coursebytes=0, $modulebytes=0)
* @param int $coursebytes Current course $course->maxbytes (in bytes)
* @param int $modulebytes Current module ->maxbytes (in bytes)
* @param stdClass $user The user
* @param bool $usespost Does the upload we're getting the max size for use a post request?
* @return int The maximum size for uploading files.
*/
function get_user_max_upload_file_size($context, $sitebytes = 0, $coursebytes = 0, $modulebytes = 0, $user = null) {
function get_user_max_upload_file_size($context, $sitebytes = 0, $coursebytes = 0, $modulebytes = 0, $user = null,
$usespost = true) {
global $USER;

if (empty($user)) {
$user = $USER;
}

if (has_capability('moodle/course:ignorefilesizelimits', $context, $user)) {
return get_max_upload_file_size(USER_CAN_IGNORE_FILE_SIZE_LIMITS);
return get_max_upload_file_size(USER_CAN_IGNORE_FILE_SIZE_LIMITS, 0, 0, $usespost);
}

return get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes);
return get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes, $usespost);
}

/**
Expand Down
47 changes: 47 additions & 0 deletions lib/tests/moodlelib_test.php
Expand Up @@ -2216,6 +2216,53 @@ public function test_get_max_upload_sizes() {
$this->assertArrayHasKey(get_max_upload_file_size(), $result);
}

public function test_get_max_upload_file_size() {
// Get the smallest upload limit from ini settings.
$inisize = min(array(get_real_size(ini_get('post_max_size')), get_real_size(ini_get('upload_max_filesize'))));

// The inisize is the smallest.
$sitebytes = $inisize + 10;
$coursebytes = $inisize + 20;
$modulebytes = $inisize + 30;
$this->assertEquals($inisize, get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes));

// Site limit is the smallest.
$sitebytes = $inisize - 30;
$coursebytes = $inisize - 20;
$modulebytes = $inisize - 10;
$this->assertEquals($sitebytes, get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes));

// Course limit is the smallest.
$sitebytes = $inisize - 20;
$coursebytes = $inisize - 30;
$modulebytes = $inisize - 10;
$this->assertEquals($coursebytes, get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes));

// Module limit is the smallest.
$sitebytes = $inisize - 20;
$coursebytes = $inisize - 10;
$modulebytes = $inisize - 30;
$this->assertEquals($modulebytes, get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes));

// The inisize is the smallest, the upload does not use post.
$sitebytes = $inisize + 10;
$coursebytes = $inisize + 20;
$modulebytes = $inisize + 30;
$this->assertEquals($sitebytes, get_max_upload_file_size($sitebytes, $coursebytes, $modulebytes, false));

// The user can ignore file size limits, the upload does use post.
$this->assertEquals($inisize, get_max_upload_file_size(USER_CAN_IGNORE_FILE_SIZE_LIMITS, 0, 0));

// The user can ignore file size limits, the upload not does use post.
$this->assertEquals(USER_CAN_IGNORE_FILE_SIZE_LIMITS,
get_max_upload_file_size(USER_CAN_IGNORE_FILE_SIZE_LIMITS, 0, 0, false));

// If not using post we have to provide at least one other limit.
$this->setExpectedException('coding_exception', 'You must specify at least one filesize limit.');
get_max_upload_file_size(0, 0, 0, false);

}

/**
* Test function password_is_legacy_hash().
*/
Expand Down
6 changes: 5 additions & 1 deletion repository/filepicker.php
Expand Up @@ -77,6 +77,8 @@
}
$PAGE->set_course($course);

$usespost = true;

if ($repo_id) {
// Get repository instance information
$repooptions = array(
Expand All @@ -87,12 +89,14 @@

// Check permissions
$repo->check_capability();

$usespost = $repo->uses_post_requests();
}

$context = context::instance_by_id($contextid);

// Make sure maxbytes passed is within site filesize limits.
$maxbytes = get_user_max_upload_file_size($context, $CFG->maxbytes, $course->maxbytes, $maxbytes);
$maxbytes = get_user_max_upload_file_size($context, $CFG->maxbytes, $course->maxbytes, $maxbytes, null, $usespost);

$params = array('ctx_id' => $contextid, 'itemid' => $itemid, 'env' => $env, 'course'=>$courseid, 'maxbytes'=>$maxbytes, 'areamaxbytes'=>$areamaxbytes, 'maxfiles'=>$maxfiles, 'subdirs'=>$subdirs, 'sesskey'=>sesskey());
$params['action'] = 'browse';
Expand Down
11 changes: 11 additions & 0 deletions repository/filesystem/lib.php
Expand Up @@ -594,6 +594,17 @@ public function send_relative_file(stored_file $mainfile, $relativepath) {
public function supports_relative_file() {
return $this->get_option('relativefiles');
}

/**
* Helper funtion to indicate if this repository uses post requests for uploading files.
*
* Files are copied from the filesystem so don't rely on POST requests.
*
* @return bool
*/
public function uses_post_requests() {
return false;
}
}

/**
Expand Down
12 changes: 12 additions & 0 deletions repository/lib.php
Expand Up @@ -2826,6 +2826,18 @@ public function send_relative_file(stored_file $mainfile, $relativepath) {
public function supports_relative_file() {
return false;
}

/**
* Helper funtion to indicate if this repository uses post requests for uploading files.
*
* If the respository doesn't rely on uploading via POST requests, this can be overridden to return true,
* allowing users with the right permissions to upload files of any size from this repository.
*
* @return bool
*/
public function uses_post_requests() {
return true;
}
}

/**
Expand Down
3 changes: 2 additions & 1 deletion repository/repository_ajax.php
Expand Up @@ -86,7 +86,8 @@
$coursemaxbytes = $course->maxbytes;
}
// Make sure maxbytes passed is within site filesize limits.
$maxbytes = get_user_max_upload_file_size($context, $CFG->maxbytes, $coursemaxbytes, $maxbytes);
$maxbytes = get_user_max_upload_file_size($context, $CFG->maxbytes, $coursemaxbytes, $maxbytes,
null, $repo->uses_post_requests());

// Wait as long as it takes for this script to finish
core_php_time_limit::raise();
Expand Down

0 comments on commit 539c1cf

Please sign in to comment.