Changeset 339
- Timestamp:
- 01/21/08 14:22:53 (6 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/2.3/classes/phing/tasks/ext/ManifestTask.php
r325 r339 26 26 * ManifestTask 27 27 * 28 * Generates a simple MANIFEST file with optional checksums 28 * Generates a simple Manifest file with optional checksums. 29 * 30 * 31 * Manifest schema: 32 * ... 33 * path/to/file CHECKSUM [CHECKSUM2] [CHECKSUM3] 34 * path/to/secondfile CHECKSUM [CHECKSUM2] [CHECKSUM3] 35 * ... 36 * 37 * Example usage: 38 * <manifest checksum="crc32" file="${dir_build}/Manifest"> 39 * <fileset refid="files_build" /> 40 * </manifest> 41 * 42 * <manifest checksum="md5,adler32,sha256" file="${dir_build}/Manifest"> 43 * <fileset refid="files_build" /> 44 * </manifest> 45 * 46 * 29 47 * 30 48 * @author David Persson <davidpersson at qeweurope dot org> … … 35 53 var $taskname = 'manifest'; 36 54 55 /** 56 * Action 57 * 58 * "w" for reading in files from fileSet 59 * and writing manifest 60 * 61 * or 62 * 63 * "r" for reading in files from fileSet 64 * and checking against manifest 65 * 66 * @var string "r" or "w" 67 */ 68 private $action = 'w'; 69 37 70 /** 38 71 * The target file passed in the buildfile. 39 72 */ 40 private $file = null; 41 73 private $destFile = null; 74 75 /** 76 * Holds filesets 77 * 78 * @var array An Array of objects 79 */ 42 80 private $filesets = array(); 43 81 44 82 /** 45 * Enable/Disable checksuming (md5) 83 * Enable/Disable checksuming or/and select algorithm 84 * true defaults to md5 85 * false disables checksuming 86 * string "md5,sha256,..." enables generation of multiple checksums 87 * string "sha256" generates sha256 checksum only 88 * 89 * @var mixed 46 90 */ 47 91 private $checksum = false; 48 92 49 93 /** 94 * A string used in hashing method 95 * 96 * @var string 97 */ 98 private $salt = ''; 99 100 /** 101 * Holds some data collected during runtime 102 * 103 * @var array 104 */ 105 private $meta = array('totalFileCount' => 0,'totalFileSize' => 0); 106 107 50 108 /** 51 109 * The setter for the attribute "file" 52 */ 53 public function setFile(PhingFile $file) { 110 * This is where the manifest will be written to/read from 111 * 112 * @param string Path to readable file 113 * @return void 114 */ 115 public function setFile(PhingFile $file) 116 { 54 117 $this->file = $file; 55 118 } … … 57 120 /** 58 121 * The setter for the attribute "checksum" 59 */ 60 public function setChecksum($bool) { 61 $this->checksum = $bool; 62 } 122 * 123 * @param mixed $mixed 124 * @return void 125 */ 126 public function setChecksum($mixed) 127 { 128 if(is_string($mixed)) { 129 $data = array(strtolower($mixed)); 130 131 if(strpos($data[0],',')) { 132 $data = explode(',',$mixed); 133 } 134 135 $this->checksum = $data; 136 137 } elseif($mixed === true) { 138 $this->checksum = array('md5'); 139 140 } 141 } 142 143 /** 144 * The setter for the optional attribute "salt" 145 * 146 * @param string $string 147 * @return void 148 */ 149 public function setSalt($string) 150 { 151 $this->salt = $string; 152 } 63 153 64 154 /** … … 68 158 * @return object The created fileset object 69 159 */ 70 function createFileSet() { 160 public function createFileSet() 161 { 71 162 $num = array_push($this->filesets, new FileSet()); 72 163 return $this->filesets[$num-1]; … … 76 167 * The init method: Do init steps. 77 168 */ 78 public function init() { 169 public function init() 170 { 79 171 // nothing to do here 80 172 } 81 173 82 174 /** 83 * do the work 84 */ 85 public function main() { 175 * Delegate the work 176 */ 177 public function main() 178 { 179 $this->validateAttributes(); 180 181 if($this->action == 'w') { 182 $this->write(); 183 184 } elseif($this->action == 'r') { 185 $this->read(); 186 187 } 188 } 189 190 /** 191 * Creates Manifest file 192 * Writes to $this->file 193 * 194 * @throws BuildException 195 */ 196 private function write() 197 { 86 198 $project = $this->getProject(); 87 $this->validateAttributes();88 199 89 $this->log("Building Manifest: " . $this->file->__toString(), Project::MSG_INFO); 200 if(!touch($this->file->getPath())) { 201 throw new BuildException("Unable to write to ".$this->file->getPath()."."); 202 } 203 204 $this->log("Writing to " . $this->file->__toString(), Project::MSG_INFO); 205 206 if(is_array($this->checksum)) { 207 $this->log("Using " . implode(', ',$this->checksum)." for checksuming.", Project::MSG_INFO); 208 } 90 209 91 210 foreach($this->filesets as $fs) { 92 211 93 $dir = $fs->getDir($this->project) ;212 $dir = $fs->getDir($this->project)->getPath(); 94 213 95 214 $ds = $fs->getDirectoryScanner($project); … … 98 217 $srcDirs = $ds->getIncludedDirectories(); 99 218 100 foreach($ds->getIncludedFiles() as $file_path) {219 foreach($ds->getIncludedFiles() as $file_path) { 101 220 $line = $file_path; 102 221 if($this->checksum) { 103 $line .= "\t".md5_file($dir.'/'.$file_path); 222 foreach($this->checksum as $algo) { 223 if(!$hash = $this->hashFile($dir.'/'.$file_path,$algo)) { 224 throw new BuildException("Hashing $dir/$file_path with $algo failed!"); 225 } 226 227 $line .= "\t".$hash; 228 } 104 229 } 105 230 $line .= "\n"; 106 231 $manifest[] = $line; 232 $this->log("Adding file ".$file_path,Project::MSG_VERBOSE); 233 $this->meta['totalFileCount'] ++; 234 $this->meta['totalFileSize'] += filesize($dir.'/'.$file_path); 107 235 } 108 236 … … 110 238 111 239 file_put_contents($this->file,$manifest); 112 113 } 114 240 241 $this->log("Done. Total files: ".$this->meta['totalFileCount'].". Total file size: ".$this->meta['totalFileSize']." bytes.", Project::MSG_INFO); 242 } 243 244 /** 245 * @todo implement 246 */ 247 private function read() 248 { 249 throw new BuildException("Checking against manifest not yet supported."); 250 } 251 252 /** 253 * Wrapper method for hash generation 254 * Automatically selects extension 255 * Falls back to built-in functions 256 * 257 * @link http://www.php.net/mhash 258 * @link http://www.php.net/hash 259 * 260 * @param string $msg The string that should be hashed 261 * @param string $algo Algorithm 262 * @return mixed String on success, false if $algo is not available 263 */ 264 private function hash($msg,$algo) 265 { 266 if(extension_loaded('hash')) { 267 $algo = strtolower($algo); 268 269 if(in_array($algo,hash_algos())) { 270 return hash($algo,$this->salt.$msg); 271 } 272 273 } 274 275 if(extension_loaded('mhash')) { 276 $algo = strtoupper($algo); 277 278 if(defined('MHASH_'.$algo)) { 279 return mhash('MHASH_'.$algo,$this->salt.$msg); 280 281 } 282 } 283 284 switch(strtolower($algo)) { 285 case 'md5': 286 return md5($this->salt.$msg); 287 case 'crc32': 288 return abs(crc32($this->salt.$msg)); 289 } 290 291 return false; 292 } 293 294 /** 295 * Hash a files contents 296 * plus it's size an modification time 297 * 298 * @param string $file 299 * @param string $algo 300 * @return mixed String on success, false if $algo is not available 301 */ 302 private function hashFile($file,$algo) 303 { 304 if(!file_exists($file)) { 305 return false; 306 } 307 308 $msg = file_get_contents($file).filesize($file).filemtime($file); 309 310 return $this->hash($msg,$algo); 311 } 312 115 313 /** 116 314 * Validates attributes coming in from XML … … 120 318 * @throws BuildException 121 319 */ 122 protected function validateAttributes() { 123 124 if ($this->file === null && count($this->filesets) === 0) { 320 protected function validateAttributes() 321 { 322 if($this->action != 'r' && $this->action != 'w') { 323 throw new BuildException("'action' attribute has non valid value. Use 'r' or 'w'"); 324 } 325 326 if(empty($this->salt)) { 327 $this->log("No salt provided. Specify one with the 'salt' attribute.", Project::MSG_WARN); 328 } 329 330 if (is_null($this->file) && count($this->filesets) === 0) { 125 331 throw new BuildException("Specify at least sources and destination - a file or a fileset."); 126 332 } 127 333 128 if ( $this->file !== null&& $this->file->exists() && $this->file->isDirectory()) {334 if (!is_null($this->file) && $this->file->exists() && $this->file->isDirectory()) { 129 335 throw new BuildException("Destination file cannot be a directory."); 130 336 } … … 133 339 } 134 340 341
