mirror of
https://github.com/moodle/moodle.git
synced 2025-01-29 19:50:14 +01:00
MDL-70864 files: Fix zip_packer extracting files with trailing dots
File and folder names cannot end with dots on Windows. So replace the trailing dots with underscore consistently with how some other zip tools (such as 7-zip) handle this case.
This commit is contained in:
parent
0a986fdf13
commit
260c2bdb00
@ -260,6 +260,8 @@ class core_files_zip_packer_testcase extends advanced_testcase implements file_p
|
||||
* @link https://bugs.php.net/bug.php?id=77214
|
||||
*/
|
||||
public function test_zip_entry_path_having_folder_ending_with_dot() {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest(false);
|
||||
|
||||
$packer = get_file_packer('application/zip');
|
||||
@ -276,6 +278,28 @@ class core_files_zip_packer_testcase extends advanced_testcase implements file_p
|
||||
'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' => [''],
|
||||
];
|
||||
|
||||
if ($CFG->ostype === 'WINDOWS') {
|
||||
// File names cannot end with dots on Windows and trailing dots are replaced with underscore.
|
||||
$filenamemap = [
|
||||
'HOW.TO' => 'HOW.TO',
|
||||
'README.' => 'README_',
|
||||
'./Current time' => 'Current time',
|
||||
'Data/sub1./sub2/1221' => 'Data/sub1_/sub2/1221',
|
||||
'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' =>
|
||||
'Data/sub1_/sub2_/Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt',
|
||||
];
|
||||
|
||||
} else {
|
||||
$filenamemap = [
|
||||
'HOW.TO' => 'HOW.TO',
|
||||
'README.' => 'README.',
|
||||
'./Current time' => 'Current time',
|
||||
'Data/sub1./sub2/1221' => 'Data/sub1./sub2/1221',
|
||||
'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' =>
|
||||
'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt',
|
||||
];
|
||||
}
|
||||
|
||||
// Check that the archive can be created.
|
||||
$result = $packer->archive_to_pathname($zipcontents, $zippath, false);
|
||||
$this->assertTrue($result);
|
||||
@ -298,8 +322,8 @@ class core_files_zip_packer_testcase extends advanced_testcase implements file_p
|
||||
|
||||
foreach ($zipcontents as $filename => $filecontents) {
|
||||
$filecontents = reset($filecontents);
|
||||
$this->assertTrue(is_readable($targetpath . '/' . $filename));
|
||||
$this->assertEquals($filecontents, file_get_contents($targetpath . '/' . $filename));
|
||||
$this->assertTrue(is_readable($targetpath . '/' . $filenamemap[$filename]));
|
||||
$this->assertEquals($filecontents, file_get_contents($targetpath . '/' . $filenamemap[$filename]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,11 +297,17 @@ class zip_packer extends file_packer {
|
||||
|
||||
$size = $info->size;
|
||||
$name = $info->pathname;
|
||||
$origname = $name;
|
||||
|
||||
// File names cannot end with dots on Windows and trailing dots are replaced with underscore.
|
||||
if ($CFG->ostype === 'WINDOWS') {
|
||||
$name = preg_replace('~([^/]+)\.(/|$)~', '\1_\2', $name);
|
||||
}
|
||||
|
||||
if ($name === '' or array_key_exists($name, $processed)) {
|
||||
// Probably filename collisions caused by filename cleaning/conversion.
|
||||
continue;
|
||||
} else if (is_array($onlyfiles) && !in_array($name, $onlyfiles)) {
|
||||
} else if (is_array($onlyfiles) && !in_array($origname, $onlyfiles)) {
|
||||
// Skipping files which are not in the list.
|
||||
continue;
|
||||
}
|
||||
@ -342,7 +348,7 @@ class zip_packer extends file_packer {
|
||||
|
||||
$newfile = "$newdir/$filename";
|
||||
|
||||
if (strpos($newfile, './') > 1) {
|
||||
if (strpos($newfile, './') > 1 || $name !== $origname) {
|
||||
// The path to the entry contains a directory ending with dot. We cannot use extract_to() due to
|
||||
// upstream PHP bugs #69477, #74619 and #77214. Extract the file from its stream which is slower but
|
||||
// should work even in this case.
|
||||
|
Loading…
x
Reference in New Issue
Block a user