1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4/** 5 * Writer to files 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: Files.php,v 1.21 2005/06/18 23:08:16 vincentlascaux Exp $ 29 * @link http://pear.php.net/package/File_Archive 30 */ 31 32require_once "File/Archive/Writer.php"; 33 34/** 35 * Writer to files 36 */ 37class File_Archive_Writer_Files extends File_Archive_Writer 38{ 39 /** 40 * @var Object Handle to the file where the data are currently written 41 * @access private 42 */ 43 var $handle = null; 44 var $basePath; 45 var $stat = array(); 46 var $filename; 47 48 function File_Archive_Writer_Files($base = '') 49 { 50 if ($base === null || $base == '') { 51 $this->basePath = ''; 52 } else { 53 if (substr($base, -1) == '/') { 54 $this->basePath = $base; 55 } else { 56 $this->basePath = $base.'/'; 57 } 58 } 59 } 60 61 function getFilename($filename) 62 { 63 return $this->basePath.$filename; 64 } 65 66 /** 67 * Ensure that $pathname exists, or create it if it does not 68 * @access private 69 */ 70 function mkdirr($pathname) 71 { 72 // Check if directory already exists 73 if (is_dir($pathname) || empty($pathname)) { 74 return; 75 } 76 77 // Ensure a file does not already exist with the same name 78 if (is_file($pathname)) { 79 return PEAR::raiseError( 80 "File $pathname exists, unable to create directory" 81 ); 82 } 83 84 // Crawl up the directory tree 85 $next_pathname = substr( 86 $pathname, 87 0, strrpos($pathname, "/")); 88 $error = $this->mkdirr($next_pathname); 89 if (PEAR::isError($error)) { 90 return $error; 91 } 92 if (!@mkdir($pathname)) { 93 return PEAR::raiseError("Unable to create directory $pathname"); 94 } 95 } 96 97 /** 98 * Open a file for writing from a given position 99 * 100 * @param string $filename The name of the file to open 101 * @param int $pos the initial position in the file 102 * @param $stat the stats of the file 103 */ 104 function openFile($filename, $pos = 0) 105 { 106 $this->close(); 107 108 $this->handle = fopen($filename, 'r+'); 109 $this->stat = array(); 110 $this->filename = $filename; 111 112 if (!is_resource($this->handle)) { 113 return PEAR::raiseError("Unable to open file $filename"); 114 } 115 116 if ($pos > 0) { 117 if (fseek($this->handle, $pos) == -1) { 118 fread($this->handle, $pos); 119 } 120 } 121 } 122 123 /** 124 * Open a file for appending after having removed a block of data from it 125 * See File_Archive_Reader::makeWriterRemoveBlocks 126 */ 127 function openFileRemoveBlock($filename, $pos, $blocks) 128 { 129 $error = $this->openFile($filename, $pos); 130 if (PEAR::isError($error)) { 131 return $error; 132 } 133 134 if (!empty($blocks)) { 135 //This will be used to read the initial file 136 //The data, with the unusefull block removed will be written to $this->handle 137 $read = fopen($filename, 'r'); 138 if ($pos > 0) { 139 if (fseek($this->handle, $pos) == -1) { 140 fread($this->handle, $pos); 141 } 142 } 143 144 $keep = false; 145 $data = ''; 146 foreach ($blocks as $length) { 147 if ($keep) { 148 while ($length > 0 && 149 ($data = fread($read, min($length, 8192))) != '') { 150 $length -= strlen($data); 151 fwrite($this->handle, $data); 152 } 153 } else { 154 fseek($read, $length, SEEK_CUR); 155 } 156 $keep = !$keep; 157 } 158 if ($keep) { 159 while(!feof($this->handle)) { 160 fwrite($this->handle, fread($read, 8196)); 161 } 162 } 163 164 fclose($read); 165 } 166 167 ftruncate($this->handle, ftell($this->handle)); 168 } 169 170 171 /** 172 * @see File_Archive_Writer::newFile() 173 */ 174 function newFile($filename, $stat = array(), $mime = "application/octet-stream") 175 { 176 $this->close(); 177 $this->stat = $stat; 178 $this->filename = $this->getFilename($filename); 179 180 $pos = strrpos($this->filename, "/"); 181 if ($pos !== false) { 182 $error = $this->mkdirr(substr($this->filename, 0, $pos)); 183 if (PEAR::isError($error)) { 184 return $error; 185 } 186 } 187 $this->handle = @fopen($this->filename, "w"); 188 if (!is_resource($this->handle)) { 189 return PEAR::raiseError("Unable to write to file $filename"); 190 } 191 } 192 /** 193 * @see File_Archive_Writer::writeData() 194 */ 195 function writeData($data) { fwrite($this->handle, $data); } 196 /** 197 * @see File_Archive_Writer::newFromTempFile() 198 */ 199 function newFromTempFile($tmpfile, $filename, $stat = array(), $mime = "application/octet-stream") 200 { 201 $this->filename = filename; 202 $complete = $this->getFilename($filename); 203 $pos = strrpos($complete, "/"); 204 if ($pos !== false) { 205 $error = $this->mkdirr(substr($complete, 0, $pos)); 206 if (PEAR::isError($error)) { 207 return $error; 208 } 209 } 210 211 if ((file_exists($complete) && !@unlink($complete)) || 212 !@rename($tmpfile, $complete)) { 213 return parent::newFromTempFile($tmpfile, $filename, $stat, $mime); 214 } 215 } 216 217 218 /** 219 * @see File_Archive_Writer::close() 220 */ 221 function close() 222 { 223 if ($this->handle !== null) { 224 fclose($this->handle); 225 $this->handle = null; 226 227 if (isset($this->stat[9])) { 228 if (isset($this->stat[8])) { 229 touch($this->filename, $this->stat[9], $this->stat[8]); 230 } else { 231 touch($this->filename, $this->stat[9]); 232 } 233 } else if (isset($this->stat[8])) { 234 touch($this->filename, time(), $this->stat[8]); 235 } 236 237 if (isset($this->stat[2])) { 238 chmod($this->filename, $this->stat[2]); 239 } 240 if (isset($this->stat[5])) { 241 chgrp($this->filename, $this->stat[5]); 242 } 243 if (isset($this->stat[4])) { 244 chown($this->filename, $this->stat[4]); 245 } 246 } 247 } 248} 249 250?>