1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4/** 5 * Reader that represents a single file 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: File.php,v 1.30 2005/07/11 11:53:53 vincentlascaux Exp $ 29 * @link http://pear.php.net/package/File_Archive 30 */ 31 32require_once "File/Archive/Reader.php"; 33require_once "MIME/Type.php"; 34 35/** 36 * Reader that represents a single file 37 */ 38class File_Archive_Reader_File extends File_Archive_Reader 39{ 40 /** 41 * @var object Handle to the file being read 42 * @access private 43 */ 44 var $handle = null; 45 /** 46 * @var string Name of the physical file being read 47 * @access private 48 */ 49 var $filename; 50 /** 51 * @var string Name of the file returned by the reader 52 * @access private 53 */ 54 var $symbolic; 55 /** 56 * @var array Stats of the file 57 * Will only be set after a call to $this->getStat() 58 * @access private 59 */ 60 var $stat = null; 61 /** 62 * @var string Mime type of the file 63 * Will only be set after a call to $this->getMime() 64 */ 65 var $mime = null; 66 /** 67 * @var boolean Has the file already been read 68 * @access private 69 */ 70 var $alreadyRead = false; 71 72 /** 73 * $filename is the physical file to read 74 * $symbolic is the name declared by the reader 75 * If $symbolic is not specified, $filename is assumed 76 */ 77 function File_Archive_Reader_File($filename, $symbolic = null, $mime = null) 78 { 79 $this->filename = $filename; 80 $this->mime = $mime; 81 if ($symbolic === null) { 82 $this->symbolic = $this->getStandardURL($filename); 83 } else { 84 $this->symbolic = $this->getStandardURL($symbolic); 85 } 86 } 87 /** 88 * @see File_Archive_Reader::close() 89 * 90 * Close the file handle 91 */ 92 function close() 93 { 94 $this->alreadyRead = false; 95 if ($this->handle !== null) { 96 fclose($this->handle); 97 $this->handle = null; 98 } 99 } 100 /** 101 * @see File_Archive_Reader::next() 102 * 103 * The first time next is called, it will open the file handle and return 104 * true. Then it will return false 105 * Raise an error if the file does not exist 106 */ 107 function next() 108 { 109 if ($this->alreadyRead) { 110 return false; 111 } else { 112 $this->alreadyRead = true; 113 return true; 114 } 115 } 116 /** 117 * @see File_Archive_Reader::getFilename() 118 */ 119 function getFilename() { return $this->symbolic; } 120 /** 121 * @see File_Archive_Reader::getDataFilename() 122 * 123 * Return the name of the file 124 */ 125 function getDataFilename() { return $this->filename; } 126 /** 127 * @see File_Archive_Reader::getStat() stat() 128 */ 129 function getStat() 130 { 131 if ($this->stat === null) { 132 $this->stat = @stat($this->filename); 133 134 //If we can't use the stat function 135 if ($this->stat === false) { 136 $this->stat = array(); 137 } 138 } 139 return $this->stat; 140 } 141 142 /** 143 * @see File_Archive_Reader::getMime 144 */ 145 function getMime() 146 { 147 if ($this->mime === null) { 148 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 149 $this->mime = MIME_Type::autoDetect($this->getDataFilename()); 150 PEAR::popErrorHandling(); 151 152 if (PEAR::isError($this->mime)) { 153 $this->mime = parent::getMime(); 154 } 155 } 156 return $this->mime; 157 } 158 159 /** 160 * Opens the file if it was not already opened 161 */ 162 function _ensureFileOpened() 163 { 164 if ($this->handle === null) { 165 $this->handle = @fopen($this->filename, "r"); 166 167 if (!is_resource($this->handle)) { 168 $this->handle = null; 169 return PEAR::raiseError("Can't open {$this->filename} for reading"); 170 } 171 if ($this->handle === false) { 172 $this->handle = null; 173 return PEAR::raiseError("File {$this->filename} not found"); 174 } 175 } 176 } 177 178 /** 179 * @see File_Archive_Reader::getData() 180 */ 181 function getData($length = -1) 182 { 183 $error = $this->_ensureFileOpened(); 184 if (PEAR::isError($error)) { 185 return $error; 186 } 187 188 if (feof($this->handle)) { 189 return null; 190 } 191 if ($length == -1) { 192 $contents = ''; 193 $blockSize = File_Archive::getOption('blockSize'); 194 while (!feof($this->handle)) { 195 $contents .= fread($this->handle, $blockSize); 196 } 197 return $contents; 198 } else { 199 if ($length == 0) { 200 return ""; 201 } else { 202 return fread($this->handle, $length); 203 } 204 } 205 } 206 207 /** 208 * @see File_Archive_Reader::skip() 209 */ 210 function skip($length = -1) 211 { 212 $error = $this->_ensureFileOpened(); 213 if (PEAR::isError($error)) { 214 return $error; 215 } 216 217 $before = ftell($this->handle); 218 if (($length == -1 && @fseek($this->handle, 0, SEEK_END) === -1) || 219 ($length >= 0 && @fseek($this->handle, $length, SEEK_CUR) === -1)) { 220 return parent::skip($length); 221 } else { 222 return ftell($this->handle) - $before; 223 } 224 } 225 226 /** 227 * @see File_Archive_Reader::rewind 228 */ 229 function rewind($length = -1) 230 { 231 if ($this->handle === null) { 232 return 0; 233 } 234 235 $before = ftell($this->handle); 236 if (($length == -1 && @fseek($this->handle, 0, SEEK_SET) === -1) || 237 ($length >= 0 && @fseek($this->handle, -$length, SEEK_CUR) === -1)) { 238 return parent::rewind($length); 239 } else { 240 return $before - ftell($this->handle); 241 } 242 } 243 244 /** 245 * @see File_Archive_Reader::tell() 246 */ 247 function tell() 248 { 249 if ($this->handle === null) { 250 return 0; 251 } else { 252 return ftell($this->handle); 253 } 254 } 255 256 257 /** 258 * @see File_Archive_Reader::makeWriterRemoveFiles() 259 */ 260 function makeWriterRemoveFiles($pred) 261 { 262 return PEAR::raiseError( 263 'File_Archive_Reader_File represents a single file, you cant remove it'); 264 } 265 266 /** 267 * @see File_Archive_Reader::makeWriterRemoveBlocks() 268 */ 269 function makeWriterRemoveBlocks($blocks, $seek = 0) 270 { 271 require_once "File/Archive/Writer/Files.php"; 272 273 $writer = new File_Archive_Writer_Files(); 274 275 $file = $this->getDataFilename(); 276 $pos = $this->tell(); 277 $this->close(); 278 279 $writer->openFileRemoveBlock($file, $pos + $seek, $blocks); 280 281 return $writer; 282 } 283 284 /** 285 * @see File_Archive_Reader::makeAppendWriter 286 */ 287 function makeAppendWriter() 288 { 289 return PEAR::raiseError( 290 'File_Archive_Reader_File represents a single file.'. 291 ' makeAppendWriter cant be executed on it' 292 ); 293 } 294} 295 296?>