2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * Abstraction of general file archives.
22 * @copyright 2008 Petr Skoda (http://skodak.org)
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die();
29 * Each file archive type must extend this class.
32 * @copyright 2008 Petr Skoda (http://skodak.org)
33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 abstract class file_archive
implements Iterator
{
37 /** Open archive if exists, fail if does not exist. */
40 /** Open archive if exists, create if does not. */
43 /** Always create new archive */
46 /** @var string Encoding of file names - windows usually expects DOS single-byte charset*/
47 protected $encoding = 'utf-8';
50 * Open or create archive (depending on $mode).
52 * @param string $archivepathname archive path name
53 * @param int $mode OPEN, CREATE or OVERWRITE constant
54 * @param string $encoding archive local paths encoding
55 * @return bool success
57 public abstract function open($archivepathname, $mode=file_archive
::CREATE
, $encoding='utf-8');
62 * @return bool success
64 public abstract function close();
67 * Returns file stream for reading of content.
69 * @param int $index index of file
70 * @return stream|bool stream or false if error
72 public abstract function get_stream($index);
75 * Returns file information.
77 * @param int $index index of file
78 * @return stdClass|bool object or false if error
80 public abstract function get_info($index);
83 * Returns array of info about all files in archive.
85 * @return array of file infos
87 public abstract function list_files();
90 * Returns number of files in archive.
92 * @return int number of files
94 public abstract function count();
97 * Add file into archive.
99 * @param string $localname name of file in archive
100 * @param string $pathname location of file
101 * @return bool success
103 public abstract function add_file_from_pathname($localname, $pathname);
106 * Add content of string into archive.
108 * @param string $localname name of file in archive
109 * @param string $contents contents
110 * @return bool success
112 public abstract function add_file_from_string($localname, $contents);
115 * Add empty directory into archive.
117 * @param string $localname name of file in archive
118 * @return bool success
120 public abstract function add_directory($localname);
123 * Tries to convert $localname into another encoding,
124 * please note that it may fail really badly.
126 * @param string $localname name of file in utf-8 encoding
129 protected function mangle_pathname($localname) {
130 if ($this->encoding
=== 'utf-8') {
134 $converted = core_text
::convert($localname, 'utf-8', $this->encoding
);
135 $original = core_text
::convert($converted, $this->encoding
, 'utf-8');
137 if ($original === $localname) {
138 $result = $converted;
141 // try ascii conversion
142 $converted2 = core_text
::specialtoascii($localname);
143 $converted2 = core_text
::convert($converted2, 'utf-8', $this->encoding
);
144 $original2 = core_text
::convert($converted, $this->encoding
, 'utf-8');
146 if ($original2 === $localname) {
147 //this looks much better
148 $result = $converted2;
150 //bad luck - the file name may not be usable at all
151 $result = $converted;
155 $result = preg_replace('/\.\.+\//', '', $result); // Cleanup any potential ../ transversal (any number of dots).
156 $result = preg_replace('/\.\.+/', '.', $result); // Join together any number of consecutive dots.
157 $result = ltrim($result); // no leading /
159 if ($result === '.') {
167 * Tries to convert $localname into utf-8
168 * please note that it may fail really badly.
169 * The resulting file name is cleaned.
171 * @param string $localname name of file in $this->encoding
172 * @return string in utf-8
174 protected function unmangle_pathname($localname) {
175 $result = str_replace('\\', '/', $localname); // no MS \ separators
176 $result = ltrim($result, '/'); // no leading /
178 if ($this->encoding
!== 'utf-8') {
179 $result = core_text
::convert($result, $this->encoding
, 'utf-8');
182 return clean_param($result, PARAM_PATH
);
186 * Returns current file info.
189 //public abstract function current();
192 * Returns the index of current file.
193 * @return int current file index
195 //public abstract function key();
198 * Moves forward to next file.
201 //public abstract function next();
204 * Rewinds back to the first file.
207 //public abstract function rewind();
210 * Did we reach the end?
213 //public abstract function valid();