Changeset 339

Show
Ignore:
Timestamp:
01/21/08 14:22:53 (6 months ago)
Author:
mrook
Message:

#193 - Apply updated patch for ManifestTask

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/2.3/classes/phing/tasks/ext/ManifestTask.php

    r325 r339  
    2626 * ManifestTask 
    2727 *  
    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 *  
    2947 *  
    3048 * @author David Persson <davidpersson at qeweurope dot org> 
     
    3553        var $taskname = 'manifest'; 
    3654         
     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         
    3770    /** 
    3871     * The target file passed in the buildfile. 
    3972     */ 
    40     private $file = null; 
    41      
     73    private $destFile = null; 
     74     
     75    /** 
     76     * Holds filesets 
     77     * 
     78     * @var array An Array of objects 
     79     */ 
    4280        private $filesets = array(); 
    4381 
    4482    /** 
    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 
    4690     */ 
    4791        private $checksum = false; 
    4892         
    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         
    50108    /** 
    51109     * 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    { 
    54117        $this->file = $file; 
    55118    } 
     
    57120    /** 
    58121     * 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    }     
    63153     
    64154    /** 
     
    68158     * @return  object  The created fileset object 
    69159     */ 
    70     function createFileSet() { 
     160    public function createFileSet() 
     161    { 
    71162        $num = array_push($this->filesets, new FileSet()); 
    72163        return $this->filesets[$num-1]; 
     
    76167     * The init method: Do init steps. 
    77168     */ 
    78     public function init() { 
     169    public function init() 
     170    { 
    79171      // nothing to do here 
    80172    } 
    81173 
    82174    /** 
    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    { 
    86198        $project = $this->getProject(); 
    87         $this->validateAttributes(); 
    88199         
    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                } 
    90209                 
    91210                foreach($this->filesets as $fs) { 
    92211                         
    93                         $dir = $fs->getDir($this->project)
     212                        $dir = $fs->getDir($this->project)->getPath()
    94213 
    95214            $ds = $fs->getDirectoryScanner($project); 
     
    98217            $srcDirs  = $ds->getIncludedDirectories();                   
    99218 
    100                        foreach($ds->getIncludedFiles() as $file_path) { 
     219            foreach($ds->getIncludedFiles() as $file_path) { 
    101220                                $line = $file_path; 
    102221                                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                                        } 
    104229                                } 
    105230                                $line .= "\n"; 
    106231                                $manifest[] = $line; 
     232                                $this->log("Adding file ".$file_path,Project::MSG_VERBOSE); 
     233                                $this->meta['totalFileCount'] ++; 
     234                                $this->meta['totalFileSize'] += filesize($dir.'/'.$file_path); 
    107235                        } 
    108236                         
     
    110238                 
    111239                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     
    115313    /** 
    116314     * Validates attributes coming in from XML 
     
    120318     * @throws  BuildException 
    121319     */ 
    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) { 
    125331            throw new BuildException("Specify at least sources and destination - a file or a fileset."); 
    126332        } 
    127333 
    128         if ($this->file !== null && $this->file->exists() && $this->file->isDirectory()) { 
     334        if (!is_null($this->file) && $this->file->exists() && $this->file->isDirectory()) { 
    129335            throw new BuildException("Destination file cannot be a directory."); 
    130336        } 
     
    133339} 
    134340 
     341