Merge branch 'MDL-64012' of https://github.com/timhunt/moodle
[moodle.git] / lib / filestorage / file_archive.php
blob8d9ab818c89f3f1eefc699cff75933eadc59c32f
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
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.
8 //
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/>.
18 /**
19 * Abstraction of general file archives.
21 * @package core_files
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();
28 /**
29 * Each file archive type must extend this class.
31 * @package core_files
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. */
38 const OPEN = 1;
40 /** Open archive if exists, create if does not. */
41 const CREATE = 2;
43 /** Always create new archive */
44 const OVERWRITE = 4;
46 /** @var string Encoding of file names - windows usually expects DOS single-byte charset*/
47 protected $encoding = 'utf-8';
49 /**
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');
59 /**
60 * Close archive.
62 * @return bool success
64 public abstract function close();
66 /**
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);
74 /**
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);
82 /**
83 * Returns array of info about all files in archive.
85 * @return array of file infos
87 public abstract function list_files();
89 /**
90 * Returns number of files in archive.
92 * @return int number of files
94 public abstract function count();
96 /**
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
127 * @return string
129 protected function mangle_pathname($localname) {
130 if ($this->encoding === 'utf-8') {
131 return $localname;
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;
140 } else {
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;
149 } else {
150 //bad luck - the file name may not be usable at all
151 $result = $converted;
155 $result = preg_replace('/\.\.+/', '', $result);
156 $result = ltrim($result); // no leading /
158 if ($result === '.') {
159 $result = '';
162 return $result;
166 * Tries to convert $localname into utf-8
167 * please note that it may fail really badly.
168 * The resulting file name is cleaned.
170 * @param string $localname name of file in $this->encoding
171 * @return string in utf-8
173 protected function unmangle_pathname($localname) {
174 $result = str_replace('\\', '/', $localname); // no MS \ separators
175 $result = ltrim($result, '/'); // no leading /
177 if ($this->encoding !== 'utf-8') {
178 $result = core_text::convert($result, $this->encoding, 'utf-8');
181 return clean_param($result, PARAM_PATH);
185 * Returns current file info.
186 * @return object
188 //public abstract function current();
191 * Returns the index of current file.
192 * @return int current file index
194 //public abstract function key();
197 * Moves forward to next file.
198 * @return void
200 //public abstract function next();
203 * Rewinds back to the first file.
204 * @return void
206 //public abstract function rewind();
209 * Did we reach the end?
210 * @return boolean
212 //public abstract function valid();