MDL-37429 zipping improvements
[moodle.git] / lib / filestorage / file_archive.php
CommitLineData
33488ad6 1<?php
33488ad6 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.
13//
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/>.
16
17
18/**
19 * Abstraction of general file archives.
20 *
d2b7803e
DC
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
33488ad6 24 */
0b0bfa93 25
64f93798
PS
26defined('MOODLE_INTERNAL') || die();
27
28/**
5d92c29c 29 * Each file archive type must extend this class.
64f93798 30 *
d2b7803e
DC
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
64f93798 34 */
0b0bfa93 35abstract class file_archive implements Iterator {
36
37 /** Open archive if exists, fail if does not exist. */
38 const OPEN = 1;
39
40 /** Open archive if exists, create if does not. */
41 const CREATE = 2;
42
43 /** Always create new archive */
44 const OVERWRITE = 4;
45
d2b7803e 46 /** @var string Encoding of file names - windows usually expects DOS single-byte charset*/
0b0bfa93 47 protected $encoding = 'utf-8';
48
49 /**
01b4040a 50 * Open or create archive (depending on $mode).
d2b7803e
DC
51 *
52 * @param string $archivepathname archive path name
0b0bfa93 53 * @param int $mode OPEN, CREATE or OVERWRITE constant
54 * @param string $encoding archive local paths encoding
55 * @return bool success
56 */
57 public abstract function open($archivepathname, $mode=file_archive::CREATE, $encoding='utf-8');
58
59 /**
01b4040a 60 * Close archive.
d2b7803e 61 *
0b0bfa93 62 * @return bool success
63 */
64 public abstract function close();
65
66 /**
01b4040a 67 * Returns file stream for reading of content.
d2b7803e
DC
68 *
69 * @param int $index index of file
70 * @return stream|bool stream or false if error
0b0bfa93 71 */
72 public abstract function get_stream($index);
73
74 /**
01b4040a 75 * Returns file information.
d2b7803e
DC
76 *
77 * @param int $index index of file
78 * @return stdClass|bool object or false if error
0b0bfa93 79 */
80 public abstract function get_info($index);
81
82 /**
01b4040a 83 * Returns array of info about all files in archive.
d2b7803e 84 *
0b0bfa93 85 * @return array of file infos
86 */
87 public abstract function list_files();
88
89 /**
01b4040a 90 * Returns number of files in archive.
d2b7803e 91 *
0b0bfa93 92 * @return int number of files
93 */
94 public abstract function count();
95
96 /**
01b4040a 97 * Add file into archive.
d2b7803e 98 *
0b0bfa93 99 * @param string $localname name of file in archive
83020ca0 100 * @param string $pathname location of file
0b0bfa93 101 * @return bool success
102 */
103 public abstract function add_file_from_pathname($localname, $pathname);
104
105 /**
01b4040a 106 * Add content of string into archive.
d2b7803e 107 *
0b0bfa93 108 * @param string $localname name of file in archive
d2b7803e 109 * @param string $contents contents
0b0bfa93 110 * @return bool success
111 */
112 public abstract function add_file_from_string($localname, $contents);
113
114 /**
01b4040a 115 * Add empty directory into archive.
d2b7803e
DC
116 *
117 * @param string $localname name of file in archive
0b0bfa93 118 * @return bool success
119 */
120 public abstract function add_directory($localname);
121
122 /**
123 * Tries to convert $localname into another encoding,
124 * please note that it may fail really badly.
d2b7803e
DC
125 *
126 * @param string $localname name of file in utf-8 encoding
0b0bfa93 127 * @return string
128 */
129 protected function mangle_pathname($localname) {
130 if ($this->encoding === 'utf-8') {
131 return $localname;
132 }
0b0bfa93 133
f8311def
PS
134 $converted = textlib::convert($localname, 'utf-8', $this->encoding);
135 $original = textlib::convert($converted, $this->encoding, 'utf-8');
0b0bfa93 136
137 if ($original === $localname) {
138 $result = $converted;
139
140 } else {
5d92c29c 141 // try ascii conversion
f8311def
PS
142 $converted2 = textlib::specialtoascii($localname);
143 $converted2 = textlib::convert($converted2, 'utf-8', $this->encoding);
144 $original2 = textlib::convert($converted, $this->encoding, 'utf-8');
0b0bfa93 145
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;
152 }
153 }
154
c78a948e 155 $result = preg_replace('/\.\.+/', '', $result);
5d92c29c 156 $result = ltrim($result); // no leading /
0b0bfa93 157
158 if ($result === '.') {
159 $result = '';
160 }
161
162 return $result;
163 }
164
165 /**
166 * Tries to convert $localname into utf-8
167 * please note that it may fail really badly.
168 * The resulting file name is cleaned.
169 *
d2b7803e 170 * @param string $localname name of file in $this->encoding
0b0bfa93 171 * @return string in utf-8
172 */
173 protected function unmangle_pathname($localname) {
320e50b7
PS
174 $result = str_replace('\\', '/', $localname); // no MS \ separators
175 $result = ltrim($result, '/'); // no leading /
0b0bfa93 176
320e50b7 177 if ($this->encoding !== 'utf-8') {
f8311def 178 $result = textlib::convert($result, $this->encoding, 'utf-8');
320e50b7 179 }
0b0bfa93 180
320e50b7 181 return clean_param($result, PARAM_PATH);
0b0bfa93 182 }
183
184 /**
01b4040a 185 * Returns current file info.
0b0bfa93 186 * @return object
187 */
188 //public abstract function current();
189
190 /**
01b4040a 191 * Returns the index of current file.
0b0bfa93 192 * @return int current file index
193 */
194 //public abstract function key();
195
196 /**
01b4040a 197 * Moves forward to next file.
0b0bfa93 198 * @return void
199 */
200 //public abstract function next();
201
202 /**
01b4040a 203 * Rewinds back to the first file.
0b0bfa93 204 * @return void
205 */
206 //public abstract function rewind();
207
208 /**
209 * Did we reach the end?
210 * @return boolean
211 */
212 //public abstract function valid();
213
4a0e2e63 214}