File: D:/HostingSpaces/PvdBoogaard/indoorski.nl/backup/oude-site/cms/lib/class.manifest.php
<?php
/**
* Manifest
* Class library for assisting with Manifest list generation and comparison.
* This is meant to be portable, so several related classes are included in this file, and is coded for PHP4/5 (IWP4/5), which may cause some issues with PHP6 in future.
*
* @version $Id$
* @author Gwilym Evans <gwilym.evans@interspire.com>
* @package Interspire
* @subpackage Manifest
*/
define('MANIFEST_RESULT_UNMODIFIED', 0);
define('MANIFEST_RESULT_NEW', 1);
define('MANIFEST_RESULT_MODIFIED', 2);
define('MANIFEST_RESULT_MISSING', 4);
/**
* ManifestResult
* Class for storing result information.
*
* @package Interspire
* @subpackage Manifest
*/
class ManifestResult
{
/**
* Relative path of file
*
* @var String
*/
var $path;
/**
* Result, represented as a bit field of MANIFEST_RESULT_* flags
*
* @var Integer
*/
var $result;
function ManifestResult ($path, $result)
{
$this->path = $path;
$this->result = $result;
}
/**
* Return a string representation of the result
*
* @return String
*/
function resultAsString ()
{
$list = array();
if ($this->result & MANIFEST_RESULT_UNMODIFIED)
array_push($list, 'Unmodified');
if ($this->result & MANIFEST_RESULT_NEW)
array_push($list, 'New');
if ($this->result & MANIFEST_RESULT_MODIFIED)
array_push($list, 'Modified');
if ($this->result & MANIFEST_RESULT_MISSING)
array_push($list, 'Missing');
return implode(', ', $list);
}
}
/**
* ManifestFile
* Class for storing file information. Mainly used to represetnt a file in a data structure, rather than for file-oriented functionality.
*
*/
class ManifestFile
{
var $path;
var $size;
var $hash;
function ManifestFile ($path, $size = 0, $hash = '')
{
$this->path = $path;
$this->size = $size;
$this->hash = $hash;
}
}
/**
* Manifest
* Class containing main manifest functionality
*
*/
class Manifest
{
/**
* Default white list patterns
*
* @var Array
*/
var $defaultWhiteList = array('/^.*\/(\.|\.\.|cvs|\.svn|\.settings|\.cache|\.project|\.cvsignore|Thumbs\.db)$/i');
/**
* Default text file extensions
*
* @var Array
*/
var $defaultTextExtensions = array('php', 'htm', 'html', 'tpl', 'txt', 'ini', 'js', 'css', 'htaccess', 'inc', 'log');
/**
* White list patterns specific to this instance
*
* @var Array
*/
var $whiteList;
/**
* Text extensions specific to this instance
*
* @var Array
*/
var $textExtensions;
/**
* Directory to work from.
*
* @var String
*/
var $workingDirectory;
function Manifest ()
{
$this->whiteList = $this->defaultWhiteList;
$this->textExtensions = $this->defaultTextExtensions;
$this->SetWorkingDirectory(getcwd());
}
/**
* Sets the current working (base) directory for the script, which is otherwise set to the result of getcwd()
*
* @param String $directory
*/
function setWorkingDirectory ($directory)
{
$this->workingDirectory = $directory;
}
/**
* Returns the current working directory for this Manifest instance
*
* @return String
*/
function getWorkingDirectory ()
{
return $this->workingDirectory;
}
/**
* Add an entry to this instance's text extension list
*
* @param String $extension
*/
function textExtensionAdd ($extension)
{
array_push($this->textExtensions, $extension);
}
/**
* Add an entry to this instance's white list patterns
*
* @param String $pattern
*/
function whiteListAdd ($pattern)
{
array_push($this->whiteList, $pattern);
}
/**
* Checks the given file path against this instance's white list patterns, returns true if the file is white-listed and should be ignored.
*
* @param String $check The relative file path to check.
* @return Boolean True if the file is white-listed and should be ignored.
*/
function inWhiteList ($check)
{
$match = false;
foreach ($this->whiteList as $whiteItem)
{
if (preg_match($whiteItem, $check) > 0)
{
$match = true;
break;
}
}
return $match;
}
/**
* Checks the given file extension against this instance's text extension list, returns true if the extension is a known text extension
*
* @param String $ext
* @return Boolean True if the extension is a known text extension.
*/
function inTextExtensions ($ext)
{
return in_array($ext, $this->textExtensions);
}
/**
* Gets the file extension of a given filename / path.
*
* @param String $filename The filename or path to check.
* @return String The extension.
*/
function getFileExtension ($filename)
{
$pathinfo = pathinfo($filename);
if (isset($pathinfo['extension']))
return $pathinfo['extension'];
else
return '';
}
/**
* Returns the contents of a file with all line endings converted to UNIX \n line endings.
*
* @param String $filename
*/
function getTextFileContentsUnixLineEndings ($filename)
{
$contents = file_get_contents($filename);
// convert DOS \r\n to \n, will ignore MAC single \r
$contents = str_replace("\r\n", "\n", $contents);
// convert remaining MAC \r to \n
$contents = str_replace("\r", "\n", $contents);
return $contents;
}
/**
* Generates a hash code
*
* @param String $filename
* @return String
*/
function generateHash ($filename)
{
$ext = iwp_strtolower($this->getFileExtension($filename));
$size = filesize($filename);
if ($size < 1048576 && $this->inTextExtensions($ext)) // limit text files to 1mb
{
// generate line-ending-neutral md5
return md5($this->getTextFileContentsUnixLineEndings($filename));
}
else
{
// generate binary md5
return md5_file($filename);
}
}
/**
* Serialize a given file list which can be unserialized with Manifest::unSerializeFileList
*
* @param Array $files
* @return String
*/
function serializeFileList (&$files)
{
//return serialize($files);
$serialized = '';
foreach ($files as $file)
{
$serialized .= $file->path ."\t". $file->size ."\t". $file->hash ."\n";
}
return $serialized;
}
/**
* Unserialize a given file list which was serialized with Manifest::serializeFileList
*
* @param String $serialized
* @return Array
*/
function unSerializeFileList ($serialized)
{
//return unserialize($serialized);
$files = explode("\n", $serialized);
foreach ($files as $index => $file)
{
if (!$file) {
// blank line, ignore and remove it
unset($files[$index]);
continue;
}
$row = explode("\t", $file);
$files[$index] = new ManifestFile($row[0], intval($row[1]), $row[2]);
}
return $files;
}
/**
* Loads a file list from a given URL, unserializing it via UnSerializeFileList in the process
*
* @param String $uri Filename or URL of serialized file list.
* @return Array Array of ManifestFile objects
*/
function loadFileList ($url)
{
$serialized = '';
if (ini_get('allow_url_fopen')) {
// try fopen-style stuff
if (function_exists('file_get_contents')) {
$serialized = file_get_contents($url);
}
} else if (function_exists('curl_init')) {
// try CURL
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
ob_start();
curl_exec($ch);
curl_close($ch);
$serialized = ob_get_contents();
ob_end_clean();
}
if (!$serialized) {
// fall back to local stuff if it exists
if (file_exists('manifest.txt')) {
if (function_exists('file_get_contents')) {
$serialized = file_get_contents('manifest.txt');
}
}
}
if (!$serialized) {
die('loading file list from '. $url .' failed.');
}
return $this->unSerializeFileList($serialized);
}
/**
* Compares two file lists, returning an array of ManifestResult objects
*
* @param Array $mine File list array representing local manifest (subject for comparison)
* @param Array $theirs File list array representing 'standard' manifest (to be compared to)
*/
function compareFileLists ($mine, &$theirs)
{
$results = array();
foreach ($theirs as $file)
{
$result = 0;
if (isset($mine[$file->path]))
{
if ($file->hash == $mine[$file->path]->hash)
{
$result |= MANIFEST_RESULT_UNMODIFIED;
}
else
{
$result |= MANIFEST_RESULT_MODIFIED;
}
unset($mine[$file->path]);
}
else
{
$result |= MANIFEST_RESULT_MISSING;
}
if ($result)
$results[$file->path] = new ManifestResult($file->path, $result);
}
foreach ($mine as $file)
{
$results[$file->path] = new ManifestResult($file->path, MANIFEST_RESULT_NEW);
}
ksort($results);
return $results;
}
/**
* Generates an array of ManifestFile objects populated with data for the current working directory.
*
* @param Boolean $ignoreWhiteList Set this to ignore the whitelist
* @return Array Array of ManifestFile objects
*/
function generateFileList ($ignoreWhiteList = false, $generateHashes = true)
{
$base = $this->workingDirectory; // base working directory
$subdirectories = array('/'); // subdirectory stack to check
$files = array(); // storage for list of files
while (count($subdirectories))
{
$subdirectory = array_shift($subdirectories);
$directoryPath = $base . $subdirectory;
$directoryHandle = opendir($directoryPath);
while (false !== ($fileName = readdir($directoryHandle)))
{
$fileRelativePath = $subdirectory . $fileName;
$fileAbsolutePath = $directoryPath . $fileName;
$fileIsDirectory = is_dir($fileAbsolutePath);
if ($this->inWhiteList($fileRelativePath))
continue;
if ($fileIsDirectory)
{
array_push($subdirectories, $fileRelativePath .'/');
continue;
}
$fileSize = filesize($fileAbsolutePath);
$fileHash = $generateHashes ? $this->generateHash($fileAbsolutePath) : '';
$files[$fileRelativePath] = new ManifestFile($fileRelativePath, $fileSize, $fileHash);
}
closedir($directoryHandle);
}
ksort($files);
return $files;
}
}