From 4e5a22df7a66ee912bd3206963b9c20f4f9d3b47 Mon Sep 17 00:00:00 2001 From: Jonathon Fowler Date: Fri, 13 Jun 2014 10:58:55 +1000 Subject: [PATCH 1/4] MDL-39913 filetypes: mimetypes remediation Going by http://www.iana.org/assignments/media-types/media-types.xhtml. Disambiguated the Office 2007 types, Apple iWorks and other types changes by tonyjbutler. --- lang/en/mimetypes.php | 40 ++++++++++++++++++++++++++++++++++----- lib/classes/filetypes.php | 13 +++++++------ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lang/en/mimetypes.php b/lang/en/mimetypes.php index c2b48d7780c..bba3cd00b26 100644 --- a/lang/en/mimetypes.php +++ b/lang/en/mimetypes.php @@ -40,17 +40,47 @@ $string['application/msword'] = 'Word document'; $string['application/pdf'] = 'PDF document'; $string['application/vnd.moodle.backup'] = 'Moodle backup'; $string['application/vnd.ms-excel'] = 'Excel spreadsheet'; +$string['application/vnd.ms-excel.sheet.macroEnabled.12'] = 'Excel 2007 macro-enabled workbook'; $string['application/vnd.ms-powerpoint'] = 'Powerpoint presentation'; -$string['application/vnd.openxmlformats-officedocument.presentationml.presentation'] = 'Powerpoint presentation'; -$string['application/vnd.openxmlformats-officedocument.presentationml.slideshow'] = 'Powerpoint slideshow'; -$string['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] = 'Excel spreadsheet'; -$string['application/vnd.openxmlformats-officedocument.spreadsheetml.template'] = 'Excel template'; -$string['application/vnd.openxmlformats-officedocument.wordprocessingml.document'] = 'Word document'; +$string['application/vnd.oasis.opendocument.spreadsheet'] = 'OpenDocument Spreadsheet'; +$string['application/vnd.oasis.opendocument.spreadsheet-template'] = 'OpenDocument Spreadsheet template'; +$string['application/vnd.oasis.opendocument.text'] = 'OpenDocument Text document'; +$string['application/vnd.oasis.opendocument.text-template'] = 'OpenDocument Text template'; +$string['application/vnd.oasis.opendocument.text-web'] = 'OpenDocument Web page template'; +$string['application/vnd.openxmlformats-officedocument.presentationml.presentation'] = 'Powerpoint 2007 presentation'; +$string['application/vnd.openxmlformats-officedocument.presentationml.slideshow'] = 'Powerpoint 2007 slideshow'; +$string['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] = 'Excel 2007 spreadsheet'; +$string['application/vnd.openxmlformats-officedocument.spreadsheetml.template'] = 'Excel 2007 template'; +$string['application/vnd.openxmlformats-officedocument.wordprocessingml.document'] = 'Word 2007 document'; +$string['application/x-iwork-keynote-sffkey'] = 'iWork Keynote presentation'; +$string['application/x-iwork-numbers-sffnumbers'] = 'iWork Numbers spreadsheet'; +$string['application/x-iwork-pages-sffpages'] = 'iWork Pages document'; +$string['application/x-javascript'] = 'JavaScript source'; +$string['application/x-mspublisher'] = 'Publisher document'; +$string['application/x-shockwave-flash'] = 'Flash animation'; +$string['application/xhtml_xml'] = 'XHTML document'; $string['archive'] = 'Archive ({$a->EXT})'; $string['audio'] = 'Audio file ({$a->EXT})'; $string['default'] = '{$a->mimetype}'; $string['document/unknown'] = 'File'; +$string['group:archive'] = 'Archive files'; +$string['group:audio'] = 'Audio files'; +$string['group:document'] = 'Document files'; +$string['group:html_audio'] = 'Audio files natively supported by browsers'; +$string['group:html_video'] = 'Video files natively supported by browsers'; +$string['group:image'] = 'Image files'; +$string['group:presentation'] = 'Presentation files'; +$string['group:sourcecode'] = 'Source code'; +$string['group:spreadsheet'] = 'Spreadsheet files'; +$string['group:video'] = 'Video files'; +$string['group:web_audio'] = 'Audio files used on the web'; +$string['group:web_file'] = 'Web files'; +$string['group:web_image'] = 'Image files used on the web'; +$string['group:web_video'] = 'Video files used on the web'; $string['image'] = 'Image ({$a->MIMETYPE2})'; +$string['image/vnd.microsoft.icon'] = 'Windows icon'; +$string['text/css'] = 'Cascading Style-Sheet'; +$string['text/csv'] = 'Comma-separated values'; $string['text/html'] = 'HTML document'; $string['text/plain'] = 'Text file'; $string['text/rtf'] = 'RTF document'; diff --git a/lib/classes/filetypes.php b/lib/classes/filetypes.php index 97ff4568271..23c01913b0c 100644 --- a/lib/classes/filetypes.php +++ b/lib/classes/filetypes.php @@ -90,7 +90,7 @@ abstract class core_filetypes { 'dxr' => array('type' => 'application/x-director', 'icon' => 'flash'), 'eps' => array('type' => 'application/postscript', 'icon' => 'eps'), 'epub' => array('type' => 'application/epub+zip', 'icon' => 'epub', 'groups' => array('document')), - 'fdf' => array('type' => 'application/pdf', 'icon' => 'pdf'), + 'fdf' => array('type' => 'application/vnd.fdf', 'icon' => 'pdf'), 'flac' => array('type' => 'audio/flac', 'icon' => 'audio', 'groups' => array('audio', 'html_audio', 'web_audio'), 'string' => 'audio'), 'flv' => array('type' => 'video/x-flv', 'icon' => 'flash', @@ -197,7 +197,7 @@ abstract class core_filetypes { 'string' => 'video'), 'pct' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), - 'pdf' => array('type' => 'application/pdf', 'icon' => 'pdf'), + 'pdf' => array('type' => 'application/pdf', 'icon' => 'pdf', 'groups' => array('document')), 'php' => array('type' => 'text/plain', 'icon' => 'sourcecode'), 'pic' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), 'pict' => array('type' => 'image/pict', 'icon' => 'image', 'groups' => array('image'), 'string' => 'image'), @@ -283,12 +283,13 @@ abstract class core_filetypes { 'wma' => array('type' => 'audio/x-ms-wma', 'icon' => 'audio', 'groups' => array('audio'), 'string' => 'audio'), 'xbk' => array('type' => 'application/x-smarttech-notebook', 'icon' => 'archive'), - 'xdp' => array('type' => 'application/pdf', 'icon' => 'pdf'), - 'xfd' => array('type' => 'application/pdf', 'icon' => 'pdf'), - 'xfdf' => array('type' => 'application/pdf', 'icon' => 'pdf'), + 'xdp' => array('type' => 'application/vnd.adobe.xdp+xml', 'icon' => 'pdf'), + 'xfd' => array('type' => 'application/vnd.xfdl', 'icon' => 'pdf'), + 'xfdf' => array('type' => 'application/vnd.adobe.xfdf', 'icon' => 'pdf'), 'xls' => array('type' => 'application/vnd.ms-excel', 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), - 'xlsx' => array('type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'icon' => 'spreadsheet'), + 'xlsx' => array('type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'icon' => 'spreadsheet', + 'groups' => array('spreadsheet')), 'xlsm' => array('type' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 'icon' => 'spreadsheet', 'groups' => array('spreadsheet')), 'xltx' => array('type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', From 4044cad5ea062a714330e69f69c02a8407501f29 Mon Sep 17 00:00:00 2001 From: Jonathon Fowler Date: Fri, 13 Jun 2014 10:58:55 +1000 Subject: [PATCH 2/4] MDL-39913 assignsubmission_file: add file types restriction Testing for uploading a non-permitted file won't work as things stand currently because the filemanager throws an exception that Behat catches, which causes a fail. --- lang/en/mimetypes.php | 1 + .../file/lang/en/assignsubmission_file.php | 3 + mod/assign/submission/file/locallib.php | 67 +++++++++++++++++- .../tests/behat/file_type_restriction.feature | 68 +++++++++++++++++++ mod/assign/submission/file/version.php | 2 +- 5 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 mod/assign/submission/file/tests/behat/file_type_restriction.feature diff --git a/lang/en/mimetypes.php b/lang/en/mimetypes.php index bba3cd00b26..38892265c60 100644 --- a/lang/en/mimetypes.php +++ b/lang/en/mimetypes.php @@ -67,6 +67,7 @@ $string['group:archive'] = 'Archive files'; $string['group:audio'] = 'Audio files'; $string['group:document'] = 'Document files'; $string['group:html_audio'] = 'Audio files natively supported by browsers'; +$string['group:html_track'] = 'HTML track files'; $string['group:html_video'] = 'Video files natively supported by browsers'; $string['group:image'] = 'Image files'; $string['group:presentation'] = 'Presentation files'; diff --git a/mod/assign/submission/file/lang/en/assignsubmission_file.php b/mod/assign/submission/file/lang/en/assignsubmission_file.php index 5f1bf0d84f5..5e51401328e 100644 --- a/mod/assign/submission/file/lang/en/assignsubmission_file.php +++ b/mod/assign/submission/file/lang/en/assignsubmission_file.php @@ -23,6 +23,7 @@ */ +$string['acceptedfiletypes'] = 'Accepted file types'; $string['configmaxbytes'] = 'Maximum file size'; $string['countfiles'] = '{$a} files'; $string['default'] = 'Enabled by default'; @@ -31,6 +32,8 @@ $string['enabled'] = 'File submissions'; $string['enabled_help'] = 'If enabled, students are able to upload one or more files as their submission.'; $string['eventassessableuploaded'] = 'A file has been uploaded.'; $string['file'] = 'File submissions'; +$string['filesofthesetypes'] = 'Files of these types may be added to the submission:'; +$string['filetypewithexts'] = '{$a->name} — {$a->extlist}'; $string['maxbytes'] = 'Maximum file size'; $string['maxfiles'] = 'Maximum files per submission'; $string['maxfiles_help'] = 'If file submissions are enabled, each assignment can be set to accept up to this number of files for their submission.'; diff --git a/mod/assign/submission/file/locallib.php b/mod/assign/submission/file/locallib.php index cd54142cb34..f991e3ecba4 100644 --- a/mod/assign/submission/file/locallib.php +++ b/mod/assign/submission/file/locallib.php @@ -71,6 +71,7 @@ class assign_submission_file extends assign_submission_plugin { $defaultmaxfilesubmissions = $this->get_config('maxfilesubmissions'); $defaultmaxsubmissionsizebytes = $this->get_config('maxsubmissionsizebytes'); + $defaultfiletypes = (string)$this->get_config('filetypeslist'); $settings = array(); $options = array(); @@ -105,6 +106,12 @@ class assign_submission_file extends assign_submission_plugin { $mform->disabledIf('assignsubmission_file_maxsizebytes', 'assignsubmission_file_enabled', 'notchecked'); + + $name = get_string('acceptedfiletypes', 'assignsubmission_file'); + $mform->addElement('text', 'assignsubmission_file_filetypes', $name); + $mform->setType('assignsubmission_file_filetypes', PARAM_RAW); + $mform->setDefault('assignsubmission_file_filetypes', $defaultfiletypes); + $mform->disabledIf('assignsubmission_file_filetypes', 'assignsubmission_file_enabled', 'notchecked'); } /** @@ -116,6 +123,13 @@ class assign_submission_file extends assign_submission_plugin { public function save_settings(stdClass $data) { $this->set_config('maxfilesubmissions', $data->assignsubmission_file_maxfiles); $this->set_config('maxsubmissionsizebytes', $data->assignsubmission_file_maxsizebytes); + + if (!empty($data->assignsubmission_file_filetypes)) { + $this->set_config('filetypeslist', $data->assignsubmission_file_filetypes); + } else { + $this->set_config('filetypeslist', ''); + } + return true; } @@ -128,7 +142,7 @@ class assign_submission_file extends assign_submission_plugin { $fileoptions = array('subdirs' => 1, 'maxbytes' => $this->get_config('maxsubmissionsizebytes'), 'maxfiles' => $this->get_config('maxfilesubmissions'), - 'accepted_types' => '*', + 'accepted_types' => $this->get_accepted_types(), 'return_types' => (FILE_INTERNAL | FILE_CONTROLLED_LINK)); if ($fileoptions['maxbytes'] == 0) { // Use module default. @@ -163,6 +177,26 @@ class assign_submission_file extends assign_submission_plugin { $submissionid); $mform->addElement('filemanager', 'files_filemanager', $this->get_name(), null, $fileoptions); + if (!empty($this->get_config('filetypeslist'))) { + $text = html_writer::tag('p', get_string('filesofthesetypes', 'assignsubmission_file')); + $text .= html_writer::start_tag('ul'); + + $typesets = $this->get_configured_typesets(); + foreach ($typesets as $type) { + $a = new stdClass(); + if (strpos($type, '/') !== false) { + $a->name = get_mimetype_description($type); + } else { + $a->name = get_string("group:$type", 'mimetypes'); + } + $a->extlist = implode(' ', file_get_typegroup('extension', $type)); + $text .= html_writer::tag('li', get_string('filetypewithexts', 'assignsubmission_file', $a)); + } + + $text .= html_writer::end_tag('ul'); + $mform->addElement('static', '', '', $text); + } + return true; } @@ -570,4 +604,35 @@ class assign_submission_file extends assign_submission_plugin { } return (array) $configs; } + + /** + * Get the type sets configured for this assignment. + * + * @return array('groupname', 'mime/type', ...) + */ + private function get_configured_typesets() { + $typeslist = (string)$this->get_config('filetypeslist'); + + $sets = array(); + if (!empty($typeslist)) { + $sets = explode(';', $typeslist); + } + return $sets; + } + + + /** + * Return the accepted types list for the file manager component. + * + * @return array|string + */ + private function get_accepted_types() { + $acceptedtypes = $this->get_configured_typesets(); + + if (!empty($acceptedtypes)) { + return $acceptedtypes; + } + + return '*'; + } } diff --git a/mod/assign/submission/file/tests/behat/file_type_restriction.feature b/mod/assign/submission/file/tests/behat/file_type_restriction.feature new file mode 100644 index 00000000000..ed765b70805 --- /dev/null +++ b/mod/assign/submission/file/tests/behat/file_type_restriction.feature @@ -0,0 +1,68 @@ +@mod @mod_assign @assignsubmission_file +Feature: In an assignment, limit submittable file types + In order to constrain student submissions for marking + As a teacher + I need to limit the submittable file types + + Background: + Given the following "courses" exist: + | fullname | shortname | category | groupmode | + | Course 1 | C1 | 0 | 1 | + And the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | teacher1@example.com | + | student1 | Student | 1 | student1@example.com | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + | student1 | C1 | student | + And the following config values are set as admin: + | filetypes | image/png;spreadsheet | assignsubmission_file | + + @javascript + Scenario: Configuring permitted file types for an assignment + Given the following "activities" exist: + | activity | course | idnumber | name | intro | duedate | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | assignsubmission_file_maxfiles | assignsubmission_file_maxsizebytes | + | assign | C1 | assign1 | Test assignment name | Test assignment description | 1388534400 | 0 | 1 | 1 | 0 | + And I log in as "teacher1" + And I am on "Course 1" course homepage + And I follow "Test assignment name" + And I navigate to "Edit settings" in current page administration + When I set the field "Accepted file types" to "image/png;spreadsheet" + And I press "Save and display" + And I navigate to "Edit settings" in current page administration + Then the field "Accepted file types" matches value "image/png;spreadsheet" + + @javascript @_file_upload + Scenario: Uploading permitted file types for an assignment + Given the following "activities" exist: + | activity | course | idnumber | name | intro | duedate | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | assignsubmission_file_maxfiles | assignsubmission_file_maxsizebytes | assignsubmission_file_filetypes | + | assign | C1 | assign1 | Test assignment name | Test assignment description | 1388534400 | 0 | 1 | 2 | 0 | image/png;spreadsheet | + And I log in as "student1" + And I am on "Course 1" course homepage + And I follow "Test assignment name" + When I press "Add submission" + And I should see "Files of these types may be added to the submission" + And I should see "Image (PNG) — .png" + And I should see "Spreadsheet files — .csv .ods .ots .xls .xlsx .xlsm" + And I upload "lib/tests/fixtures/gd-logo.png" file to "File submissions" filemanager + And I upload "lib/tests/fixtures/tabfile.csv" file to "File submissions" filemanager + And I press "Save changes" + Then "gd-logo.png" "link" should exist + And "tabfile.csv" "link" should exist + + @javascript @_file_upload + Scenario: No filetypes allows all + Given the following "activities" exist: + | activity | course | idnumber | name | intro | duedate | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | assignsubmission_file_maxfiles | assignsubmission_file_maxsizebytes | assignsubmission_file_filetypes | + | assign | C1 | assign1 | Test assignment name | Test assignment description | 1388534400 | 0 | 1 | 2 | 0 | | + And I log in as "student1" + And I am on "Course 1" course homepage + And I follow "Test assignment name" + When I press "Add submission" + And I should not see "Files of these types may be added to the submission" + And I upload "lib/tests/fixtures/gd-logo.png" file to "File submissions" filemanager + And I upload "lib/tests/fixtures/tabfile.csv" file to "File submissions" filemanager + And I press "Save changes" + Then "gd-logo.png" "link" should exist + And "tabfile.csv" "link" should exist diff --git a/mod/assign/submission/file/version.php b/mod/assign/submission/file/version.php index f7ee6360bdb..fe6bfce64d0 100644 --- a/mod/assign/submission/file/version.php +++ b/mod/assign/submission/file/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016120500; +$plugin->version = 2017032000; $plugin->requires = 2016112900; $plugin->component = 'assignsubmission_file'; From 62e87ae4b8b3eeca65bd63cbfdccc5b9b2c5d982 Mon Sep 17 00:00:00 2001 From: John Okely Date: Mon, 27 Mar 2017 11:14:02 +0800 Subject: [PATCH 3/4] MDL-39913 assign: Add help on filetype submissions --- mod/assign/submission/file/lang/en/assignsubmission_file.php | 1 + mod/assign/submission/file/locallib.php | 1 + 2 files changed, 2 insertions(+) diff --git a/mod/assign/submission/file/lang/en/assignsubmission_file.php b/mod/assign/submission/file/lang/en/assignsubmission_file.php index 5e51401328e..9c83b5824a8 100644 --- a/mod/assign/submission/file/lang/en/assignsubmission_file.php +++ b/mod/assign/submission/file/lang/en/assignsubmission_file.php @@ -24,6 +24,7 @@ $string['acceptedfiletypes'] = 'Accepted file types'; +$string['acceptedfiletypes_help'] = 'Accepted file types can be restricted by entering a semicolon-separated list of mimetypes, for example \'video/mp4; audio/mp3; image/png; image/jpeg\'. You may also limit to extensions by including the dot, for example \'.png; .jpg\' If the field is left empty, then all file types are allowed.'; $string['configmaxbytes'] = 'Maximum file size'; $string['countfiles'] = '{$a} files'; $string['default'] = 'Enabled by default'; diff --git a/mod/assign/submission/file/locallib.php b/mod/assign/submission/file/locallib.php index f991e3ecba4..479f6d55f54 100644 --- a/mod/assign/submission/file/locallib.php +++ b/mod/assign/submission/file/locallib.php @@ -109,6 +109,7 @@ class assign_submission_file extends assign_submission_plugin { $name = get_string('acceptedfiletypes', 'assignsubmission_file'); $mform->addElement('text', 'assignsubmission_file_filetypes', $name); + $mform->addHelpButton('assignsubmission_file_filetypes', 'acceptedfiletypes', 'assignsubmission_file'); $mform->setType('assignsubmission_file_filetypes', PARAM_RAW); $mform->setDefault('assignsubmission_file_filetypes', $defaultfiletypes); $mform->disabledIf('assignsubmission_file_filetypes', 'assignsubmission_file_enabled', 'notchecked'); From 61527865a1fb4aa16f0424e495b7d0a9d739934e Mon Sep 17 00:00:00 2001 From: John Okely Date: Mon, 3 Apr 2017 14:38:52 +0800 Subject: [PATCH 4/4] MDL-39913 assignsubmission_file: Add validation --- .../file/lang/en/assignsubmission_file.php | 1 + mod/assign/submission/file/locallib.php | 71 ++++++++++++++++--- .../tests/behat/file_type_restriction.feature | 14 ++-- .../submission/file/tests/locallib_test.php | 64 +++++++++++++++++ 4 files changed, 138 insertions(+), 12 deletions(-) diff --git a/mod/assign/submission/file/lang/en/assignsubmission_file.php b/mod/assign/submission/file/lang/en/assignsubmission_file.php index 9c83b5824a8..381adb28b0f 100644 --- a/mod/assign/submission/file/lang/en/assignsubmission_file.php +++ b/mod/assign/submission/file/lang/en/assignsubmission_file.php @@ -42,6 +42,7 @@ $string['maxfilessubmission'] = 'Maximum number of uploaded files'; $string['maxfilessubmission_help'] = 'If file submissions are enabled, each student will be able to upload up to this number of files for their submission.'; $string['maximumsubmissionsize'] = 'Maximum submission size'; $string['maximumsubmissionsize_help'] = 'Files uploaded by students may be up to this size.'; +$string['nonexistentfiletypes'] = 'The following file types were not recognised: {$a}'; $string['numfilesforlog'] = 'The number of file(s) : {$a} file(s).'; $string['pluginname'] = 'File submissions'; $string['siteuploadlimit'] = 'Site upload limit'; diff --git a/mod/assign/submission/file/locallib.php b/mod/assign/submission/file/locallib.php index 479f6d55f54..b0816c3a2be 100644 --- a/mod/assign/submission/file/locallib.php +++ b/mod/assign/submission/file/locallib.php @@ -113,6 +113,18 @@ class assign_submission_file extends assign_submission_plugin { $mform->setType('assignsubmission_file_filetypes', PARAM_RAW); $mform->setDefault('assignsubmission_file_filetypes', $defaultfiletypes); $mform->disabledIf('assignsubmission_file_filetypes', 'assignsubmission_file_enabled', 'notchecked'); + $mform->addFormRule(function ($values, $files) { + if (empty($values['assignsubmission_file_filetypes'])) { + return true; + } + $nonexistent = $this->get_nonexistent_file_types($values['assignsubmission_file_filetypes']); + if (empty($nonexistent)) { + return true; + } else { + $a = join(' ', $nonexistent); + return ["assignsubmission_file_filetypes" => get_string('nonexistentfiletypes', 'assignsubmission_file', $a)]; + } + }); } /** @@ -185,13 +197,21 @@ class assign_submission_file extends assign_submission_plugin { $typesets = $this->get_configured_typesets(); foreach ($typesets as $type) { $a = new stdClass(); - if (strpos($type, '/') !== false) { - $a->name = get_mimetype_description($type); - } else { - $a->name = get_string("group:$type", 'mimetypes'); + $extensions = file_get_typegroup('extension', $type); + $typetext = html_writer::tag('li', $type); + // Only bother checking if it's a mimetype or group if it has extensions in the group. + if (!empty($extensions)) { + if (strpos($type, '/') !== false) { + $a->name = get_mimetype_description($type); + $a->extlist = implode(' ', $extensions); + $typetext = html_writer::tag('li', get_string('filetypewithexts', 'assignsubmission_file', $a)); + } else if (get_string_manager()->string_exists("group:$type", 'mimetypes')) { + $a->name = get_string("group:$type", 'mimetypes'); + $a->extlist = implode(' ', $extensions); + $typetext = html_writer::tag('li', get_string('filetypewithexts', 'assignsubmission_file', $a)); + } } - $a->extlist = implode(' ', file_get_typegroup('extension', $type)); - $text .= html_writer::tag('li', get_string('filetypewithexts', 'assignsubmission_file', $a)); + $text .= $typetext; } $text .= html_writer::end_tag('ul'); @@ -614,9 +634,21 @@ class assign_submission_file extends assign_submission_plugin { private function get_configured_typesets() { $typeslist = (string)$this->get_config('filetypeslist'); + $sets = $this->get_typesets($typeslist); + + return $sets; + } + + /** + * Get the type sets passed. + * + * @param string $types The space , ; separated list of types + * @return array('groupname', 'mime/type', ...) + */ + private function get_typesets($types) { $sets = array(); - if (!empty($typeslist)) { - $sets = explode(';', $typeslist); + if (!empty($types)) { + $sets = preg_split('/[\s,;:"\']+/', $types, null, PREG_SPLIT_NO_EMPTY); } return $sets; } @@ -636,4 +668,27 @@ class assign_submission_file extends assign_submission_plugin { return '*'; } + + /** + * List the nonexistent file types that need to be removed. + * + * @param string $types space , or ; separated types + * @return array A list of the nonexistent file types. + */ + private function get_nonexistent_file_types($types) { + $nonexistent = []; + foreach ($this->get_typesets($types) as $type) { + $coretypes = core_filetypes::get_types(); + // We can allow any extension, but validate groups & mimetypes. + if (strpos($type, '.') === false) { + // If there's no dot, check if it's a group. + $extensions = file_get_typegroup('extension', [$type]); + if (empty($extensions)) { + // If there's no extensions under that group, it doesn't exist. + $nonexistent[$type] = true; + } + } + } + return array_keys($nonexistent); + } } diff --git a/mod/assign/submission/file/tests/behat/file_type_restriction.feature b/mod/assign/submission/file/tests/behat/file_type_restriction.feature index ed765b70805..4990daece70 100644 --- a/mod/assign/submission/file/tests/behat/file_type_restriction.feature +++ b/mod/assign/submission/file/tests/behat/file_type_restriction.feature @@ -20,7 +20,7 @@ Feature: In an assignment, limit submittable file types | filetypes | image/png;spreadsheet | assignsubmission_file | @javascript - Scenario: Configuring permitted file types for an assignment + Scenario: File types validation for an assignment Given the following "activities" exist: | activity | course | idnumber | name | intro | duedate | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | assignsubmission_file_maxfiles | assignsubmission_file_maxsizebytes | | assign | C1 | assign1 | Test assignment name | Test assignment description | 1388534400 | 0 | 1 | 1 | 0 | @@ -28,7 +28,10 @@ Feature: In an assignment, limit submittable file types And I am on "Course 1" course homepage And I follow "Test assignment name" And I navigate to "Edit settings" in current page administration - When I set the field "Accepted file types" to "image/png;spreadsheet" + When I set the field "Accepted file types" to "image/png;doesntexist;.anything;unreal/mimetype;nodot" + And I press "Save and display" + And I should see "The following file types were not recognised: doesntexist unreal/mimetype nodot" + And I set the field "Accepted file types" to "image/png;spreadsheet" And I press "Save and display" And I navigate to "Edit settings" in current page administration Then the field "Accepted file types" matches value "image/png;spreadsheet" @@ -37,19 +40,22 @@ Feature: In an assignment, limit submittable file types Scenario: Uploading permitted file types for an assignment Given the following "activities" exist: | activity | course | idnumber | name | intro | duedate | assignsubmission_onlinetext_enabled | assignsubmission_file_enabled | assignsubmission_file_maxfiles | assignsubmission_file_maxsizebytes | assignsubmission_file_filetypes | - | assign | C1 | assign1 | Test assignment name | Test assignment description | 1388534400 | 0 | 1 | 2 | 0 | image/png;spreadsheet | + | assign | C1 | assign1 | Test assignment name | Test assignment description | 1388534400 | 0 | 1 | 3 | 0 | image/png;spreadsheet;.xml;.txt | And I log in as "student1" And I am on "Course 1" course homepage And I follow "Test assignment name" When I press "Add submission" And I should see "Files of these types may be added to the submission" And I should see "Image (PNG) — .png" - And I should see "Spreadsheet files — .csv .ods .ots .xls .xlsx .xlsm" + And I should see "Spreadsheet files — .csv .gsheet .ods .ots .xls .xlsx .xlsm" + And I should see ".txt" And I upload "lib/tests/fixtures/gd-logo.png" file to "File submissions" filemanager And I upload "lib/tests/fixtures/tabfile.csv" file to "File submissions" filemanager + And I upload "lib/tests/fixtures/empty.txt" file to "File submissions" filemanager And I press "Save changes" Then "gd-logo.png" "link" should exist And "tabfile.csv" "link" should exist + And "empty.txt" "link" should exist @javascript @_file_upload Scenario: No filetypes allows all diff --git a/mod/assign/submission/file/tests/locallib_test.php b/mod/assign/submission/file/tests/locallib_test.php index 8df613a58da..c8b1082bdaf 100644 --- a/mod/assign/submission/file/tests/locallib_test.php +++ b/mod/assign/submission/file/tests/locallib_test.php @@ -137,5 +137,69 @@ class assignsubmission_file_locallib_testcase extends advanced_testcase { ]; } + /** + * Data provider for testing test_get_nonexistent_file_types. + * + * @return array + */ + public function get_nonexistent_file_types_provider() { + return [ + 'Nonexistent extensions are allowed' => [ + 'filetypes' => '.rat', + 'expected' => [] + ], + 'Multiple nonexistent extensions are allowed' => [ + 'filetypes' => '.ricefield .rat', + 'expected' => [] + ], + 'Existent extension is allowed' => [ + 'filetypes' => '.xml', + 'expected' => [] + ], + 'Existent group is allowed' => [ + 'filetypes' => 'web_file', + 'expected' => [] + ], + 'Nonexistent group is not allowed' => [ + 'filetypes' => '©ç√√ß∂å√©åß©√', + 'expected' => ['©ç√√ß∂å√©åß©√'] + ], + 'Existent mimetype is allowed' => [ + 'filetypes' => 'application/xml', + 'expected' => [] + ], + 'Nonexistent mimetype is not allowed' => [ + 'filetypes' => 'ricefield/rat', + 'expected' => ['ricefield/rat'] + ], + 'Multiple nonexistent mimetypes are not allowed' => [ + 'filetypes' => 'ricefield/rat cam/ball', + 'expected' => ['ricefield/rat', 'cam/ball'] + ], + 'Missing dot in extension is not allowed' => [ + 'filetypes' => 'png', + 'expected' => ['png'] + ], + 'Some existent some not' => [ + 'filetypes' => '.txt application/xml web_file ©ç√√ß∂å√©åß©√ .png ricefield/rat document png', + 'expected' => ['©ç√√ß∂å√©åß©√', 'ricefield/rat', 'png'] + ] + ]; + } + + /** + * Test get_nonexistent_file_types(). + * @dataProvider get_nonexistent_file_types_provider + * @param string $filetypes The filetypes to check + * @param array $expected The expected result. The list of non existent file types. + */ + public function test_get_nonexistent_file_types($filetypes, $expected) { + $this->resetAfterTest(); + $method = new ReflectionMethod(assign_submission_file::class, 'get_nonexistent_file_types'); + $method->setAccessible(true); + $plugin = $this->assign->get_submission_plugin_by_type('file'); + $nonexistentfiletypes = $method->invokeArgs($plugin, [$filetypes]); + $this->assertSame($expected, $nonexistentfiletypes); + } }