[ Index ] |
PHP Cross Reference of PHK Manager |
[Summary view] [Print] [Text view]
1 <?php 2 //============================================================================= 3 // 4 // Copyright Francois Laupretre <phk@tekwire.net> 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 // 18 //============================================================================= 19 /** 20 * @copyright Francois Laupretre <phk@tekwire.net> 21 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, V 2.0 22 * @category PHK 23 * @package PHK 24 *///========================================================================== 25 26 namespace PHK { 27 28 if (!class_exists('PHK\PkgFile',false)) 29 { 30 31 //============================================================================= 32 /** 33 * Contains the code to physically access PHK package files. 34 * 35 * API status: Private 36 * Included in the PHK PHP runtime: Yes 37 * Implemented in the extension: No 38 *///========================================================================== 39 40 class PkgFile 41 { 42 43 private $fp=null; 44 private $path; 45 private $size; 46 private $open_count=0; 47 private $keep_open_flag; 48 49 //------ 50 // Special case : keep sub-PHKs open (in stream wrapper memory) 51 52 public function __construct($path,$flags) 53 { 54 $this->setParams($path,$flags); 55 56 if (($this->size=filesize($path))===false) 57 throw new \Exception($path.': Cannot get file size'); 58 } 59 60 //------ 61 62 public function setParams($path,$flags) 63 { 64 $this->path=$path; 65 66 $this->keep_open_flag=\PHK\Mgr::isPhkUri($path); 67 } 68 69 //--- 70 71 public function __sleep() 72 { 73 return array('size'); 74 } 75 76 //------ 77 78 public function __destruct() 79 { 80 $this->reallyClose(); 81 } 82 83 //------ 84 85 private function reallyClose() 86 { 87 if (!is_null($this->fp)) 88 { 89 fclose($this->fp); 90 $this->fp=null; 91 $this->open_count=0; 92 } 93 } 94 95 //------ 96 // Open in read-only mode. Maintains a count for close(), throws exceptions, 97 // and force 'b' mode (for Windows). 98 // Called from self or \PHK\PkgFileSpace only 99 100 public function _open() 101 { 102 if (is_null($this->fp)) 103 { 104 if (!($this->fp=fopen($this->path,'rb',false))) //-- 'b' mode is for Windows 105 throw new \Exception($this->path.': Cannot open for reading'); 106 $this->open_count=1; 107 } 108 else $this->open_count++; 109 } 110 111 //----- 112 // fclose() the file pointer. Maintains an open count. 113 // Called from self or \PHK\PkgFileSpace only 114 115 public function _close() 116 { 117 $this->open_count--; 118 if (($this->open_count <= 0) && (!$this->keep_open_flag)) $this->reallyClose(); 119 } 120 121 //----- 122 // Same as PHP fread() but reads any size, throws exceptions, and checks size 123 // I don't use stream_get_contents() because, sometimes, it crashes 124 // on Windows (detected with PHP 5.1.4). 125 126 private function read($size) 127 { 128 $data=''; 129 $nb_chunks=intval($size/8192); 130 $rest=$size % 8192; 131 132 \PHK\Tools\Util::disableMQR(); 133 while ($nb_chunks > 0) 134 { 135 $data .= $this->readChunk(8192); 136 $nb_chunks--; 137 } 138 139 if ($rest) $data .= $this->readChunk($rest); 140 \PHK\Tools\Util::restoreMQR(); 141 142 return $data; 143 } 144 145 //----- 146 // Read up to 8192 bytes 147 148 private function readChunk($size) 149 { 150 $buf=fread($this->fp,$size); 151 if ($buf===false) throw new \Exception('Cannot read'); 152 if (($bsize=strlen($buf))!=$size) 153 throw new \Exception("Short read ($bsize/$size)"); 154 return $buf; 155 } 156 157 //----- 158 // Reads a block from file. 159 // Called only from \PHK\PkgFileSpace. So: 160 // - we don't need to check bounds, 161 // - we don't provide default args, 162 // - we are sure that size is > 0 163 164 public function _readBlock($offset,$size) 165 { 166 try 167 { 168 $this->_open(); 169 if (fseek($this->fp,$offset,SEEK_SET) == -1) 170 throw new \Exception('Cannot seek'); 171 $buf=$this->read($size); 172 $this->_close(); // At the end. Everything before can raise an exception 173 } // and we don't want to close it twice 174 catch (\Exception $e) 175 { 176 $this->_close(); 177 throw new \Exception($e->getMessage()); 178 } 179 return $buf; 180 } 181 182 //------ 183 184 public function size() 185 { 186 return $this->size; 187 } 188 189 //------ 190 191 public function path() 192 { 193 return $this->path; 194 } 195 196 } // End of class PHK\PkgFile 197 //------------------------- 198 } // End of class_exists 199 //============================================================================= 200 201 if (!class_exists('PHK\PkgFileSpace',false)) 202 { 203 //------------------------- 204 class PkgFileSpace 205 { 206 207 public $file; // underlying \PHK\PkgFile object 208 private $offset; 209 private $size; 210 211 //------ 212 // Two possibles syntaxes : 213 // new \PHK\PkgFileSpace(string $path,int $flags) : creates a first space for a file 214 // new \PHK\PkgFileSpace(PkgFileSpace $parent, int $offset, int $size) : 215 // creates a subspace inside an existing FileSpace. 216 217 public function __construct($arg1,$arg2,$size=null) 218 { 219 if (is_string($arg1)) 220 { 221 $this->file=new \PHK\PkgFile($arg1,$arg2); 222 $this->offset=0; 223 $this->size=$this->file->size(); 224 } 225 else 226 { 227 if ((!($arg1 instanceof self)) 228 || (!is_numeric($arg2)) 229 || (!is_numeric($size)) 230 || ($arg2 < 0) 231 || (($arg2+$size) > $arg1->size)) 232 throw new \Exception("PkgFileSpace: cannot create - invalid arguments"); 233 234 $this->file=$arg1->file; 235 $this->offset=$arg1->offset + $arg2; 236 $this->size=$size; 237 } 238 } 239 240 //------ 241 // Default args so that readBlock() without args returns the whole filespace 242 243 public function readBlock($offset=0,$size=null) 244 { 245 //\PHK\Tools\Util::trace("Starting PkgFileSpace::read_block - offset=$offset - size=$size");//TRACE 246 247 if (is_null($size)) $size=$this->size-$offset; // Read up to the end 248 249 if (($offset<0)||($size<0)||($offset+$size>$this->size)) 250 throw new \Exception('PkgFileSpace: Read out of bound'); 251 252 if ($size==0) return ''; 253 254 $data=$this->file->_readBlock($this->offset+$offset,$size); 255 256 //\PHK\Tools\Util::trace("Ending PkgFileSpace::read_block");//TRACE 257 return $data; 258 } 259 260 //------ 261 // Used to force the file to remain open temporarily 262 263 public function open() 264 { 265 $this->file->_open(); 266 } 267 268 //------ 269 270 public function close() 271 { 272 $this->file->_close(); 273 } 274 275 //------ 276 277 public function size() 278 { 279 return $this->size; 280 } 281 282 //------ 283 // Returns path of underlying file (can be a PHK URI) 284 285 public function path() 286 { 287 return $this->file->path(); 288 } 289 290 //--- 291 } // End of class 292 //=========================================================================== 293 } // End of class_exists 294 //=========================================================================== 295 } // End of namespace 296 //=========================================================================== 297 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jun 4 18:33:15 2015 | Cross-referenced by PHPXref 0.7.1 |