diff options
Diffstat (limited to 'buildscripts/phing/classes/phing/system/io')
16 files changed, 3305 insertions, 0 deletions
diff --git a/buildscripts/phing/classes/phing/system/io/BufferedReader.php b/buildscripts/phing/classes/phing/system/io/BufferedReader.php new file mode 100644 index 00000000..4946985c --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/BufferedReader.php @@ -0,0 +1,170 @@ +<?php +/* + *  $Id: BufferedReader.php,v 1.6 2005/12/27 19:12:13 hlellelid Exp $ + * + * 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>. +*/ + +include_once 'phing/system/io/Reader.php'; + +/* + * Convenience class for reading files. + * + * @author    <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> + * @version   $Revision: 1.6 $ $Date: 2005/12/27 19:12:13 $ + * @access    public + * @see       FilterReader + * @package   phing.system.io +*/ +class BufferedReader extends Reader { + +    private $bufferSize = 0; +    private $buffer     = null; +    private $bufferPos  = 0; +     +    /** +     * The Reader we are buffering for. +     */ +    private $in; +     +    /** +     *  +     * @param object $reader The reader (e.g. FileReader). +     * @param integer $buffsize The size of the buffer we should use for reading files. +     *                             A large buffer ensures that most files (all scripts?) are parsed in 1 buffer. +     */      +    function __construct(Reader $reader, $buffsize = 65536) { +        $this->in = $reader; +        $this->bufferSize = $buffsize; +    } + +    /** +     * Reads and returns $_bufferSize chunk of data. +     * @return mixed buffer or -1 if EOF. +     */ +    function read($len = null) { +        // ignore $len param, not sure how to hanlde it, since  +        // this should only read bufferSize amount of data. +        if ($len !== null) { +            $this->currentPosition = ftell($this->fd); +        } +         +        if ( ($data = $this->in->read($this->bufferSize)) !== -1 ) { +		 +			// not all files end with a newline character, so we also need to check EOF +			if (!$this->in->eof()) { +			 +	            $notValidPart = strrchr($data, "\n"); +	            $notValidPartSize = strlen($notValidPart); +	         +	            if ( $notValidPartSize > 1 ) { +	                // Block doesn't finish on a EOL +	                // Find the last EOL and forgot all following stuff +	                $dataSize = strlen($data); +	                $validSize = $dataSize - $notValidPartSize + 1; +	             +	                $data = substr($data, 0, $validSize); +	 +	                // Rewind to the begining of the forgotten stuff. +	                $this->in->skip(-$notValidPartSize+1); +	            } +				 +			} // if !EOF +        } +        return $data; +    } +     +    function skip($n) { +        return $this->in->skip($n); +    } +     +    function reset() { +        return $this->in->reset(); +    } +     +    function close() { +        return $this->in->close(); +    } +     +    function open() { +        return $this->in->open(); +    } +     +    /** +     * Read a line from input stream. +     */ +    function readLine() { +        $line = null; +        while ( ($ch = $this->readChar()) !== -1 ) { +            if ( $ch === "\n" ) { +                break; +            } +            $line .= $ch; +        } + +        // Warning : Not considering an empty line as an EOF +        if ( $line === null && $ch !== -1 ) +            return ""; + +        return $line; +    } +     +    /** +     * Reads a single char from the reader. +     * @return string single char or -1 if EOF. +     */ +    function readChar() {         + +        if ( $this->buffer === null ) { +            // Buffer is empty, fill it ... +            $read = $this->in->read($this->bufferSize); +            if ($read === -1) { +                $ch = -1; +            } else { +                $this->buffer = $read; +                return $this->readChar(); // recurse +            } +        } else {             +            // Get next buffered char ... +            // handle case where buffer is read-in, but is empty.  The next readChar() will return -1 EOF, +            // so we just return empty string (char) at this point.  (Probably could also return -1 ...?) +            $ch = ($this->buffer !== "") ? $this->buffer{$this->bufferPos} : ''; +            $this->bufferPos++; +            if ( $this->bufferPos >= strlen($this->buffer) ) { +                $this->buffer = null; +                $this->bufferPos = 0; +            } +        } + +        return $ch; +    } +     +    /** +     * Returns whether eof has been reached in stream. +     * This is important, because filters may want to know if the end of the file (and not just buffer) +     * has been reached. +     * @return boolean +     */  +    function eof() { +        return $this->in->eof(); +    } + +    function getResource() { +        return $this->in->getResource(); +    }     +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/BufferedWriter.php b/buildscripts/phing/classes/phing/system/io/BufferedWriter.php new file mode 100644 index 00000000..c982db28 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/BufferedWriter.php @@ -0,0 +1,72 @@ +<?php +/* + *  $Id: BufferedWriter.php,v 1.10 2005/05/26 13:10:52 mrook Exp $ + * + * 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>.  + */ +  +include_once 'phing/system/io/Writer.php'; + +/** + * Convenience class for writing files. + * + * @author    Hans Lellelid <hans@xmpl.org> + * @version   $Revision: 1.10 $ + * @package   phing.system.io  + */ +class BufferedWriter extends Writer { +     +    /** +     * The size of the buffer in kb. +     */ +    private $bufferSize    = 0; +     +    /** +     * The Writer we are buffering output to. +     */ +    private $out; + +    function __construct(Writer $writer, $buffsize = 8192) { +        $this->out = $writer; +        $this->bufferSize = $buffsize; +    } + +    function write($buf, $off = null, $len = null) { +        return $this->out->write($buf, $off, $len); +    } +     +    function newLine() { +        $this->write(Phing::getProperty('line.separator')); +    } +     +    function getResource() { +        return $this->out->getResource(); +    } + +    function reset() { +        return $this->out->reset(); +    } +     +    function close() { +        return $this->out->close(); +    } +     +    function open() { +        return $this->out->open(); +    } +     +} diff --git a/buildscripts/phing/classes/phing/system/io/ConsoleReader.php b/buildscripts/phing/classes/phing/system/io/ConsoleReader.php new file mode 100644 index 00000000..33b37619 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/ConsoleReader.php @@ -0,0 +1,84 @@ +<?php +/* + *  $Id: ConsoleReader.php,v 1.4 2004/08/12 16:26:12 matthewh Exp $ + * + * 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>.  + */ +  +include_once 'phing/system/io/Reader.php'; + +/** + * Convenience class for reading console input. + *  + * @author Hans Lellelid <hans@xmpl.org> + * @author Matthew Hershberger <matthewh@lightsp.com> + * @version $Revision: 1.4 $ + * @package phing.system.io + */ +class ConsoleReader extends Reader { +     +    function readLine() { +         +        $out = fgets(STDIN); // note: default maxlen is 1kb +        $out = rtrim($out); + +        return $out; +    } +     +    /** +     *  +     * @param int $len Num chars to read. +     * @return string chars read or -1 if eof. +     */ +    function read($len = null) { +         +        $out = fread(STDIN, $len); +         +         +        return $out; +        // FIXME +        // read by chars doesn't work (yet?) with PHP stdin.  Maybe +        // this is just a language feature, maybe there's a way to get +        // ability to read chars w/o <enter> ? +         +    }    +         +    function close() { +		// STDIN is always open +    } + +    function open() { +		// STDIN is always open +    } + +    /** +     * Whether eof has been reached with stream. +     * @return boolean +     */ +    function eof() { +        return feof(STDIN); +    }         +     +    /** +     * Returns path to file we are reading. +     * @return string +     */ +    function getResource() { +        return "console"; +    } +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/FileReader.php b/buildscripts/phing/classes/phing/system/io/FileReader.php new file mode 100644 index 00000000..cbea2c7e --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/FileReader.php @@ -0,0 +1,179 @@ +<?php +/* + *  $Id: FileReader.php,v 1.9 2005/05/26 13:10:52 mrook Exp $ + * + * 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>.  + */ +  +include_once 'phing/system/io/PhingFile.php'; +include_once 'phing/system/io/Reader.php'; + +/** + * Convenience class for reading files. The constructor of this + *  @package   phing.system.io + */ + +class FileReader extends Reader { + +    protected $file; +    protected $fd; + +    protected $currentPosition = 0; +    protected $mark = 0; + +    function __construct($file, $exclusive = false) { +     +        if ($file instanceof PhingFile) { +            $this->file = $file; +        } elseif (is_string($file)) { +            $this->file = new PhingFile($file); +        } else { +            throw new Exception("Illegal argument type to " . __METHOD__); +        } +    } + +    function skip($n) { +        $this->open(); + +        $start = $this->currentPosition; + +        $ret = @fseek($this->fd, $n, SEEK_CUR); +        if ( $ret === -1 ) +            return -1; + +        $this->currentPosition = ftell($this->fd); + +        if ( $start > $this->currentPosition ) +            $skipped = $start - $this->currentPosition; +        else +            $skipped = $this->currentPosition - $start; + +        return $skipped; +    } +     +    /** +     * Read data from file. +     * @param int $len Num chars to read. +     * @return string chars read or -1 if eof. +     */ +    function read($len = null) { +        $this->open(); +        if (feof($this->fd)) { +            return -1; +        } + +        // Compute length to read +        // possible that filesize($this->file) will be larger than  +        // available bytes to read, but that's fine -- better to err on high end +        $length = ($len === null) ? filesize($this->file->getAbsolutePath()) : $len; + +        // Read data +        $out = fread($this->fd, $length + 1); // adding 1 seems to ensure that next call to read() will return EOF (-1) +        $this->currentPosition = ftell($this->fd); + +        return $out; +    }     +     +    function mark($n = null) { +        $this->mark = $this->currentPosition; +    } +     +    function reset() { +        // goes back to last mark, by default this would be 0 (i.e. rewind file). +        fseek($this->fd, SEEK_SET, $this->mark); +        $this->mark = 0; +    } + +    function close() { +        if ($this->fd === null) { +            return true; +        } + +        if (false === @fclose($this->fd)) { +            // FAILED. +            $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg"; +            throw new IOException($msg); +        } else { +            $this->fd = null; +            return true; +        } +    } + +    function open() { +        global $php_errormsg; +         +        if ($this->fd === null) { +            $this->fd = @fopen($this->file->getAbsolutePath(), "rb"); +        } + +        if ($this->fd === false) { +            // fopen FAILED. +            // Add error from php to end of log message. $php_errormsg. +            $msg = "Cannot fopen ".$this->file->getAbsolutePath().". $php_errormsg"; +            throw new IOException($msg); +        } + +        if (false) { +            // Locks don't seem to work on windows??? HELP!!!!!!!!! +            // if (FALSE === @flock($fp, LOCK_EX)) { // FAILED. +            $msg = "Cannot acquire flock on $file. $php_errormsg"; +            throw new IOException($msg); +        } + +        return true; +    } + +    /** +     * Whether eof has been reached with stream. +     * @return boolean +     */ +    function eof() { +        return feof($this->fd); +    } +      +    /** +     * Reads a entire file and stores the data in the variable +     * passed by reference. +     * +     * @param    string $file    String. Path and/or name of file to read. +     * @param    object &$rBuffer    Reference. Variable of where to put contents. +     * +     * @return    TRUE on success. Err object on failure. +     * @author  Charlie Killian, charlie@tizac.com +     */ +    function readInto(&$rBuffer) { + +        $this->open(); + +        $fileSize = $this->file->length(); +        if ($fileSize === false) { +            $msg = "Cannot get filesize of " . $this->file->__toString() . " $php_errormsg"; +            throw new IOException($msg); +        } +        $rBuffer = fread($this->fd, $fileSize); +        $this->close(); +    } +     +    /** +     * Returns path to file we are reading. +     * @return string +     */ +    function getResource() { +        return $this->file->toString(); +    } +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/FileSystem.php b/buildscripts/phing/classes/phing/system/io/FileSystem.php new file mode 100644 index 00000000..2802ddfb --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/FileSystem.php @@ -0,0 +1,657 @@ +<?php + +/*  + *  $Id: FileSystem.php,v 1.11 2005/12/01 20:56:59 hlellelid Exp $ + * + * 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>.  + */ + +/** + * This is an abstract class for platform specific filesystem implementations + * you have to implement each method in the platform specific filesystem implementation + * classes Your local filesytem implementation must extend this class. + * You should also use this class as a template to write your local implementation + * Some native PHP filesystem specific methods are abstracted here as well. Anyway + * you _must_ always use this methods via a PhingFile object (that by nature uses the + * *FileSystem drivers to access the real filesystem via this class using natives. + * + * FIXME: + *  - Error handling reduced to min fallthrough runtime excetions + *    more precise errorhandling is done by the PhingFile class + *     + * @author Charlie Killian <charlie@tizac.com> + * @author Hans Lellelid <hans@xmpl.org> + * @version $Revision: 1.11 $ + * @package phing.system.io + */ +abstract class FileSystem {     + +    /* properties for simple boolean attributes */ +    const BA_EXISTS    = 0x01; +    const BA_REGULAR   = 0x02; +    const BA_DIRECTORY = 0x04; +    const BA_HIDDEN    = 0x08; +     +    /** Instance for getFileSystem() method. */ +    private static $fs; +     +    /** +     * Static method to return the FileSystem singelton representing +     * this platform's local filesystem driver. +     */ +    function getFileSystem() { +        if (self::$fs === null) { +            switch(Phing::getProperty('host.fstype')) { +                case 'UNIX': +                    include_once 'phing/system/io/UnixFileSystem.php'; +                    self::$fs = new UnixFileSystem(); +                break; +                case 'WIN32': +                    include_once 'phing/system/io/Win32FileSystem.php'; +                    self::$fs = new Win32FileSystem(); +                break; +                case 'WINNT': +                    include_once 'phing/system/io/WinNTFileSystem.php'; +                    self::$fs = new WinNTFileSystem(); +                break; +                default: +                    throw new Exception("Host uses unsupported filesystem, unable to proceed"); +            } +        } +        return self::$fs; +    } + +    /* -- Normalization and construction -- */ + +    /** +     * Return the local filesystem's name-separator character. +     */ +    abstract function getSeparator(); + +    /** +     * Return the local filesystem's path-separator character. +     */ +    abstract function getPathSeparator(); + +    /** +     * Convert the given pathname string to normal form.  If the string is +     * already in normal form then it is simply returned. +     */ +    abstract function normalize($strPath); + +    /** +     * Compute the length of this pathname string's prefix.  The pathname +     * string must be in normal form. +     */ +    abstract function prefixLength($pathname); + +    /** +     * Resolve the child pathname string against the parent. +     * Both strings must be in normal form, and the result +     * will be a string in normal form. +     */ +    abstract function resolve($parent, $child); +     +    /** +     * Resolve the given abstract pathname into absolute form.  Invoked by the +     * getAbsolutePath and getCanonicalPath methods in the PhingFile class. +     */ +    abstract function resolveFile(PhingFile $f); + +    /** +     * Return the parent pathname string to be used when the parent-directory +     * argument in one of the two-argument PhingFile constructors is the empty +     * pathname. +     */ +    abstract function getDefaultParent(); + +    /** +     * Post-process the given URI path string if necessary.  This is used on +     * win32, e.g., to transform "/c:/foo" into "c:/foo".  The path string +     * still has slash separators; code in the PhingFile class will translate them +     * after this method returns. +     */ +    abstract function fromURIPath($path); + +    /* -- Path operations -- */ + +    /** +     * Tell whether or not the given abstract pathname is absolute. +     */ +    abstract function isAbsolute(PhingFile $f); + +    /**  +     * canonicalize filename by checking on disk  +     * @return mixed Canonical path or false if the file doesn't exist. +     */ +    function canonicalize($strPath) { +        return @realpath($strPath);         +    } + +    /* -- Attribute accessors -- */ + +    /** +     * Return the simple boolean attributes for the file or directory denoted +     * by the given abstract pathname, or zero if it does not exist or some +     * other I/O error occurs. +     */ +    function getBooleanAttributes($f) { +        throw new Exception("SYSTEM ERROR method getBooleanAttributes() not implemented by fs driver"); +    } + +    /** +     * Check whether the file or directory denoted by the given abstract +     * pathname may be accessed by this process.  If the second argument is +     * false, then a check for read access is made; if the second +     * argument is true, then a check for write (not read-write) +     * access is made.  Return false if access is denied or an I/O error +     * occurs. +     */ +    function checkAccess(PhingFile $f, $write = false) { +        // we clear stat cache, its expensive to look up from scratch, +        // but we need to be sure +        @clearstatcache(); + + +        // Shouldn't this be $f->GetAbsolutePath() ? +        // And why doesn't GetAbsolutePath() work? + +        $strPath = (string) $f->getPath(); + +        // FIXME +        // if file object does denote a file that yet not existst +        // path rights are checked +        if (!@file_exists($strPath) && !is_dir($strPath)) { +            $strPath = $f->getParent(); +            if ($strPath === null || !is_dir($strPath)) { +                $strPath = Phing::getProperty("user.dir"); +            } +            //$strPath = dirname($strPath); +        } + +        if (!$write) { +            return (boolean) @is_readable($strPath); +        } else { +            return (boolean) @is_writable($strPath); +        } +    } + +    /** +     * Return the time at which the file or directory denoted by the given +     * abstract pathname was last modified, or zero if it does not exist or +     * some other I/O error occurs. +     */ +    function getLastModifiedTime(PhingFile $f) { +         +        if (!$f->exists()) { +            return 0; +        } + +        @clearstatcache(); +        $strPath = (string) $f->getPath(); +        $mtime = @filemtime($strPath); +        if (false === $mtime) { +            // FAILED. Log and return err. +            $msg = "FileSystem::Filemtime() FAILED. Cannot can not get modified time of $strPath. $php_errormsg"; +            throw new Exception($msg); +        } else { +            return (int) $mtime; +        } +    } + +    /** +     * Return the length in bytes of the file denoted by the given abstract +     * pathname, or zero if it does not exist, is a directory, or some other +     * I/O error occurs. +     */ +    function getLength(PhingFile $f) { +        $strPath = (string) $f->getAbsolutePath(); +        $fs = filesize((string) $strPath); +        if ($fs !== false) { +            return $fs; +        } else { +            $msg = "FileSystem::Read() FAILED. Cannot get filesize of $strPath. $php_errormsg"; +            throw new Exception($msg); +        } +    } + +    /* -- File operations -- */ + +    /** +     * Create a new empty file with the given pathname.  Return +     * true if the file was created and false if a +     * file or directory with the given pathname already exists.  Throw an +     * IOException if an I/O error occurs. +     * +     * @param       string      Path of the file to be created. +     *      +     * @throws      IOException +     */ +    function createNewFile($strPathname) { +        if (@file_exists($strPathname)) +            return false; +             +        // Create new file +        $fp = @fopen($strPathname, "w"); +        if ($fp === false) { +            throw new IOException("The file \"$strPathname\" could not be created");             +        } +        @fclose($fp);         +        return true; +    } + +    /** +     * Delete the file or directory denoted by the given abstract pathname, +     * returning true if and only if the operation succeeds. +     */ +    function delete(PhingFile $f) { +        if ($f->isDirectory()) { +            return $this->rmdir($f->getPath()); +        } else { +            return $this->unlink($f->getPath()); +        } +    } + +    /** +     * Arrange for the file or directory denoted by the given abstract +     * pathname to be deleted when Phing::shutdown is called, returning +    * true if and only if the operation succeeds. +     */ +    function deleteOnExit($f) { +        throw new Exception("deleteOnExit() not implemented by local fs driver"); +    } + +    /** +     * List the elements of the directory denoted by the given abstract +     * pathname.  Return an array of strings naming the elements of the +     * directory if successful; otherwise, return <code>null</code>. +     */ +    function listDir(PhingFile $f) { +        $strPath = (string) $f->getAbsolutePath(); +        $d = @dir($strPath); +        if (!$d) { +            return null; +        } +        $list = array(); +        while($entry = $d->read()) { +            if ($entry != "." && $entry != "..") { +                array_push($list, $entry); +            } +        } +        $d->close(); +        unset($d); +        return $list; +    } + +    /** +     * Create a new directory denoted by the given abstract pathname, +     * returning true if and only if the operation succeeds. +     */ +    function createDirectory(&$f) { +        return @mkdir($f->getAbsolutePath(),0755); +    } + +    /** +     * Rename the file or directory denoted by the first abstract pathname to +     * the second abstract pathname, returning true if and only if +     * the operation succeeds. +     * +     * @param PhingFile $f1 abstract source file +     * @param PhingFile $f2 abstract destination file +     * @return void     +     * @throws Exception if rename cannot be performed +     */ +    function rename(PhingFile $f1, PhingFile $f2) {         +        // get the canonical paths of the file to rename +        $src = $f1->getAbsolutePath(); +        $dest = $f2->getAbsolutePath(); +        if (false === @rename($src, $dest)) { +            $msg = "Rename FAILED. Cannot rename $src to $dest. $php_errormsg"; +            throw new Exception($msg); +        } +    } + +    /** +     * Set the last-modified time of the file or directory denoted by the +     * given abstract pathname returning true if and only if the +     * operation succeeds. +     * @return void +     * @throws Exception +     */ +    function setLastModifiedTime(PhingFile $f, $time) {         +        $path = $f->getPath(); +        $success = @touch($path, $time); +        if (!$success) { +            throw new Exception("Could not create directory due to: $php_errormsg"); +        } +    } + +    /** +     * Mark the file or directory denoted by the given abstract pathname as +     * read-only, returning <code>true</code> if and only if the operation +     * succeeds. +     */ +    function setReadOnly($f) { +        throw new Exception("setReadonle() not implemented by local fs driver"); +    } + +    /* -- Filesystem interface -- */ + +    /** +     * List the available filesystem roots, return array of PhingFile objects +     */ +    function listRoots() { +        throw new Exception("SYSTEM ERROR [listRoots() not implemented by local fs driver]"); +    } + +    /* -- Basic infrastructure -- */ + +    /** +     * Compare two abstract pathnames lexicographically. +     */ +    function compare($f1, $f2) { +        throw new Exception("SYSTEM ERROR [compare() not implemented by local fs driver]"); +    } + +    /** +     * Copy a file. +     * +     * @param PhingFile $src Source path and name file to copy. +     * @param PhingFile $dest Destination path and name of new file. +     * +     * @return void      +     * @throws Exception if file cannot be copied. +     */ +    function copy(PhingFile $src, PhingFile $dest) { +        global $php_errormsg; +        $srcPath  = $src->getAbsolutePath(); +        $destPath = $dest->getAbsolutePath(); + +        if (false === @copy($srcPath, $destPath)) { // Copy FAILED. Log and return err. +            // Add error from php to end of log message. $php_errormsg. +            $msg = "FileSystem::copy() FAILED. Cannot copy $srcPath to $destPath. $php_errormsg"; +            throw new Exception($msg); +        } +         +        try { +            $dest->setMode($src->getMode()); +        } catch(Exception $exc) { +            // [MA] does chmod returns an error on systems that do not support it ? +            // eat it up for now. +        } +    } + +    /** +     * Change the permissions on a file or directory. +     * +     * @param    pathname    String. Path and name of file or directory. +     * @param    mode        Int. The mode (permissions) of the file or +     *                        directory. If using octal add leading 0. eg. 0777. +     *                        Mode is affected by the umask system setting. +     * +     * @return void      +     * @throws Exception if operation failed. +     */ +    function chmod($pathname, $mode) {     +        $str_mode = decoct($mode); // Show octal in messages.     +        if (false === @chmod($pathname, $mode)) {// FAILED. +            $msg = "FileSystem::chmod() FAILED. Cannot chmod $pathname. Mode $str_mode. $php_errormsg"; +            throw new Exception($msg); +        } +    } + +    /** +     * Locks a file and throws an Exception if this is not possible. +     * @return void +     * @throws Exception +     */ +    function lock(PhingFile $f) { +        $filename = $f->getPath(); +        $fp = @fopen($filename, "w"); +        $result = @flock($fp, LOCK_EX); +        @fclose($fp); +        if (!$result) { +            throw new Exception("Could not lock file '$filename'"); +        } +    } + +    /** +     * Unlocks a file and throws an IO Error if this is not possible. +     * +     * @throws Exception +     * @return void +     */ +    function unlock(PhingFile $f) { +        $filename = $f->getPath(); +        $fp = @fopen($filename, "w"); +        $result = @flock($fp, LOCK_UN); +        fclose($fp); +        if (!$result) { +            throw new Exception("Could not unlock file '$filename'"); +        } +    } + +    /** +     * Delete a file. +     * +     * @param    file    String. Path and/or name of file to delete. +     * +     * @return void +     * @throws Exception - if an error is encountered. +     */ +    function unlink($file) { +        global $php_errormsg; +        if (false === @unlink($file)) { +            $msg = "FileSystem::unlink() FAILED. Cannot unlink '$file'. $php_errormsg"; +            throw new Exception($msg); +        } +    } + +    /** +     * Symbolically link a file to another name. +     *  +     * Currently symlink is not implemented on Windows. Don't use if the application is to be portable. +     * +     * @param string $target Path and/or name of file to link. +     * @param string $link Path and/or name of link to be created. +     * @return void +     */ +    function symlink($target, $link) { +     +        // If Windows OS then symlink() will report it is not supported in +        // the build. Use this error instead of checking for Windows as the OS. + +        if (false === @symlink($target, $link)) { +            // Add error from php to end of log message. $php_errormsg. +            $msg = "FileSystem::Symlink() FAILED. Cannot symlink '$target' to '$link'. $php_errormsg"; +            throw new Exception($msg); +        } + +    } + +    /** +     * Set the modification and access time on a file to the present time. +     * +     * @param string $file Path and/or name of file to touch. +     * @param int $time  +     * @return void +     */ +    function touch($file, $time = null) { +        global $php_errormsg; +         +        if (null === $time) { +            $error = @touch($file); +        } else { +            $error = @touch($file, $time); +        } + +        if (false === $error) { // FAILED. +            // Add error from php to end of log message. $php_errormsg. +            $msg = "FileSystem::touch() FAILED. Cannot touch '$file'. $php_errormsg";             +            throw new Exception($msg);             +        } +    } + +    /** +     * Delete an empty directory OR a directory and all of its contents. +     * +     * @param    dir    String. Path and/or name of directory to delete. +     * @param    children    Boolean.    False: don't delete directory contents. +     *                                    True: delete directory contents. +     * +     * @return void +     */ +    function rmdir($dir, $children = false) { +        global $php_errormsg; +         +        // If children=FALSE only delete dir if empty. +        if (false === $children) { +         +            if (false === @rmdir($dir)) { // FAILED. +                // Add error from php to end of log message. $php_errormsg. +                $msg = "FileSystem::rmdir() FAILED. Cannot rmdir $dir. $php_errormsg"; +                throw new Exception($msg); +            } +             +        } else { // delete contents and dir. + +            $handle = @opendir($dir); + +            if (false === $handle) { // Error. + +                $msg = "FileSystem::rmdir() FAILED. Cannot opendir() $dir. $php_errormsg";                 +                throw new Exception($msg); + +            } else { // Read from handle. + +                // Don't error on readdir(). +                while (false !== ($entry = @readdir($handle))) { + +                    if ($entry != '.' && $entry != '..') { + +                        // Only add / if it isn't already the last char. +                        // This ONLY serves the purpose of making the Logger +                        // output look nice:) + +                        if (strpos(strrev($dir), DIRECTORY_SEPARATOR) === 0) {// there is a / +                            $next_entry = $dir . $entry; +                        } else { // no / +                            $next_entry = $dir . DIRECTORY_SEPARATOR . $entry; +                        } + +                        // NOTE: As of php 4.1.1 is_dir doesn't return FALSE it +                        // returns 0. So use == not ===. + +                        // Don't error on is_dir() +                        if (false == @is_dir($next_entry)) { // Is file. +                             +                            try { +                                self::unlink($next_entry); // Delete. +                            } catch (Exception $e) {                             +                                $msg = "FileSystem::Rmdir() FAILED. Cannot FileSystem::Unlink() $next_entry. ". $e->getMessage(); +                                throw new Exception($msg); +                            } + +                        } else { // Is directory. +                             +                            try { +                                self::rmdir($next_entry, true); // Delete +                            } catch (Exception $e) { +                                $msg = "FileSystem::rmdir() FAILED. Cannot FileSystem::rmdir() $next_entry. ". $e->getMessage(); +                                throw new Exception($msg); +                            } + +                        } // end is_dir else +                    } // end .. if +                } // end while +            } // end handle if + +            // Don't error on closedir() +            @closedir($handle); +             +            if (false === @rmdir($dir)) { // FAILED. +                // Add error from php to end of log message. $php_errormsg. +                $msg = "FileSystem::rmdir() FAILED. Cannot rmdir $dir. $php_errormsg"; +                throw new Exception($msg); +            } +             +        } +                 +    } + +    /** +     * Set the umask for file and directory creation. +     * +     * @param    mode    Int. Permissions ususally in ocatal. Use leading 0 for +     *                    octal. Number between 0 and 0777. +     * +     * @return void +     * @throws Exception if there is an error performing operation.      +     */ +    function umask($mode) { +        global $php_errormsg; +         +        // CONSIDERME: +        // Throw a warning if mode is 0. PHP converts illegal octal numbers to +        // 0 so 0 might not be what the user intended. +                         +        $str_mode = decoct($mode); // Show octal in messages. + +        if (false === @umask($mode)) { // FAILED. +            // Add error from php to end of log message. $php_errormsg. +            $msg = "FileSystem::Umask() FAILED. Value $mode. $php_errormsg"; +            throw new Exception($msg); +        } +    } + +    /** +     * Compare the modified time of two files. +     * +     * @param    file1    String. Path and name of file1. +     * @param    file2    String. Path and name of file2. +     * +     * @return    Int.     1 if file1 is newer. +     *                 -1 if file2 is newer. +     *                  0 if files have the same time. +     *                  Err object on failure. +     *      +     * @throws Exception - if cannot get modified time of either file. +     */ +    function compareMTimes($file1, $file2) { + +        $mtime1 = filemtime($file1); +        $mtime2 = filemtime($file2); + +        if ($mtime1 === false) { // FAILED. Log and return err.         +            // Add error from php to end of log message. $php_errormsg. +            $msg = "FileSystem::compareMTimes() FAILED. Cannot can not get modified time of $file1."; +            throw new Exception($msg);             +        } elseif ($mtime2 === false) { // FAILED. Log and return err. +            // Add error from php to end of log message. $php_errormsg. +            $msg = "FileSystem::compareMTimes() FAILED. Cannot can not get modified time of $file2."; +            throw new Exception($msg); +        } else { // Worked. Log and return compare.                 +            // Compare mtimes. +            if ($mtime1 == $mtime2) { +                return 0; +            } else { +                return ($mtime1 < $mtime2) ? -1 : 1; +            } // end compare +        } +    } +         +} diff --git a/buildscripts/phing/classes/phing/system/io/FileWriter.php b/buildscripts/phing/classes/phing/system/io/FileWriter.php new file mode 100644 index 00000000..d6265777 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/FileWriter.php @@ -0,0 +1,139 @@ +<?php +/* + *  $Id: FileWriter.php,v 1.7 2005/05/26 13:10:52 mrook Exp $   + *  + * 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>. + */ +  +include_once 'phing/system/io/PhingFile.php'; +include_once 'phing/system/io/Writer.php'; + +/** + * Convenience class for reading files. The constructor of this + * + * @package   phing.system.io + */ +class FileWriter extends Writer { + +    protected $file; +    protected $fd; +     +    /** Whether to append contents to file. */ +    protected $append; +     +    /** Whether we should attempt to lock the file (currently disabled). */ +    protected $exclusive; +     +    /** +     * Construct a new FileWriter. +     * @param mixed $file PhingFile or string pathname. +     * @param boolean $append Append to existing file? +     * @param boolean $exclusive Lock file? (currently disabled due to windows incompatibility) +     */ +    function __construct($file, $append = false, $exclusive = false) { +        if ($file instanceof PhingFile) { +            $this->file = $file; +        } elseif (is_string($file)) { +            $this->file = new PhingFile($file); +        } else { +            throw new Exception("Invalid argument type for \$file."); +        } +        $this->append = $append; +        $this->exclusive = $exclusive; +    } + +    function close() { +        if ($this->fd === null) { +            return true; +        } + +        if (false === @fclose($this->fd)) { +            // FAILED. +            $msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg"; +            throw new IOException($msg); +        } else { +            $this->fd = null; +            return true; +        } +    } + +    function open() { +        if ($this->fd === null) { +            if ($this->append) { $flags = "ab"; } else { $flags = "wb"; } +            $this->fd = @fopen($this->file->getPath(), $flags); +        } + +        if ($this->fd === false) { +            // fopen FAILED. +            // Add error from php to end of log message. $php_errormsg. +            $msg = "Cannot fopen ".$this->file->getPath()." $php_errormsg"; +            throw new IOException($msg); +        } + +        if (false) { +            // Locks don't seem to work on windows??? HELP!!!!!!!!! +            // if (FALSE === @flock($fp, LOCK_EX)) { // FAILED. +            $msg = "Cannot acquire flock on $file. $php_errormsg"; +            throw new IOException($msg); +        } + +        return true; +    } +     +    function reset() { +        // FIXME -- what exactly should this do, if anything? +        // reset to beginning of file (i.e. re-open)? +    } +     +    function writeBuffer($buffer) { + +        if (!$this->file->canWrite()) { +            throw new IOException("No permission to write to file: " . $this->file->__toString()); +        } + +        $this->open(); +        $result = @fwrite($this->fd, $buffer); +        $this->close(); + +        if ($result === false) { +            throw new IOException("Error writing file: ". $this->file->toString()); +        } else { +            return true; +        } +    } + +    function write($buf, $off = null, $len = null) { +        if ( $off === null && $len === null ) +            $to_write = $buf; +        else +            $to_write = substr($buf, $off, $len); + +        $this->open(); +        $result = @fwrite($this->fd, $to_write); + +        if ( $result === false ) { +            throw new IOException("Error writing file."); +        } else { +            return true; +        } +    } +     +    function getResource() { +        return $this->file->toString(); +    } +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/FilterReader.php b/buildscripts/phing/classes/phing/system/io/FilterReader.php new file mode 100644 index 00000000..8c683408 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/FilterReader.php @@ -0,0 +1,72 @@ +<?php +/* + *  $Id: FilterReader.php,v 1.6 2005/05/26 13:10:52 mrook Exp $ + * + * 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>.  + */ + +include_once 'phing/system/io/Reader.php'; + +/** + * Convenience class for reading files. The constructor of this + *  @package   phing.system.io + * + * TODO: All filters should be ProjectComponents, too! + */ +class FilterReader extends Reader { +     +    protected $in; +     +    function __construct(Reader $in = null) { +        $this->in = $in; +        //parent::__construct(new FileReader($file, $exclusive)); +    } +     +    public function setReader(Reader $in) { +        $this->in = $in; +    } +     +    public function skip($n) { +        return $this->in->skip($n); +    } +     +    /** +     * Read data from source. +     * FIXME: Clean up this function signature, as it a) params aren't being used +     * and b) it doesn't make much sense. +     */ +    public function read($len = null) { +        return $this->in->read($len); +    } + +    public function reset() { +        return $this->in->reset(); +    } +     +    public function close() { +        return $this->in->close(); +    } +     +    public function open() { +        return $this->in->open(); +    } + +    function getResource() { +        return $this->in->getResource(); +    } +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/IOException.php b/buildscripts/phing/classes/phing/system/io/IOException.php new file mode 100644 index 00000000..e2c73b27 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/IOException.php @@ -0,0 +1,28 @@ +<?php +/* + *  $Id: IOException.php,v 1.4 2005/02/27 20:52:09 mrook Exp $ + * + * 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>.  + */ + +/** + * Extends Exception to take advantage of methods therein. + * + * @package   phing.system.io + */ +class IOException extends Exception {} +?>
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/system/io/PhingFile.php b/buildscripts/phing/classes/phing/system/io/PhingFile.php new file mode 100644 index 00000000..cd881963 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/PhingFile.php @@ -0,0 +1,866 @@ +<?php +/* + *  $Id: PhingFile.php,v 1.1 2005/05/26 13:10:52 mrook Exp $ + * + * 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>. + */ + +include_once 'phing/system/io/FileSystem.php'; +include_once 'phing/system/lang/NullPointerException.php'; + +/** + * An abstract representation of file and directory pathnames. + * + * @version   $Revision: 1.1 $ + * @package   phing.system.io + */ +class PhingFile { + +    /** separator string, static, obtained from FileSystem */ +    public static $separator; + +    /** path separator string, static, obtained from FileSystem (; or :)*/ +    public static $pathSeparator; +     +    /** +     * This abstract pathname's normalized pathname string.  A normalized +     * pathname string uses the default name-separator character and does not +     * contain any duplicate or redundant separators. +     */ +    private $path = null; + +    /** The length of this abstract pathname's prefix, or zero if it has no prefix. */ +    private $prefixLength = 0; + +    /** constructor */ +    function __construct($arg1 = null, $arg2 = null) { +         +        if (self::$separator === null || self::$pathSeparator === null) { +            $fs = FileSystem::getFileSystem(); +            self::$separator = $fs->getSeparator(); +            self::$pathSeparator = $fs->getPathSeparator(); +        } + +        /* simulate signature identified constructors */ +        if ($arg1 instanceof PhingFile && is_string($arg2)) { +            $this->_constructFileParentStringChild($arg1, $arg2); +        } elseif (is_string($arg1) && ($arg2 === null)) { +            $this->_constructPathname($arg1); +        } elseif(is_string($arg1) && is_string($arg2)) { +            $this->_constructStringParentStringChild($arg1, $arg2); +        } else { +            if ($arg1 === null) { +                throw new NullPointerException("Argument1 to function must not be null"); +            } +            $this->path = (string) $arg1; +            $this->prefixLength = (int) $arg2; +        } +    } + +    /** Returns the length of this abstract pathname's prefix. */ +    function getPrefixLength() { +        return (int) $this->prefixLength; +    } +     +    /* -- constructors not called by signature match, so we need some helpers --*/ + +    function _constructPathname($pathname) { +        // obtain ref to the filesystem layer +        $fs = FileSystem::getFileSystem(); + +        if ($pathname === null) { +            throw new NullPointerException("Argument to function must not be null"); +        } + +        $this->path = (string) $fs->normalize($pathname); +        $this->prefixLength = (int) $fs->prefixLength($this->path); +    } + +    function _constructStringParentStringChild($parent, $child = null) { +        // obtain ref to the filesystem layer +        $fs = FileSystem::getFileSystem(); + +        if ($child === null) { +            throw new NullPointerException("Argument to function must not be null"); +        } +        if ($parent !== null) { +            if ($parent === "") { +                $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child)); +            } else { +                $this->path = $fs->resolve($fs->normalize($parent), $fs->normalize($child)); +            } +        } else { +            $this->path = (string) $fs->normalize($child); +        } +        $this->prefixLength = (int) $fs->prefixLength($this->path); +    } + +    function _constructFileParentStringChild($parent, $child = null) { +        // obtain ref to the filesystem layer +        $fs = FileSystem::getFileSystem(); + +        if ($child === null) { +            throw new NullPointerException("Argument to function must not be null"); +        } + +        if ($parent !== null) { +            if ($parent->path === "") { +                $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child)); +            } else { +                $this->path = $fs->resolve($parent->path, $fs->normalize($child)); +            } +        } else { +            $this->path = $fs->normalize($child); +        } +        $this->prefixLength = $fs->prefixLength($this->path); +    } + +    /* -- Path-component accessors -- */ + +    /** +     * Returns the name of the file or directory denoted by this abstract +     * pathname.  This is just the last name in the pathname's name +     * sequence.  If the pathname's name sequence is empty, then the empty +     * string is returned. +     * +     * @return  The name of the file or directory denoted by this abstract +     *          pathname, or the empty string if this pathname's name sequence +     *          is empty +     */ +    function getName() { +        // that's a lastIndexOf +        $index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res); +        if ($index < $this->prefixLength) { +            return substr($this->path, $this->prefixLength); +        } +        return substr($this->path, $index + 1); +    } + +    /** +     * Returns the pathname string of this abstract pathname's parent, or +     * null if this pathname does not name a parent directory. +     * +     * The parent of an abstract pathname consists of the pathname's prefix, +     * if any, and each name in the pathname's name sequence except for the last. +     * If the name sequence is empty then the pathname does not name a parent +     * directory. +     * +     * @return  The pathname string of the parent directory named by this +     *          abstract pathname, or null if this pathname does not name a parent +     */ +    function getParent() { +        // that's a lastIndexOf +        $index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res); +        if ($index < $this->prefixLength) { +            if (($this->prefixLength > 0) && (strlen($this->path > $this->prefixLength))) { +                return substr($this->path, 0, $this->prefixLength); +            } +            return null; +        } +        return substr($this->path, 0, $index); +    } + +    /** +     * Returns the abstract pathname of this abstract pathname's parent, +     * or null if this pathname does not name a parent directory. +     * +     * The parent of an abstract pathname consists of the pathname's prefix, +     * if any, and each name in the pathname's name sequence except for the +     * last.  If the name sequence is empty then the pathname does not name +     * a parent directory. +     * +     * @return  The abstract pathname of the parent directory named by this +     *          abstract pathname, or null if this pathname +     *          does not name a parent +     */ +    function getParentFile() { +        $p = $this->getParent(); +        if ($p === null) { +            return null; +        } +        return new PhingFile((string) $p, (int) $this->prefixLength); +    } + +    /** +     * Converts this abstract pathname into a pathname string.  The resulting +     * string uses the default name-separator character to separate the names +     * in the name sequence. +     * +     * @return  The string form of this abstract pathname +     */ +    function getPath() { +        return (string) $this->path; +    } + +    /** +     * Tests whether this abstract pathname is absolute.  The definition of +     * absolute pathname is system dependent.  On UNIX systems, a pathname is +     * absolute if its prefix is "/".  On Win32 systems, a pathname is absolute +     * if its prefix is a drive specifier followed by "\\", or if its prefix +     * is "\\". +     * +     * @return  true if this abstract pathname is absolute, false otherwise +     */ +    function isAbsolute() { +        return ($this->prefixLength !== 0); +    } + + +    /** +     * Returns the absolute pathname string of this abstract pathname. +     * +     * If this abstract pathname is already absolute, then the pathname +     * string is simply returned as if by the getPath method. +     * If this abstract pathname is the empty abstract pathname then +     * the pathname string of the current user directory, which is named by the +     * system property user.dir, is returned.  Otherwise this +     * pathname is resolved in a system-dependent way.  On UNIX systems, a +     * relative pathname is made absolute by resolving it against the current +     * user directory.  On Win32 systems, a relative pathname is made absolute +     * by resolving it against the current directory of the drive named by the +     * pathname, if any; if not, it is resolved against the current user +     * directory. +     * +     * @return  The absolute pathname string denoting the same file or +     *          directory as this abstract pathname +     * @see     #isAbsolute() +     */ +    function getAbsolutePath() { +        $fs = FileSystem::getFileSystem();         +        return $fs->resolveFile($this); +    } + +    /** +     * Returns the absolute form of this abstract pathname.  Equivalent to +     * getAbsolutePath. +     * +     * @return  The absolute abstract pathname denoting the same file or +     *          directory as this abstract pathname +     */ +    function getAbsoluteFile() { +        return new PhingFile((string) $this->getAbsolutePath()); +    } + + +    /** +     * Returns the canonical pathname string of this abstract pathname. +     * +     * A canonical pathname is both absolute and unique. The precise +     * definition of canonical form is system-dependent. This method first +     * converts this pathname to absolute form if necessary, as if by invoking the +     * getAbsolutePath() method, and then maps it to its unique form in a +     * system-dependent way.  This typically involves removing redundant names +     * such as "." and .. from the pathname, resolving symbolic links +     * (on UNIX platforms), and converting drive letters to a standard case +     * (on Win32 platforms). +     * +     * Every pathname that denotes an existing file or directory has a +     * unique canonical form.  Every pathname that denotes a nonexistent file +     * or directory also has a unique canonical form.  The canonical form of +     * the pathname of a nonexistent file or directory may be different from +     * the canonical form of the same pathname after the file or directory is +     * created.  Similarly, the canonical form of the pathname of an existing +     * file or directory may be different from the canonical form of the same +     * pathname after the file or directory is deleted. +     * +     * @return  The canonical pathname string denoting the same file or +     *          directory as this abstract pathname +     */ +    function getCanonicalPath() { +        $fs = FileSystem::getFileSystem(); +        return $fs->canonicalize($this->path); +    } + + +    /** +     * Returns the canonical form of this abstract pathname.  Equivalent to +     * getCanonicalPath(. +     * +     * @return  PhingFile The canonical pathname string denoting the same file or +     *          directory as this abstract pathname +     */ +    function getCanonicalFile() { +        return new PhingFile($this->getCanonicalPath()); +    } + +    /** +     * Converts this abstract pathname into a file: URL.  The +     * exact form of the URL is system-dependent.  If it can be determined that +     * the file denoted by this abstract pathname is a directory, then the +     * resulting URL will end with a slash. +     * +     * Usage note: This method does not automatically escape +     * characters that are illegal in URLs.  It is recommended that new code +     * convert an abstract pathname into a URL by first converting it into a +     * URI, via the toURI() method, and then converting the URI +     * into a URL via the URI::toURL() +     * +     * @return  A URL object representing the equivalent file URL +     * +     * +     */ +    function toURL() { +        /* +        // URL class not implemented yet +        return new URL("file", "", $this->_slashify($this->getAbsolutePath(), $this->isDirectory())); +        */ +    } + +    /** +     * Constructs a file: URI that represents this abstract pathname. +     * Not implemented yet +     */ +    function toURI() { +        /* +        $f = $this->getAbsoluteFile(); +           $sp = (string) $this->slashify($f->getPath(), $f->isDirectory()); +           if (StringHelper::startsWith('//', $sp)) +        $sp = '//' + sp; +           return new URI('file', null, $sp, null); +        */ +    } + +    function _slashify($path, $isDirectory) { +        $p = (string) $path; + +        if (self::$separator !== '/') { +            $p = str_replace(self::$separator, '/', $p); +        } + +        if (!StringHelper::startsWith('/', $p)) { +            $p = '/'.$p; +        } + +        if (!StringHelper::endsWith('/', $p) && $isDirectory) { +            $p = $p.'/'; +        } + +        return $p; +    } + +    /* -- Attribute accessors -- */ + +    /** +     * Tests whether the application can read the file denoted by this +     * abstract pathname. +     * +     * @return  true if and only if the file specified by this +     *          abstract pathname exists and can be read by the +     *          application; false otherwise +     */ +    function canRead() { +        $fs = FileSystem::getFileSystem(); + +        if ($fs->checkAccess($this)) { +            return (boolean) @is_readable($this->getAbsolutePath()); +        } +        return false; +    } + +    /** +     * Tests whether the application can modify to the file denoted by this +     * abstract pathname. +     * +     * @return  true if and only if the file system actually +     *          contains a file denoted by this abstract pathname and +     *          the application is allowed to write to the file; +     *          false otherwise. +     * +     */ +    function canWrite() { +        $fs = FileSystem::getFileSystem(); +        return $fs->checkAccess($this, true); +    } + +    /** +     * Tests whether the file denoted by this abstract pathname exists. +     * +     * @return  true if and only if the file denoted by this +     *          abstract pathname exists; false otherwise +     * +     */ +    function exists() {                 +        if ($this->isFile()) { +            return @file_exists($this->path); +        } else { +            return @is_dir($this->path); +        } +    } + +    /** +     * Tests whether the file denoted by this abstract pathname is a +     * directory. +     * +     * @return true if and only if the file denoted by this +     *         abstract pathname exists and is a directory; +     *         false otherwise +     * +     */ +    function isDirectory() { +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this) !== true) { +            throw new IOException("No read access to ".$this->path); +        } +        return @is_dir($this->path); +    } + +    /** +     * Tests whether the file denoted by this abstract pathname is a normal +     * file.  A file is normal if it is not a directory and, in +     * addition, satisfies other system-dependent criteria.  Any non-directory +     * file created by a Java application is guaranteed to be a normal file. +     * +     * @return  true if and only if the file denoted by this +     *          abstract pathname exists and is a normal file; +     *          false otherwise +     */ +    function isFile() { +        //$fs = FileSystem::getFileSystem(); +        return @is_file($this->path); +    } + +    /** +     * Tests whether the file named by this abstract pathname is a hidden +     * file.  The exact definition of hidden is system-dependent.  On +     * UNIX systems, a file is considered to be hidden if its name begins with +     * a period character ('.').  On Win32 systems, a file is considered to be +     * hidden if it has been marked as such in the filesystem. Currently there +     * seems to be no way to dermine isHidden on Win file systems via PHP +     * +     * @return  true if and only if the file denoted by this +     *          abstract pathname is hidden according to the conventions of the +     *          underlying platform +     */ +    function isHidden() { +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this) !== true) { +            throw new IOException("No read access to ".$this->path); +        } +        return (($fs->getBooleanAttributes($this) & $fs->BA_HIDDEN) !== 0); +    } + +    /** +     * Returns the time that the file denoted by this abstract pathname was +     * last modified. +     * +     * @return  A integer value representing the time the file was +     *          last modified, measured in milliseconds since the epoch +     *          (00:00:00 GMT, January 1, 1970), or 0 if the +     *          file does not exist or if an I/O error occurs +     */ +    function lastModified() { +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this) !== true) { +            throw new IOException("No read access to " . $this->path); +        } +        return $fs->getLastModifiedTime($this); +    } + +    /** +     * Returns the length of the file denoted by this abstract pathname. +     * The return value is unspecified if this pathname denotes a directory. +     * +     * @return  The length, in bytes, of the file denoted by this abstract +     *          pathname, or 0 if the file does not exist +     */ +    function length() { +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this) !== true) { +            throw new IOException("No read access to ".$this->path."\n"); +        } +        return $fs->getLength($this); +    } + +    /** +     * Convenience method for returning the contents of this file as a string. +     * This method uses file_get_contents() to read file in an optimized way. +     * @return string +     * @throws Exception - if file cannot be read +     */ +    function contents() { +        if (!$this->canRead() || !$this->isFile()) { +            throw new IOException("Cannot read file contents!"); +        } +        return file_get_contents($this->getAbsolutePath()); +    } +     +    /* -- File operations -- */ + +    /** +     * Atomically creates a new, empty file named by this abstract pathname if +     * and only if a file with this name does not yet exist.  The check for the +     * existence of the file and the creation of the file if it does not exist +     * are a single operation that is atomic with respect to all other +     * filesystem activities that might affect the file. +     * +     * @return  true if the named file does not exist and was +     *          successfully created; <code>false</code> if the named file +     *          already exists +     * @throws IOException if file can't be created +     */ +    function createNewFile($parents=true, $mode=0777) { +        $file = FileSystem::getFileSystem()->createNewFile($this->path); +        return $file; +    } + +    /** +     * Deletes the file or directory denoted by this abstract pathname.  If +     * this pathname denotes a directory, then the directory must be empty in +     * order to be deleted. +     * +     * @return  true if and only if the file or directory is +     *          successfully deleted; false otherwise +     */ +    function delete() { +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this, true) !== true) { +            throw new IOException("No read access to " . $this->path."\n"); +        } +        return $fs->delete($this); +    } + +    /** +     * Requests that the file or directory denoted by this abstract pathname +     * be deleted when php terminates.  Deletion will be attempted only for +     * normal termination of php and if and if only Phing::shutdown() is +     * called. +     * +     * Once deletion has been requested, it is not possible to cancel the +     * request.  This method should therefore be used with care. +     * +     */ +    function deleteOnExit() { +        $fs = FileSystem::getFileSystem(); +        $fs->deleteOnExit($this); +    } + +    /** +     * Returns an array of strings naming the files and directories in the +     * directory denoted by this abstract pathname. +     * +     * If this abstract pathname does not denote a directory, then this +     * method returns null  Otherwise an array of strings is +     * returned, one for each file or directory in the directory.  Names +     * denoting the directory itself and the directory's parent directory are +     * not included in the result.  Each string is a file name rather than a +     * complete path. +     * +     * There is no guarantee that the name strings in the resulting array +     * will appear in any specific order; they are not, in particular, +     * guaranteed to appear in alphabetical order. +     * +     * @return  An array of strings naming the files and directories in the +     *          directory denoted by this abstract pathname.  The array will be +     *          empty if the directory is empty.  Returns null if +     *          this abstract pathname does not denote a directory, or if an +     *          I/O error occurs. +     * +     */ +    function listDir($filter = null) { +        $fs = FileSystem::getFileSystem(); +        return $fs->lister($this, $filter); +    } + +    function listFiles($filter = null) { +        $ss = $this->listDir($filter); +        if ($ss === null) { +            return null; +        } +        $n = count($ss); +        $fs = array(); +        for ($i = 0; $i < $n; $i++) { +            $fs[$i] = new PhingFile((string)$this->path, (string)$ss[$i]); +        } +        return $fs; +    } + +    /** +     * Creates the directory named by this abstract pathname, including any +     * necessary but nonexistent parent directories.  Note that if this +     * operation fails it may have succeeded in creating some of the necessary +     * parent directories. +     * +     * @return  true if and only if the directory was created, +     *          along with all necessary parent directories; false +     *          otherwise +     * @throws  IOException +     */ +    function mkdirs() { +        if ($this->exists()) { +            return false; +        } +		try { +			if ($this->mkdir()) { +	            return true; +	        } +		} catch (IOException $ioe) { +			// IOException from mkdir() means that directory propbably didn't exist. +		}         +        $parentFile = $this->getParentFile(); +        return (($parentFile !== null) && ($parentFile->mkdirs() && $this->mkdir())); +    } + +    /** +     * Creates the directory named by this abstract pathname. +     * +     * @return  true if and only if the directory was created; false otherwise +     * @throws  IOException +     */ +    function mkdir() { +        $fs = FileSystem::getFileSystem(); + +        if ($fs->checkAccess(new PhingFile($this->path), true) !== true) { +            throw new IOException("No write access to " . $this->getPath()); +        } +        return $fs->createDirectory($this); +    } + +    /** +     * Renames the file denoted by this abstract pathname. +     * +     * @param   destFile  The new abstract pathname for the named file +     * @return  true if and only if the renaming succeeded; false otherwise +     */ +    function renameTo(PhingFile $destFile) { +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this) !== true) { +            throw new IOException("No write access to ".$this->getPath()); +        } +        return $fs->rename($this, $destFile); +    } + +    /** +     * Simple-copies file denoted by this abstract pathname into another +     * PhingFile +     * +     * @param PhingFile $destFile  The new abstract pathname for the named file +     * @return true if and only if the renaming succeeded; false otherwise +     */ +    function copyTo(PhingFile $destFile) { +        $fs = FileSystem::getFileSystem(); + +        if ($fs->checkAccess($this) !== true) { +            throw new IOException("No read access to ".$this->getPath()."\n"); +        } + +        if ($fs->checkAccess($destFile, true) !== true) { +            throw new IOException("File::copyTo() No write access to ".$destFile->getPath()); +        } +        return $fs->copy($this, $destFile); +    } + +    /** +     * Sets the last-modified time of the file or directory named by this +     * abstract pathname. +     * +     * All platforms support file-modification times to the nearest second, +     * but some provide more precision.  The argument will be truncated to fit +     * the supported precision.  If the operation succeeds and no intervening +     * operations on the file take place, then the next invocation of the +     * lastModified method will return the (possibly truncated) time argument +     * that was passed to this method. +     * +     * @param  time  The new last-modified time, measured in milliseconds since +     *               the epoch (00:00:00 GMT, January 1, 1970) +     * @return true if and only if the operation succeeded; false otherwise +     */ +    function setLastModified($time) { +        $time = (int) $time; +        if ($time < 0) { +            throw new Exception("IllegalArgumentException, Negative $time\n"); +        } + +        // FIXME check if accessible +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this, true) !== true) { +            throw new IOException("File::setLastModified(). No write access to file\n"); +        } +        return $fs->setLastModifiedTime($this, $time); +    } + +    /** +     * Marks the file or directory named by this abstract pathname so that +     * only read operations are allowed.  After invoking this method the file +     * or directory is guaranteed not to change until it is either deleted or +     * marked to allow write access.  Whether or not a read-only file or +     * directory may be deleted depends upon the underlying system. +     * +     * @return true if and only if the operation succeeded; false otherwise +     */ +    function setReadOnly() { +        $fs = FileSystem::getFileSystem(); +        if ($fs->checkAccess($this, true) !== true) { +            // Error, no write access +            throw new IOException("No write access to " . $this->getPath()); +        } +        return $fs->setReadOnly($this); +    } + +    /** +     * Sets the mode of the file +     * @param int $mode Ocatal mode. +     */ +    function setMode($mode) { +        $fs = FileSystem::getFileSystem(); +        return $fs->chmod($this->getPath(), $mode); +    } + +    /** +     * Retrieve the mode of this file. +     * @return int +     */ +    function getMode() { +        return @fileperms($this->getPath()); +    } + +    /* -- Filesystem interface -- */ + +    /** +     * List the available filesystem roots. +     * +     * A particular platform may support zero or more hierarchically-organized +     * file systems.  Each file system has a root  directory from which all +     * other files in that file system can be reached. +     * Windows platforms, for example, have a root directory for each active +     * drive; UNIX platforms have a single root directory, namely "/". +     * The set of available filesystem roots is affected by various system-level +     * operations such the insertion or ejection of removable media and the +     * disconnecting or unmounting of physical or virtual disk drives. +     * +     * This method returns an array of PhingFile objects that +     * denote the root directories of the available filesystem roots.  It is +     * guaranteed that the canonical pathname of any file physically present on +     * the local machine will begin with one of the roots returned by this +     * method. +     * +     * The canonical pathname of a file that resides on some other machine +     * and is accessed via a remote-filesystem protocol such as SMB or NFS may +     * or may not begin with one of the roots returned by this method.  If the +     * pathname of a remote file is syntactically indistinguishable from the +     * pathname of a local file then it will begin with one of the roots +     * returned by this method.  Thus, for example, PhingFile objects +     * denoting the root directories of the mapped network drives of a Windows +     * platform will be returned by this method, while PhingFile +     * objects containing UNC pathnames will not be returned by this method. +     * +     * @return  An array of PhingFile objects denoting the available +     *          filesystem roots, or null if the set of roots +     *          could not be determined.  The array will be empty if there are +     *          no filesystem roots. +     */ +    function listRoots() { +        $fs = FileSystem::getFileSystem(); +        return (array) $fs->listRoots(); +    } + +    /* -- Tempfile management -- */ + +    /** +     * Returns the path to the temp directory. +     */ +    function getTempDir() { +        return Phing::getProperty('php.tmpdir'); +    } + +    /** +     * Static method that creates a unique filename whose name begins with +     * $prefix and ends with $suffix in the directory $directory. $directory +     * is a reference to a PhingFile Object. +     * Then, the file is locked for exclusive reading/writing. +     * +     * @author      manuel holtgrewe, grin@gmx.net +     * @throws      IOException +     * @access      public +     */ +    function createTempFile($prefix, $suffix, PhingFile $directory) { +         +        // quick but efficient hack to create a unique filename ;-) +        $result = null; +        do { +            $result = new PhingFile($directory, $prefix . substr(md5(time()), 0, 8) . $suffix); +        } while (file_exists($result->getPath())); + +        $fs = FileSystem::getFileSystem(); +        $fs->createNewFile($result->getPath()); +        $fs->lock($result); + +        return $result; +    } + +    /** +     * If necessary, $File the lock on $File is removed and then the file is +     * deleted +     * +     * @access      public +     */ +    function removeTempFile() { +        $fs = FileSystem::getFileSystem(); +        // catch IO Exception +        $fs->unlock($this); +        $this->delete(); +    } + + +    /* -- Basic infrastructure -- */ + +    /** +     * Compares two abstract pathnames lexicographically.  The ordering +     * defined by this method depends upon the underlying system.  On UNIX +     * systems, alphabetic case is significant in comparing pathnames; on Win32 +     * systems it is not. +     * +     * @param PhingFile $file Th file whose pathname sould be compared to the pathname of this file. +     * +     * @return int Zero if the argument is equal to this abstract pathname, a +     *        value less than zero if this abstract pathname is +     *        lexicographically less than the argument, or a value greater +     *        than zero if this abstract pathname is lexicographically +     *        greater than the argument +     */ +    function compareTo(PhingFile $file) { +        $fs = FileSystem::getFileSystem(); +        return $fs->compare($this, $file); +    } + +    /** +     * Tests this abstract pathname for equality with the given object. +     * Returns <code>true</code> if and only if the argument is not +     * <code>null</code> and is an abstract pathname that denotes the same file +     * or directory as this abstract pathname.  Whether or not two abstract +     * pathnames are equal depends upon the underlying system.  On UNIX +     * systems, alphabetic case is significant in comparing pathnames; on Win32 +     * systems it is not. +     * @return boolean +     */ +    function equals($obj) { +        if (($obj !== null) && ($obj instanceof PhingFile)) { +            return ($this->compareTo($obj) === 0); +        } +        return false; +    } + +    /** Backwards compatibility -- use PHP5's native __tostring method. */ +    function toString() { +        return $this->getPath(); +    } +     +    /** PHP5's native method. */ +    function __toString() { +        return $this->getPath(); +    } +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/Reader.php b/buildscripts/phing/classes/phing/system/io/Reader.php new file mode 100644 index 00000000..1e377378 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/Reader.php @@ -0,0 +1,88 @@ +<?php +/* + *  $Id: Reader.php,v 1.5 2003/12/24 12:38:40 hlellelid Exp $ + * + * 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>. +*/ + +/** + * Abstract class for reading character streams. + * @author Hans Lellelid <hans@xmpl.org> + * @author Yannick Lecaillez <yl@seasonfive.com> + * @version $Revision: 1.5 $ + * @package phing.system.io + */ +abstract class Reader { + +    /** +     * Read data from source. +     * If length is specified, then only that number of chars is read, +     * otherwise stream is read until EOF. +     * @param int $len +     */ +    abstract public function read($len = null); +             +    /** +     * Close stream. +     */ +    abstract public function close(); +     +    /** +     * Open stream for reading. +     */ +    abstract public function open(); +     +    /** +     * Returns the filename, url, etc. that is being read from. +     * This is critical for, e.g., ExpatParser's ability to know +     * the filename that is throwing an ExpatParserException, etc. +     * @return string +     */ +    abstract function getResource(); + +    /** +     * Move stream position relative to current pos. +     * @param int $n +     */ +    public function skip($n) {} +     +    /** +     * Reset the current position in stream to beginning or last mark (if supported). +     */     +    public function reset() {} +         +    /** +     * If supported, places a "marker" (like a bookmark) at current stream position. +     * A subsequent call to reset() will move stream position back +     * to last marker (if supported). +     */     +    public function mark() {} + +    /** +     * Whether marking is supported. +     * @return boolean +     */ +    public function markSupported() {} +     +    /** +     * Is stream ready for reading. +     * @return boolean +     */ +    public function ready() {} + +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/StringReader.php b/buildscripts/phing/classes/phing/system/io/StringReader.php new file mode 100644 index 00000000..689a2115 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/StringReader.php @@ -0,0 +1,73 @@ +<?php +/* + *  $Id: StringReader.php,v 1.8 2005/05/26 13:10:52 mrook Exp $ + * + * 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>.  + */ + +/** + * Dummy class for reading character streams.  + * @package phing.system.io + */ +class StringReader extends Reader { +     +    private    $_string; +    private $mark = 0; +    private $currPos = 0; +     +    function __construct($string) { +        $this->_string = $string; +    } + +    function skip($n) {} + +    function read($len = null) { +        if ($len === null) { +            return $this->_string; +        } else {             +            if ($this->currPos >= strlen($this->_string)) { +                return -1; +            }             +            $out = substr($this->_string, $this->currPos, $len); +            $this->currPos += $len; +            return $out; +        } +    } + +    function mark() { +        $this->mark = $this->currPos; +    } + +    function reset() { +        $this->currPos = $this->mark; +    } + +    function close() {} + +    function open() {} + +    function ready() {} + +    function markSupported() { +        return true; +    } +     +    function getResource() { +        return '(string) "'.$this->_string . '"'; +    } +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/TokenReader.php b/buildscripts/phing/classes/phing/system/io/TokenReader.php new file mode 100644 index 00000000..a57d994c --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/TokenReader.php @@ -0,0 +1,51 @@ +<?php +/* + *  $Id: TokenReader.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $ + * + * 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>. +*/ + +include_once 'phing/system/io/Reader.php'; +include_once 'phing/filters/ReplaceTokens.php'; // for class Token + +/** + * Abstract class for reading Tokens from a resource + * + * @author    Manuel Holtgewe + * @version   $Revision: 1.3 $ + * @access    public + * @package   phing.system.io + */ +class TokenReader extends Reader { + +    /** +     * Constructor +     */ +    function __construct() { +    } + +    /** +     * Reads a token from the resource and returns it as a +     * Token object. +     * +     * @access  public +     */ +    function readToken() { +    } +} + +?> diff --git a/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php b/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php new file mode 100644 index 00000000..fb4e49b4 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/UnixFileSystem.php @@ -0,0 +1,266 @@ +<?php +/* + *  $Id: UnixFileSystem.php,v 1.10 2005/05/26 13:10:52 mrook Exp $ + * + * 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>. + */ + +include_once 'phing/system/io/FileSystem.php'; + +/** + * UnixFileSystem class. This class encapsulates the basic file system functions + * for platforms using the unix (posix)-stylish filesystem. It wraps php native + * functions suppressing normal PHP error reporting and instead uses Exception + * to report and error. + * + * This class is part of a oop based filesystem abstraction and targeted to run + * on all supported php platforms. + * + * Note: For debugging turn track_errors on in the php.ini. The error messages + * and log messages from this class will then be clearer because $php_errormsg + * is passed as part of the message. + * + * FIXME: + *  - Comments + *  - Error handling reduced to min, error are handled by PhingFile mainly + * + * @author    Andreas Aderhold, andi@binarycloud.com + * @version   $Revision: 1.10 $ + * @package   phing.system.io + */ +class UnixFileSystem extends FileSystem { + +    /** +     * returns OS dependant path separator char +     */ +    function getSeparator() { +        return '/'; +    } + +    /** +     * returns OS dependant directory separator char +     */ +    function getPathSeparator() { +        return ':'; +    } + +    /** +     * A normal Unix pathname contains no duplicate slashes and does not end +     * with a slash.  It may be the empty string. +     * +     * Check that the given pathname is normal.  If not, invoke the real +     * normalizer on the part of the pathname that requires normalization. +     * This way we iterate through the whole pathname string only once. +     */ +    function normalize($strPathname) { +         +        if (empty($strPathname)) { +            return; +        } +         +        // Resolve home directories. We assume /home is where all home +        // directories reside, b/c there is no other way to do this with +        // PHP AFAIK. +        if ($strPathname{0} === "~") { +            if ($strPathname{1} === "/") { // like ~/foo => /home/user/foo +                $strPathname = "/home/" . get_current_user() . substr($strPathname, 1); +            } else { // like ~foo => /home/foo +                $pos = strpos($strPathname, "/"); +                $name = substr($strPathname, 1, $pos - 2); +                $strPathname = "/home/" . $name . substr($strPathname, $pos); +            } +        } + +        $n = strlen($strPathname); +        $prevChar = 0; +        for ($i=0; $i < $n; $i++) { +            $c = $strPathname{$i}; +            if (($prevChar === '/') && ($c === '/')) { +                return self::normalizer($strPathname, $n, $i - 1); +            } +            $prevChar = $c; +        } +        if ($prevChar === '/') { +            return self::normalizer($strPathname, $n, $n - 1); +        } +        return $strPathname; +    } + +    /** +     * Normalize the given pathname, whose length is $len, starting at the given +     * $offset; everything before this offset is already normal. +     */ +    protected function normalizer($pathname, $len, $offset) { +        if ($len === 0) { +            return $pathname; +        } +        $n = (int) $len; +        while (($n > 0) && ($pathname{$n-1} === '/')) { +            $n--; +        } +        if ($n === 0) { +            return '/'; +        } +        $sb = ""; + +        if ($offset > 0) { +            $sb .= substr($pathname, 0, $offset); +        } +        $prevChar = 0; +        for ($i = $offset; $i < $n; $i++) { +            $c = $pathname{$i}; +            if (($prevChar === '/') && ($c === '/')) { +                continue; +            } +            $sb .= $c; +            $prevChar = $c; +        } +        return $sb; +    } + +    /** +     * Compute the length of the pathname string's prefix.  The pathname +     * string must be in normal form. +     */ +    function prefixLength($pathname) { +        if (strlen($pathname === 0)) { +            return 0; +        } +        return (($pathname{0} === '/') ? 1 : 0); +    } + +    /** +     * Resolve the child pathname string against the parent. +     * Both strings must be in normal form, and the result +     * will be in normal form. +     */ +    function resolve($parent, $child) { + +        if ($child === "") { +            return $parent; +        } + +        if ($child{0} === '/') { +            if ($parent === '/') { +                return $child; +            } +            return $parent.$child; +        } + +        if ($parent === '/') { +            return $parent.$child; +        } + +        return $parent.'/'.$child; +    } + +    function getDefaultParent() { +        return '/'; +    } + +    function isAbsolute(PhingFile $f) { +        return ($f->getPrefixLength() !== 0); +    } + +    /** +     * the file resolver +     */ +    function resolveFile(PhingFile $f) { +        // resolve if parent is a file oject only +        if ($this->isAbsolute($f)) { +            return $f->getPath(); +        } else { +            return $this->resolve(Phing::getProperty("user.dir"), $f->getPath()); +        }        +    } + +    /* -- most of the following is mapped to the php natives wrapped by FileSystem */     + +    /* -- Attribute accessors -- */ +    function getBooleanAttributes(&$f) { +        //$rv = getBooleanAttributes0($f); +        $name = $f->getName(); +        $hidden = (strlen($name) > 0) && ($name{0} == '.'); +        return ($hidden ? $this->BA_HIDDEN : 0); +    } + +    /** +     * set file readonly on unix +     */ +    function setReadOnly($f) { +        if ($f instanceof File) { +            $strPath = (string) $f->getPath(); +            $perms = (int) (@fileperms($strPath) & 0444); +            return FileSystem::Chmod($strPath, $perms); +        } else { +            throw new Exception("IllegalArgutmentType: Argument is not File"); +        } +    } + +    /** +     * compares file paths lexicographically +     */ +    function compare($f1, $f2) { +        if ( ($f1 instanceof PhingFile) && ($f2 instanceof PhingFile) ) { +            $f1Path = $f1->getPath(); +            $f2Path = $f2->getPath(); +            return (boolean) strcmp((string) $f1Path, (string) $f2Path); +        } else { +            throw new Exception("IllegalArgutmentType: Argument is not PhingFile"); +        } +    } + +    /* -- fs interface --*/ + +    function listRoots() { +        if (!$this->checkAccess('/', false)) { +            die ("Can not access root"); +        } +        return array(new PhingFile("/")); +    } + +    /** +     * returns the contents of a directory in an array +     */ +    function lister($f) { +        $dir = @opendir($f->getAbsolutePath()); +        if (!$dir) { +            throw new Exception("Can't open directory " . $f->__toString()); +        } +        $vv = array(); +        while (($file = @readdir($dir)) !== false) { +            if ($file == "." || $file == "..") { +                continue; +            } +            $vv[] = (string) $file; +        } +        @closedir($dir); +        return $vv; +    } + +    function fromURIPath($p) { +        if (StringHelper::endsWith("/", $p) && (strlen($p) > 1)) { + +            // "/foo/" --> "/foo", but "/" --> "/"             +            $p = substr($p, 0, strlen($p) - 1); + +        } + +        return $p; +    } +     +} diff --git a/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php b/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php new file mode 100644 index 00000000..c32c21ff --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/Win32FileSystem.php @@ -0,0 +1,477 @@ +<?php +/* + *  $Id: Win32FileSystem.php,v 1.10 2005/05/26 13:10:52 mrook Exp $ + * + * 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>.  + */ + +include_once 'phing/system/io/FileSystem.php'; + +/** + *  @package   phing.system.io + */ +class Win32FileSystem extends FileSystem { + +    protected $slash; +    protected $altSlash; +    protected $semicolon; + +    private static $driveDirCache = array(); + +    function __construct() { +        $this->slash = self::getSeparator(); +        $this->semicolon = self::getPathSeparator(); +        $this->altSlash = ($this->slash === '\\') ? '/' : '\\'; +    } + +    function isSlash($c) { +        return ($c == '\\') || ($c == '/'); +    } + +    function isLetter($c) { +        return ((ord($c) >= ord('a')) && (ord($c) <= ord('z'))) +               || ((ord($c) >= ord('A')) && (ord($c) <= ord('Z'))); +    } + +    function slashify($p) { +        if ((strlen($p) > 0) && ($p{0} != $this->slash)) { +            return $this->slash.$p; +        } +        else { +            return $p; +        } +    } + +    /* -- Normalization and construction -- */ + +    function getSeparator() { +        // the ascii value of is the \ +        return chr(92); +    } + +    function getPathSeparator() { +        return ';'; +    } + +    /** +     * A normal Win32 pathname contains no duplicate slashes, except possibly +     * for a UNC prefix, and does not end with a slash.  It may be the empty +     * string.  Normalized Win32 pathnames have the convenient property that +     * the length of the prefix almost uniquely identifies the type of the path +     * and whether it is absolute or relative: +     * +     *    0  relative to both drive and directory +     *    1  drive-relative (begins with '\\') +     *    2  absolute UNC (if first char is '\\'), else directory-relative (has form "z:foo") +     *    3  absolute local pathname (begins with "z:\\") +     */ +    function normalizePrefix($strPath, $len, $sb) { +        $src = 0; +        while (($src < $len) && $this->isSlash($strPath{$src})) { +            $src++; +        } +        $c = ""; +        if (($len - $src >= 2) +                && $this->isLetter($c = $strPath{$src}) +                && $strPath{$src + 1} === ':') { +            /* Remove leading slashes if followed by drive specifier. +             * This hack is necessary to support file URLs containing drive +             * specifiers (e.g., "file://c:/path").  As a side effect, +             * "/c:/path" can be used as an alternative to "c:/path". */ +            $sb .= $c; +            $sb .= ':'; +            $src += 2; +        } +        else { +            $src = 0; +            if (($len >= 2) +                    && $this->isSlash($strPath{0}) +                    && $this->isSlash($strPath{1})) { +                /* UNC pathname: Retain first slash; leave src pointed at +                 * second slash so that further slashes will be collapsed +                 * into the second slash.  The result will be a pathname +                 * beginning with "\\\\" followed (most likely) by a host +                 * name. */ +                $src = 1; +                $sb.=$this->slash; +            } +        } +        return $src; +    } + +    /** Normalize the given pathname, whose length is len, starting at the given +       offset; everything before this offset is already normal. */ +    protected function normalizer($strPath, $len, $offset) { +        if ($len == 0) { +            return $strPath; +        } +        if ($offset < 3) { +            $offset = 0;    //Avoid fencepost cases with UNC pathnames +        } +        $src = 0; +        $slash = $this->slash; +        $sb = ""; + +        if ($offset == 0) { +            // Complete normalization, including prefix +            $src = $this->normalizePrefix($strPath, $len, $sb); +        } else { +            // Partial normalization +            $src = $offset; +            $sb .= substr($strPath, 0, $offset); +        } + +        // Remove redundant slashes from the remainder of the path, forcing all +        // slashes into the preferred slash +        while ($src < $len) { +            $c = $strPath{$src++}; +            if ($this->isSlash($c)) { +                while (($src < $len) && $this->isSlash($strPath{$src})) { +                    $src++; +                } +                if ($src === $len) { +                    /* Check for trailing separator */ +                    $sn = (int) strlen($sb); +                    if (($sn == 2) && ($sb{1} === ':')) { +                        // "z:\\" +                        $sb .= $slash; +                        break; +                    } +                    if ($sn === 0) { +                        // "\\" +                        $sb .= $slash; +                        break; +                    } +                    if (($sn === 1) && ($this->isSlash($sb{0}))) { +                        /* "\\\\" is not collapsed to "\\" because "\\\\" marks +                        the beginning of a UNC pathname.  Even though it is +                        not, by itself, a valid UNC pathname, we leave it as +                        is in order to be consistent with the win32 APIs, +                        which treat this case as an invalid UNC pathname +                        rather than as an alias for the root directory of +                        the current drive. */ +                        $sb .= $slash; +                        break; +                    } +                    // Path does not denote a root directory, so do not append +                    // trailing slash +                    break; +                } else { +                    $sb .= $slash; +                } +            } else { +                $sb.=$c; +            } +        } +        $rv = (string) $sb; +        return $rv; +    } + +    /** +     * Check that the given pathname is normal.  If not, invoke the real +     * normalizer on the part of the pathname that requires normalization. +     * This way we iterate through the whole pathname string only once. +     * @param string $strPath +     * @return string +     */ +    function normalize($strPath) { +        $n = strlen($strPath); +        $slash    = $this->slash; +        $altSlash = $this->altSlash; +        $prev = 0; +        for ($i = 0; $i < $n; $i++) { +            $c = $strPath{$i}; +            if ($c === $altSlash) { +                return $this->normalizer($strPath, $n, ($prev === $slash) ? $i - 1 : $i); +            } +            if (($c === $slash) && ($prev === $slash) && ($i > 1)) { +                return $this->normalizer($strPath, $n, $i - 1); +            } +            if (($c === ':') && ($i > 1)) { +                return $this->normalizer($strPath, $n, 0); +            } +            $prev = $c; +        } +        if ($prev === $slash) { +            return $this->normalizer($strPath, $n, $n - 1); +        } +        return $strPath; +    } + +    function prefixLength($strPath) { +        $path  = (string) $strPath; +        $slash = (string) $this->slash; +        $n = (int) strlen($path); +        if ($n === 0) { +            return 0; +        } +        $c0 = $path{0}; +        $c1 = ($n > 1) ? $path{1} : +              0; +        if ($c0 === $slash) { +            if ($c1 === $slash) { +                return 2;            // absolute UNC pathname "\\\\foo" +            } +            return 1;                // drive-relative "\\foo" +        } + +        if ($this->isLetter($c0) && ($c1 === ':')) { +            if (($n > 2) && ($path{2}) === $slash) { +                return 3;            // Absolute local pathname "z:\\foo" */ +            } +            return 2;                // Directory-relative "z:foo" +        } +        return 0;                    // Completely relative +    } + +    function resolve($parent, $child) { +        $parent = (string) $parent; +        $child  = (string) $child; +        $slash  = (string) $this->slash; + +        $pn = (int) strlen($parent); +        if ($pn === 0) { +            return $child; +        } +        $cn = (int) strlen($child); +        if ($cn === 0) { +            return $parent; +        } + +        $c = $child; +        if (($cn > 1) && ($c{0} === $slash)) { +            if ($c{1} === $slash) { +                // drop prefix when child is a UNC pathname +                $c = substr($c, 2); +            } +            else { +                //Drop prefix when child is drive-relative */ +                $c = substr($c, 1); +            } +        } + +        $p = $parent; +        if ($p{$pn - 1} === $slash) { +            $p = substr($p, 0, $pn - 1); +        } +        return $p.$this->slashify($c); +    } + +    function getDefaultParent() { +        return (string) ("".$this->slash); +    } + +    function fromURIPath($strPath) { +        $p = (string) $strPath; +        if ((strlen($p) > 2) && ($p{2} === ':')) { + +            // "/c:/foo" --> "c:/foo" +            $p = substr($p,1); + +            // "c:/foo/" --> "c:/foo", but "c:/" --> "c:/" +            if ((strlen($p) > 3) && StringHelper::endsWith('/', $p)) { +                $p = substr($p, 0, strlen($p) - 1); +            } +        } elseif ((strlen($p) > 1) && StringHelper::endsWith('/', $p)) { +            // "/foo/" --> "/foo" +            $p = substr($p, 0, strlen($p) - 1); +        } +        return (string) $p; +    } + + +    /* -- Path operations -- */ + +    function isAbsolute(PhingFile $f) { +        $pl = (int) $f->getPrefixLength(); +        $p  = (string) $f->getPath(); +        return ((($pl === 2) && ($p{0} === $this->slash)) || ($pl === 3) || ($pl === 1 && $p{0} === $this->slash)); +    } + +    /** private */ +    function _driveIndex($d) { +        $d = (string) $d{0}; +        if ((ord($d) >= ord('a')) && (ord($d) <= ord('z'))) { +            return ord($d) - ord('a'); +        } +        if ((ord($d) >= ord('A')) && (ord($d) <= ord('Z'))) { +            return ord($d) - ord('A'); +        } +        return -1; +    } + +    /** private */ +    function _getDriveDirectory($drive) { +        $drive = (string) $drive{0}; +        $i = (int) $this->_driveIndex($drive); +        if ($i < 0) { +            return null; +        } + +        $s = (isset(self::$driveDirCache[$i]) ? self::$driveDirCache[$i] : null); + +        if ($s !== null) { +            return $s; +        } + +        $s = $this->_getDriveDirectory($i + 1); +        self::$driveDirCache[$i] = $s; +        return $s; +    } + +    function _getUserPath() { +        //For both compatibility and security, we must look this up every time +        return (string) $this->normalize(Phing::getProperty("user.dir")); +    } + +    function _getDrive($path) { +        $path = (string) $path; +        $pl   = $this->prefixLength($path); +        return ($pl === 3) ? substr($path, 0, 2) : null; +    } + +    function resolveFile(PhingFile $f) { +        $path = $f->getPath(); +        $pl   = (int) $f->getPrefixLength(); + +        if (($pl === 2) && ($path{0} === $this->slash)) { +            return path;            // UNC +        } + +        if ($pl === 3) { +            return $path;            // Absolute local +        } + +        if ($pl === 0) { +            return (string) ($this->_getUserPath().$this->slashify($path)); //Completely relative +        } + +        if ($pl === 1) {            // Drive-relative +            $up = (string) $this->_getUserPath(); +            $ud = (string) $this->_getDrive($up); +            if ($ud !== null) { +                return (string) $ud.$path; +            } +            return (string) $up.$path;            //User dir is a UNC path +        } + +        if ($pl === 2) {                // Directory-relative +            $up = (string) $this->_getUserPath(); +            $ud = (string) $this->_getDrive($up); +            if (($ud !== null) && StringHelper::startsWith($ud, $path)) { +                return (string) ($up . $this->slashify(substr($path,2))); +            } +            $drive = (string) $path{0}; +            $dir   = (string) $this->_getDriveDirectory($drive); + +            $np = (string) ""; +            if ($dir !== null) { +                /* When resolving a directory-relative path that refers to a +                drive other than the current drive, insist that the caller +                have read permission on the result */ +                $p = (string) $drive . (':'.$dir.$this->slashify(substr($path,2))); + +                if (!$this->checkAccess($p, false)) { +                    // FIXME +                    // throw security error +                    die("Can't resolve path $p"); +                } +                return $p; +            } +            return (string) $drive.':'.$this->slashify(substr($path,2)); //fake it +        } +         +        throw new Exception("Unresolvable path: " . $path); +    } + +    /* -- most of the following is mapped to the functions mapped th php natives in FileSystem */ + +    /* -- Attribute accessors -- */ + +    function setReadOnly($f) { +        // dunno how to do this on win +        throw new Exception("WIN32FileSystem doesn't support read-only yet."); +    } + +    /* -- Filesystem interface -- */ + +    protected function _access($path) { +        if (!$this->checkAccess($path, false)) { +            throw new Exception("Can't resolve path $p"); +        } +        return true; +    } + +    function _nativeListRoots() { +        // FIXME +    } + +    function listRoots() { +        $ds = _nativeListRoots(); +        $n = 0; +        for ($i = 0; $i < 26; $i++) { +            if ((($ds >> $i) & 1) !== 0) { +                if (!$this->access((string)( chr(ord('A') + $i) . ':' . $this->slash))) { +                    $ds &= ~(1 << $i); +                } else { +                    $n++; +                } +            } +        } +        $fs = array(); +        $j = (int) 0; +        $slash = (string) $this->slash; +        for ($i = 0; $i < 26; $i++) { +            if ((($ds >> $i) & 1) !== 0) { +                $fs[$j++] = new PhingFile(chr(ord('A') + $i) . ':' . $this->slash); +            } +        } +        return $fs; +    } + +    /* -- Basic infrastructure -- */ + +    /** compares file paths lexicographically */ +    function compare(PhingFile $f1, PhingFile $f2) { +        $f1Path = $f1->getPath(); +        $f2Path = $f2->getPath(); +        return (boolean) strcasecmp((string) $f1Path, (string) $f2Path);         +    } + + +    /** +     * returns the contents of a directory in an array +     */ +    function lister($f) { +        $dir = @opendir($f->getAbsolutePath()); +        if (!$dir) { +            throw new Exception("Can't open directory " . $f->__toString()); +        } +        $vv = array(); +        while (($file = @readdir($dir)) !== false) { +            if ($file == "." || $file == "..") { +                continue; +            } +            $vv[] = (string) $file; +        } +        @closedir($dir); +        return $vv; +    } + +} + +?> diff --git a/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php b/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php new file mode 100644 index 00000000..86f76d80 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/WinNTFileSystem.php @@ -0,0 +1,35 @@ +<?php +/* + *  $Id: WinNTFileSystem.php,v 1.3 2003/11/19 05:48:29 hlellelid Exp $ + * + * 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>.  + */ + +include_once 'phing/system/io/Win32FileSystem.php'; + +/** + * FileSystem for Windows NT/2000. + *  @package   phing.system.io + */ + +class WinNTFileSystem extends Win32FileSystem { + +    /* -- class only for convenience and future use everything is inherinted --*/ + + +} +?> diff --git a/buildscripts/phing/classes/phing/system/io/Writer.php b/buildscripts/phing/classes/phing/system/io/Writer.php new file mode 100644 index 00000000..5e1a69b9 --- /dev/null +++ b/buildscripts/phing/classes/phing/system/io/Writer.php @@ -0,0 +1,48 @@ +<?php +/* + *  $Id: Writer.php,v 1.6 2005/05/26 13:10:52 mrook Exp $ + * + * 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>.  + */ + +/** + * Abstract class for writing character streams.  + * @package   phing.system.io + */ +abstract class Writer { + +    abstract public function write($buf, $off = null, $len = null); + +    abstract public function reset(); +     +    abstract public function close(); +     +    abstract public function open(); + +    public function mark() {} +     +    public function ready() {} + +    public function markSupported() {} +     +    /** +     * Returns the filename, url, etc. that is being written to. +     * @return string +     */     +    abstract function getResource(); +} +?>  | 
