|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00018 00028 defined('MOODLE_INTERNAL') || die(); 00029 00030 require_once("$CFG->libdir/filestorage/file_archive.php"); 00031 00040 class zip_archive extends file_archive { 00041 00043 protected $archivepathname = null; 00044 00046 protected $usedmem = 0; 00047 00049 protected $pos = 0; 00050 00052 protected $za; 00053 00061 public function open($archivepathname, $mode=file_archive::CREATE, $encoding='utf-8') { 00062 $this->close(); 00063 00064 $this->usedmem = 0; 00065 $this->pos = 0; 00066 00067 $this->za = new ZipArchive(); 00068 00069 switch($mode) { 00070 case file_archive::OPEN: $flags = 0; break; 00071 case file_archive::OVERWRITE: $flags = ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE; break; //changed in PHP 5.2.8 00072 case file_archive::CREATE: 00073 default : $flags = ZIPARCHIVE::CREATE; break; 00074 } 00075 00076 $result = $this->za->open($archivepathname, $flags); 00077 00078 if ($result === true) { 00079 $this->encoding = $encoding; 00080 if (file_exists($archivepathname)) { 00081 $this->archivepathname = realpath($archivepathname); 00082 } else { 00083 $this->archivepathname = $archivepathname; 00084 } 00085 return true; 00086 00087 } else { 00088 $this->za = null; 00089 $this->archivepathname = null; 00090 $this->encooding = 'utf-8'; 00091 // TODO: maybe we should return some error info 00092 return false; 00093 } 00094 } 00095 00100 public function close() { 00101 if (!isset($this->za)) { 00102 return false; 00103 } 00104 00105 $res = $this->za->close(); 00106 $this->za = null; 00107 00108 return $res; 00109 } 00110 00116 public function get_stream($index) { 00117 if (!isset($this->za)) { 00118 return false; 00119 } 00120 00121 $name = $this->za->getNameIndex($index); 00122 if ($name === false) { 00123 return false; 00124 } 00125 00126 return $this->za->getStream($name); 00127 } 00128 00134 public function get_info($index) { 00135 if (!isset($this->za)) { 00136 return false; 00137 } 00138 00139 if ($index < 0 or $index >=$this->count()) { 00140 return false; 00141 } 00142 00143 $result = $this->za->statIndex($index); 00144 00145 if ($result === false) { 00146 return false; 00147 } 00148 00149 $info = new stdClass(); 00150 $info->index = $index; 00151 $info->original_pathname = $result['name']; 00152 $info->pathname = $this->unmangle_pathname($result['name']); 00153 $info->mtime = (int)$result['mtime']; 00154 00155 if ($info->pathname[strlen($info->pathname)-1] === '/') { 00156 $info->is_directory = true; 00157 $info->size = 0; 00158 } else { 00159 $info->is_directory = false; 00160 $info->size = (int)$result['size']; 00161 } 00162 00163 return $info; 00164 } 00165 00170 public function list_files() { 00171 if (!isset($this->za)) { 00172 return false; 00173 } 00174 00175 $infos = array(); 00176 00177 for ($i=0; $i<$this->count(); $i++) { 00178 $info = $this->get_info($i); 00179 if ($info === false) { 00180 continue; 00181 } 00182 $infos[$i] = $info; 00183 } 00184 00185 return $infos; 00186 } 00187 00192 public function count() { 00193 if (!isset($this->za)) { 00194 return false; 00195 } 00196 00197 return $this->za->numFiles; 00198 } 00199 00206 public function add_file_from_pathname($localname, $pathname) { 00207 if (!isset($this->za)) { 00208 return false; 00209 } 00210 00211 if ($this->archivepathname === realpath($pathname)) { 00212 // do not add self into archive 00213 return false; 00214 } 00215 00216 if (is_null($localname)) { 00217 $localname = clean_param($pathname, PARAM_PATH); 00218 } 00219 $localname = trim($localname, '/'); // no leading slashes in archives 00220 $localname = $this->mangle_pathname($localname); 00221 00222 if ($localname === '') { 00223 //sorry - conversion failed badly 00224 return false; 00225 } 00226 00227 if (!check_php_version('5.2.8')) { 00228 // workaround for open file handles problem, ZipArchive uses file locking in order to prevent file modifications before the close() (strange, eh?) 00229 if ($this->count() > 0 and $this->count() % 500 === 0) { 00230 $this->close(); 00231 $res = $this->open($this->archivepathname, file_archive::OPEN, $this->encoding); 00232 if ($res !== true) { 00233 print_error('cannotopenzip'); //TODO ?? 00234 } 00235 } 00236 } 00237 00238 return $this->za->addFile($pathname, $localname); 00239 } 00240 00247 public function add_file_from_string($localname, $contents) { 00248 if (!isset($this->za)) { 00249 return false; 00250 } 00251 00252 $localname = trim($localname, '/'); // no leading slashes in archives 00253 $localname = $this->mangle_pathname($localname); 00254 00255 if ($localname === '') { 00256 //sorry - conversion failed badly 00257 return false; 00258 } 00259 00260 if ($this->usedmem > 2097151) { 00262 $this->close(); 00263 $res = $this->open($this->archivepathname, file_archive::OPEN, $this->encoding); 00264 if ($res !== true) { 00265 print_error('cannotopenzip'); //TODO ?? 00266 } 00267 } 00268 $this->usedmem += strlen($contents); 00269 00270 return $this->za->addFromString($localname, $contents); 00271 00272 } 00273 00279 public function add_directory($localname) { 00280 if (!isset($this->za)) { 00281 return false; 00282 } 00283 $localname = ltrim($localname, '/'). '/'; 00284 $localname = $this->mangle_pathname($localname); 00285 00286 if ($localname === '/') { 00287 //sorry - conversion failed badly 00288 return false; 00289 } 00290 00291 return $this->za->addEmptyDir($localname); 00292 } 00293 00298 public function current() { 00299 if (!isset($this->za)) { 00300 return false; 00301 } 00302 00303 return $this->get_info($this->pos); 00304 } 00305 00310 public function key() { 00311 return $this->pos; 00312 } 00313 00318 public function next() { 00319 $this->pos++; 00320 } 00321 00326 public function rewind() { 00327 $this->pos = 0; 00328 } 00329 00334 public function valid() { 00335 if (!isset($this->za)) { 00336 return false; 00337 } 00338 00339 return ($this->pos < $this->count()); 00340 } 00341 }