1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4/** 5 * Recursively reads a directory 6 * 7 * PHP versions 4 and 5 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA 22 * 23 * @category File Formats 24 * @package File_Archive 25 * @author Vincent Lascaux <vincentlascaux@php.net> 26 * @copyright 1997-2005 The PHP Group 27 * @license http://www.gnu.org/copyleft/lesser.html LGPL 28 * @version CVS: $Id$ 29 * @link http://pear.php.net/package/File_Archive 30 */ 31 32require_once "File/Archive/Reader/Relay.php"; 33require_once "File/Archive/Reader/File.php"; 34 35/** 36 * Recursively reads a directory 37 */ 38class File_Archive_Reader_Directory extends File_Archive_Reader_Relay 39{ 40 /** 41 * @var String URL of the directory that must be read 42 * @access private 43 */ 44 var $directory; 45 /** 46 * @var Int The subdirectories will be read up to a depth of maxRecurs 47 * If maxRecurs == 0, the subdirectories will not be read 48 * If maxRecurs == -1, the depth is considered infinite 49 * @access private 50 */ 51 var $maxRecurs; 52 /** 53 * @var Object Handle returned by the openedDirectory function 54 * @access private 55 */ 56 var $directoryHandle = null; 57 58 /** 59 * $directory is the path of the directory that must be read 60 * If $maxRecurs is specified, the subdirectories will be read up to a depth 61 * of $maxRecurs. In particular, if $maxRecurs == 0, the subdirectories 62 * won't be read. 63 */ 64 function File_Archive_Reader_Directory($directory, $symbolic='', 65 $maxRecurs=-1) 66 { 67 parent::File_Archive_Reader_Relay($tmp = null); 68 $this->directory = empty($directory) ? '.' : $directory; 69 $this->symbolic = $this->getStandardURL($symbolic); 70 $this->maxRecurs = $maxRecurs; 71 } 72 73 /** 74 * @see File_Archive_Reader::close() 75 */ 76 function close() 77 { 78 $error = parent::close(); 79 80 if ($this->directoryHandle !== null) { 81 closedir($this->directoryHandle); 82 $this->directoryHandle = null; 83 } 84 85 return $error; 86 } 87 88 /** 89 * @see File_Archive_Reader::next() 90 * 91 * The files are returned in the same order as readdir 92 */ 93 function next() 94 { 95 if ($this->directoryHandle === null) { 96 $this->directoryHandle = opendir($this->directory); 97 if (!is_resource($this->directoryHandle)) { 98 return PEAR::raiseError( 99 "Directory {$this->directory} not found" 100 ); 101 } 102 $this->source = null; 103 104 if (!empty($this->symbolic)) 105 return true; 106 } 107 108 while ($this->source === null || 109 ($error = $this->source->next()) !== true) { 110 111 if ($this->source !== null) { 112 $this->source->close(); 113 } 114 115 $file = readdir($this->directoryHandle); 116 if ($file == '.' || $file == '..') { 117 continue; 118 } 119 if ($file === false) { 120 return false; 121 } 122 123 $current = $this->directory.'/'.$file; 124 if (is_dir($current)) { 125 if ($this->maxRecurs != 0) { 126 $this->source = new File_Archive_Reader_Directory( 127 $current, $file.'/', $this->maxRecurs-1 128 ); 129 } 130 131 } else { 132 $this->source = new File_Archive_Reader_File($current, $file); 133 } 134 } 135 136 return $error; 137 } 138 139 /** 140 * @see File_Archive_Reader::getFilename() 141 */ 142 function getFilename() 143 { 144 if ($this->source === null) { 145 return $this->symbolic; 146 } else { 147 return $this->symbolic . parent::getFilename(); 148 } 149 } 150 /** 151 * @see File_Archive_Reader::getStat() 152 */ 153 function getStat() 154 { 155 if ($this->source === null) { 156 return stat($this->directory); 157 } else { 158 return parent::getStat(); 159 } 160 } 161 /** 162 * @see File_Archive_Reader::getMime() 163 */ 164 function getMime() 165 { 166 if ($this->source === null) { 167 return ''; 168 } else { 169 return parent::getMime(); 170 } 171 } 172 /** 173 * @see File_Archive_Reader::getDataFilename() 174 */ 175 function getDataFilename() 176 { 177 if ($this->source === null) { 178 return null; 179 } else { 180 return parent::getDataFilename(); 181 } 182 } 183 /** 184 * @see File_Archive_Reader::getData() 185 */ 186 function getData($length = -1) 187 { 188 if ($this->source === null) { 189 return null; 190 } else { 191 return parent::getData($length); 192 } 193 } 194 /** 195 * @see File_Archive_Reader::skip() 196 */ 197 function skip($length = -1) 198 { 199 if ($this->source === null) { 200 return 0; 201 } else { 202 return parent::skip($length); 203 } 204 } 205 /** 206 * @see File_Archive_Reader::rewind() 207 */ 208 function rewind($length = -1) 209 { 210 if ($this->source === null) { 211 return 0; 212 } else { 213 return parent::rewind($length); 214 } 215 } 216 /** 217 * @see File_Archive_Reader::tell() 218 */ 219 function tell() 220 { 221 if ($this->source === null) { 222 return 0; 223 } else { 224 return parent::tell(); 225 } 226 } 227 228 /** 229 * @see File_Archive_Reader::makeWriterRemoveFiles() 230 */ 231 function makeWriterRemoveFiles($pred) 232 { 233 if ($source !== null && $pred->isTrue($this)) { 234 $toUnlink = $this->getDataFilename(); 235 } else { 236 $toUnlink = null; 237 } 238 239 while ($this->next()) { 240 if ($toUnlink !== null && 241 !@unlink($toUnlink)) { 242 return PEAR::raiseError("Unable to unlink $toUnlink"); 243 } 244 $toUnlink = ($pred->isTrue($this) ? $this->getDataFilename() : null); 245 } 246 if ($toUnlink !== null && 247 !@unlink("Unable to unlink $toUnlink")) { 248 return PEAR::raiseError($pred); 249 } 250 251 require_once "File/Archive/Writer/Files.php"; 252 253 $writer = new File_Archive_Writer_Files($this->directory); 254 $this->close(); 255 return $writer; 256 } 257 258 function &getLastSource() 259 { 260 if ($this->source === null || 261 is_a($this->source, 'File_Archive_Reader_File')) { 262 return $this->source; 263 } else { 264 return $this->source->getLastSource(); 265 } 266 } 267 268 /** 269 * @see File_Archive_Reader::makeWriterRemoveBlocks() 270 */ 271 function makeWriterRemoveBlocks($blocks, $seek = 0) 272 { 273 $lastSource = &$this->getLastSource(); 274 if ($lastSource === null) { 275 return PEAR::raiseError('No file selected'); 276 } 277 278 require_once "File/Archive/Writer/Files.php"; 279 280 $writer = $lastSource->makeWriterRemoveBlocks($blocks, $seek); 281 if (!PEAR::isError($writer)) { 282 $writer->basePath = $this->directory; 283 $this->close(); 284 } 285 286 return $writer; 287 } 288 289 /** 290 * @see File_Archive_Reader::makeAppendWriter 291 */ 292 function makeAppendWriter() 293 { 294 require_once "File/Archive/Writer/Files.php"; 295 296 if ($this->source === null || 297 is_a($this->source, 'File_Archive_Reader_File') ) { 298 $writer = new File_Archive_Writer_Files($this->directory); 299 } else { 300 $writer = $this->source->makeAppendWriter($seek); 301 } 302 303 $this->close(); 304 305 return $writer; 306 } 307} 308 309?> 310