<?php
//
// +--------------------------------------------------------------------------+
// | |
// | XS PHP Library Generic Classes Library |
// | |
// | Copyright (c) 2001-2002 XSPHPLib Group. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Distributed under the terms of the GNU Lesser General Public License as |
// | published by the Free Software Foundation version 2.1 |
// | See the GNU Lesser General Public License for more details. You should |
// | have received a copy of the GNU Lesser General Public License along with |
// | this package; if not, write to the Free Software Foundation, Inc., |
// | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
// | |
// +--------------------------------------------------------------------------+
// | |
// | Authors: Robert Bala <hide@address.com> |
// | |
// +--------------------------------------------------------------------------+
//
// $Id: file.inc.php,v 1.2 2002/11/28 09:50:30 rbala Exp $
/**
* The sort order used during file sorting operations.
*
* This variable shouldn't be modified. It is used internally by
* {@link Dir::read()}, {@link Dir::readFiles()} methods.
*
* @global string $file_sortOrder
*
*/
$file_sortOrder = 'asc';
/**
* The sorting field used during file sorting operations.
*
* This variable shouldn't be modified. It is used internally by
* {@link Dir::read()}, {@link Dir::readFiles()} methods. Files can be sorted
* according to its names, size and modification date.
*
* @global string $file_sortField
*
*/
$file_sortField = 'name';
/**
* File manipulation class.
*
* File class is a wrapper used for basic file operations just like reading,
* writing, coping, etc.
*
* @author Robert Bala <hide@address.com>
* @access public
* @package io
* @version $Id: file.inc.php,v 1.2 2002/11/28 09:50:30 rbala Exp $
*/
class File extends Object {
/**
* Temporary file name when working with copy of the file.
* @access private
* @var string
*/
var $_temp;
/**
* Path to file or file name.
* @access private
* @var string
*/
var $_name;
/**
* File access mode.
* @access private
* @var string
*/
var $_mode;
/**
* File handle.
* @access private
* @var mixed
*/
var $_handle;
/**
* Indicates whether the file is locked or not.
* @access private
* @var boolean
*/
var $_locked;
/**
* Indicates whether works on orginal file or its copy.
* @access private
* @var boolean
*/
var $_backup;
/**
* Number of bytes to read and write at IO operations.
* @access private
* @var int
*/
var $_buffer;
/**
* File class constructor.
*
* Creates the new instance of File class and sets up basic properties.
*
* @access public
* @param string $name the path to file or file name, defaults to "".
* @param string $mode the access mode to file stream, defaults to "r".
* @param boolean $backup indicates whether works with orginal file or its copy.
* @param boolean $buffer the number of bytes to read and write at IO operations.
* @return void
*/
function File($name='', $mode='r', $backup=false, $buffer=1024) {
Object::Object();
$this->_temp = '';
$this->_name = $name;
$this->_mode = $mode;
$this->_handle = null;
$this->_locked = false;
$this->_backup = $backup;
$this->_buffer = $buffer;
}
/**
* Gets path to file or file name.
*
* Returns path to file or file name or empty string if it has not been set
* in object constructor.
*
* @access public
* @return string
*/
function getName() {
return $this->_name;
}
/**
* Gets the file access mode.
*
* Returns file access mode.
*
* @access public
* @return mixed
*/
function getMode() {
return $this->_mode;
}
/**
* Gets the file handle.
*
* Returns resource handle if the file is opened, null otherwise.
*
* @access public
* @return mixed
*/
function getHandle() {
return $this->_handle;
}
/**
* Gets the file buffer size.
*
* Returns number of bytes used at file IO operations.
*
* @access public
* @return int
*/
function getBuffer() {
return $this->_buffer;
}
/**
* Gets the size of the file in bytes.
*
* Returns the size of the file in bytes if the file exists, error object otherwise.
*
* @access public
* @return mixed
*/
function getSize() {
if (file_exists($this->_name)) {
return @filesize($this->_name);
}
return new Error('getsize(): File does not exists.');
}
/**
* Gets the user ID of the owner of the file.
*
* If called when the file does not exists it returns error object, otherwise
* it returns the user ID of the owner of the file in numerical format.
*
* @access public
* @return mixed
*/
function getOwner() {
if (file_exists($this->_name)) {
return @fileowner($this->_name);
}
return new Error('getowner(): File does not exists.');
}
/**
* Gets the group ID of the owner of the file.
*
* If called when the file does not exists it returns error object, otherwise
* it returns the group ID of the owner of the file in numerical format.
*
* @access public
* @return mixed
*/
function getGroup() {
if (file_exists($this->_name)) {
return @filegroup($this->_name);
}
return new Error('getgroup(): File does not exists.');
}
/**
* Gets the time the file was last accessed.
*
* If called when the file does not exists it returns error object, otherwise
* it returns the time the file was last accessed. The time is returned as
* a Unix timestamp.
*
* @access public
* @return int
*/
function getATime() {
if (file_exists($this->_name)) {
return @fileatime($this->_name);
}
return new Error('getatime(): File does not exists.');
}
/**
* Gets the time the file was last changed.
*
* If called when the file does not exists it returns error object, otherwise
* it returns the time the file was last changed. The time is returned as
* a Unix timestamp.
*
* @access public
* @return int
*/
function getCTime() {
if (file_exists($this->_name)) {
return @filectime($this->_name);
}
return new Error('getctime(): File does not exists.');
}
/**
* Gets the time the file was last modified.
*
* If called when the file does not exists it returns error object, otherwise
* it returns the time the file was last modified. The time is returned as
* a Unix timestamp.
*
* @access public
* @return int
*/
function getMTime() {
if (file_exists($this->_name)) {
return @filemtime($this->_name);
}
return new Error('getmtime(): File does not exists.');
}
/**
* Sets the file access mode.
*
* The mode specifies the type of access you require to the file stream.
* If called when the file is opened, it returns error object otherwise it
* returns true on success.
*
* @access public
* @return mixed
*/
function setMode($mode) {
if (strlen($mode)) {
if (empty($this->_handle)) {
$this->_mode = $mode;
} else {
return new Error('setmode(): File is already opened.');
}
} else {
return new Error('setmode(): File mode is not specified.');
}
return true;
}
/**
* Sets the file buffer size.
*
* Returns true on success or a error object if the buffer size is not a
* valid integer value.
*
* @access public
* @return mixed
*/
function setBuffer($buffer) {
if (is_integer($buffer)) {
$this->_buffer = $buffer;
} else {
return new Error('setbuffer(): Invalid file buffer size.');
}
return true;
}
/**
* Attempts to copy the file.
*
* Returns true on success or error object with an error message on any
* kind of failure. File is copied to specified destination and access
* permissions are changed according to the mode param. Note that mode is
* not automatically assumed to be an octal value. To ensure the expected
* operation, you need to prefix mode with a zero (0):
*
* @access public
* @param string $destination the new file name.
* @param int $mode the access permissions, defaults to 0644.
* @return mixed
*/
function copy($destination, $mode=0644) {
if (strlen($destination)) {
if (file_exists($this->_name) && is_file($this->_name)) {
if (!@copy($this->_name, $destination)) {
return new Error('copy(): File could not be copied.');
}
if (!@chmod($destination, $mode)) {
return new Error('copy(): Could not change file mode.');
}
} else {
return new Error('copy(): File is not regular file or does not exists.');
}
} else {
return new Error('copy(): Specified file destination is empty.');
}
return true;
}
/**
* Attempts to change the mode of the file.
*
* Returns true on success or error object with an error message on any
* kind of failure. Note that mode is not automatically assumed to be an
* octal value. To ensure the expected operation, you need to prefix mode
* with a zero (0):
*
* @access public
* @param int $mode the access permissions, defaults to 0644.
* @return mixed
*/
function chmod($mode=0644) {
if (file_exists($this->_name) && is_file($this->_name)) {
if (!@chmod($this->_name, $mode)) {
return new Error('chmod(): Could not change file mode.');
}
} else {
return new Error('chmod(): File is not regular file or does not exists.');
}
return true;
}
/**
* Attempts to delete the file.
*
* If called when the file is already opened, it returns error object
* otherwise it returns true on success or error object with an error
* message on any kind of failure.
*
* @access public
* @param string $path the path where to create the subdirectory.
* @param int $mode the access permissions, defaults to 0755.
* @return mixed
*/
function delete() {
if (!is_resource($this->_handle)) {
if (file_exists($this->_name) && is_file($this->_name)) {
if (!@unlink($this->_name)) {
return new Error('delete(): File could not be deleted.');
}
} else {
return new Error('delete(): File is not regular file or does not exists.');
}
} else {
return new Error('delete(): File is already opened.');
}
return true;
}
/**
* Checks whether a file exists.
*
* Returns true if the file exists, false otherwise.
*
* @access public
* @return boolean
*/
function exists() {
return (file_exists($this->_name) && is_file($this->_name));
}
/**
* Attempts to rename the file.
*
* Returns true on success or error object with an error message on any
* kind of failure.
*
* @access public
* @param string $name the new file name.
* @return mixed
*/
function rename($name) {
if (strlen($name)) {
if (file_exists($this->_name) && is_file($this->_name)) {
$name = dirname($this->_name) . '/' . $name;
if (@rename($this->_name, $name)) {
$this->_name = $name;
} else {
return new Error('rename(): File could not be renamed.');
}
} else {
return new Error('rename(): File is not regular file or does not exists.');
}
} else {
return new Error('rename(): File name is empty.');
}
return true;
}
/**
* Opens the file.
*
* If called when the the file is already opened, it returns error
* object otherwise it will try to open a file stream and returns true.
* The file must be accessible to PHP, so you need to ensure that the file
* access permissions allow this access. Type of access to the stream is
* controled by the mode property.
*
* @access public
* @return mixed
*/
function open() {
if (!is_resource($this->_handle)) {
if (!$this->_backup) {
$this->_handle = @fopen($this->_name, $this->_mode);
} else {
$this->_temp = tempnam('', 'php');
if (file_exists($this->_name)) {
@copy($this->_name, $this->_temp);
}
$this->_handle = @fopen($this->_temp, $this->_mode);
}
if (empty($this->_handle)) {
if (file_exists($this->_temp)) {
unlink($this->_temp);
}
return new Error('open(): File could not be opened.');
}
} else {
return new Error('open(): File is already opened.');
}
return true;
}
/**
* Closes the file.
*
* If called when the file is closed or it couldn't be closed,
* it returns error object, otherwise it returns true.
*
* @access public
* @return mixed
*/
function close() {
if (is_resource($this->_handle)) {
if (@fclose($this->_handle)) {
$this->_handle = null;
$this->_locked = false;
if ($this->_backup) {
if (!@copy($this->_temp, $this->_name)) {
return new Error('close(): Could not update file.');
}
unlink($this->_temp);
}
} else {
return new Error('close(): File could not be closed.');
}
} else {
return new Error('close(): File has not been opened.');
}
return true;
}
/**
* Attempts to lock access to the file.
*
* Returns true on success or error object with an error message on any
* kind of failure.
*
* @access public
* @return mixed
*/
function lock() {
if (is_resource($this->_handle)) {
if (@flock($this->_handle, LOCK_EX)) {
$this->_locked = true;
} else {
return new Error('lock(): File could not be locked.');
}
} else {
return new Error('lock(): File has not been opened.');
}
return true;
}
/**
* Attempts to unlock access to the file.
*
* Returns true on success or error object with an error message on any
* kind of failure.
*
* @access public
* @return mixed
*/
function unlock() {
if (is_resource($this->_handle)) {
if (@flock($this->_handle, LOCK_UN)) {
$this->_locked = false;
} else {
return new Error('unlock(): File could not be unlocked.');
}
} else {
return new Error('unlock(): File has not been opened.');
}
return true;
}
/**
* Read data from a file.
*
* Reads up to the file buffer size from the opened file. Reading stops when
* the file buffer size have been read or end-of-file reached, whichever
* comes first. If called when the file is closed, it returns error object
* otherwise it returns fread() result.
*
* @access public
* @return mixed
*/
function read() {
if (is_resource($this->_handle)) {
if (is_readable($this->_name)) {
$result = @fread($this->_handle, @filesize($this->_name));
} else {
return new Error('read(): Could not read from file.');
}
} else {
return new Error('read(): File has not been opened.');
}
return $result;
}
/**
* Write data to a file.
*
* Write data to a file. Writing will stop after file buffer
* length bytes have been written or the end of string is reached, whichever
* comes first. If called when the file is closed, it returns error object
* otherwise it returns fwrite() result.
*
* @access public
* @param string $string the data to write.
* @return mixed
*/
function write($string) {
if (is_resource($this->_handle)) {
if (is_writable($this->_name)) {
$result = @fwrite($this->_handle, $string);
} else {
return new Error('write(): Could not write to file.');
}
} else {
return new Error('write(): File has not been opened.');
}
return $result;
}
/**
* Read a line of data from a file.
*
* Read until either the end of the file or a newline, whichever comes
* first. If called when the file is closed, it returns error object
* otherwise it returns all available data up to a newline, without
* that newline, or until the end of the file as string.
*
* @access public
* @return mixed
*/
function readLine() {
if (is_resource($this->_handle)) {
if (is_readable($this->_name)) {
$result = '';
while (!feof($this->_handle)) {
$result .= fgets($this->_handle, $this->_buffer);
if (ereg("\r\n|\n", $result)) {
$result = ereg_replace("\r\n|\n", "", $result);
break;
}
}
} else {
return new Error('readline(): Could not read from file.');
}
} else {
return new Error('readline(): File has not been opened.');
}
return $result;
}
/**
* Write a line of data to a file.
*
* Write a line of data to the opened file, followed by a trailing "\r\n".
* If called when the file is closed, it returns error object
* otherwise it returns fputs result.
*
* @access public
* @param string $string the data to write.
* @return mixed
*/
function writeLine($string) {
if (is_resource($this->_handle)) {
if (is_writable($this->_name)) {
$result = fputs($this->_handle, $string . "\r\n");
} else {
return new Error('writeline(): Could not write to file.');
}
} else {
return new Error('writeline(): File has not been opened.');
}
return $result;
}
/**
* Read buffer from a file.
*
* Reads up to the specified buffer size from the opened file. Reading
* stops when the specified buffer size have been read or end-of-stream
* reached, whichever comes first. If called when the file is closed,
* it returns error object otherwise it returns fread() result.
*
* @access public
* @param string $buffer the data to read.
* @param int $length the buffer length, defaults to 0.
* @return mixed
*/
function readBuffer(&$buffer, $length=0) {
if (is_resource($this->_handle)) {
if (is_readable($this->_name)) {
$buffer = '';
if ($length > 0) {
$buffer = @fread($this->_handle, $length);
} else {
$buffer = @fread($this->_handle, $this->_buffer);
}
$result = strlen($buffer);
} else {
return new Error('readbuffer(): Could not read from file.');
}
} else {
return new Error('readbuffer(): File has not been opened.');
}
return $result;
}
/**
* Write buffer to a file.
*
* Write data to a opened file. Writing will stop after specified buffer
* length bytes have been written or the end of string is reached, whichever
* comes first. If called when the file is closed, it returns error object
* otherwise it returns fwrite() result.
*
* @access public
* @param string $buffer the data to write.
* @param int $length the buffer length, defaults to 0.
* @return mixed
*/
function writeBuffer(&$buffer, $length=0) {
if (is_resource($this->_handle)) {
if (is_writable($this->_name)) {
if ($length > 0) {
$result = @fwrite($this->_handle, $buffer, $length);
} else {
$result = @fwrite($this->_handle, $buffer, $this->_buffer);
}
} else {
return new Error('writebuffer(): Could not write to file.');
}
} else {
return new Error('writebuffer(): File has not been opened.');
}
return $result;
}
/**
* Finds whether the file is at end-of-file or closed.
*
* Returns true if the file is closed or the file is at end-of-file,
* false otherwise.
*
* @access public
* @return boolean
*/
function isEof() {
return is_null($this->_handle) || feof($this->_handle);
}
/**
* Finds whether the file is a symbolic link.
*
* Returns true if the file exists and is a symbolic link, false otherwise.
*
* @access public
* @return boolean
*/
function isLink() {
return is_link($this->_name);
}
/**
* Finds whether the file is locked.
*
* Returns true if the file is locked, false otherwise.
*
* @access public
* @return boolean
*/
function isLocked() {
return $this->_locked;
}
/**
* Finds whether the file is opened.
*
* Returns true if the file is opened, false otherwise.
*
* @access public
* @return boolean
*/
function isOpened() {
return is_resource($this->_handle);
}
/**
* Finds whether the file was uploaded via HTTP POST.
*
* Returns true if the file was uploaded via HTTP POST, false otherwise.
*
* @access public
* @return boolean
*/
function isUploaded() {
return is_uploaded_file($this->_name);
}
/**
* Finds whether the file is readable.
*
* Returns true if the file exists and is readable, false otherwise.
*
* @access public
* @return boolean
*/
function isReadable() {
return is_readable($this->_name);
}
/**
* Finds whether the file is writeable.
*
* Returns true if the file exists and is writeable, false otherwise.
*
* @access public
* @return boolean
*/
function isWriteable() {
return is_writeable($this->_name);
}
/**
* Finds whether the file is executable.
*
* Returns true if the file exists and is executable, false otherwise.
*
* @access public
* @return boolean
*/
function isExecutable() {
return is_executable($this->_name);
}
}
/**
* Performs files comparison.
*
* This function is used internally by {@link Dir::read()},
* {@link Dir::readFiles()} methods and it shouldn't be
* used outside these methods. Returns < 0 if $obj1->_root is less than
* $obj2->_root; > 0 if $obj1->_root is greater than $obj2->_root, and 0 if
* they are equal.
*
* @author Robert Bala <hide@address.com>
* @access private
* @param string $obj1 the File object.
* @param string $obj2 the File object.
* @return int
*/
function file_cmp($obj1, $obj2) {
global $file_sortOrder;
global $file_sortField;
switch($file_sortField) {
case 'name':
$field = 'getName';
break;
case 'size':
$field = 'getSize';
break;
case 'date':
$field = 'getMTime';
break;
}
$str1 = strtolower($obj1->$field());
$str2 = strtolower($obj2->$field());
if ($str1 == $str2) {
return 0;
}
if ($file_sortOrder != 'dsc') {
if ($str1 < $str2) {
return -1;
} else {
return 1;
}
} else {
if ($str1 > $str2) {
return -1;
} else {
return 1;
}
}
}
/**
* Retrieves the file MIME media type and sub type.
*
* Returns the array containing MIME media type and sub type according to file
* extension.
*
* @author Robert Bala <hide@address.com>
* @access public
* @param string $filename the file name.
* @return array
*/
function file_getMime($filename) {
$extension = strrchr($filename, '.');
switch (strtolower($extension)) {
case '.avi':
$result['mtype'] = 'video';
$result['stype'] = 'x-msvideo';
break;
case '.bmp':
$result['mtype'] = 'image';
$result['stype'] = 'bmp';
break;
case '.gif' :
$result['mtype'] = 'image';
$result['stype'] = 'gif';
break;
case '.jpg' :
$result['mtype'] = 'image';
$result['stype'] = 'gif';
break;
case '.jpeg':
$result['mtype'] = 'image';
$result['stype'] = 'jpeg';
break;
case '.js':
$result['mtype'] = 'application';
$result['stype'] = 'x-javascript';
break;
case '.doc':
$result['mtype'] = 'application';
$result['stype'] = 'msword';
break;
case '.pl':
$result['mtype'] = 'text';
$result['stype'] = 'plain';
break;
case '.css':
$result['mtype'] = 'text';
$result['stype'] = 'css';
break;
case '.htm':
$result['mtype'] = 'text';
$result['stype'] = 'html';
break;
case '.html':
$result['mtype'] = 'text';
$result['stype'] = 'html';
break;
case '.mid':
$result['mtype'] = 'audio';
$result['stype'] = 'midi';
break;
case '.mov':
$result['mtype'] = 'video';
$result['stype'] = 'quicktime';
break;
case '.mp3':
$result['mtype'] = 'audio';
$result['stype'] = 'mpeg';
break;
case '.mpeg':
$result['mtype'] = 'video';
$result['stype'] = 'mpeg';
break;
case '.mpg':
$result['mtype'] = 'video';
$result['stype'] = 'mpeg';
break;
case '.php':
$result['mtype'] = 'application';
$result['stype'] = 'x-httpd-php';
break;
case '.php3':
$result['mtype'] = 'application';
$result['stype'] = 'x-httpd-php';
break;
case '.phps':
$result['mtype'] = 'application';
$result['stype'] = 'x-httpd-php-source';
break;
case '.pdf':
$result['mtype'] = 'application';
$result['stype'] = 'pdf';
break;
case '.txt':
$result['mtype'] = 'text';
$result['stype'] = 'plain';
break;
case '.wav':
$result['mtype'] = 'audio';
$result['stype'] = 'x-wav';
break;
case '.ram':
$result['mtype'] = 'audio';
$result['stype'] = 'x-pn-realaudio';
break;
case '.zip':
$result['mtype'] = 'application';
$result['stype'] = 'zip';
break;
case '.tar':
$result['mtype'] = 'application';
$result['stype'] = 'x-tar';
break;
case '.gz':
$result['mtype'] = 'application';
$result['stype'] = 'x-gzip';
break;
case '.tgz':
$result['mtype'] = 'application';
$result['stype'] = 'x-tar';
break;
default:
$result['mtype'] = 'application';
$result['stype'] = 'octetstream';
}
return $result;
}
/**
* Syntax highlighting of a file.
*
* Returns a syntax higlighted version of the code contained in file using the
* colors defined in the built-in syntax highlighter for PHP. If the file could
* not be readed the empty string is returned.
*
* @author Robert Bala <hide@address.com>
* @access public
* @param string $filename the file name.
* @return string
*/
function file_highlight($filename) {
$opened = is_integer(ob_get_length());
if ($opened == true) {
ob_end_clean();
}
ob_start();
if (highlight_file($filename)) {
$result = ob_get_contents();
ob_end_clean();
if ($opened) {
ob_start();
}
return $result;
}
if ($opened == false) {
ob_end_clean();
}
return '';
}
?>