Commit 4e24b183 authored by Cecilia Vela Gurovic's avatar Cecilia Vela Gurovic Committed by Gerrit Code Review

Merge "Bug 1855351: Allow restriction of file uploads to a whitelist"

parents 30d592c3 a064f3d6
......@@ -381,3 +381,6 @@ $string['progress_video'] = array(
);
$string['anytypeoffile'] = 'File (any type)';
$string['viruszipfile'] = 'Clam AV has found a file that is infected with a virus. The compressed file has been quarantined and removed from your account.';
$string['filetypenotallowed'] = 'Files with extension "%s" are not allowed.';
$string['filetypenotmatchingmimetype'] = 'File extension does not match file mimetype "%s".';
$string['validfiletypes'] = 'You can upload the following file types:';
......@@ -1232,6 +1232,27 @@ class ArtefactTypeFile extends ArtefactTypeFileBase {
}
$f->commit();
if ($validfiletypes = get_config('validfiletypes')) {
$validext = array_map('trim', explode(',', $validfiletypes));
$oldext = $f->get('oldextension');
if (!in_array($oldext, $validext)) {
// the extension is not one of the valid options
log_debug(get_string('filetypenotallowed', 'artefact.file', $oldext));
$f->delete();
return false;
}
$typeparts = explode('/', $f->get('filetype'));
$oldext = $oldext == 'jpg' ? 'jpeg' : $oldext;
$mimetype = file_mime_type('foo.' . $oldext); // check the file mimetype against it's extension
$mimetypeparts = explode('/', $mimetype);
if ($typeparts[0] !== $mimetypeparts[0]) {
// the extension is not correct type for the file
log_debug(get_string('filetypenotmatchingmimetype', 'artefact.file', $mimetype));
$f->delete();
return false;
}
}
$id = $f->get('id');
if (isset($data->artefacttype) && $data->artefacttype == 'profileicon') {
......
......@@ -808,3 +808,9 @@ $cfg->sessionhandler = 'file';
* activites on your install of Mahara. No friends allowed - this is a site-wide setting.
*/
//$cfg->friendsnotallowed = true;
/**
* Restrict the site to only allow the upload of certain file types.
* Set as a comma seperated string of valid file extensions
*/
//$cfg->validfiletypes = 'doc,docx,gif,jpeg,jpg,m4a,mp3,mp4,pdf,png'; // for example
......@@ -178,7 +178,10 @@ function pieform_element_filebrowser(Pieform $form, $element) {
$fileliststr = json_encode($filedata);
$smarty->assign('prefix', $prefix);
$accepts = isset($element['accept']) ? 'accept="' . Pieform::hsc($element['accept']) . '"' : '';
// if validfiletypes set then only accept those types
$accepts = get_config('validfiletypes') ? 'accept="' . Pieform::hsc('.' . str_replace(',', ',.', get_config('validfiletypes'))) . '"' : '';
// if form element accept is set then only accept those types
$accepts = isset($element['accept']) ? 'accept="' . Pieform::hsc($element['accept']) . '"' : $accepts;
$smarty->assign('accepts', $accepts);
$initjs = "{$prefix} = new FileBrowser('{$prefix}', {$folder}, {$configstr}, config);
......@@ -247,7 +250,11 @@ function pieform_element_filebrowser(Pieform $form, $element) {
$colspan++;
}
$smarty->assign('colspan', $colspan);
if ($validfiletypes = get_config('validfiletypes')) {
$validext = array_map('trim', explode(',', $validfiletypes));
sort($validext);
$smarty->assign('validfiletypes', $validext);
}
return $smarty->fetch('artefact:file:form/filebrowser.tpl');
}
......
......@@ -43,6 +43,12 @@ function pieform_element_files(Pieform $form, $element) {
$maxfilesize = get_max_upload_size(false);
}
$smarty->assign('maxfilesizedesc', get_string('maxuploadsize', 'artefact.file') . ' ' . display_size($maxfilesize));
// if validfiletypes set then only accept those types
$accepts = get_config('validfiletypes') ? 'accept="' . Pieform::hsc('.' . str_replace(',', ',.', get_config('validfiletypes'))) . '"' : '';
// if form element accept is set then only accept those types
$accepts = isset($element['accept']) ? 'accept="' . Pieform::hsc($element['accept']) . '"' : $accepts;
$smarty->assign('accepts', $accepts);
return $smarty->fetch('form/files.tpl');
}
......
......@@ -38,9 +38,11 @@ function pieform_element_file(Pieform $form, $element) {/*{{{*/
$result = '<input type="hidden" name="MAX_FILE_SIZE" value="' . $element['maxfilesize'] . '"/>';
$maxfilesize = $element['maxfilesize'];
}
$result .= '<div class="' . (empty($element['description']) ? 'align-with-input file' : 'align-with-input-desc') . '"><input type="file"' . $form->element_attributes($element) .
(isset($element['accept']) ? ' accept="' . Pieform::hsc($element['accept']) . '"' : '') .
'>';
// if validfiletypes set then only accept those types
$accepts = get_config('validfiletypes') ? ' accept="' . Pieform::hsc('.' . str_replace(',', ',.', get_config('validfiletypes'))) . '"' : '';
$accepts = isset($element['accept']) ? ' accept="' . Pieform::hsc($element['accept']) . '"' : $accepts;
// if form element accept is set then only accept those types
$result .= '<div class="' . (empty($element['description']) ? 'align-with-input file' : 'align-with-input-desc') . '"><input type="file"' . $form->element_attributes($element) . $accepts . '>';
if (!$maxfilesize) {
// not supplied by form element
$maxfilesize = get_max_upload_size(false);
......
......@@ -88,11 +88,13 @@ class upload_manager {
$size = $file['size'][$this->inputindex];
$error = $file['error'][$this->inputindex];
$tmpname = $file['tmp_name'][$this->inputindex];
$type = $file['type'][$this->inputindex];
}
else {
$size = $file['size'];
$error = $file['error'];
$tmpname = $file['tmp_name'];
$type = $file['type'];
}
$maxfilesize = !empty($this->maxfilesize) ? display_size($this->maxfilesize) : display_size(get_max_upload_size(false));
if ($maxsize && $size > $maxsize) {
......@@ -134,6 +136,21 @@ class upload_manager {
}
$this->file = $file;
$ext = $this->original_filename_extension();
if ($validfiletypes = get_config('validfiletypes')) {
$validext = array_map('trim', explode(',', $validfiletypes));
if (!in_array($ext, $validext)) {
// the extension is not one of the valid options
return get_string('filetypenotallowed', 'artefact.file', $ext);
}
$typeparts = explode('/', $type);
$mimetype = file_mime_type($tmpname);
$mimetypeparts = explode('/', $mimetype);
if ($typeparts[0] !== $mimetypeparts[0]) {
// the extension is not correct type for the file
return get_string('filetypenotmatchingmimetype', 'artefact.file', $mimetype);
}
}
return false;
}
......
......@@ -132,6 +132,14 @@
</div>
</div>
</div>
{if $validfiletypes}
<div class="validfiletypes">
<span class="label">{str tag='validfiletypes' section='artefact.file'}</span>
{foreach from=$validfiletypes item=itype name=loopidx}
.<span>{$itype}</span>
{/foreach}
</div>
{/if}
</div>
</div>
{/if}
......
......@@ -940,3 +940,18 @@ a.online-users {
font-weight: normal;
}
}
.validfiletypes {
border: 1px solid $card-border-color;
margin: 15px;
padding: 5px;
background-color: #F8F4F6; /* $theme-accent-color for rangaranga */
span {
padding-right: 3px;
display: inline-block;
&.label {
font-weight: 700;
}
}
}
......@@ -2,12 +2,13 @@
var {{$name}}_current = 0;
var {{$name}}_newrefinput;
var {{$name}}_newref;
var {{$name}}_accept = "{{$accepts}}";
function {{$name}}_new() {
{{$name}}_current++;
var id = '{{$name}}_files_' + {{$name}}_current;
{{$name}}_newlabel = jQuery('<label>', {'for': id, 'class': 'sr-only'}).append(jQuery('#{{$name}}_files_label').html());
{{$name}}_newrefinput = jQuery('<input>', {'type': 'file', 'id': id, 'name': id, 'class': 'file'});
{{$name}}_newrefinput = jQuery('<input>', {'type': 'file', 'id': id, 'name': id, 'class': 'file', 'accept': {{$name}}_accept });
{{$name}}_newmaxsize = jQuery('<span>', {'id': id, 'class': 'file-description'}).append(jQuery('#{{$name}}_files_maxsize').html());
var {{$name}}_newref = jQuery('<div>', {'class': 'file-wrapper'}).append({{$name}}_newlabel, {{$name}}_newrefinput, {{$name}}_newmaxsize);
......@@ -23,7 +24,7 @@
{{/if}}
<div class="file-wrapper">
<label id="{{$name}}_files_label" class="accessible-hidden sr-only" for="{{$name}}_files_0">{{$title}}</label>
<input type="file" id="{{$name}}_files_0" name="{{$name}}_files_0">
<input type="file" id="{{$name}}_files_0" name="{{$name}}_files_0" {{if $accepts}}accept="{{$accepts}}"{{/if}}>
<span id="{{$name}}_files_maxsize" class="file-description">({{$maxfilesizedesc}})</span>
</div>
</div>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment