forked from moodle/moodle
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'MDL-68533_master-clean_param' of git://github.com/mdjne…
…lson/moodle
- Loading branch information
Showing
8 changed files
with
631 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<?php | ||
// This file is part of Moodle - http://moodle.org/ | ||
// | ||
// Moodle is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Moodle is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
/** | ||
* Abstraction of general file archives. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
|
||
namespace core_files; | ||
|
||
use core_files\local\archive_writer\file_writer_interface as file_writer_interface; | ||
use core_files\local\archive_writer\stream_writer_interface as stream_writer_interface; | ||
|
||
/** | ||
* Each file archive type must extend this class. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
abstract class archive_writer { | ||
|
||
/** | ||
* The zip writer class. | ||
*/ | ||
public const ZIP_WRITER = 'zip_writer'; | ||
|
||
/** | ||
* Returns the stream writer. | ||
* | ||
* @param string $filename | ||
* @param string $type | ||
* @return stream_writer_interface | ||
*/ | ||
public static function get_stream_writer(string $filename, string $type): stream_writer_interface { | ||
$classname = self::get_classname_for_type($type); | ||
|
||
if (!is_a($classname, stream_writer_interface::class, true)) { | ||
throw new \InvalidArgumentException("{$type} does not support streaming"); | ||
} | ||
|
||
return $classname::stream_instance($filename); | ||
} | ||
|
||
/** | ||
* Returns the file writer. | ||
* | ||
* @param string $filepath | ||
* @param string $type | ||
* @return file_writer_interface | ||
*/ | ||
public static function get_file_writer(string $filepath, string $type): file_writer_interface { | ||
$classname = self::get_classname_for_type($type); | ||
|
||
if (!is_a($classname, file_writer_interface::class, true)) { | ||
throw new \InvalidArgumentException("{$type} does not support writing to files"); | ||
} | ||
|
||
return $classname::file_instance($filepath); | ||
} | ||
|
||
/** | ||
* Sanitise the file path, removing any unsuitable characters. | ||
* | ||
* @param string $filepath | ||
* @return string | ||
*/ | ||
public function sanitise_filepath(string $filepath): string { | ||
return clean_param($filepath, PARAM_PATH); | ||
} | ||
|
||
/** | ||
* Returns the class name for the type that was provided in get_file_writer(). | ||
* | ||
* @param string $type | ||
* @return string | ||
*/ | ||
protected static function get_classname_for_type(string $type): string { | ||
return "core_files\local\archive_writer\\" . $type; | ||
} | ||
|
||
/** | ||
* The archive_writer Constructor. | ||
*/ | ||
protected function __construct() { | ||
|
||
} | ||
|
||
/** | ||
* Adds a file from a file path. | ||
* | ||
* @param string $name The path of file in archive (including directory). | ||
* @param string $path The path to file on disk (note: paths should be encoded using | ||
* UNIX-style forward slashes -- e.g '/path/to/some/file'). | ||
*/ | ||
abstract public function add_file_from_filepath(string $name, string $path): void; | ||
|
||
/** | ||
* Adds a file from a string. | ||
* | ||
* @param string $name The path of file in archive (including directory). | ||
* @param string $data The contents of file | ||
*/ | ||
abstract public function add_file_from_string(string $name, string $data): void; | ||
|
||
/** | ||
* Adds a file from a stream. | ||
* | ||
* @param string $name The path of file in archive (including directory). | ||
* @param resource $stream The contents of file as a stream resource | ||
*/ | ||
abstract public function add_file_from_stream(string $name, $stream): void; | ||
|
||
/** | ||
* Adds a stored_file to archive. | ||
* | ||
* @param string $name The path of file in archive (including directory). | ||
* @param \stored_file $file | ||
*/ | ||
abstract public function add_file_from_stored_file(string $name, \stored_file $file): void; | ||
|
||
/** | ||
* Finish writing the zip footer. | ||
*/ | ||
abstract public function finish(): void; | ||
} |
50 changes: 50 additions & 0 deletions
50
files/classes/local/archive_writer/file_writer_interface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
// This file is part of Moodle - http://moodle.org/ | ||
// | ||
// Moodle is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Moodle is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
/** | ||
* Interface used by archives that write to files. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
|
||
namespace core_files\local\archive_writer; | ||
|
||
/** | ||
* Interface used by archives that write to files. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
interface file_writer_interface { | ||
|
||
/** | ||
* Return the file instance. | ||
* | ||
* @param string $filename | ||
* @return static | ||
*/ | ||
public static function file_instance(string $filename): self; | ||
|
||
/** | ||
* Get the path of the zip. | ||
* | ||
* @return string | ||
*/ | ||
public function get_path_to_zip(): string; | ||
} |
43 changes: 43 additions & 0 deletions
43
files/classes/local/archive_writer/stream_writer_interface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
// This file is part of Moodle - http://moodle.org/ | ||
// | ||
// Moodle is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Moodle is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
/** | ||
* Interface used by archives that write to streams. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
|
||
namespace core_files\local\archive_writer; | ||
|
||
/** | ||
* Interface used by archives that write to streams. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
interface stream_writer_interface { | ||
|
||
/** | ||
* Return the stream instance. | ||
* | ||
* @param string $filename | ||
* @return static | ||
*/ | ||
public static function stream_instance(string $filename): self; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
<?php | ||
// This file is part of Moodle - http://moodle.org/ | ||
// | ||
// Moodle is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Moodle is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
/** | ||
* Class used for creating ZIP archives. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
|
||
namespace core_files\local\archive_writer; | ||
|
||
use ZipStream\Option\Archive; | ||
use ZipStream\ZipStream; | ||
use core_files\archive_writer; | ||
use core_files\local\archive_writer\file_writer_interface as file_writer_interface; | ||
use core_files\local\archive_writer\stream_writer_interface as stream_writer_interface; | ||
|
||
/** | ||
* Class used for creating ZIP archives. | ||
* | ||
* @package core_files | ||
* @copyright 2020 Mark Nelson <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
class zip_writer extends archive_writer implements file_writer_interface, stream_writer_interface { | ||
|
||
/** | ||
* @var resource File resource for the file handle for a file-based zip stream | ||
*/ | ||
private $zipfilehandle = null; | ||
|
||
/** | ||
* @var String The location of the zip file. | ||
*/ | ||
private $zipfilepath = null; | ||
|
||
/** | ||
* @var ZipStream The zip stream. | ||
*/ | ||
private $archive; | ||
|
||
/** | ||
* The zip_writer constructor. | ||
* | ||
* @param ZipStream $archive | ||
*/ | ||
protected function __construct(ZipStream $archive) { | ||
parent::__construct(); | ||
$this->archive = $archive; | ||
} | ||
|
||
public static function stream_instance(string $filename): stream_writer_interface { | ||
$options = new Archive(); | ||
$options->setSendHttpHeaders(true); | ||
$options->setContentDisposition('attachment'); | ||
$options->setContentType('application/x-zip'); | ||
$zipwriter = new ZipStream($filename, $options); | ||
|
||
return new static($zipwriter); | ||
} | ||
|
||
public static function file_instance(string $filename): file_writer_interface { | ||
$dir = make_request_directory(); | ||
$filepath = "$dir/$filename"; | ||
$fh = fopen($filepath, 'w'); | ||
|
||
$exportoptions = new Archive(); | ||
$exportoptions->setOutputStream($fh); | ||
$exportoptions->setSendHttpHeaders(false); | ||
$zipstream = new ZipStream($filename, $exportoptions); | ||
|
||
$zipwriter = new static($zipstream); | ||
// ZipStream only takes a file handle resource. | ||
// It does not close this resource itself, and it does not know the location of this resource on disk. | ||
// Store references to the filehandle, and the location of the filepath in the new class so that the `finish()` | ||
// function can close the fh, and move the temporary file into place. | ||
// The filehandle must be closed when finishing the archive. ZipStream does not close it automatically. | ||
$zipwriter->zipfilehandle = $fh; | ||
$zipwriter->zipfilepath = $filepath; | ||
|
||
return $zipwriter; | ||
} | ||
|
||
public function add_file_from_filepath(string $name, string $path): void { | ||
$this->archive->addFileFromPath($this->sanitise_filepath($name), $path); | ||
} | ||
|
||
public function add_file_from_string(string $name, string $data): void { | ||
$this->archive->addFile($this->sanitise_filepath($name), $data); | ||
} | ||
|
||
public function add_file_from_stream(string $name, $stream): void { | ||
$this->archive->addFileFromStream($this->sanitise_filepath($name), $stream); | ||
fclose($stream); | ||
} | ||
|
||
public function add_file_from_stored_file(string $name, \stored_file $file): void { | ||
$filehandle = $file->get_content_file_handle(); | ||
$this->archive->addFileFromStream($this->sanitise_filepath($name), $filehandle); | ||
fclose($filehandle); | ||
} | ||
|
||
public function finish(): void { | ||
$this->archive->finish(); | ||
|
||
if ($this->zipfilehandle) { | ||
fclose($this->zipfilehandle); | ||
} | ||
} | ||
|
||
public function get_path_to_zip(): string { | ||
return $this->zipfilepath; | ||
} | ||
|
||
public function sanitise_filepath(string $filepath): string { | ||
$filepath = parent::sanitise_filepath($filepath); | ||
|
||
return \ZipStream\File::filterFilename($filepath); | ||
} | ||
} |
Oops, something went wrong.