diff --git a/admin/settings/development.php b/admin/settings/development.php index b99d519640b..a1ad6e02bfc 100644 --- a/admin/settings/development.php +++ b/admin/settings/development.php @@ -27,6 +27,9 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page $temp->add(new admin_setting_configcheckbox('enabletgzbackups', new lang_string('enabletgzbackups', 'admin'), new lang_string('enabletgzbackups_desc', 'admin'), 0)); + $temp->add(new admin_setting_php_extension_enabled('zlibenabled', + get_string('zlibenabled', 'admin'), + get_string('enabletgzbackups_nozlib', 'admin'), 'zlib')); $ADMIN->add('experimental', $temp); diff --git a/lang/en/admin.php b/lang/en/admin.php index 1d06ba401dd..34b8fa658b1 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -491,6 +491,7 @@ $string['enablesafebrowserintegration'] = 'Enable Safe Exam Browser integration' $string['enablestats'] = 'Enable statistics'; $string['enabletgzbackups'] = 'Enable new backup format'; $string['enabletgzbackups_desc'] = 'If enabled, future backups will be created in a new compression format for .mbz files (internally stored as a .tar.gz file). This removes the 4GB backup size restriction and may improve performance. Restore supports both formats and the difference should be transparent to users.'; +$string['enabletgzbackups_nozlib'] = 'PHP extension ‘zlib’ is not available. The new backup format relies on this extension and will be disabled until zlib is installed and enabled.'; $string['enabletrusttext'] = 'Enable trusted content'; $string['enablewebservices'] = 'Enable web services'; $string['enablewsdocumentation'] = 'Web services documentation'; @@ -1130,6 +1131,7 @@ $string['webproxyinfo'] = 'Fill in following options if your Moodle server can n $string['xmlrpcrecommended'] = 'The xmlrpc extension is needed for hub communication, and useful for web services and Moodle networking'; $string['yuicomboloading'] = 'YUI combo loading'; $string['ziprequired'] = 'The Zip PHP extension is now required by Moodle, info-ZIP binaries or PclZip library are not used anymore.'; +$string['zlibenabled'] = 'zlib enabled'; $string['caching'] = 'Caching'; diff --git a/lang/en/backup.php b/lang/en/backup.php index 18a34ff3719..fbc4bc3f226 100644 --- a/lang/en/backup.php +++ b/lang/en/backup.php @@ -117,6 +117,7 @@ $string['errorminbackup20version'] = 'This backup file has been created with one $string['errorrestorefrontpage'] = 'Restoring over front page is not allowed.'; $string['errorinvalidformat'] = 'Unknown backup format'; $string['errorinvalidformatinfo'] = 'The selected file is not a valid Moodle backup file and can\'t be restored.'; +$string['errortgznozlib'] = 'The selected file is in the new backup format and cannot be restored because the zlib PHP extension is not available on this system.'; $string['executionsuccess'] = 'The backup file was successfully created.'; $string['filename'] = 'Filename'; $string['filealiasesrestorefailures'] = 'Aliases restore failures'; diff --git a/lib/filestorage/mbz_packer.php b/lib/filestorage/mbz_packer.php index e149e35b284..c4c08e20f95 100644 --- a/lib/filestorage/mbz_packer.php +++ b/lib/filestorage/mbz_packer.php @@ -137,14 +137,16 @@ class mbz_packer extends file_packer { } /** - * Selects appropriate packer for new archive depending on system option. + * Selects appropriate packer for new archive depending on system option + * and whether required extension is available. * * @return file_packer Suitable packer */ protected function get_packer_for_archive_operation() { global $CFG; + require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php'); - if ($CFG->enabletgzbackups) { + if ($CFG->enabletgzbackups && tgz_packer::has_required_extension()) { return get_file_packer('application/x-gzip'); } else { return get_file_packer('application/zip'); @@ -156,13 +158,18 @@ class mbz_packer extends file_packer { * * @param string|stored_file $archivefile full pathname of zip file or stored_file instance * @return file_packer Suitable packer + * @throws moodle_exception If the file cannot be restored because of missing zlib */ protected function get_packer_for_read_operation($archivefile) { global $CFG; require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php'); if (tgz_packer::is_tgz_file($archivefile)) { - return get_file_packer('application/x-gzip'); + if (tgz_packer::has_required_extension()) { + return get_file_packer('application/x-gzip'); + } else { + throw new moodle_exception('errortgznozlib', 'backup'); + } } else { return get_file_packer('application/zip'); } diff --git a/lib/filestorage/tests/mbz_packer_test.php b/lib/filestorage/tests/mbz_packer_test.php index cdb7bef92fb..b232e4f94e4 100644 --- a/lib/filestorage/tests/mbz_packer_test.php +++ b/lib/filestorage/tests/mbz_packer_test.php @@ -35,6 +35,11 @@ class core_files_mbz_packer_testcase extends advanced_testcase { // Get backup packer. $packer = get_file_packer('application/vnd.moodle.backup'); + require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php'); + if (!tgz_packer::has_required_extension()) { + $this->markTestSkipped('zlib not available'); + return; + } // Set up basic archive contents. $files = array('1.txt' => array('frog')); diff --git a/lib/filestorage/tests/tgz_packer_test.php b/lib/filestorage/tests/tgz_packer_test.php index d61d264d2d2..d495ec82fd3 100644 --- a/lib/filestorage/tests/tgz_packer_test.php +++ b/lib/filestorage/tests/tgz_packer_test.php @@ -114,6 +114,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p public function test_to_normal_files() { global $CFG; $packer = get_file_packer('application/x-gzip'); + if (self::skip_because_missing_zlib()) { + return; + } // Archive files. $files = $this->prepare_file_list(); @@ -154,6 +157,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p */ public function test_to_stored_files() { global $CFG; + if (self::skip_because_missing_zlib()) { + return; + } $packer = get_file_packer('application/x-gzip'); // Archive files. @@ -220,6 +226,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p */ public function test_only_specified_files() { global $CFG; + if (self::skip_because_missing_zlib()) { + return; + } $packer = get_file_packer('application/x-gzip'); // Archive files. @@ -252,6 +261,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p */ public function test_file_progress() { global $CFG; + if (self::skip_because_missing_zlib()) { + return; + } // Set up. $filelist = $this->prepare_file_list(); @@ -309,6 +321,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p */ public function test_list_files() { global $CFG; + if (self::skip_because_missing_zlib()) { + return; + } // Set up. $filelist = $this->prepare_file_list(); @@ -376,6 +391,9 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p public function test_is_tgz_file() { global $CFG; + if (self::skip_because_missing_zlib()) { + return; + } // Set up. $filelist = $this->prepare_file_list(); @@ -428,4 +446,19 @@ class core_files_tgz_packer_testcase extends advanced_testcase implements file_p public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) { $this->progress[] = array($progress, $max); } + + /** + * Checks if zlib is available. If not, marks current test as skipped. + * + * @return bool True if text should be skipped + */ + protected function skip_because_missing_zlib() { + global $CFG; + require_once($CFG->dirroot . '/lib/filestorage/tgz_packer.php'); + if (!tgz_packer::has_required_extension()) { + $this->markTestSkipped('zlib not available'); + return true; + } + return false; + } } diff --git a/lib/filestorage/tgz_packer.php b/lib/filestorage/tgz_packer.php index bfa459d7a7b..c47662aaa05 100644 --- a/lib/filestorage/tgz_packer.php +++ b/lib/filestorage/tgz_packer.php @@ -695,6 +695,16 @@ class tgz_packer extends file_packer { fclose($fp); return ($firstbytes[0] == "\x1f" && $firstbytes[1] == "\x8b"); } + + /** + * The zlib extension is required for this packer to work. This is a single + * location for the code to check whether the extension is available. + * + * @return bool True if the extension is available OK + */ + public static function has_required_extension() { + return extension_loaded('zlib'); + } } diff --git a/mod/assign/feedback/editpdf/lang/en/assignfeedback_editpdf.php b/mod/assign/feedback/editpdf/lang/en/assignfeedback_editpdf.php index a5046043d0c..088fd9f94dc 100644 --- a/mod/assign/feedback/editpdf/lang/en/assignfeedback_editpdf.php +++ b/mod/assign/feedback/editpdf/lang/en/assignfeedback_editpdf.php @@ -89,5 +89,4 @@ $string['unsavedchanges'] = 'Unsaved changes'; $string['viewfeedbackonline'] = 'View annotated pdf...'; $string['white'] = 'White'; $string['yellow'] = 'Yellow'; -$string['zlibenabled'] = 'zlib enabled'; $string['zlibnotavailable'] = 'Php extension "zlib" is not available. The annotate PDF feature relies on this php extension and will be disabled until zlib is installed and enabled.'; diff --git a/mod/assign/feedback/editpdf/settings.php b/mod/assign/feedback/editpdf/settings.php index 10493d0a856..783126230f8 100644 --- a/mod/assign/feedback/editpdf/settings.php +++ b/mod/assign/feedback/editpdf/settings.php @@ -40,7 +40,7 @@ $settings->add(new admin_setting_configexecutable('assignfeedback_editpdf/gspath '/usr/bin/gs')); $setting = new admin_setting_php_extension_enabled('assignfeedback_editpdf/zlibenabled', - get_string('zlibenabled', 'assignfeedback_editpdf'), + get_string('zlibenabled', 'admin'), get_string('zlibnotavailable', 'assignfeedback_editpdf'), 'zlib');