1<?php 2/** 3 * Write data to a file and save as an ar 4 * 5 * PHP versions 4 and 5 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330,Boston,MA 02111-1307 USA 20 * 21 * @category File Formats 22 * @package File_Archive 23 * @author Pablo Fischer <pablo@pablo.com.mx> 24 * @copyright 1997-2005 The PHP Group 25 * @license http://www.gnu.org/copyleft/lesser.html LGPL 26 * @version CVS: $Id: 27 * @link http://pear.php.net/package/File_Archive 28 */ 29 30require_once "File/Archive/Writer/Archive.php"; 31 32/** 33 * Write the files as an AR archive 34 */ 35class File_Archive_Writer_Ar extends File_Archive_Writer_Archive 36{ 37 38 /** 39 * @var string Current data of the file. 40 * @access private 41 */ 42 var $_buffer = ""; 43 44 /** 45 * @var string Filename of the current filename 46 * @access private 47 */ 48 var $_currentFilename = null; 49 50 /** 51 * @var boolean Flag: use buffer or not. 52 * @access private 53 */ 54 var $_useBuffer; 55 56 /** 57 * @var array Stats of the current filename 58 * @access private 59 */ 60 var $_currentStat = array (); 61 62 /** 63 * @var boolean Flag: beginning of the archive or not 64 * @access private 65 */ 66 var $_atStart = true; 67 68 /** 69 * Returns the header of the current file. 70 * 71 * More Info: 72 * http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/files/aixfiles/ar_IA64.htm 73 * 74 * @access private 75 * @param string $filename Name of the current file 76 * @param array $stat Stat array of the current file 77 * @return string The built header struct 78 */ 79 function arHeader ($filename, $stat) 80 { 81 $mode = isset($stat[2]) ? $stat[2] : 0x8000; 82 $uid = isset($stat[4]) ? $stat[4] : 0; 83 $gid = isset($stat[5]) ? $stat[5] : 0; 84 $size = $stat[7]; 85 $time = isset($stat[9]) ? $stat[9] : time(); 86 87 $struct = ""; 88 $currentSize = $size; 89 //if file length is > than 16.. 90 if (strlen($filename) > 16) { 91 $currentSize += strlen($filename); 92 $struct .= sprintf("#1/%-13d", strlen($filename)); 93 $struct .= sprintf("%-12d%-6d%-6d%-8s%-10d", 94 $time, $uid, $gid, $mode, $currentSize); 95 $struct .= "`\n".$filename; 96 } else { 97 $struct .= sprintf("%-16s", $filename); 98 $struct .= sprintf("%-12d%-6d%-6d%-8s%-10d`\n", 99 $time, $uid, $gid, $mode, $size); 100 } 101 return $struct; 102 } 103 104 /** 105 * Returns the footer of the current file, the footer depends 106 * of the size of the file 107 * 108 * @access private 109 * @param string $filename Name of the file, the footer depends on its length 110 * @param int $size Size of the current file, here the size does matters! 111 * @return string The footer struct 112 */ 113 function arFooter($filename, $size) 114 { 115 $size = (strlen ($filename) > 16) ? $size + strlen($filename) : $size; 116 117 return ($size % 2 == 1) ? "\n" : ""; 118 } 119 120 121 /** 122 * Flush the memory we have in the ar. 123 * 124 * Build the buffer if its called at the end or initialize 125 * it if we are just creating it from the start. 126 */ 127 function flush() 128 { 129 if ($this->_atStart) { 130 $this->innerWriter->writeData("!<arch>\n"); 131 $this->_atStart = false; 132 } 133 if ($this->_currentFilename !== null) { 134 $this->_currentStat[7] = strlen($this->_buffer); 135 if ($this->_useBuffer) { 136 $this->innerWriter->writeData( 137 $this->arHeader($this->_currentFilename, $this->_currentStat) 138 ); 139 $this->innerWriter->writeData($this->_buffer); 140 } 141 $this->innerWriter->writeData($this->arFooter($this->_currentFilename, $this->_currentStat[7])); 142 } 143 $this->_buffer = ""; 144 } 145 146 /** 147 * @see File_Archive_Writer::newFile() 148 * 149 */ 150 function newFile($filename, $stat = array (), 151 $mime = "application/octet-stream") 152 { 153 $this->flush(); 154 /* 155 * If the file is empty, there's no reason to have a buffer 156 * or use memory 157 */ 158 $this->_useBuffer = !isset($stats[7]); 159 /* 160 * Becaue ar fileformats doesn't support files in directories, 161 * then we need to just save with the filename an ommit the 162 * directory 163 */ 164 $this->_currentFilename = basename($filename); 165 $this->_currentStat = $stat; 166 167 if(!$this->_useBuffer) { 168 return $this->innerWriter->writeData($this->arHeader($filename, $stat)); 169 } 170 } 171 172 /** 173 * @see File_Archive_Writer::close() 174 */ 175 function close() 176 { 177 $this->flush(); 178 parent::close(); 179 } 180 181 /** 182 * @see File_Archive_Writer::writeData() 183 */ 184 function writeData($data) 185 { 186 if ($this->_useBuffer) { 187 $this->_buffer .= $data; 188 } else { 189 $this->innerWriter->writeData($data); 190 } 191 192 } 193 /** 194 * @see File_Archive_Writer::writeFile() 195 */ 196 function writeFile($filename) 197 { 198 if ($this->_useBuffer) { 199 $this->_buffer .= file_get_contents($filename); 200 } else { 201 $this->innerWriter->writeFile($filename); 202 } 203 } 204}