Commit 223f06fc authored by Nigel McNie's avatar Nigel McNie Committed by Nigel McNie
Browse files

Added PEAR and File_CSV, used for the CSV uploader.

parent 3ad3e8a0
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Richard Heyes <richard@php.net> |
// | Tal Peer <tal@php.net> |
// +----------------------------------------------------------------------+
/*
* Example 1:
* $stdin = File::readAll('php://stdin');
*
* Example 2:
* while ($data = File::read('/blaat/bar')) {
* // Code...
* }
*/
require_once('PEAR.php');
/**
* The default number of bytes for reading
* @const FILE_DEFAULT_READSIZE
*/
define('FILE_DEFAULT_READSIZE', 1024, true);
/**
* Mode to use for reading from files
* @const FILE_MODE_READ
*/
define('FILE_MODE_READ', 'rb', true);
/**
* Mode to use for truncating files, then writing
* @const FILE_MODE_WRITE
*/
define('FILE_MODE_WRITE', 'wb', true);
/**
* Mode to use for appending to files
* @const FILE_MODE_APPEND
*/
define('FILE_MODE_APPEND', 'ab', true);
/**
* Use this when a shared (read) lock is required
* @const FILE_LOCK_SHARED
*/
define('FILE_LOCK_SHARED', LOCK_SH, true);
/**
* Use this when an exclusive (write) lock is required
* @const FILE_LOCK_EXCLUSIVE
*/
define('FILE_LOCK_EXCLUSIVE', LOCK_EX, true);
/**
* Class for handling files
*
* A class with common functions for writing,
* reading and handling files and directories
*
*
* @author Richard Heyes <richard@php.net>
* @author Tal Peer <tal@php.net>
* @access public
* @version 0.9
* @package File
*/
class File extends PEAR
{
/**
* Destructor
*
* Unlocks any locked file pointers and closes all filepointers
* @access private
*/
function _File()
{
$locks = &PEAR::getStaticProperty('File', 'locks');
$filePointers = &PEAR::getStaticProperty('File', 'filePointers');
for ($i = 0; $i < count($locks); $i++) {
flock($this->locks[$i], LOCK_UN);
}
if (!empty($filePointers)) {
foreach ($filePointers as $fname => $value) {
foreach ($value as $mode => $value) {
@fclose($filePointers[$fname][$mode]);
}
}
}
}
/**
* Handles file pointers. If a file pointer needs to be opened,
* it will be. If it already exists (based on filename and mode)
* then the existing one will be returned.
*
* @access private
* @param string $filename Filename to be used
* @param string $mode Mode to open the file in
* @param mixed $lock Type of lock to use
* @return mixed PEAR_Error on error and file pointer resource on success
*/
function &_getFilePointer($filename, $mode, $lock = false)
{
$filePointers = &PEAR::getStaticProperty('File', 'filePointers');
// Need to open first...
if (!isset($filePointers[$filename][$mode]) OR !is_resource($filePointers[$filename][$mode])) {
// Check it exists
if (FILE_MODE_READ == $mode AND !preg_match('/^(http|https|ftp|php):\/\//i', $filename) AND !file_exists($filename)) {
return PEAR::raiseError('File does not exist: ' . $filename);
// Writeable?
} elseif ( (FILE_MODE_WRITE == $mode OR FILE_MODE_APPEND == $mode)
AND !file_exists($filename)
AND !is_writeable(dirname($filename))) {
return PEAR::raiseError('Could not create file: ' . $filename);
} elseif ( (FILE_MODE_WRITE == $mode OR FILE_MODE_APPEND == $mode)
AND !is_writeable(dirname($filename))) {
return PEAR::raiseError('File is not writeable: ' . $filename);
}
$filePointers[$filename][$mode] = @fopen($filename, $mode);
if (false === $filePointers[$filename][$mode]) {
return PEAR::raiseError('Failed to open file: ' . $filename);
}
}
// Lock it?
if ($lock) {
$locks = &PEAR::getStaticProperty('File', 'locks');
if (flock($filePointers[$filename][$mode], $lock)) {
$this->locks[] = &$filePointers[$filename][$mode];
}
}
return $filePointers[$filename][$mode];
}
/**
* Reads an entire file and returns it.
*
* @access public
* @param string $filename Name of file to read from
* @param mixed $lock Type of lock to use
* @return mixed PEAR_Error if an error has occured or a string with the contents of the the file
*/
function readAll($filename, $lock = false)
{
$file = '';
while (($tmp = File::read($filename, FILE_DEFAULT_READSIZE, $lock)) !== FALSE) {
if (PEAR::isError($tmp)) {
return $tmp;
}
$file .= $tmp;
}
return $file;
}
/**
* Returns a specified number of bytes of a file. Defaults to 1024.
*
* @access public
* @param string $filename Name of file to read from
* @param integer $size Bytes to read
* @param mixed $lock Type of lock to use
* @return mixed PEAR_Error on error or a string which contains the data read
* Will also return false upon EOF
*/
function read($filename, $size = FILE_DEFAULT_READSIZE, $lock = false)
{
static $filePointers; // Used to prevent unnecessary calls to _getFilePointer()
if (0 == $size) {
return File::readAll($filename);
}
if (!isset($filePointers[$filename]) OR !is_resource($filePointers[$filename])) {
if (PEAR::isError($fp = &File::_getFilePointer($filename, FILE_MODE_READ, $lock))) {
return $fp;
}
$filePointers[$filename] = &$fp;
} else {
$fp = &$filePointers[$filename];
}
return !feof($fp) ? fread($fp, $size) : false;
}
/**
* Writes the given data to the given filename. Defaults to no lock, append mode.
*
* @access public
* @param string $filename Name of file to write to
* @param string $data Data to write to file
* @param string $mode Mode to open file in
* @param mixed $lock Type of lock to use
* @return mixed PEAR_Error on error or number of bytes written to file.
*/
function write($filename, $data, $mode = FILE_MODE_APPEND, $lock = false)
{
if (!PEAR::isError($fp = &File::_getFilePointer($filename, $mode, $lock))) {
if (($bytes = fwrite($fp, $data, strlen($data))) == -1) {
return PEAR::raiseError(sprintf('fwrite() call failed to write data: "%s" to file: "%s"', $data, $filename));
} else {
return $bytes;
}
}
return $fp;
}
/**
* Reads and returns a single character from given filename
*
* @access public
* @param string $filename Name of file to read from
* @param mixed $lock Type of lock to use
* @return mixed PEAR_Error on error or one character of the specified file
*/
function readChar($filename, $lock = false)
{
return File::read($filename, 1, $lock);
}
/**
* Writes a single character to a file
*
* @access public
* @param string $filename Name of file to write to
* @param string $char Character to write
* @param string $mode Mode to use when writing
* @param mixed $lock Type of lock to use
* @return mixed PEAR_Error on error, or 1 on success
*/
function writeChar($filename, $char, $mode = FILE_MODE_APPEND, $lock = false)
{
if (!PEAR::isError($fp = &File::_getFilePointer($filename, $mode, $lock))) {
if (fwrite($fp, $char, 1) == -1) {
return PEAR::raiseError(sprintf('fwrite() call failed to write data: "%s" to file: "%s"', $data, $filename));
} else {
return 1;
}
}
return $fp;
}
/**
* Returns a line of the file
*
* @access public
* @param string $filename Name of file to read from
* @param boolean $lock Type of lock to use
* @return mixed PEAR_Error on error or a string containing the line read from file
*/
function readLine($filename, $lock = false)
{
static $filePointers; // Used to prevent unnecessary calls to _getFilePointer()
if (!isset($filePointers[$filename]) OR !is_resource($filePointers[$filename])) {
if (PEAR::isError($fp = &File::_getFilePointer($filename, FILE_MODE_READ, $lock))) {
return $fp;
}
$filePointers[$filename] = &$fp;
} else {
$fp = &$filePointers[$filename];
}
if (feof($fp)) {
return false;
}
$fileString = '';
while (($fileChar = fgetc($fp)) != "\n" AND !feof($fp)) {
$fileString .= $fileChar;
}
return substr($fileString, -1) == "\r" ? substr($fileString, 0, -1) : $fileString;
}
/**
* Writes a single line, appending a LF (by default)
*
* @access public
* @param string $filename Name of file to write to
* @param string $line Line of data to be written to file
* @param string $mode Write mode, can be either FILE_MODE_WRITE or FILE_MODE_APPEND
* @param string $crlf The CRLF your system is using. UNIX = \n Windows = \r\n Mac = \r
* @param mixed $lock Type of lock to use
* @return mixed PEAR_Error on error or number of bytes written to file (including appended crlf)
*/
function writeLine($filename, $line, $mode = FILE_MODE_APPEND, $crlf = "\n", $lock = false)
{
if(!PEAR::isError($fp = &File::_getFilePointer($filename, $mode, $lock))){
if (($bytes = fwrite($fp, $line . $crlf)) == -1) {
return PEAR::raiseError(sprintf('fwrite() call failed to write data: "%s" to file: "%s"', $data, $filename));
} else {
return $bytes;
}
}
return $fp;
}
/**
* This rewinds a filepointer to the start of a file
*
* @access public
* @param string $filename The filename
* @param string $mode Mode the file was opened in
* @return mixed PEAR Error on error, true on success
*/
function rewind($filename, $mode)
{
if (!PEAR::isError($fp = &File::_getFilePointer($filename, $mode))) {
return rewind($fp) ? true : PEAR::raiseError('Failed to rewind file: ' . $filename);
}
return $fp;
}
/**
* This closes an open file pointer
*
* @access public
* @param string $filename The filename that was opened
* @param string $mode Mode the file was opened in
* @return mixed PEAR Error on error, true otherwise
*/
function close($filename, $mode)
{
if (!PEAR::isError($fp = &File::_getFilePointer($filename, $mode))) {
$filePointers = &PEAR::getStaticProperty('File', 'filePointers');
unset($filePointers[$filename][$mode]);
return fclose($fp) ? true : PEAR::raiseError('Failed to close file: ' . $filename);
}
return $fp;
}
/**
* This unlocks a locked file pointer.
*
* @access public
* @param string $filename The filename that was opened
* @param string $mode Mode the file was opened in
* @return mixed PEAR Error on error, true otherwise
*/
function unlock($filename, $mode)
{
if (!PEAR::isError($fp = &FILE::_getFilePointer($filename, $mode))) {
return flock($fp, LOCK_UN) ? true : PEAR::raiseError('Failed to unlock file: ' . $filename);
}
return $fp;
}
/**
* Returns a string path built from the array $pathParts. Where a join occurs
* multiple separators are removed. Joins using the optional separator, defaulting
* to the PHP DIRECTORY_SEPARATOR constant.
*
* @access public
* @param array $parts Array containing the parts to be joined
* @param string $separator The system directory seperator
*/
function buildPath($parts, $separator = DIRECTORY_SEPARATOR)
{
for ($i = 0; $i < count($parts); $i++) {
if (0 == $i) {
$parts[$i] = File::stripTrailingSeparators($parts[$i], $separator);
} elseif(count($parts) - 1 == $i) {
$parts[$i] = File::stripLeadingSeparators($parts[$i], $separator);
} else {
$parts[$i] = File::stripTrailingSeparators($parts[$i], $separator);
$parts[$i] = File::stripLeadingSeparators($parts[$i], $separator);
}
}
return implode($separator, $parts);
}
/**
* Strips trailing separators from the given path
*
* @access public
* @param string $path Path to use
* @param string $separator Separator to look for
* @return string Resulting path
*/
function stripTrailingSeparators($path, $separator = DIRECTORY_SEPARATOR)
{
while (substr($path, -1) == $separator) {
$path = substr($path, 0, -1);
}
return $path;
}
/**
* Strips leading separators from the given path
*
* @access public
* @param string $path Path to use
* @param string $separator Separator to look for
* @return string Resulting path
*/
function stripLeadingSeparators($path, $separator = DIRECTORY_SEPARATOR)
{
while (substr($path, 0, 1) == $separator) {
$path = substr($path, 1);
}
return $path;
}
/**
* Returns a path without leading / or C:\. If this is not
* present the path is returned as is.
*
* @access public
* @param string $path The path to be processed
* @return string The processed path or the path as is
*/
function skipRoot($path)
{
if (File::isAbsolute($path)) {
if (DIRECTORY_SEPARATOR == "/") {
return substr($path,1);
} elseif(DIRECTORY_SEPARATOR == "\\") {
return substr($path, 3);
}
} else {
return $path;
}
}
/**
* Returns the temp directory according to either the TMP, TMPDIR, or TEMP env
* variables. If these are not set it will also check for the existence of
* /tmp, %WINDIR%\temp
*
* @access public
* @return string The system tmp directory
*/
function getTempDir()
{
if (OS_WINDOWS){
if (isset($_ENV['TEMP'])) {
return $_ENV['TEMP'];
}
if (isset($_ENV['TMP'])) {
return $_ENV['TMP'];
}
if (isset($_ENV['windir'])) {
return $_ENV['windir'] . '\temp';
}
return $_ENV['SystemRoot'] . '\temp';
}
if (isset($_ENV['TMPDIR'])) {
return $_ENV['TMPDIR'];
}
return '/tmp';
}
/**
* Returns a temporary filename using tempnam() and the above getTmpDir() function.
*
* @access public
* @param string $dirname Optional directory name for the tmp file
* @return string Filename and path of the tmp file
*/
function getTempFile($dirname = NULL)
{
if (is_null($dirname)) {
$dirname = File::getTempDir();
}
return tempnam($dirname, 'temp.');
}
/**
* Returns boolean based on whether given path is absolute or not.
*
* @access public
* @param string $path Given path
* @return boolean True if the path is absolute, false if it is not
*/
function isAbsolute($path)
{
if (preg_match("/\.\./", $path)) {
return false;
}
if (DIRECTORY_SEPARATOR == '/' AND (substr($path, 0, 1) == '/' OR substr($path, 0, 1) == '~')) {
return true;
} elseif(DIRECTORY_SEPARATOR == '\\' AND preg_match('/^[a-z]:\\\/i', $path)) {
return true;
}
return false;
}
}
PEAR::registerShutdownFunc(array('File', '_File'));
?>
<?php
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 2002-2003 Tomas Von Veschler Cox |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Tomas V.V.Cox <cox@idecnet.com> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: CSV.php,v 1.13 2003/01/04 11:54:55 mj Exp $
require_once 'PEAR.php';
require_once 'File.php';
/**
* File class for handling CSV files (Comma Separated Values), a common format
* for exchanging data.
*
* TODO:
* - Usage example and Doc
* - Use getPointer() in discoverFormat
* - Add a line counter for being able to output better error reports
* - Store the last error in GLOBALS and add File_CSV::getLastError()
*
* Wish:
* - Support Mac EOL format
* - Other methods like readAll(), writeAll(), numFields(), numRows()
* - Try to detect if a CSV has header or not in discoverFormat()
*
* Known Bugs:
* (they has been analyzed but for the moment the impact in the speed for
* properly handle this uncommon cases is too high and won't be supported)
* - A field which is composed only by a single quoted separator (ie -> ;";";)
* is not handled properly
* - When there is exactly one field minus than the expected number and there
* is a field with a separator inside, the parser will throw the "wrong count" error
*
* @author Tomas V.V.Cox <cox@idecnet.com>
* @package File
*/
class File_CSV
{
/**
* This raiseError method works in a different way. It will always return
* false (an error occurred) but it will call PEAR::raiseError() before
* it. If no default PEAR global handler is set, will trigger an error.
*
* @param string $error The error message
* @return bool always false
*/
function raiseError($error)
{
// If a default PEAR Error handler is not set trigger the error
// XXX Add a PEAR::isSetHandler() method?
if ($GLOBALS['_PEAR_default_error_mode'] == PEAR_ERROR_RETURN) {
PEAR::raiseError($error, null, PEAR_ERROR_TRIGGER, E_USER_WARNING);
} else {
PEAR::raiseError($error);
}
return false;
}
/**
* Checks the configuration given by the user
*
* @param array &$conf The configuration assoc array
* @param string &$error The error will be written here if any
*/
function _conf(&$conf, &$error)
{
// check conf
if (!is_array($conf)) {
return $error = "Invalid configuration";
}
if (isset($conf['sep'])) {
if (strlen($conf['sep']) != 1) {
return $error = 'Separator can only be one char';
}
} else {
return $error = 'Missing separator (the "sep" key)';