1<?php 2// stolen from PEAR2_Pyrus_Developer_Creator_Tar by Greg Beaver, the original author, for use in unit tests 3class corrupt_tarmaker 4{ 5 /** 6 * Path to archive file 7 * 8 * @var string 9 */ 10 protected $archive; 11 /** 12 * Temporary stream used for creating the archive 13 * 14 * @var stream 15 */ 16 protected $tmp; 17 protected $path; 18 protected $compress; 19 function __construct($path, $compress = 'zlib') 20 { 21 $this->compress = $compress; 22 if ($compress === 'bz2' && !function_exists('bzopen')) { 23 throw new PEAR2_Pyrus_Developer_Creator_Exception( 24 'bzip2 extension not available'); 25 } 26 if ($compress === 'zlib' && !function_exists('gzopen')) { 27 throw new PEAR2_Pyrus_Developer_Creator_Exception( 28 'zlib extension not available'); 29 } 30 $this->path = $path; 31 } 32 33 /** 34 * save a file inside this package 35 * 36 * This code is modified from Vincent Lascaux's File_Archive 37 * package, which is licensed under the LGPL license. 38 * @param string relative path within the package 39 * @param string|resource file contents or open file handle 40 */ 41 function addFile($path, $fileOrStream, $stat = null, $corrupt = null) 42 { 43 clearstatcache(); 44 if ($stat === null) { 45 if (is_resource($fileOrStream)) { 46 $stat = fstat($fileOrStream); 47 } else { 48 $stat = array( 49 'mode' => 0x8000 + 0644, 50 'uid' => 0, 51 'gid' => 0, 52 'size' => strlen($fileOrStream), 53 'mtime' => time(), 54 ); 55 } 56 } 57 58 $link = null; 59 if ($stat['mode'] & 0xA000 && $corrupt === 'symlink') { 60 $type = 2; // Symbolic Link 61 $link = $fileOrStream; 62 $stat['size'] = 0; 63 $fileOrStream = ''; 64 } else if ($stat['mode'] & 0xA000) { 65 $type = 1; // Link 66 $link = $fileOrStream; 67 $stat['size'] = 0; 68 $fileOrStream = ''; 69 } else if ($stat['mode'] & 0x4000) { 70 $type = 5; // Directory 71 } else if ($stat['mode'] & 0x8000) { 72 $type = 0; // Regular 73 } else { 74 $type = 9; // Unknown 75 } 76 77 $filePrefix = ''; 78 if (strlen($path) > 255) { 79 throw new Exception( 80 "$path is too long, must be 255 characters or less" 81 ); 82 } else if (strlen($path) > 100) { 83 $filePrefix = substr($path, 0, strlen($path)-100); 84 $path = substr($path, -100); 85 } 86 87 $block = pack('a100a8a8a8a12A12', 88 $path, 89 decoct($stat['mode']), 90 sprintf('%6s ',decoct($stat['uid'])), 91 sprintf('%6s ',decoct($stat['gid'])), 92 sprintf('%11s ',decoct($stat['size'])), 93 sprintf('%11s ',decoct($stat['mtime'])) 94 ); 95 96 $blockend = pack('a1a100a6a2a32a32a8a8a155a12', 97 $type, 98 $link, 99 'ustar', 100 '00', 101 'Pyrus', 102 'Pyrus', 103 '', 104 '', 105 $filePrefix, 106 ''); 107 108 $checkheader = array_merge(str_split($block), str_split($blockend)); 109 if (!function_exists('_pear2tarchecksum')) { 110 function _pear2tarchecksum($a, $b) {return $a + ord($b);} 111 } 112 $checksum = 256; // 8 * ord(' '); 113 $checksum += array_reduce($checkheader, '_pear2tarchecksum'); 114 115 if ($corrupt === 'checksum') $checksum++; 116 $checksum = pack('a8', sprintf('%6s ', decoct($checksum))); 117 118 fwrite($this->tmp, $block . $checksum . $blockend, 512); 119 if (is_resource($fileOrStream)) { 120 stream_copy_to_stream($fileOrStream, $this->tmp); 121 if ($stat['size'] % 512) { 122 fwrite($this->tmp, str_repeat("\0", 512 - $stat['size'] % 512)); 123 } 124 } else { 125 fwrite($this->tmp, $fileOrStream); 126 if (strlen($fileOrStream) && !isset($link) && strlen($fileOrStream) % 512) { 127 fwrite($this->tmp, str_repeat("\0", 512 - strlen($fileOrStream) % 512)); 128 } 129 } 130 } 131 132 /** 133 * Initialize the package creator 134 */ 135 function init() 136 { 137 switch ($this->compress) { 138 case 'zlib' : 139 $this->tmp = gzopen($this->path, 'wb'); 140 break; 141 case 'bz2' : 142 $this->tmp = bzopen($this->path, 'w'); 143 break; 144 case 'none' : 145 $this->tmp = fopen($this->path, 'wb'); 146 break; 147 default : 148 throw new Exception( 149 'unknown compression type ' . $this->compress); 150 } 151 } 152 153 /** 154 * Create an internal directory, creating parent directories as needed 155 * 156 * @param string $dir 157 */ 158 function mkdir($dir) 159 { 160 $this->addFile($dir, "", array( 161 'mode' => 0x4000 + 0644, 162 'uid' => 0, 163 'gid' => 0, 164 'size' => 0, 165 'mtime' => time(), 166 )); 167 } 168 169 /** 170 * Finish saving the package 171 */ 172 function close() 173 { 174 fwrite($this->tmp, pack('a1024', '')); 175 fclose($this->tmp); 176 } 177}