d27d2c6a6da78ec585d82678de93037424525ce2
[moodle.git] / lib / filestorage / file_archive.php
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.
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/>.
18 /**
19  * Abstraction of general file archives.
20  *
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
24  */
26 defined('MOODLE_INTERNAL') || die();
28 /**
29  * Each file archive type must extend this class.
30  *
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
34  */
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)
51      *
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
56      */
57     public abstract function open($archivepathname, $mode=file_archive::CREATE, $encoding='utf-8');
59     /**
60      * Close archive
61      *
62      * @return bool success
63      */
64     public abstract function close();
66     /**
67      * Returns file stream for reading of content
68      *
69      * @param int $index index of file
70      * @return stream|bool stream or false if error
71      */
72     public abstract function get_stream($index);
74     /**
75      * Returns file information
76      *
77      * @param int $index index of file
78      * @return stdClass|bool object or false if error
79      */
80     public abstract function get_info($index);
82     /**
83      * Returns array of info about all files in archive
84      *
85      * @return array of file infos
86      */
87     public abstract function list_files();
89     /**
90      * Returns number of files in archive
91      *
92      * @return int number of files
93      */
94     public abstract function count();
96     /**
97      * Add file into archive
98      *
99      * @param string $localname name of file in archive
100      * @param string $pathname location of file
101      * @return bool success
102      */
103     public abstract function add_file_from_pathname($localname, $pathname);
105     /**
106      * Add content of string into archive
107      *
108      * @param string $localname name of file in archive
109      * @param string $contents contents
110      * @return bool success
111      */
112     public abstract function add_file_from_string($localname, $contents);
114     /**
115      * Add empty directory into archive
116      *
117      * @param string $localname name of file in archive
118      * @return bool success
119      */
120     public abstract function add_directory($localname);
122     /**
123      * Tries to convert $localname into another encoding,
124      * please note that it may fail really badly.
125      *
126      * @param string $localname name of file in utf-8 encoding
127      * @return string
128      */
129     protected function mangle_pathname($localname) {
130         if ($this->encoding === 'utf-8') {
131             return $localname;
132         }
134         $converted = textlib::convert($localname, 'utf-8', $this->encoding);
135         $original  = textlib::convert($converted, $this->encoding, 'utf-8');
137         if ($original === $localname) {
138             $result = $converted;
140         } else {
141             // try ascii conversion
142             $converted2 = textlib::specialtoascii($localname);
143             $converted2 = textlib::convert($converted2, 'utf-8', $this->encoding);
144             $original2  = textlib::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;
152             }
153         }
155         $result = preg_replace('/\.\.+/', '', $result);
156         $result = ltrim($result); // no leading /
158         if ($result === '.') {
159             $result = '';
160         }
162         return $result;
163     }
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      *
170      * @param string $localname name of file in $this->encoding
171      * @return string in utf-8
172      */
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 = textlib::convert($result, $this->encoding, 'utf-8');
179         }
181         return clean_param($result, PARAM_PATH);
182     }
184     /**
185      * Returns current file info
186      * @return object
187      */
188     //public abstract function current();
190     /**
191      * Returns the index of current file
192      * @return int current file index
193      */
194     //public abstract function key();
196     /**
197      * Moves forward to next file
198      * @return void
199      */
200     //public abstract function next();
202     /**
203      * Rewinds back to the first file
204      * @return void
205      */
206     //public abstract function rewind();
208     /**
209      * Did we reach the end?
210      * @return boolean
211      */
212     //public abstract function valid();