summaryrefslogtreecommitdiff
path: root/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php
diff options
context:
space:
mode:
Diffstat (limited to 'buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php')
-rw-r--r--buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php343
1 files changed, 343 insertions, 0 deletions
diff --git a/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php b/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php
new file mode 100644
index 00000000..b9cfae64
--- /dev/null
+++ b/buildscripts/phing/classes/phing/tasks/ext/ManifestTask.php
@@ -0,0 +1,343 @@
+<?php
+/**
+ * $Id: 7f8f119fe5dd44ca9f374e24d776a1a764260e33 $
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information please see
+ * <http://phing.info>.
+ */
+
+require_once "phing/Task.php";
+require_once 'phing/system/io/PhingFile.php';
+
+/**
+ * ManifestTask
+ *
+ * Generates a simple Manifest file with optional checksums.
+ *
+ *
+ * Manifest schema:
+ * ...
+ * path/to/file CHECKSUM [CHECKSUM2] [CHECKSUM3]
+ * path/to/secondfile CHECKSUM [CHECKSUM2] [CHECKSUM3]
+ * ...
+ *
+ * Example usage:
+ * <manifest checksum="crc32" file="${dir_build}/Manifest">
+ * <fileset refid="files_build" />
+ * </manifest>
+ *
+ * <manifest checksum="md5,adler32,sha256" file="${dir_build}/Manifest">
+ * <fileset refid="files_build" />
+ * </manifest>
+ *
+ *
+ *
+ * @author David Persson <davidpersson at qeweurope dot org>
+ * @package phing.tasks.ext
+ * @version $Id: 7f8f119fe5dd44ca9f374e24d776a1a764260e33 $
+ * @since 2.3.1
+ */
+class ManifestTask extends Task
+{
+ var $taskname = 'manifest';
+
+ /**
+ * Action
+ *
+ * "w" for reading in files from fileSet
+ * and writing manifest
+ *
+ * or
+ *
+ * "r" for reading in files from fileSet
+ * and checking against manifest
+ *
+ * @var string "r" or "w"
+ */
+ private $action = 'w';
+
+ /**
+ * The target file passed in the buildfile.
+ */
+ private $destFile = null;
+
+ /**
+ * Holds filesets
+ *
+ * @var array An Array of objects
+ */
+ private $filesets = array();
+
+ /**
+ * Enable/Disable checksuming or/and select algorithm
+ * true defaults to md5
+ * false disables checksuming
+ * string "md5,sha256,..." enables generation of multiple checksums
+ * string "sha256" generates sha256 checksum only
+ *
+ * @var mixed
+ */
+ private $checksum = false;
+
+ /**
+ * A string used in hashing method
+ *
+ * @var string
+ */
+ private $salt = '';
+
+ /**
+ * Holds some data collected during runtime
+ *
+ * @var array
+ */
+ private $meta = array('totalFileCount' => 0,'totalFileSize' => 0);
+
+
+ /**
+ * The setter for the attribute "file"
+ * This is where the manifest will be written to/read from
+ *
+ * @param string Path to readable file
+ * @return void
+ */
+ public function setFile(PhingFile $file)
+ {
+ $this->file = $file;
+ }
+
+ /**
+ * The setter for the attribute "checksum"
+ *
+ * @param mixed $mixed
+ * @return void
+ */
+ public function setChecksum($mixed)
+ {
+ if(is_string($mixed)) {
+ $data = array(strtolower($mixed));
+
+ if(strpos($data[0],',')) {
+ $data = explode(',',$mixed);
+ }
+
+ $this->checksum = $data;
+
+ } elseif($mixed === true) {
+ $this->checksum = array('md5');
+
+ }
+ }
+
+ /**
+ * The setter for the optional attribute "salt"
+ *
+ * @param string $string
+ * @return void
+ */
+ public function setSalt($string)
+ {
+ $this->salt = $string;
+ }
+
+ /**
+ * Nested creator, creates a FileSet for this task
+ *
+ * @access public
+ * @return object The created fileset object
+ */
+ public function createFileSet()
+ {
+ $num = array_push($this->filesets, new FileSet());
+ return $this->filesets[$num-1];
+ }
+
+ /**
+ * The init method: Do init steps.
+ */
+ public function init()
+ {
+ // nothing to do here
+ }
+
+ /**
+ * Delegate the work
+ */
+ public function main()
+ {
+ $this->validateAttributes();
+
+ if($this->action == 'w') {
+ $this->write();
+
+ } elseif($this->action == 'r') {
+ $this->read();
+
+ }
+ }
+
+ /**
+ * Creates Manifest file
+ * Writes to $this->file
+ *
+ * @throws BuildException
+ */
+ private function write()
+ {
+ $project = $this->getProject();
+
+ if(!touch($this->file->getPath())) {
+ throw new BuildException("Unable to write to ".$this->file->getPath().".");
+ }
+
+ $this->log("Writing to " . $this->file->__toString(), Project::MSG_INFO);
+
+ if(is_array($this->checksum)) {
+ $this->log("Using " . implode(', ',$this->checksum)." for checksuming.", Project::MSG_INFO);
+ }
+
+ foreach($this->filesets as $fs) {
+
+ $dir = $fs->getDir($this->project)->getPath();
+
+ $ds = $fs->getDirectoryScanner($project);
+ $fromDir = $fs->getDir($project);
+ $srcFiles = $ds->getIncludedFiles();
+ $srcDirs = $ds->getIncludedDirectories();
+
+ foreach($ds->getIncludedFiles() as $file_path) {
+ $line = $file_path;
+ if($this->checksum) {
+ foreach($this->checksum as $algo) {
+ if(!$hash = $this->hashFile($dir.'/'.$file_path,$algo)) {
+ throw new BuildException("Hashing $dir/$file_path with $algo failed!");
+ }
+
+ $line .= "\t".$hash;
+ }
+ }
+ $line .= "\n";
+ $manifest[] = $line;
+ $this->log("Adding file ".$file_path,Project::MSG_VERBOSE);
+ $this->meta['totalFileCount'] ++;
+ $this->meta['totalFileSize'] += filesize($dir.'/'.$file_path);
+ }
+
+ }
+
+ file_put_contents($this->file,$manifest);
+
+ $this->log("Done. Total files: ".$this->meta['totalFileCount'].". Total file size: ".$this->meta['totalFileSize']." bytes.", Project::MSG_INFO);
+ }
+
+ /**
+ * @todo implement
+ */
+ private function read()
+ {
+ throw new BuildException("Checking against manifest not yet supported.");
+ }
+
+ /**
+ * Wrapper method for hash generation
+ * Automatically selects extension
+ * Falls back to built-in functions
+ *
+ * @link http://www.php.net/mhash
+ * @link http://www.php.net/hash
+ *
+ * @param string $msg The string that should be hashed
+ * @param string $algo Algorithm
+ * @return mixed String on success, false if $algo is not available
+ */
+ private function hash($msg,$algo)
+ {
+ if(extension_loaded('hash')) {
+ $algo = strtolower($algo);
+
+ if(in_array($algo,hash_algos())) {
+ return hash($algo,$this->salt.$msg);
+ }
+
+ }
+
+ if(extension_loaded('mhash')) {
+ $algo = strtoupper($algo);
+
+ if(defined('MHASH_'.$algo)) {
+ return mhash('MHASH_'.$algo,$this->salt.$msg);
+
+ }
+ }
+
+ switch(strtolower($algo)) {
+ case 'md5':
+ return md5($this->salt.$msg);
+ case 'crc32':
+ return abs(crc32($this->salt.$msg));
+ }
+
+ return false;
+ }
+
+ /**
+ * Hash a files contents
+ * plus it's size an modification time
+ *
+ * @param string $file
+ * @param string $algo
+ * @return mixed String on success, false if $algo is not available
+ */
+ private function hashFile($file,$algo)
+ {
+ if(!file_exists($file)) {
+ return false;
+ }
+
+ $msg = file_get_contents($file).filesize($file).filemtime($file);
+
+ return $this->hash($msg,$algo);
+ }
+
+ /**
+ * Validates attributes coming in from XML
+ *
+ * @access private
+ * @return void
+ * @throws BuildException
+ */
+ protected function validateAttributes()
+ {
+ if($this->action != 'r' && $this->action != 'w') {
+ throw new BuildException("'action' attribute has non valid value. Use 'r' or 'w'");
+ }
+
+ if(empty($this->salt)) {
+ $this->log("No salt provided. Specify one with the 'salt' attribute.", Project::MSG_WARN);
+ }
+
+ if (is_null($this->file) && count($this->filesets) === 0) {
+ throw new BuildException("Specify at least sources and destination - a file or a fileset.");
+ }
+
+ if (!is_null($this->file) && $this->file->exists() && $this->file->isDirectory()) {
+ throw new BuildException("Destination file cannot be a directory.");
+ }
+
+ }
+}
+
+