/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php |
---|
New file |
0,0 → 1,229 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (C) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_OLE |
* @copyright Copyright (c) 2006 - 2007 Christian Schmidt |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_OLE_ChainedBlockStream |
* |
* Stream wrapper for reading data stored in an OLE file. Implements methods |
* for PHP's stream_wrapper_register(). For creating streams using this |
* wrapper, use PHPExcel_Shared_OLE_PPS_File::getStream(). |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_OLE |
*/ |
class PHPExcel_Shared_OLE_ChainedBlockStream |
{ |
/** |
* The OLE container of the file that is being read. |
* @var OLE |
*/ |
public $ole; |
/** |
* Parameters specified by fopen(). |
* @var array |
*/ |
public $params; |
/** |
* The binary data of the file. |
* @var string |
*/ |
public $data; |
/** |
* The file pointer. |
* @var int byte offset |
*/ |
public $pos; |
/** |
* Implements support for fopen(). |
* For creating streams using this wrapper, use OLE_PPS_File::getStream(). |
* |
* @param string $path resource name including scheme, e.g. |
* ole-chainedblockstream://oleInstanceId=1 |
* @param string $mode only "r" is supported |
* @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH |
* @param string &$openedPath absolute path of the opened stream (out parameter) |
* @return bool true on success |
*/ |
public function stream_open($path, $mode, $options, &$openedPath) |
{ |
if ($mode != 'r') { |
if ($options & STREAM_REPORT_ERRORS) { |
trigger_error('Only reading is supported', E_USER_WARNING); |
} |
return false; |
} |
// 25 is length of "ole-chainedblockstream://" |
parse_str(substr($path, 25), $this->params); |
if (!isset($this->params['oleInstanceId'], |
$this->params['blockId'], |
$GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']])) { |
if ($options & STREAM_REPORT_ERRORS) { |
trigger_error('OLE stream not found', E_USER_WARNING); |
} |
return false; |
} |
$this->ole = $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']]; |
$blockId = $this->params['blockId']; |
$this->data = ''; |
if (isset($this->params['size']) && |
$this->params['size'] < $this->ole->bigBlockThreshold && |
$blockId != $this->ole->root->_StartBlock) { |
// Block id refers to small blocks |
$rootPos = $this->ole->_getBlockOffset($this->ole->root->_StartBlock); |
while ($blockId != -2) { |
$pos = $rootPos + $blockId * $this->ole->bigBlockSize; |
$blockId = $this->ole->sbat[$blockId]; |
fseek($this->ole->_file_handle, $pos); |
$this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize); |
} |
} else { |
// Block id refers to big blocks |
while ($blockId != -2) { |
$pos = $this->ole->_getBlockOffset($blockId); |
fseek($this->ole->_file_handle, $pos); |
$this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize); |
$blockId = $this->ole->bbat[$blockId]; |
} |
} |
if (isset($this->params['size'])) { |
$this->data = substr($this->data, 0, $this->params['size']); |
} |
if ($options & STREAM_USE_PATH) { |
$openedPath = $path; |
} |
return true; |
} |
/** |
* Implements support for fclose(). |
* |
*/ |
public function stream_close() |
{ |
$this->ole = null; |
unset($GLOBALS['_OLE_INSTANCES']); |
} |
/** |
* Implements support for fread(), fgets() etc. |
* |
* @param int $count maximum number of bytes to read |
* @return string |
*/ |
public function stream_read($count) |
{ |
if ($this->stream_eof()) { |
return false; |
} |
$s = substr($this->data, $this->pos, $count); |
$this->pos += $count; |
return $s; |
} |
/** |
* Implements support for feof(). |
* |
* @return bool TRUE if the file pointer is at EOF; otherwise FALSE |
*/ |
public function stream_eof() |
{ |
$eof = $this->pos >= strlen($this->data); |
// Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508 |
if (version_compare(PHP_VERSION, '5.0', '>=') && |
version_compare(PHP_VERSION, '5.1', '<')) { |
$eof = !$eof; |
} |
return $eof; |
} |
/** |
* Returns the position of the file pointer, i.e. its offset into the file |
* stream. Implements support for ftell(). |
* |
* @return int |
*/ |
public function stream_tell() |
{ |
return $this->pos; |
} |
/** |
* Implements support for fseek(). |
* |
* @param int $offset byte offset |
* @param int $whence SEEK_SET, SEEK_CUR or SEEK_END |
* @return bool |
*/ |
public function stream_seek($offset, $whence) |
{ |
if ($whence == SEEK_SET && $offset >= 0) { |
$this->pos = $offset; |
} elseif ($whence == SEEK_CUR && -$offset <= $this->pos) { |
$this->pos += $offset; |
} elseif ($whence == SEEK_END && -$offset <= sizeof($this->data)) { |
$this->pos = strlen($this->data) + $offset; |
} else { |
return false; |
} |
return true; |
} |
/** |
* Implements support for fstat(). Currently the only supported field is |
* "size". |
* @return array |
*/ |
public function stream_stat() |
{ |
return array( |
'size' => strlen($this->data), |
); |
} |
// Methods used by stream_wrapper_register() that are not implemented: |
// bool stream_flush ( void ) |
// int stream_write ( string data ) |
// bool rename ( string path_from, string path_to ) |
// bool mkdir ( string path, int mode, int options ) |
// bool rmdir ( string path, int options ) |
// bool dir_opendir ( string path, int options ) |
// array url_stat ( string path, int flags ) |
// string dir_readdir ( void ) |
// bool dir_rewinddir ( void ) |
// bool dir_closedir ( void ) |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS.php |
---|
New file |
0,0 → 1,230 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 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. | |
// +----------------------------------------------------------------------+ |
// | Author: Xavier Noguer <xnoguer@php.net> | |
// | Based on OLE::Storage_Lite by Kawai, Takanori | |
// +----------------------------------------------------------------------+ |
// |
// $Id: PPS.php,v 1.7 2007/02/13 21:00:42 schmidt Exp $ |
/** |
* Class for creating PPS's for OLE containers |
* |
* @author Xavier Noguer <xnoguer@php.net> |
* @category PHPExcel |
* @package PHPExcel_Shared_OLE |
*/ |
class PHPExcel_Shared_OLE_PPS |
{ |
/** |
* The PPS index |
* @var integer |
*/ |
public $No; |
/** |
* The PPS name (in Unicode) |
* @var string |
*/ |
public $Name; |
/** |
* The PPS type. Dir, Root or File |
* @var integer |
*/ |
public $Type; |
/** |
* The index of the previous PPS |
* @var integer |
*/ |
public $PrevPps; |
/** |
* The index of the next PPS |
* @var integer |
*/ |
public $NextPps; |
/** |
* The index of it's first child if this is a Dir or Root PPS |
* @var integer |
*/ |
public $DirPps; |
/** |
* A timestamp |
* @var integer |
*/ |
public $Time1st; |
/** |
* A timestamp |
* @var integer |
*/ |
public $Time2nd; |
/** |
* Starting block (small or big) for this PPS's data inside the container |
* @var integer |
*/ |
public $_StartBlock; |
/** |
* The size of the PPS's data (in bytes) |
* @var integer |
*/ |
public $Size; |
/** |
* The PPS's data (only used if it's not using a temporary file) |
* @var string |
*/ |
public $_data; |
/** |
* Array of child PPS's (only used by Root and Dir PPS's) |
* @var array |
*/ |
public $children = array(); |
/** |
* Pointer to OLE container |
* @var OLE |
*/ |
public $ole; |
/** |
* The constructor |
* |
* @access public |
* @param integer $No The PPS index |
* @param string $name The PPS name |
* @param integer $type The PPS type. Dir, Root or File |
* @param integer $prev The index of the previous PPS |
* @param integer $next The index of the next PPS |
* @param integer $dir The index of it's first child if this is a Dir or Root PPS |
* @param integer $time_1st A timestamp |
* @param integer $time_2nd A timestamp |
* @param string $data The (usually binary) source data of the PPS |
* @param array $children Array containing children PPS for this PPS |
*/ |
public function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $time_2nd, $data, $children) |
{ |
$this->No = $No; |
$this->Name = $name; |
$this->Type = $type; |
$this->PrevPps = $prev; |
$this->NextPps = $next; |
$this->DirPps = $dir; |
$this->Time1st = $time_1st; |
$this->Time2nd = $time_2nd; |
$this->_data = $data; |
$this->children = $children; |
if ($data != '') { |
$this->Size = strlen($data); |
} else { |
$this->Size = 0; |
} |
} |
/** |
* Returns the amount of data saved for this PPS |
* |
* @access public |
* @return integer The amount of data (in bytes) |
*/ |
public function _DataLen() |
{ |
if (!isset($this->_data)) { |
return 0; |
} |
//if (isset($this->_PPS_FILE)) { |
// fseek($this->_PPS_FILE, 0); |
// $stats = fstat($this->_PPS_FILE); |
// return $stats[7]; |
//} else { |
return strlen($this->_data); |
//} |
} |
/** |
* Returns a string with the PPS's WK (What is a WK?) |
* |
* @access public |
* @return string The binary string |
*/ |
public function _getPpsWk() |
{ |
$ret = str_pad($this->Name,64,"\x00"); |
$ret .= pack("v", strlen($this->Name) + 2) // 66 |
. pack("c", $this->Type) // 67 |
. pack("c", 0x00) //UK // 68 |
. pack("V", $this->PrevPps) //Prev // 72 |
. pack("V", $this->NextPps) //Next // 76 |
. pack("V", $this->DirPps) //Dir // 80 |
. "\x00\x09\x02\x00" // 84 |
. "\x00\x00\x00\x00" // 88 |
. "\xc0\x00\x00\x00" // 92 |
. "\x00\x00\x00\x46" // 96 // Seems to be ok only for Root |
. "\x00\x00\x00\x00" // 100 |
. PHPExcel_Shared_OLE::LocalDate2OLE($this->Time1st) // 108 |
. PHPExcel_Shared_OLE::LocalDate2OLE($this->Time2nd) // 116 |
. pack("V", isset($this->_StartBlock)? |
$this->_StartBlock:0) // 120 |
. pack("V", $this->Size) // 124 |
. pack("V", 0); // 128 |
return $ret; |
} |
/** |
* Updates index and pointers to previous, next and children PPS's for this |
* PPS. I don't think it'll work with Dir PPS's. |
* |
* @access public |
* @param array &$raList Reference to the array of PPS's for the whole OLE |
* container |
* @return integer The index for this PPS |
*/ |
public static function _savePpsSetPnt(&$raList, $to_save, $depth = 0) |
{ |
if ( !is_array($to_save) || (empty($to_save)) ) { |
return 0xFFFFFFFF; |
} elseif( count($to_save) == 1 ) { |
$cnt = count($raList); |
// If the first entry, it's the root... Don't clone it! |
$raList[$cnt] = ( $depth == 0 ) ? $to_save[0] : clone $to_save[0]; |
$raList[$cnt]->No = $cnt; |
$raList[$cnt]->PrevPps = 0xFFFFFFFF; |
$raList[$cnt]->NextPps = 0xFFFFFFFF; |
$raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++); |
} else { |
$iPos = floor(count($to_save) / 2); |
$aPrev = array_slice($to_save, 0, $iPos); |
$aNext = array_slice($to_save, $iPos + 1); |
$cnt = count($raList); |
// If the first entry, it's the root... Don't clone it! |
$raList[$cnt] = ( $depth == 0 ) ? $to_save[$iPos] : clone $to_save[$iPos]; |
$raList[$cnt]->No = $cnt; |
$raList[$cnt]->PrevPps = self::_savePpsSetPnt($raList, $aPrev, $depth++); |
$raList[$cnt]->NextPps = self::_savePpsSetPnt($raList, $aNext, $depth++); |
$raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++); |
} |
return $cnt; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/Root.php |
---|
New file |
0,0 → 1,467 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 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. | |
// +----------------------------------------------------------------------+ |
// | Author: Xavier Noguer <xnoguer@php.net> | |
// | Based on OLE::Storage_Lite by Kawai, Takanori | |
// +----------------------------------------------------------------------+ |
// |
// $Id: Root.php,v 1.9 2005/04/23 21:53:49 dufuz Exp $ |
/** |
* Class for creating Root PPS's for OLE containers |
* |
* @author Xavier Noguer <xnoguer@php.net> |
* @category PHPExcel |
* @package PHPExcel_Shared_OLE |
*/ |
class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS |
{ |
/** |
* Directory for temporary files |
* @var string |
*/ |
protected $_tmp_dir = NULL; |
/** |
* @param integer $time_1st A timestamp |
* @param integer $time_2nd A timestamp |
*/ |
public function __construct($time_1st, $time_2nd, $raChild) |
{ |
$this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); |
parent::__construct( |
null, |
PHPExcel_Shared_OLE::Asc2Ucs('Root Entry'), |
PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT, |
null, |
null, |
null, |
$time_1st, |
$time_2nd, |
null, |
$raChild); |
} |
/** |
* Method for saving the whole OLE container (including files). |
* In fact, if called with an empty argument (or '-'), it saves to a |
* temporary file and then outputs it's contents to stdout. |
* If a resource pointer to a stream created by fopen() is passed |
* it will be used, but you have to close such stream by yourself. |
* |
* @param string|resource $filename The name of the file or stream where to save the OLE container. |
* @access public |
* @return mixed true on success |
*/ |
public function save($filename) |
{ |
// Initial Setting for saving |
$this->_BIG_BLOCK_SIZE = pow(2, |
((isset($this->_BIG_BLOCK_SIZE))? self::_adjust2($this->_BIG_BLOCK_SIZE) : 9)); |
$this->_SMALL_BLOCK_SIZE= pow(2, |
((isset($this->_SMALL_BLOCK_SIZE))? self::_adjust2($this->_SMALL_BLOCK_SIZE): 6)); |
if (is_resource($filename)) { |
$this->_FILEH_ = $filename; |
} else if ($filename == '-' || $filename == '') { |
if ($this->_tmp_dir === NULL) |
$this->_tmp_dir = PHPExcel_Shared_File::sys_get_temp_dir(); |
$this->_tmp_filename = tempnam($this->_tmp_dir, "OLE_PPS_Root"); |
$this->_FILEH_ = fopen($this->_tmp_filename,"w+b"); |
if ($this->_FILEH_ == false) { |
throw new PHPExcel_Writer_Exception("Can't create temporary file."); |
} |
} else { |
$this->_FILEH_ = fopen($filename, "wb"); |
} |
if ($this->_FILEH_ == false) { |
throw new PHPExcel_Writer_Exception("Can't open $filename. It may be in use or protected."); |
} |
// Make an array of PPS's (for Save) |
$aList = array(); |
PHPExcel_Shared_OLE_PPS::_savePpsSetPnt($aList, array($this)); |
// calculate values for header |
list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo); |
// Save Header |
$this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt); |
// Make Small Data string (write SBD) |
$this->_data = $this->_makeSmallData($aList); |
// Write BB |
$this->_saveBigData($iSBDcnt, $aList); |
// Write PPS |
$this->_savePps($aList); |
// Write Big Block Depot and BDList and Adding Header informations |
$this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt); |
if (!is_resource($filename)) { |
fclose($this->_FILEH_); |
} |
return true; |
} |
/** |
* Calculate some numbers |
* |
* @access public |
* @param array $raList Reference to an array of PPS's |
* @return array The array of numbers |
*/ |
public function _calcSize(&$raList) |
{ |
// Calculate Basic Setting |
list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0); |
$iSmallLen = 0; |
$iSBcnt = 0; |
$iCount = count($raList); |
for ($i = 0; $i < $iCount; ++$i) { |
if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { |
$raList[$i]->Size = $raList[$i]->_DataLen(); |
if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { |
$iSBcnt += floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) |
+ (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); |
} else { |
$iBBcnt += (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) + |
(($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0)); |
} |
} |
} |
$iSmallLen = $iSBcnt * $this->_SMALL_BLOCK_SIZE; |
$iSlCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); |
$iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt)? 1:0); |
$iBBcnt += (floor($iSmallLen / $this->_BIG_BLOCK_SIZE) + |
(( $iSmallLen % $this->_BIG_BLOCK_SIZE)? 1: 0)); |
$iCnt = count($raList); |
$iBdCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; |
$iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0)); |
return array($iSBDcnt, $iBBcnt, $iPPScnt); |
} |
/** |
* Helper function for caculating a magic value for block sizes |
* |
* @access public |
* @param integer $i2 The argument |
* @see save() |
* @return integer |
*/ |
private static function _adjust2($i2) |
{ |
$iWk = log($i2)/log(2); |
return ($iWk > floor($iWk))? floor($iWk)+1:$iWk; |
} |
/** |
* Save OLE header |
* |
* @access public |
* @param integer $iSBDcnt |
* @param integer $iBBcnt |
* @param integer $iPPScnt |
*/ |
public function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt) |
{ |
$FILE = $this->_FILEH_; |
// Calculate Basic Setting |
$iBlCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; |
$i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; |
$iBdExL = 0; |
$iAll = $iBBcnt + $iPPScnt + $iSBDcnt; |
$iAllW = $iAll; |
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0); |
$iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0); |
// Calculate BD count |
if ($iBdCnt > $i1stBdL) { |
while (1) { |
++$iBdExL; |
++$iAllW; |
$iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0); |
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0); |
if ($iBdCnt <= ($iBdExL*$iBlCnt+ $i1stBdL)) { |
break; |
} |
} |
} |
// Save Header |
fwrite($FILE, |
"\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" |
. "\x00\x00\x00\x00" |
. "\x00\x00\x00\x00" |
. "\x00\x00\x00\x00" |
. "\x00\x00\x00\x00" |
. pack("v", 0x3b) |
. pack("v", 0x03) |
. pack("v", -2) |
. pack("v", 9) |
. pack("v", 6) |
. pack("v", 0) |
. "\x00\x00\x00\x00" |
. "\x00\x00\x00\x00" |
. pack("V", $iBdCnt) |
. pack("V", $iBBcnt+$iSBDcnt) //ROOT START |
. pack("V", 0) |
. pack("V", 0x1000) |
. pack("V", $iSBDcnt ? 0 : -2) //Small Block Depot |
. pack("V", $iSBDcnt) |
); |
// Extra BDList Start, Count |
if ($iBdCnt < $i1stBdL) { |
fwrite($FILE, |
pack("V", -2) // Extra BDList Start |
. pack("V", 0) // Extra BDList Count |
); |
} else { |
fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL)); |
} |
// BDList |
for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) { |
fwrite($FILE, pack("V", $iAll+$i)); |
} |
if ($i < $i1stBdL) { |
$jB = $i1stBdL - $i; |
for ($j = 0; $j < $jB; ++$j) { |
fwrite($FILE, (pack("V", -1))); |
} |
} |
} |
/** |
* Saving big data (PPS's with data bigger than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) |
* |
* @access public |
* @param integer $iStBlk |
* @param array &$raList Reference to array of PPS's |
*/ |
public function _saveBigData($iStBlk, &$raList) |
{ |
$FILE = $this->_FILEH_; |
// cycle through PPS's |
$iCount = count($raList); |
for ($i = 0; $i < $iCount; ++$i) { |
if ($raList[$i]->Type != PHPExcel_Shared_OLE::OLE_PPS_TYPE_DIR) { |
$raList[$i]->Size = $raList[$i]->_DataLen(); |
if (($raList[$i]->Size >= PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) || |
(($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) |
{ |
// Write Data |
//if (isset($raList[$i]->_PPS_FILE)) { |
// $iLen = 0; |
// fseek($raList[$i]->_PPS_FILE, 0); // To The Top |
// while($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) { |
// $iLen += strlen($sBuff); |
// fwrite($FILE, $sBuff); |
// } |
//} else { |
fwrite($FILE, $raList[$i]->_data); |
//} |
if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) { |
fwrite($FILE, str_repeat("\x00", $this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE))); |
} |
// Set For PPS |
$raList[$i]->_StartBlock = $iStBlk; |
$iStBlk += |
(floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) + |
(($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0)); |
} |
// Close file for each PPS, and unlink it |
//if (isset($raList[$i]->_PPS_FILE)) { |
// fclose($raList[$i]->_PPS_FILE); |
// $raList[$i]->_PPS_FILE = null; |
// unlink($raList[$i]->_tmp_filename); |
//} |
} |
} |
} |
/** |
* get small data (PPS's with data smaller than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) |
* |
* @access public |
* @param array &$raList Reference to array of PPS's |
*/ |
public function _makeSmallData(&$raList) |
{ |
$sRes = ''; |
$FILE = $this->_FILEH_; |
$iSmBlk = 0; |
$iCount = count($raList); |
for ($i = 0; $i < $iCount; ++$i) { |
// Make SBD, small data string |
if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { |
if ($raList[$i]->Size <= 0) { |
continue; |
} |
if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { |
$iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) |
+ (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); |
// Add to SBD |
$jB = $iSmbCnt - 1; |
for ($j = 0; $j < $jB; ++$j) { |
fwrite($FILE, pack("V", $j+$iSmBlk+1)); |
} |
fwrite($FILE, pack("V", -2)); |
//// Add to Data String(this will be written for RootEntry) |
//if ($raList[$i]->_PPS_FILE) { |
// fseek($raList[$i]->_PPS_FILE, 0); // To The Top |
// while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) { |
// $sRes .= $sBuff; |
// } |
//} else { |
$sRes .= $raList[$i]->_data; |
//} |
if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) { |
$sRes .= str_repeat("\x00",$this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); |
} |
// Set for PPS |
$raList[$i]->_StartBlock = $iSmBlk; |
$iSmBlk += $iSmbCnt; |
} |
} |
} |
$iSbCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); |
if ($iSmBlk % $iSbCnt) { |
$iB = $iSbCnt - ($iSmBlk % $iSbCnt); |
for ($i = 0; $i < $iB; ++$i) { |
fwrite($FILE, pack("V", -1)); |
} |
} |
return $sRes; |
} |
/** |
* Saves all the PPS's WKs |
* |
* @access public |
* @param array $raList Reference to an array with all PPS's |
*/ |
public function _savePps(&$raList) |
{ |
// Save each PPS WK |
$iC = count($raList); |
for ($i = 0; $i < $iC; ++$i) { |
fwrite($this->_FILEH_, $raList[$i]->_getPpsWk()); |
} |
// Adjust for Block |
$iCnt = count($raList); |
$iBCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; |
if ($iCnt % $iBCnt) { |
fwrite($this->_FILEH_, str_repeat("\x00",($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE)); |
} |
} |
/** |
* Saving Big Block Depot |
* |
* @access public |
* @param integer $iSbdSize |
* @param integer $iBsize |
* @param integer $iPpsCnt |
*/ |
public function _saveBbd($iSbdSize, $iBsize, $iPpsCnt) |
{ |
$FILE = $this->_FILEH_; |
// Calculate Basic Setting |
$iBbCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; |
$i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; |
$iBdExL = 0; |
$iAll = $iBsize + $iPpsCnt + $iSbdSize; |
$iAllW = $iAll; |
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0); |
$iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0); |
// Calculate BD count |
if ($iBdCnt >$i1stBdL) { |
while (1) { |
++$iBdExL; |
++$iAllW; |
$iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0); |
$iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0); |
if ($iBdCnt <= ($iBdExL*$iBbCnt+ $i1stBdL)) { |
break; |
} |
} |
} |
// Making BD |
// Set for SBD |
if ($iSbdSize > 0) { |
for ($i = 0; $i < ($iSbdSize - 1); ++$i) { |
fwrite($FILE, pack("V", $i+1)); |
} |
fwrite($FILE, pack("V", -2)); |
} |
// Set for B |
for ($i = 0; $i < ($iBsize - 1); ++$i) { |
fwrite($FILE, pack("V", $i+$iSbdSize+1)); |
} |
fwrite($FILE, pack("V", -2)); |
// Set for PPS |
for ($i = 0; $i < ($iPpsCnt - 1); ++$i) { |
fwrite($FILE, pack("V", $i+$iSbdSize+$iBsize+1)); |
} |
fwrite($FILE, pack("V", -2)); |
// Set for BBD itself ( 0xFFFFFFFD : BBD) |
for ($i = 0; $i < $iBdCnt; ++$i) { |
fwrite($FILE, pack("V", 0xFFFFFFFD)); |
} |
// Set for ExtraBDList |
for ($i = 0; $i < $iBdExL; ++$i) { |
fwrite($FILE, pack("V", 0xFFFFFFFC)); |
} |
// Adjust for Block |
if (($iAllW + $iBdCnt) % $iBbCnt) { |
$iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); |
for ($i = 0; $i < $iBlock; ++$i) { |
fwrite($FILE, pack("V", -1)); |
} |
} |
// Extra BDList |
if ($iBdCnt > $i1stBdL) { |
$iN=0; |
$iNb=0; |
for ($i = $i1stBdL;$i < $iBdCnt; $i++, ++$iN) { |
if ($iN >= ($iBbCnt - 1)) { |
$iN = 0; |
++$iNb; |
fwrite($FILE, pack("V", $iAll+$iBdCnt+$iNb)); |
} |
fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i)); |
} |
if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) { |
$iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1)); |
for ($i = 0; $i < $iB; ++$i) { |
fwrite($FILE, pack("V", -1)); |
} |
} |
fwrite($FILE, pack("V", -2)); |
} |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/File.php |
---|
New file |
0,0 → 1,84 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 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. | |
// +----------------------------------------------------------------------+ |
// | Author: Xavier Noguer <xnoguer@php.net> | |
// | Based on OLE::Storage_Lite by Kawai, Takanori | |
// +----------------------------------------------------------------------+ |
// |
// $Id: File.php,v 1.11 2007/02/13 21:00:42 schmidt Exp $ |
/** |
* Class for creating File PPS's for OLE containers |
* |
* @author Xavier Noguer <xnoguer@php.net> |
* @category PHPExcel |
* @package PHPExcel_Shared_OLE |
*/ |
class PHPExcel_Shared_OLE_PPS_File extends PHPExcel_Shared_OLE_PPS |
{ |
/** |
* The constructor |
* |
* @access public |
* @param string $name The name of the file (in Unicode) |
* @see OLE::Asc2Ucs() |
*/ |
public function __construct($name) |
{ |
parent::__construct( |
null, |
$name, |
PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE, |
null, |
null, |
null, |
null, |
null, |
'', |
array()); |
} |
/** |
* Initialization method. Has to be called right after OLE_PPS_File(). |
* |
* @access public |
* @return mixed true on success |
*/ |
public function init() |
{ |
return true; |
} |
/** |
* Append data to PPS |
* |
* @access public |
* @param string $data The data to append |
*/ |
public function append($data) |
{ |
$this->_data .= $data; |
} |
/** |
* Returns a stream for reading this file using fread() etc. |
* @return resource a read-only stream |
*/ |
public function getStream() |
{ |
$this->ole->getStream($this); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/TimeZone.php |
---|
New file |
0,0 → 1,140 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_TimeZone |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_TimeZone |
{ |
/* |
* Default Timezone used for date/time conversions |
* |
* @private |
* @var string |
*/ |
protected static $_timezone = 'UTC'; |
/** |
* Validate a Timezone name |
* |
* @param string $timezone Time zone (e.g. 'Europe/London') |
* @return boolean Success or failure |
*/ |
public static function _validateTimeZone($timezone) { |
if (in_array($timezone, DateTimeZone::listIdentifiers())) { |
return TRUE; |
} |
return FALSE; |
} |
/** |
* Set the Default Timezone used for date/time conversions |
* |
* @param string $timezone Time zone (e.g. 'Europe/London') |
* @return boolean Success or failure |
*/ |
public static function setTimeZone($timezone) { |
if (self::_validateTimezone($timezone)) { |
self::$_timezone = $timezone; |
return TRUE; |
} |
return FALSE; |
} // function setTimezone() |
/** |
* Return the Default Timezone used for date/time conversions |
* |
* @return string Timezone (e.g. 'Europe/London') |
*/ |
public static function getTimeZone() { |
return self::$_timezone; |
} // function getTimezone() |
/** |
* Return the Timezone transition for the specified timezone and timestamp |
* |
* @param DateTimeZone $objTimezone The timezone for finding the transitions |
* @param integer $timestamp PHP date/time value for finding the current transition |
* @return array The current transition details |
*/ |
private static function _getTimezoneTransitions($objTimezone, $timestamp) { |
$allTransitions = $objTimezone->getTransitions(); |
$transitions = array(); |
foreach($allTransitions as $key => $transition) { |
if ($transition['ts'] > $timestamp) { |
$transitions[] = ($key > 0) ? $allTransitions[$key - 1] : $transition; |
break; |
} |
if (empty($transitions)) { |
$transitions[] = end($allTransitions); |
} |
} |
return $transitions; |
} |
/** |
* Return the Timezone offset used for date/time conversions to/from UST |
* This requires both the timezone and the calculated date/time to allow for local DST |
* |
* @param string $timezone The timezone for finding the adjustment to UST |
* @param integer $timestamp PHP date/time value |
* @return integer Number of seconds for timezone adjustment |
* @throws PHPExcel_Exception |
*/ |
public static function getTimeZoneAdjustment($timezone, $timestamp) { |
if ($timezone !== NULL) { |
if (!self::_validateTimezone($timezone)) { |
throw new PHPExcel_Exception("Invalid timezone " . $timezone); |
} |
} else { |
$timezone = self::$_timezone; |
} |
if ($timezone == 'UST') { |
return 0; |
} |
$objTimezone = new DateTimeZone($timezone); |
if (version_compare(PHP_VERSION, '5.3.0') >= 0) { |
$transitions = $objTimezone->getTransitions($timestamp,$timestamp); |
} else { |
$transitions = self::_getTimezoneTransitions($objTimezone, $timestamp); |
} |
return (count($transitions) > 0) ? $transitions[0]['offset'] : 0; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Drawing.php |
---|
New file |
0,0 → 1,272 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Drawing |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Drawing |
{ |
/** |
* Convert pixels to EMU |
* |
* @param int $pValue Value in pixels |
* @return int Value in EMU |
*/ |
public static function pixelsToEMU($pValue = 0) { |
return round($pValue * 9525); |
} |
/** |
* Convert EMU to pixels |
* |
* @param int $pValue Value in EMU |
* @return int Value in pixels |
*/ |
public static function EMUToPixels($pValue = 0) { |
if ($pValue != 0) { |
return round($pValue / 9525); |
} else { |
return 0; |
} |
} |
/** |
* Convert pixels to column width. Exact algorithm not known. |
* By inspection of a real Excel file using Calibri 11, one finds 1000px ~ 142.85546875 |
* This gives a conversion factor of 7. Also, we assume that pixels and font size are proportional. |
* |
* @param int $pValue Value in pixels |
* @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook |
* @return int Value in cell dimension |
*/ |
public static function pixelsToCellDimension($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { |
// Font name and size |
$name = $pDefaultFont->getName(); |
$size = $pDefaultFont->getSize(); |
if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { |
// Exact width can be determined |
$colWidth = $pValue |
* PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width'] |
/ PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px']; |
} else { |
// We don't have data for this particular font and size, use approximation by |
// extrapolating from Calibri 11 |
$colWidth = $pValue * 11 |
* PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] |
/ PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] / $size; |
} |
return $colWidth; |
} |
/** |
* Convert column width from (intrinsic) Excel units to pixels |
* |
* @param float $pValue Value in cell dimension |
* @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook |
* @return int Value in pixels |
*/ |
public static function cellDimensionToPixels($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { |
// Font name and size |
$name = $pDefaultFont->getName(); |
$size = $pDefaultFont->getSize(); |
if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { |
// Exact width can be determined |
$colWidth = $pValue |
* PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px'] |
/ PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width']; |
} else { |
// We don't have data for this particular font and size, use approximation by |
// extrapolating from Calibri 11 |
$colWidth = $pValue * $size |
* PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] |
/ PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] / 11; |
} |
// Round pixels to closest integer |
$colWidth = (int) round($colWidth); |
return $colWidth; |
} |
/** |
* Convert pixels to points |
* |
* @param int $pValue Value in pixels |
* @return int Value in points |
*/ |
public static function pixelsToPoints($pValue = 0) { |
return $pValue * 0.67777777; |
} |
/** |
* Convert points to pixels |
* |
* @param int $pValue Value in points |
* @return int Value in pixels |
*/ |
public static function pointsToPixels($pValue = 0) { |
if ($pValue != 0) { |
return (int) ceil($pValue * 1.333333333); |
} else { |
return 0; |
} |
} |
/** |
* Convert degrees to angle |
* |
* @param int $pValue Degrees |
* @return int Angle |
*/ |
public static function degreesToAngle($pValue = 0) { |
return (int)round($pValue * 60000); |
} |
/** |
* Convert angle to degrees |
* |
* @param int $pValue Angle |
* @return int Degrees |
*/ |
public static function angleToDegrees($pValue = 0) { |
if ($pValue != 0) { |
return round($pValue / 60000); |
} else { |
return 0; |
} |
} |
/** |
* Create a new image from file. By alexander at alexauto dot nl |
* |
* @link http://www.php.net/manual/en/function.imagecreatefromwbmp.php#86214 |
* @param string $filename Path to Windows DIB (BMP) image |
* @return resource |
*/ |
public static function imagecreatefrombmp($p_sFile) |
{ |
// Load the image into a string |
$file = fopen($p_sFile,"rb"); |
$read = fread($file,10); |
while(!feof($file)&&($read<>"")) |
$read .= fread($file,1024); |
$temp = unpack("H*",$read); |
$hex = $temp[1]; |
$header = substr($hex,0,108); |
// Process the header |
// Structure: http://www.fastgraph.com/help/bmp_header_format.html |
if (substr($header,0,4)=="424d") |
{ |
// Cut it in parts of 2 bytes |
$header_parts = str_split($header,2); |
// Get the width 4 bytes |
$width = hexdec($header_parts[19].$header_parts[18]); |
// Get the height 4 bytes |
$height = hexdec($header_parts[23].$header_parts[22]); |
// Unset the header params |
unset($header_parts); |
} |
// Define starting X and Y |
$x = 0; |
$y = 1; |
// Create newimage |
$image = imagecreatetruecolor($width,$height); |
// Grab the body from the image |
$body = substr($hex,108); |
// Calculate if padding at the end-line is needed |
// Divided by two to keep overview. |
// 1 byte = 2 HEX-chars |
$body_size = (strlen($body)/2); |
$header_size = ($width*$height); |
// Use end-line padding? Only when needed |
$usePadding = ($body_size>($header_size*3)+4); |
// Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption |
// Calculate the next DWORD-position in the body |
for ($i=0;$i<$body_size;$i+=3) |
{ |
// Calculate line-ending and padding |
if ($x>=$width) |
{ |
// If padding needed, ignore image-padding |
// Shift i to the ending of the current 32-bit-block |
if ($usePadding) |
$i += $width%4; |
// Reset horizontal position |
$x = 0; |
// Raise the height-position (bottom-up) |
$y++; |
// Reached the image-height? Break the for-loop |
if ($y>$height) |
break; |
} |
// Calculation of the RGB-pixel (defined as BGR in image-data) |
// Define $i_pos as absolute position in the body |
$i_pos = $i*2; |
$r = hexdec($body[$i_pos+4].$body[$i_pos+5]); |
$g = hexdec($body[$i_pos+2].$body[$i_pos+3]); |
$b = hexdec($body[$i_pos].$body[$i_pos+1]); |
// Calculate and draw the pixel |
$color = imagecolorallocate($image,$r,$g,$b); |
imagesetpixel($image,$x,$height-$y,$color); |
// Raise the horizontal position |
$x++; |
} |
// Unset the body / free the memory |
unset($body); |
// Return image-object |
return $image; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/PasswordHasher.php |
---|
New file |
0,0 → 1,66 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_PasswordHasher |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_PasswordHasher |
{ |
/** |
* Create a password hash from a given string. |
* |
* This method is based on the algorithm provided by |
* Daniel Rentz of OpenOffice and the PEAR package |
* Spreadsheet_Excel_Writer by Xavier Noguer <xnoguer@rezebra.com>. |
* |
* @param string $pPassword Password to hash |
* @return string Hashed password |
*/ |
public static function hashPassword($pPassword = '') { |
$password = 0x0000; |
$charPos = 1; // char position |
// split the plain text password in its component characters |
$chars = preg_split('//', $pPassword, -1, PREG_SPLIT_NO_EMPTY); |
foreach ($chars as $char) { |
$value = ord($char) << $charPos++; // shifted ASCII value |
$rotated_bits = $value >> 15; // rotated bits beyond bit 15 |
$value &= 0x7fff; // first 15 bits |
$password ^= ($value | $rotated_bits); |
} |
$password ^= strlen($pPassword); |
$password ^= 0xCE4B; |
return(strtoupper(dechex($password))); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/XMLWriter.php |
---|
New file |
0,0 → 1,127 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
if (!defined('DATE_W3C')) { |
define('DATE_W3C', 'Y-m-d\TH:i:sP'); |
} |
if (!defined('DEBUGMODE_ENABLED')) { |
define('DEBUGMODE_ENABLED', false); |
} |
/** |
* PHPExcel_Shared_XMLWriter |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_XMLWriter extends XMLWriter { |
/** Temporary storage method */ |
const STORAGE_MEMORY = 1; |
const STORAGE_DISK = 2; |
/** |
* Temporary filename |
* |
* @var string |
*/ |
private $_tempFileName = ''; |
/** |
* Create a new PHPExcel_Shared_XMLWriter instance |
* |
* @param int $pTemporaryStorage Temporary storage location |
* @param string $pTemporaryStorageFolder Temporary storage folder |
*/ |
public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTemporaryStorageFolder = NULL) { |
// Open temporary storage |
if ($pTemporaryStorage == self::STORAGE_MEMORY) { |
$this->openMemory(); |
} else { |
// Create temporary filename |
if ($pTemporaryStorageFolder === NULL) |
$pTemporaryStorageFolder = PHPExcel_Shared_File::sys_get_temp_dir(); |
$this->_tempFileName = @tempnam($pTemporaryStorageFolder, 'xml'); |
// Open storage |
if ($this->openUri($this->_tempFileName) === false) { |
// Fallback to memory... |
$this->openMemory(); |
} |
} |
// Set default values |
if (DEBUGMODE_ENABLED) { |
$this->setIndent(true); |
} |
} |
/** |
* Destructor |
*/ |
public function __destruct() { |
// Unlink temporary files |
if ($this->_tempFileName != '') { |
@unlink($this->_tempFileName); |
} |
} |
/** |
* Get written data |
* |
* @return $data |
*/ |
public function getData() { |
if ($this->_tempFileName == '') { |
return $this->outputMemory(true); |
} else { |
$this->flush(); |
return file_get_contents($this->_tempFileName); |
} |
} |
/** |
* Fallback method for writeRaw, introduced in PHP 5.2 |
* |
* @param string $text |
* @return string |
*/ |
public function writeRawData($text) |
{ |
if (is_array($text)) { |
$text = implode("\n",$text); |
} |
if (method_exists($this, 'writeRaw')) { |
return $this->writeRaw(htmlspecialchars($text)); |
} |
return $this->text($text); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/ZipArchive.php |
---|
New file |
0,0 → 1,114 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_ZipArchive |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
if (!defined('PCLZIP_TEMPORARY_DIR')) { |
define('PCLZIP_TEMPORARY_DIR', PHPExcel_Shared_File::sys_get_temp_dir()); |
} |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PCLZip/pclzip.lib.php'; |
/** |
* PHPExcel_Shared_ZipArchive |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_ZipArchive |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_ZipArchive |
{ |
/** constants */ |
const OVERWRITE = 'OVERWRITE'; |
const CREATE = 'CREATE'; |
/** |
* Temporary storage directory |
* |
* @var string |
*/ |
private $_tempDir; |
/** |
* Zip Archive Stream Handle |
* |
* @var string |
*/ |
private $_zip; |
/** |
* Open a new zip archive |
* |
* @param string $fileName Filename for the zip archive |
* @return boolean |
*/ |
public function open($fileName) |
{ |
$this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); |
$this->_zip = new PclZip($fileName); |
return true; |
} |
/** |
* Close this zip archive |
* |
*/ |
public function close() |
{ |
} |
/** |
* Add a new file to the zip archive from a string of raw data. |
* |
* @param string $localname Directory/Name of the file to add to the zip archive |
* @param string $contents String of data to add to the zip archive |
*/ |
public function addFromString($localname, $contents) |
{ |
$filenameParts = pathinfo($localname); |
$handle = fopen($this->_tempDir.'/'.$filenameParts["basename"], "wb"); |
fwrite($handle, $contents); |
fclose($handle); |
$res = $this->_zip->add($this->_tempDir.'/'.$filenameParts["basename"], |
PCLZIP_OPT_REMOVE_PATH, $this->_tempDir, |
PCLZIP_OPT_ADD_PATH, $filenameParts["dirname"] |
); |
if ($res == 0) { |
throw new PHPExcel_Writer_Exception("Error zipping files : " . $this->_zip->errorInfo(true)); |
} |
unlink($this->_tempDir.'/'.$filenameParts["basename"]); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Font.php |
---|
New file |
0,0 → 1,775 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Font |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Font |
{ |
/* Methods for resolving autosize value */ |
const AUTOSIZE_METHOD_APPROX = 'approx'; |
const AUTOSIZE_METHOD_EXACT = 'exact'; |
private static $_autoSizeMethods = array( |
self::AUTOSIZE_METHOD_APPROX, |
self::AUTOSIZE_METHOD_EXACT, |
); |
/** Character set codes used by BIFF5-8 in Font records */ |
const CHARSET_ANSI_LATIN = 0x00; |
const CHARSET_SYSTEM_DEFAULT = 0x01; |
const CHARSET_SYMBOL = 0x02; |
const CHARSET_APPLE_ROMAN = 0x4D; |
const CHARSET_ANSI_JAPANESE_SHIFTJIS = 0x80; |
const CHARSET_ANSI_KOREAN_HANGUL = 0x81; |
const CHARSET_ANSI_KOREAN_JOHAB = 0x82; |
const CHARSET_ANSI_CHINESE_SIMIPLIFIED = 0x86; // gb2312 |
const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88; // big5 |
const CHARSET_ANSI_GREEK = 0xA1; |
const CHARSET_ANSI_TURKISH = 0xA2; |
const CHARSET_ANSI_VIETNAMESE = 0xA3; |
const CHARSET_ANSI_HEBREW = 0xB1; |
const CHARSET_ANSI_ARABIC = 0xB2; |
const CHARSET_ANSI_BALTIC = 0xBA; |
const CHARSET_ANSI_CYRILLIC = 0xCC; |
const CHARSET_ANSI_THAI = 0xDD; |
const CHARSET_ANSI_LATIN_II = 0xEE; |
const CHARSET_OEM_LATIN_I = 0xFF; |
// XXX: Constants created! |
/** Font filenames */ |
const ARIAL = 'arial.ttf'; |
const ARIAL_BOLD = 'arialbd.ttf'; |
const ARIAL_ITALIC = 'ariali.ttf'; |
const ARIAL_BOLD_ITALIC = 'arialbi.ttf'; |
const CALIBRI = 'CALIBRI.TTF'; |
const CALIBRI_BOLD = 'CALIBRIB.TTF'; |
const CALIBRI_ITALIC = 'CALIBRII.TTF'; |
const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF'; |
const COMIC_SANS_MS = 'comic.ttf'; |
const COMIC_SANS_MS_BOLD = 'comicbd.ttf'; |
const COURIER_NEW = 'cour.ttf'; |
const COURIER_NEW_BOLD = 'courbd.ttf'; |
const COURIER_NEW_ITALIC = 'couri.ttf'; |
const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf'; |
const GEORGIA = 'georgia.ttf'; |
const GEORGIA_BOLD = 'georgiab.ttf'; |
const GEORGIA_ITALIC = 'georgiai.ttf'; |
const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf'; |
const IMPACT = 'impact.ttf'; |
const LIBERATION_SANS = 'LiberationSans-Regular.ttf'; |
const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf'; |
const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf'; |
const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf'; |
const LUCIDA_CONSOLE = 'lucon.ttf'; |
const LUCIDA_SANS_UNICODE = 'l_10646.ttf'; |
const MICROSOFT_SANS_SERIF = 'micross.ttf'; |
const PALATINO_LINOTYPE = 'pala.ttf'; |
const PALATINO_LINOTYPE_BOLD = 'palab.ttf'; |
const PALATINO_LINOTYPE_ITALIC = 'palai.ttf'; |
const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf'; |
const SYMBOL = 'symbol.ttf'; |
const TAHOMA = 'tahoma.ttf'; |
const TAHOMA_BOLD = 'tahomabd.ttf'; |
const TIMES_NEW_ROMAN = 'times.ttf'; |
const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf'; |
const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf'; |
const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf'; |
const TREBUCHET_MS = 'trebuc.ttf'; |
const TREBUCHET_MS_BOLD = 'trebucbd.ttf'; |
const TREBUCHET_MS_ITALIC = 'trebucit.ttf'; |
const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf'; |
const VERDANA = 'verdana.ttf'; |
const VERDANA_BOLD = 'verdanab.ttf'; |
const VERDANA_ITALIC = 'verdanai.ttf'; |
const VERDANA_BOLD_ITALIC = 'verdanaz.ttf'; |
/** |
* AutoSize method |
* |
* @var string |
*/ |
private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX; |
/** |
* Path to folder containing TrueType font .ttf files |
* |
* @var string |
*/ |
private static $trueTypeFontPath = null; |
/** |
* How wide is a default column for a given default font and size? |
* Empirical data found by inspecting real Excel files and reading off the pixel width |
* in Microsoft Office Excel 2007. |
* |
* @var array |
*/ |
public static $defaultColumnWidths = array( |
'Arial' => array( |
1 => array('px' => 24, 'width' => 12.00000000), |
2 => array('px' => 24, 'width' => 12.00000000), |
3 => array('px' => 32, 'width' => 10.66406250), |
4 => array('px' => 32, 'width' => 10.66406250), |
5 => array('px' => 40, 'width' => 10.00000000), |
6 => array('px' => 48, 'width' => 9.59765625), |
7 => array('px' => 48, 'width' => 9.59765625), |
8 => array('px' => 56, 'width' => 9.33203125), |
9 => array('px' => 64, 'width' => 9.14062500), |
10 => array('px' => 64, 'width' => 9.14062500), |
), |
'Calibri' => array( |
1 => array('px' => 24, 'width' => 12.00000000), |
2 => array('px' => 24, 'width' => 12.00000000), |
3 => array('px' => 32, 'width' => 10.66406250), |
4 => array('px' => 32, 'width' => 10.66406250), |
5 => array('px' => 40, 'width' => 10.00000000), |
6 => array('px' => 48, 'width' => 9.59765625), |
7 => array('px' => 48, 'width' => 9.59765625), |
8 => array('px' => 56, 'width' => 9.33203125), |
9 => array('px' => 56, 'width' => 9.33203125), |
10 => array('px' => 64, 'width' => 9.14062500), |
11 => array('px' => 64, 'width' => 9.14062500), |
), |
'Verdana' => array( |
1 => array('px' => 24, 'width' => 12.00000000), |
2 => array('px' => 24, 'width' => 12.00000000), |
3 => array('px' => 32, 'width' => 10.66406250), |
4 => array('px' => 32, 'width' => 10.66406250), |
5 => array('px' => 40, 'width' => 10.00000000), |
6 => array('px' => 48, 'width' => 9.59765625), |
7 => array('px' => 48, 'width' => 9.59765625), |
8 => array('px' => 64, 'width' => 9.14062500), |
9 => array('px' => 72, 'width' => 9.00000000), |
10 => array('px' => 72, 'width' => 9.00000000), |
), |
); |
/** |
* Set autoSize method |
* |
* @param string $pValue |
* @return boolean Success or failure |
*/ |
public static function setAutoSizeMethod($pValue = self::AUTOSIZE_METHOD_APPROX) |
{ |
if (!in_array($pValue,self::$_autoSizeMethods)) { |
return FALSE; |
} |
self::$autoSizeMethod = $pValue; |
return TRUE; |
} |
/** |
* Get autoSize method |
* |
* @return string |
*/ |
public static function getAutoSizeMethod() |
{ |
return self::$autoSizeMethod; |
} |
/** |
* Set the path to the folder containing .ttf files. There should be a trailing slash. |
* Typical locations on variout some platforms: |
* <ul> |
* <li>C:/Windows/Fonts/</li> |
* <li>/usr/share/fonts/truetype/</li> |
* <li>~/.fonts/</li> |
* </ul> |
* |
* @param string $pValue |
*/ |
public static function setTrueTypeFontPath($pValue = '') |
{ |
self::$trueTypeFontPath = $pValue; |
} |
/** |
* Get the path to the folder containing .ttf files. |
* |
* @return string |
*/ |
public static function getTrueTypeFontPath() |
{ |
return self::$trueTypeFontPath; |
} |
/** |
* Calculate an (approximate) OpenXML column width, based on font size and text contained |
* |
* @param PHPExcel_Style_Font $font Font object |
* @param PHPExcel_RichText|string $cellText Text to calculate width |
* @param integer $rotation Rotation angle |
* @param PHPExcel_Style_Font|NULL $defaultFont Font object |
* @return integer Column width |
*/ |
public static function calculateColumnWidth(PHPExcel_Style_Font $font, $cellText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) { |
// If it is rich text, use plain text |
if ($cellText instanceof PHPExcel_RichText) { |
$cellText = $cellText->getPlainText(); |
} |
// Special case if there are one or more newline characters ("\n") |
if (strpos($cellText, "\n") !== false) { |
$lineTexts = explode("\n", $cellText); |
$lineWitdhs = array(); |
foreach ($lineTexts as $lineText) { |
$lineWidths[] = self::calculateColumnWidth($font, $lineText, $rotation = 0, $defaultFont); |
} |
return max($lineWidths); // width of longest line in cell |
} |
// Try to get the exact text width in pixels |
try { |
// If autosize method is set to 'approx', use approximation |
if (self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX) { |
throw new PHPExcel_Exception('AutoSize method is set to approx'); |
} |
// Width of text in pixels excl. padding |
$columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation); |
// Excel adds some padding, use 1.07 of the width of an 'n' glyph |
$columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07); // pixels incl. padding |
} catch (PHPExcel_Exception $e) { |
// Width of text in pixels excl. padding, approximation |
$columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation); |
// Excel adds some padding, just use approx width of 'n' glyph |
$columnWidth += self::getTextWidthPixelsApprox('n', $font, 0); |
} |
// Convert from pixel width to column width |
$columnWidth = PHPExcel_Shared_Drawing::pixelsToCellDimension($columnWidth, $defaultFont); |
// Return |
return round($columnWidth, 6); |
} |
/** |
* Get GD text width in pixels for a string of text in a certain font at a certain rotation angle |
* |
* @param string $text |
* @param PHPExcel_Style_Font |
* @param int $rotation |
* @return int |
* @throws PHPExcel_Exception |
*/ |
public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) { |
if (!function_exists('imagettfbbox')) { |
throw new PHPExcel_Exception('GD library needs to be enabled'); |
} |
// font size should really be supplied in pixels in GD2, |
// but since GD2 seems to assume 72dpi, pixels and points are the same |
$fontFile = self::getTrueTypeFontFileFromFont($font); |
$textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text); |
// Get corners positions |
$lowerLeftCornerX = $textBox[0]; |
$lowerLeftCornerY = $textBox[1]; |
$lowerRightCornerX = $textBox[2]; |
$lowerRightCornerY = $textBox[3]; |
$upperRightCornerX = $textBox[4]; |
$upperRightCornerY = $textBox[5]; |
$upperLeftCornerX = $textBox[6]; |
$upperLeftCornerY = $textBox[7]; |
// Consider the rotation when calculating the width |
$textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); |
return $textWidth; |
} |
/** |
* Get approximate width in pixels for a string of text in a certain font at a certain rotation angle |
* |
* @param string $columnText |
* @param PHPExcel_Style_Font $font |
* @param int $rotation |
* @return int Text width in pixels (no padding added) |
*/ |
public static function getTextWidthPixelsApprox($columnText, PHPExcel_Style_Font $font = null, $rotation = 0) |
{ |
$fontName = $font->getName(); |
$fontSize = $font->getSize(); |
// Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. |
switch ($fontName) { |
case 'Calibri': |
// value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. |
$columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); |
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size |
break; |
case 'Arial': |
// value 7 was found via interpolation by inspecting real Excel files with Arial 10 font. |
$columnWidth = (int) (7 * PHPExcel_Shared_String::CountCharacters($columnText)); |
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size |
break; |
case 'Verdana': |
// value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. |
$columnWidth = (int) (8 * PHPExcel_Shared_String::CountCharacters($columnText)); |
$columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size |
break; |
default: |
// just assume Calibri |
$columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); |
$columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size |
break; |
} |
// Calculate approximate rotated column width |
if ($rotation !== 0) { |
if ($rotation == -165) { |
// stacked text |
$columnWidth = 4; // approximation |
} else { |
// rotated text |
$columnWidth = $columnWidth * cos(deg2rad($rotation)) |
+ $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation |
} |
} |
// pixel width is an integer |
$columnWidth = (int) $columnWidth; |
return $columnWidth; |
} |
/** |
* Calculate an (approximate) pixel size, based on a font points size |
* |
* @param int $fontSizeInPoints Font size (in points) |
* @return int Font size (in pixels) |
*/ |
public static function fontSizeToPixels($fontSizeInPoints = 11) { |
return (int) ((4 / 3) * $fontSizeInPoints); |
} |
/** |
* Calculate an (approximate) pixel size, based on inch size |
* |
* @param int $sizeInInch Font size (in inch) |
* @return int Size (in pixels) |
*/ |
public static function inchSizeToPixels($sizeInInch = 1) { |
return ($sizeInInch * 96); |
} |
/** |
* Calculate an (approximate) pixel size, based on centimeter size |
* |
* @param int $sizeInCm Font size (in centimeters) |
* @return int Size (in pixels) |
*/ |
public static function centimeterSizeToPixels($sizeInCm = 1) { |
return ($sizeInCm * 37.795275591); |
} |
/** |
* Returns the font path given the font |
* |
* @param PHPExcel_Style_Font |
* @return string Path to TrueType font file |
*/ |
public static function getTrueTypeFontFileFromFont($font) { |
if (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)) { |
throw new PHPExcel_Exception('Valid directory to TrueType Font files not specified'); |
} |
$name = $font->getName(); |
$bold = $font->getBold(); |
$italic = $font->getItalic(); |
// Check if we can map font to true type font file |
switch ($name) { |
case 'Arial': |
$fontFile = ( |
$bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD) |
: ($italic ? self::ARIAL_ITALIC : self::ARIAL) |
); |
break; |
case 'Calibri': |
$fontFile = ( |
$bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD) |
: ($italic ? self::CALIBRI_ITALIC : self::CALIBRI) |
); |
break; |
case 'Courier New': |
$fontFile = ( |
$bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD) |
: ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW) |
); |
break; |
case 'Comic Sans MS': |
$fontFile = ( |
$bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS |
); |
break; |
case 'Georgia': |
$fontFile = ( |
$bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD) |
: ($italic ? self::GEORGIA_ITALIC : self::GEORGIA) |
); |
break; |
case 'Impact': |
$fontFile = self::IMPACT; |
break; |
case 'Liberation Sans': |
$fontFile = ( |
$bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD) |
: ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS) |
); |
break; |
case 'Lucida Console': |
$fontFile = self::LUCIDA_CONSOLE; |
break; |
case 'Lucida Sans Unicode': |
$fontFile = self::LUCIDA_SANS_UNICODE; |
break; |
case 'Microsoft Sans Serif': |
$fontFile = self::MICROSOFT_SANS_SERIF; |
break; |
case 'Palatino Linotype': |
$fontFile = ( |
$bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD) |
: ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE) |
); |
break; |
case 'Symbol': |
$fontFile = self::SYMBOL; |
break; |
case 'Tahoma': |
$fontFile = ( |
$bold ? self::TAHOMA_BOLD : self::TAHOMA |
); |
break; |
case 'Times New Roman': |
$fontFile = ( |
$bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD) |
: ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN) |
); |
break; |
case 'Trebuchet MS': |
$fontFile = ( |
$bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD) |
: ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS) |
); |
break; |
case 'Verdana': |
$fontFile = ( |
$bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD) |
: ($italic ? self::VERDANA_ITALIC : self::VERDANA) |
); |
break; |
default: |
throw new PHPExcel_Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file'); |
break; |
} |
$fontFile = self::$trueTypeFontPath . $fontFile; |
// Check if file actually exists |
if (!file_exists($fontFile)) { |
throw New PHPExcel_Exception('TrueType Font file not found'); |
} |
return $fontFile; |
} |
/** |
* Returns the associated charset for the font name. |
* |
* @param string $name Font name |
* @return int Character set code |
*/ |
public static function getCharsetFromFontName($name) |
{ |
switch ($name) { |
// Add more cases. Check FONT records in real Excel files. |
case 'EucrosiaUPC': return self::CHARSET_ANSI_THAI; |
case 'Wingdings': return self::CHARSET_SYMBOL; |
case 'Wingdings 2': return self::CHARSET_SYMBOL; |
case 'Wingdings 3': return self::CHARSET_SYMBOL; |
default: return self::CHARSET_ANSI_LATIN; |
} |
} |
/** |
* Get the effective column width for columns without a column dimension or column with width -1 |
* For example, for Calibri 11 this is 9.140625 (64 px) |
* |
* @param PHPExcel_Style_Font $font The workbooks default font |
* @param boolean $pPixels true = return column width in pixels, false = return in OOXML units |
* @return mixed Column width |
*/ |
public static function getDefaultColumnWidthByFont(PHPExcel_Style_Font $font, $pPixels = false) |
{ |
if (isset(self::$defaultColumnWidths[$font->getName()][$font->getSize()])) { |
// Exact width can be determined |
$columnWidth = $pPixels ? |
self::$defaultColumnWidths[$font->getName()][$font->getSize()]['px'] |
: self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width']; |
} else { |
// We don't have data for this particular font and size, use approximation by |
// extrapolating from Calibri 11 |
$columnWidth = $pPixels ? |
self::$defaultColumnWidths['Calibri'][11]['px'] |
: self::$defaultColumnWidths['Calibri'][11]['width']; |
$columnWidth = $columnWidth * $font->getSize() / 11; |
// Round pixels to closest integer |
if ($pPixels) { |
$columnWidth = (int) round($columnWidth); |
} |
} |
return $columnWidth; |
} |
/** |
* Get the effective row height for rows without a row dimension or rows with height -1 |
* For example, for Calibri 11 this is 15 points |
* |
* @param PHPExcel_Style_Font $font The workbooks default font |
* @return float Row height in points |
*/ |
public static function getDefaultRowHeightByFont(PHPExcel_Style_Font $font) |
{ |
switch ($font->getName()) { |
case 'Arial': |
switch ($font->getSize()) { |
case 10: |
// inspection of Arial 10 workbook says 12.75pt ~17px |
$rowHeight = 12.75; |
break; |
case 9: |
// inspection of Arial 9 workbook says 12.00pt ~16px |
$rowHeight = 12; |
break; |
case 8: |
// inspection of Arial 8 workbook says 11.25pt ~15px |
$rowHeight = 11.25; |
break; |
case 7: |
// inspection of Arial 7 workbook says 9.00pt ~12px |
$rowHeight = 9; |
break; |
case 6: |
case 5: |
// inspection of Arial 5,6 workbook says 8.25pt ~11px |
$rowHeight = 8.25; |
break; |
case 4: |
// inspection of Arial 4 workbook says 6.75pt ~9px |
$rowHeight = 6.75; |
break; |
case 3: |
// inspection of Arial 3 workbook says 6.00pt ~8px |
$rowHeight = 6; |
break; |
case 2: |
case 1: |
// inspection of Arial 1,2 workbook says 5.25pt ~7px |
$rowHeight = 5.25; |
break; |
default: |
// use Arial 10 workbook as an approximation, extrapolation |
$rowHeight = 12.75 * $font->getSize() / 10; |
break; |
} |
break; |
case 'Calibri': |
switch ($font->getSize()) { |
case 11: |
// inspection of Calibri 11 workbook says 15.00pt ~20px |
$rowHeight = 15; |
break; |
case 10: |
// inspection of Calibri 10 workbook says 12.75pt ~17px |
$rowHeight = 12.75; |
break; |
case 9: |
// inspection of Calibri 9 workbook says 12.00pt ~16px |
$rowHeight = 12; |
break; |
case 8: |
// inspection of Calibri 8 workbook says 11.25pt ~15px |
$rowHeight = 11.25; |
break; |
case 7: |
// inspection of Calibri 7 workbook says 9.00pt ~12px |
$rowHeight = 9; |
break; |
case 6: |
case 5: |
// inspection of Calibri 5,6 workbook says 8.25pt ~11px |
$rowHeight = 8.25; |
break; |
case 4: |
// inspection of Calibri 4 workbook says 6.75pt ~9px |
$rowHeight = 6.75; |
break; |
case 3: |
// inspection of Calibri 3 workbook says 6.00pt ~8px |
$rowHeight = 6.00; |
break; |
case 2: |
case 1: |
// inspection of Calibri 1,2 workbook says 5.25pt ~7px |
$rowHeight = 5.25; |
break; |
default: |
// use Calibri 11 workbook as an approximation, extrapolation |
$rowHeight = 15 * $font->getSize() / 11; |
break; |
} |
break; |
case 'Verdana': |
switch ($font->getSize()) { |
case 10: |
// inspection of Verdana 10 workbook says 12.75pt ~17px |
$rowHeight = 12.75; |
break; |
case 9: |
// inspection of Verdana 9 workbook says 11.25pt ~15px |
$rowHeight = 11.25; |
break; |
case 8: |
// inspection of Verdana 8 workbook says 10.50pt ~14px |
$rowHeight = 10.50; |
break; |
case 7: |
// inspection of Verdana 7 workbook says 9.00pt ~12px |
$rowHeight = 9.00; |
break; |
case 6: |
case 5: |
// inspection of Verdana 5,6 workbook says 8.25pt ~11px |
$rowHeight = 8.25; |
break; |
case 4: |
// inspection of Verdana 4 workbook says 6.75pt ~9px |
$rowHeight = 6.75; |
break; |
case 3: |
// inspection of Verdana 3 workbook says 6.00pt ~8px |
$rowHeight = 6; |
break; |
case 2: |
case 1: |
// inspection of Verdana 1,2 workbook says 5.25pt ~7px |
$rowHeight = 5.25; |
break; |
default: |
// use Verdana 10 workbook as an approximation, extrapolation |
$rowHeight = 12.75 * $font->getSize() / 10; |
break; |
} |
break; |
default: |
// just use Calibri as an approximation |
$rowHeight = 15 * $font->getSize() / 11; |
break; |
} |
return $rowHeight; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/String.php |
---|
New file |
0,0 → 1,776 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_String |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_String |
{ |
/** Constants */ |
/** Regular Expressions */ |
// Fraction |
const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)'; |
/** |
* Control characters array |
* |
* @var string[] |
*/ |
private static $_controlCharacters = array(); |
/** |
* SYLK Characters array |
* |
* $var array |
*/ |
private static $_SYLKCharacters = array(); |
/** |
* Decimal separator |
* |
* @var string |
*/ |
private static $_decimalSeparator; |
/** |
* Thousands separator |
* |
* @var string |
*/ |
private static $_thousandsSeparator; |
/** |
* Currency code |
* |
* @var string |
*/ |
private static $_currencyCode; |
/** |
* Is mbstring extension avalable? |
* |
* @var boolean |
*/ |
private static $_isMbstringEnabled; |
/** |
* Is iconv extension avalable? |
* |
* @var boolean |
*/ |
private static $_isIconvEnabled; |
/** |
* Build control characters array |
*/ |
private static function _buildControlCharacters() { |
for ($i = 0; $i <= 31; ++$i) { |
if ($i != 9 && $i != 10 && $i != 13) { |
$find = '_x' . sprintf('%04s' , strtoupper(dechex($i))) . '_'; |
$replace = chr($i); |
self::$_controlCharacters[$find] = $replace; |
} |
} |
} |
/** |
* Build SYLK characters array |
*/ |
private static function _buildSYLKCharacters() |
{ |
self::$_SYLKCharacters = array( |
"\x1B 0" => chr(0), |
"\x1B 1" => chr(1), |
"\x1B 2" => chr(2), |
"\x1B 3" => chr(3), |
"\x1B 4" => chr(4), |
"\x1B 5" => chr(5), |
"\x1B 6" => chr(6), |
"\x1B 7" => chr(7), |
"\x1B 8" => chr(8), |
"\x1B 9" => chr(9), |
"\x1B :" => chr(10), |
"\x1B ;" => chr(11), |
"\x1B <" => chr(12), |
"\x1B :" => chr(13), |
"\x1B >" => chr(14), |
"\x1B ?" => chr(15), |
"\x1B!0" => chr(16), |
"\x1B!1" => chr(17), |
"\x1B!2" => chr(18), |
"\x1B!3" => chr(19), |
"\x1B!4" => chr(20), |
"\x1B!5" => chr(21), |
"\x1B!6" => chr(22), |
"\x1B!7" => chr(23), |
"\x1B!8" => chr(24), |
"\x1B!9" => chr(25), |
"\x1B!:" => chr(26), |
"\x1B!;" => chr(27), |
"\x1B!<" => chr(28), |
"\x1B!=" => chr(29), |
"\x1B!>" => chr(30), |
"\x1B!?" => chr(31), |
"\x1B'?" => chr(127), |
"\x1B(0" => '€', // 128 in CP1252 |
"\x1B(2" => '‚', // 130 in CP1252 |
"\x1B(3" => 'ƒ', // 131 in CP1252 |
"\x1B(4" => '„', // 132 in CP1252 |
"\x1B(5" => '…', // 133 in CP1252 |
"\x1B(6" => '†', // 134 in CP1252 |
"\x1B(7" => '‡', // 135 in CP1252 |
"\x1B(8" => 'ˆ', // 136 in CP1252 |
"\x1B(9" => '‰', // 137 in CP1252 |
"\x1B(:" => 'Š', // 138 in CP1252 |
"\x1B(;" => '‹', // 139 in CP1252 |
"\x1BNj" => 'Œ', // 140 in CP1252 |
"\x1B(>" => 'Ž', // 142 in CP1252 |
"\x1B)1" => '‘', // 145 in CP1252 |
"\x1B)2" => '’', // 146 in CP1252 |
"\x1B)3" => '“', // 147 in CP1252 |
"\x1B)4" => '”', // 148 in CP1252 |
"\x1B)5" => '•', // 149 in CP1252 |
"\x1B)6" => '–', // 150 in CP1252 |
"\x1B)7" => '—', // 151 in CP1252 |
"\x1B)8" => '˜', // 152 in CP1252 |
"\x1B)9" => '™', // 153 in CP1252 |
"\x1B):" => 'š', // 154 in CP1252 |
"\x1B);" => '›', // 155 in CP1252 |
"\x1BNz" => 'œ', // 156 in CP1252 |
"\x1B)>" => 'ž', // 158 in CP1252 |
"\x1B)?" => 'Ÿ', // 159 in CP1252 |
"\x1B*0" => ' ', // 160 in CP1252 |
"\x1BN!" => '¡', // 161 in CP1252 |
"\x1BN\"" => '¢', // 162 in CP1252 |
"\x1BN#" => '£', // 163 in CP1252 |
"\x1BN(" => '¤', // 164 in CP1252 |
"\x1BN%" => '¥', // 165 in CP1252 |
"\x1B*6" => '¦', // 166 in CP1252 |
"\x1BN'" => '§', // 167 in CP1252 |
"\x1BNH " => '¨', // 168 in CP1252 |
"\x1BNS" => '©', // 169 in CP1252 |
"\x1BNc" => 'ª', // 170 in CP1252 |
"\x1BN+" => '«', // 171 in CP1252 |
"\x1B*<" => '¬', // 172 in CP1252 |
"\x1B*=" => '', // 173 in CP1252 |
"\x1BNR" => '®', // 174 in CP1252 |
"\x1B*?" => '¯', // 175 in CP1252 |
"\x1BN0" => '°', // 176 in CP1252 |
"\x1BN1" => '±', // 177 in CP1252 |
"\x1BN2" => '²', // 178 in CP1252 |
"\x1BN3" => '³', // 179 in CP1252 |
"\x1BNB " => '´', // 180 in CP1252 |
"\x1BN5" => 'µ', // 181 in CP1252 |
"\x1BN6" => '¶', // 182 in CP1252 |
"\x1BN7" => '·', // 183 in CP1252 |
"\x1B+8" => '¸', // 184 in CP1252 |
"\x1BNQ" => '¹', // 185 in CP1252 |
"\x1BNk" => 'º', // 186 in CP1252 |
"\x1BN;" => '»', // 187 in CP1252 |
"\x1BN<" => '¼', // 188 in CP1252 |
"\x1BN=" => '½', // 189 in CP1252 |
"\x1BN>" => '¾', // 190 in CP1252 |
"\x1BN?" => '¿', // 191 in CP1252 |
"\x1BNAA" => 'À', // 192 in CP1252 |
"\x1BNBA" => 'Á', // 193 in CP1252 |
"\x1BNCA" => 'Â', // 194 in CP1252 |
"\x1BNDA" => 'Ã', // 195 in CP1252 |
"\x1BNHA" => 'Ä', // 196 in CP1252 |
"\x1BNJA" => 'Å', // 197 in CP1252 |
"\x1BNa" => 'Æ', // 198 in CP1252 |
"\x1BNKC" => 'Ç', // 199 in CP1252 |
"\x1BNAE" => 'È', // 200 in CP1252 |
"\x1BNBE" => 'É', // 201 in CP1252 |
"\x1BNCE" => 'Ê', // 202 in CP1252 |
"\x1BNHE" => 'Ë', // 203 in CP1252 |
"\x1BNAI" => 'Ì', // 204 in CP1252 |
"\x1BNBI" => 'Í', // 205 in CP1252 |
"\x1BNCI" => 'Î', // 206 in CP1252 |
"\x1BNHI" => 'Ï', // 207 in CP1252 |
"\x1BNb" => 'Ð', // 208 in CP1252 |
"\x1BNDN" => 'Ñ', // 209 in CP1252 |
"\x1BNAO" => 'Ò', // 210 in CP1252 |
"\x1BNBO" => 'Ó', // 211 in CP1252 |
"\x1BNCO" => 'Ô', // 212 in CP1252 |
"\x1BNDO" => 'Õ', // 213 in CP1252 |
"\x1BNHO" => 'Ö', // 214 in CP1252 |
"\x1B-7" => '×', // 215 in CP1252 |
"\x1BNi" => 'Ø', // 216 in CP1252 |
"\x1BNAU" => 'Ù', // 217 in CP1252 |
"\x1BNBU" => 'Ú', // 218 in CP1252 |
"\x1BNCU" => 'Û', // 219 in CP1252 |
"\x1BNHU" => 'Ü', // 220 in CP1252 |
"\x1B-=" => 'Ý', // 221 in CP1252 |
"\x1BNl" => 'Þ', // 222 in CP1252 |
"\x1BN{" => 'ß', // 223 in CP1252 |
"\x1BNAa" => 'à', // 224 in CP1252 |
"\x1BNBa" => 'á', // 225 in CP1252 |
"\x1BNCa" => 'â', // 226 in CP1252 |
"\x1BNDa" => 'ã', // 227 in CP1252 |
"\x1BNHa" => 'ä', // 228 in CP1252 |
"\x1BNJa" => 'å', // 229 in CP1252 |
"\x1BNq" => 'æ', // 230 in CP1252 |
"\x1BNKc" => 'ç', // 231 in CP1252 |
"\x1BNAe" => 'è', // 232 in CP1252 |
"\x1BNBe" => 'é', // 233 in CP1252 |
"\x1BNCe" => 'ê', // 234 in CP1252 |
"\x1BNHe" => 'ë', // 235 in CP1252 |
"\x1BNAi" => 'ì', // 236 in CP1252 |
"\x1BNBi" => 'í', // 237 in CP1252 |
"\x1BNCi" => 'î', // 238 in CP1252 |
"\x1BNHi" => 'ï', // 239 in CP1252 |
"\x1BNs" => 'ð', // 240 in CP1252 |
"\x1BNDn" => 'ñ', // 241 in CP1252 |
"\x1BNAo" => 'ò', // 242 in CP1252 |
"\x1BNBo" => 'ó', // 243 in CP1252 |
"\x1BNCo" => 'ô', // 244 in CP1252 |
"\x1BNDo" => 'õ', // 245 in CP1252 |
"\x1BNHo" => 'ö', // 246 in CP1252 |
"\x1B/7" => '÷', // 247 in CP1252 |
"\x1BNy" => 'ø', // 248 in CP1252 |
"\x1BNAu" => 'ù', // 249 in CP1252 |
"\x1BNBu" => 'ú', // 250 in CP1252 |
"\x1BNCu" => 'û', // 251 in CP1252 |
"\x1BNHu" => 'ü', // 252 in CP1252 |
"\x1B/=" => 'ý', // 253 in CP1252 |
"\x1BN|" => 'þ', // 254 in CP1252 |
"\x1BNHy" => 'ÿ', // 255 in CP1252 |
); |
} |
/** |
* Get whether mbstring extension is available |
* |
* @return boolean |
*/ |
public static function getIsMbstringEnabled() |
{ |
if (isset(self::$_isMbstringEnabled)) { |
return self::$_isMbstringEnabled; |
} |
self::$_isMbstringEnabled = function_exists('mb_convert_encoding') ? |
true : false; |
return self::$_isMbstringEnabled; |
} |
/** |
* Get whether iconv extension is available |
* |
* @return boolean |
*/ |
public static function getIsIconvEnabled() |
{ |
if (isset(self::$_isIconvEnabled)) { |
return self::$_isIconvEnabled; |
} |
// Fail if iconv doesn't exist |
if (!function_exists('iconv')) { |
self::$_isIconvEnabled = false; |
return false; |
} |
// Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false, |
if (!@iconv('UTF-8', 'UTF-16LE', 'x')) { |
self::$_isIconvEnabled = false; |
return false; |
} |
// Sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0 |
// we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773) |
if (!@iconv_substr('A', 0, 1, 'UTF-8')) { |
self::$_isIconvEnabled = false; |
return false; |
} |
// CUSTOM: IBM AIX iconv() does not work |
if ( defined('PHP_OS') && @stristr(PHP_OS, 'AIX') |
&& defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) |
&& defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0) ) |
{ |
self::$_isIconvEnabled = false; |
return false; |
} |
// If we reach here no problems were detected with iconv |
self::$_isIconvEnabled = true; |
return true; |
} |
public static function buildCharacterSets() { |
if(empty(self::$_controlCharacters)) { |
self::_buildControlCharacters(); |
} |
if(empty(self::$_SYLKCharacters)) { |
self::_buildSYLKCharacters(); |
} |
} |
/** |
* Convert from OpenXML escaped control character to PHP control character |
* |
* Excel 2007 team: |
* ---------------- |
* That's correct, control characters are stored directly in the shared-strings table. |
* We do encode characters that cannot be represented in XML using the following escape sequence: |
* _xHHHH_ where H represents a hexadecimal character in the character's value... |
* So you could end up with something like _x0008_ in a string (either in a cell value (<v>) |
* element or in the shared string <t> element. |
* |
* @param string $value Value to unescape |
* @return string |
*/ |
public static function ControlCharacterOOXML2PHP($value = '') { |
return str_replace( array_keys(self::$_controlCharacters), array_values(self::$_controlCharacters), $value ); |
} |
/** |
* Convert from PHP control character to OpenXML escaped control character |
* |
* Excel 2007 team: |
* ---------------- |
* That's correct, control characters are stored directly in the shared-strings table. |
* We do encode characters that cannot be represented in XML using the following escape sequence: |
* _xHHHH_ where H represents a hexadecimal character in the character's value... |
* So you could end up with something like _x0008_ in a string (either in a cell value (<v>) |
* element or in the shared string <t> element. |
* |
* @param string $value Value to escape |
* @return string |
*/ |
public static function ControlCharacterPHP2OOXML($value = '') { |
return str_replace( array_values(self::$_controlCharacters), array_keys(self::$_controlCharacters), $value ); |
} |
/** |
* Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters. |
* |
* @param string $value |
* @return string |
*/ |
public static function SanitizeUTF8($value) |
{ |
if (self::getIsIconvEnabled()) { |
$value = @iconv('UTF-8', 'UTF-8', $value); |
return $value; |
} |
if (self::getIsMbstringEnabled()) { |
$value = mb_convert_encoding($value, 'UTF-8', 'UTF-8'); |
return $value; |
} |
// else, no conversion |
return $value; |
} |
/** |
* Check if a string contains UTF8 data |
* |
* @param string $value |
* @return boolean |
*/ |
public static function IsUTF8($value = '') { |
return utf8_encode(utf8_decode($value)) === $value; |
} |
/** |
* Formats a numeric value as a string for output in various output writers forcing |
* point as decimal separator in case locale is other than English. |
* |
* @param mixed $value |
* @return string |
*/ |
public static function FormatNumber($value) { |
if (is_float($value)) { |
return str_replace(',', '.', $value); |
} |
return (string) $value; |
} |
/** |
* Converts a UTF-8 string into BIFF8 Unicode string data (8-bit string length) |
* Writes the string using uncompressed notation, no rich text, no Asian phonetics |
* If mbstring extension is not available, ASCII is assumed, and compressed notation is used |
* although this will give wrong results for non-ASCII strings |
* see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3 |
* |
* @param string $value UTF-8 encoded string |
* @param mixed[] $arrcRuns Details of rich text runs in $value |
* @return string |
*/ |
public static function UTF8toBIFF8UnicodeShort($value, $arrcRuns = array()) |
{ |
// character count |
$ln = self::CountCharacters($value, 'UTF-8'); |
// option flags |
if(empty($arrcRuns)){ |
$opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? |
0x0001 : 0x0000; |
$data = pack('CC', $ln, $opt); |
// characters |
$data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); |
} |
else { |
$data = pack('vC', $ln, 0x09); |
$data .= pack('v', count($arrcRuns)); |
// characters |
$data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); |
foreach ($arrcRuns as $cRun){ |
$data .= pack('v', $cRun['strlen']); |
$data .= pack('v', $cRun['fontidx']); |
} |
} |
return $data; |
} |
/** |
* Converts a UTF-8 string into BIFF8 Unicode string data (16-bit string length) |
* Writes the string using uncompressed notation, no rich text, no Asian phonetics |
* If mbstring extension is not available, ASCII is assumed, and compressed notation is used |
* although this will give wrong results for non-ASCII strings |
* see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3 |
* |
* @param string $value UTF-8 encoded string |
* @return string |
*/ |
public static function UTF8toBIFF8UnicodeLong($value) |
{ |
// character count |
$ln = self::CountCharacters($value, 'UTF-8'); |
// option flags |
$opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? |
0x0001 : 0x0000; |
// characters |
$chars = self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); |
$data = pack('vC', $ln, $opt) . $chars; |
return $data; |
} |
/** |
* Convert string from one encoding to another. First try mbstring, then iconv, finally strlen |
* |
* @param string $value |
* @param string $to Encoding to convert to, e.g. 'UTF-8' |
* @param string $from Encoding to convert from, e.g. 'UTF-16LE' |
* @return string |
*/ |
public static function ConvertEncoding($value, $to, $from) |
{ |
if (self::getIsIconvEnabled()) { |
return iconv($from, $to, $value); |
} |
if (self::getIsMbstringEnabled()) { |
return mb_convert_encoding($value, $to, $from); |
} |
if($from == 'UTF-16LE'){ |
return self::utf16_decode($value, false); |
}else if($from == 'UTF-16BE'){ |
return self::utf16_decode($value); |
} |
// else, no conversion |
return $value; |
} |
/** |
* Decode UTF-16 encoded strings. |
* |
* Can handle both BOM'ed data and un-BOM'ed data. |
* Assumes Big-Endian byte order if no BOM is available. |
* This function was taken from http://php.net/manual/en/function.utf8-decode.php |
* and $bom_be parameter added. |
* |
* @param string $str UTF-16 encoded data to decode. |
* @return string UTF-8 / ISO encoded data. |
* @access public |
* @version 0.2 / 2010-05-13 |
* @author Rasmus Andersson {@link http://rasmusandersson.se/} |
* @author vadik56 |
*/ |
public static function utf16_decode($str, $bom_be = TRUE) { |
if( strlen($str) < 2 ) return $str; |
$c0 = ord($str{0}); |
$c1 = ord($str{1}); |
if( $c0 == 0xfe && $c1 == 0xff ) { $str = substr($str,2); } |
elseif( $c0 == 0xff && $c1 == 0xfe ) { $str = substr($str,2); $bom_be = false; } |
$len = strlen($str); |
$newstr = ''; |
for($i=0;$i<$len;$i+=2) { |
if( $bom_be ) { $val = ord($str{$i}) << 4; $val += ord($str{$i+1}); } |
else { $val = ord($str{$i+1}) << 4; $val += ord($str{$i}); } |
$newstr .= ($val == 0x228) ? "\n" : chr($val); |
} |
return $newstr; |
} |
/** |
* Get character count. First try mbstring, then iconv, finally strlen |
* |
* @param string $value |
* @param string $enc Encoding |
* @return int Character count |
*/ |
public static function CountCharacters($value, $enc = 'UTF-8') |
{ |
if (self::getIsMbstringEnabled()) { |
return mb_strlen($value, $enc); |
} |
if (self::getIsIconvEnabled()) { |
return iconv_strlen($value, $enc); |
} |
// else strlen |
return strlen($value); |
} |
/** |
* Get a substring of a UTF-8 encoded string. First try mbstring, then iconv, finally strlen |
* |
* @param string $pValue UTF-8 encoded string |
* @param int $pStart Start offset |
* @param int $pLength Maximum number of characters in substring |
* @return string |
*/ |
public static function Substring($pValue = '', $pStart = 0, $pLength = 0) |
{ |
if (self::getIsMbstringEnabled()) { |
return mb_substr($pValue, $pStart, $pLength, 'UTF-8'); |
} |
if (self::getIsIconvEnabled()) { |
return iconv_substr($pValue, $pStart, $pLength, 'UTF-8'); |
} |
// else substr |
return substr($pValue, $pStart, $pLength); |
} |
/** |
* Convert a UTF-8 encoded string to upper case |
* |
* @param string $pValue UTF-8 encoded string |
* @return string |
*/ |
public static function StrToUpper($pValue = '') |
{ |
if (function_exists('mb_convert_case')) { |
return mb_convert_case($pValue, MB_CASE_UPPER, "UTF-8"); |
} |
return strtoupper($pValue); |
} |
/** |
* Convert a UTF-8 encoded string to lower case |
* |
* @param string $pValue UTF-8 encoded string |
* @return string |
*/ |
public static function StrToLower($pValue = '') |
{ |
if (function_exists('mb_convert_case')) { |
return mb_convert_case($pValue, MB_CASE_LOWER, "UTF-8"); |
} |
return strtolower($pValue); |
} |
/** |
* Convert a UTF-8 encoded string to title/proper case |
* (uppercase every first character in each word, lower case all other characters) |
* |
* @param string $pValue UTF-8 encoded string |
* @return string |
*/ |
public static function StrToTitle($pValue = '') |
{ |
if (function_exists('mb_convert_case')) { |
return mb_convert_case($pValue, MB_CASE_TITLE, "UTF-8"); |
} |
return ucwords($pValue); |
} |
/** |
* Identify whether a string contains a fractional numeric value, |
* and convert it to a numeric if it is |
* |
* @param string &$operand string value to test |
* @return boolean |
*/ |
public static function convertToNumberIfFraction(&$operand) { |
if (preg_match('/^'.self::STRING_REGEXP_FRACTION.'$/i', $operand, $match)) { |
$sign = ($match[1] == '-') ? '-' : '+'; |
$fractionFormula = '='.$sign.$match[2].$sign.$match[3]; |
$operand = PHPExcel_Calculation::getInstance()->_calculateFormulaValue($fractionFormula); |
return true; |
} |
return false; |
} // function convertToNumberIfFraction() |
/** |
* Get the decimal separator. If it has not yet been set explicitly, try to obtain number |
* formatting information from locale. |
* |
* @return string |
*/ |
public static function getDecimalSeparator() |
{ |
if (!isset(self::$_decimalSeparator)) { |
$localeconv = localeconv(); |
self::$_decimalSeparator = ($localeconv['decimal_point'] != '') |
? $localeconv['decimal_point'] : $localeconv['mon_decimal_point']; |
if (self::$_decimalSeparator == '') { |
// Default to . |
self::$_decimalSeparator = '.'; |
} |
} |
return self::$_decimalSeparator; |
} |
/** |
* Set the decimal separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() |
* to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF |
* |
* @param string $pValue Character for decimal separator |
*/ |
public static function setDecimalSeparator($pValue = '.') |
{ |
self::$_decimalSeparator = $pValue; |
} |
/** |
* Get the thousands separator. If it has not yet been set explicitly, try to obtain number |
* formatting information from locale. |
* |
* @return string |
*/ |
public static function getThousandsSeparator() |
{ |
if (!isset(self::$_thousandsSeparator)) { |
$localeconv = localeconv(); |
self::$_thousandsSeparator = ($localeconv['thousands_sep'] != '') |
? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep']; |
if (self::$_thousandsSeparator == '') { |
// Default to . |
self::$_thousandsSeparator = ','; |
} |
} |
return self::$_thousandsSeparator; |
} |
/** |
* Set the thousands separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() |
* to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF |
* |
* @param string $pValue Character for thousands separator |
*/ |
public static function setThousandsSeparator($pValue = ',') |
{ |
self::$_thousandsSeparator = $pValue; |
} |
/** |
* Get the currency code. If it has not yet been set explicitly, try to obtain the |
* symbol information from locale. |
* |
* @return string |
*/ |
public static function getCurrencyCode() |
{ |
if (!isset(self::$_currencyCode)) { |
$localeconv = localeconv(); |
self::$_currencyCode = ($localeconv['currency_symbol'] != '') |
? $localeconv['currency_symbol'] : $localeconv['int_curr_symbol']; |
if (self::$_currencyCode == '') { |
// Default to $ |
self::$_currencyCode = '$'; |
} |
} |
return self::$_currencyCode; |
} |
/** |
* Set the currency code. Only used by PHPExcel_Style_NumberFormat::toFormattedString() |
* to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF |
* |
* @param string $pValue Character for currency code |
*/ |
public static function setCurrencyCode($pValue = '$') |
{ |
self::$_currencyCode = $pValue; |
} |
/** |
* Convert SYLK encoded string to UTF-8 |
* |
* @param string $pValue |
* @return string UTF-8 encoded string |
*/ |
public static function SYLKtoUTF8($pValue = '') |
{ |
// If there is no escape character in the string there is nothing to do |
if (strpos($pValue, '') === false) { |
return $pValue; |
} |
foreach (self::$_SYLKCharacters as $k => $v) { |
$pValue = str_replace($k, $v, $pValue); |
} |
return $pValue; |
} |
/** |
* Retrieve any leading numeric part of a string, or return the full string if no leading numeric |
* (handles basic integer or float, but not exponent or non decimal) |
* |
* @param string $value |
* @return mixed string or only the leading numeric part of the string |
*/ |
public static function testStringAsNumeric($value) |
{ |
if (is_numeric($value)) |
return $value; |
$v = floatval($value); |
return (is_numeric(substr($value,0,strlen($v)))) ? $v : $value; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/CodePage.php |
---|
New file |
0,0 → 1,101 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_CodePage |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_CodePage |
{ |
/** |
* Convert Microsoft Code Page Identifier to Code Page Name which iconv |
* and mbstring understands |
* |
* @param integer $codePage Microsoft Code Page Indentifier |
* @return string Code Page Name |
* @throws PHPExcel_Exception |
*/ |
public static function NumberToName($codePage = 1252) |
{ |
switch ($codePage) { |
case 367: return 'ASCII'; break; // ASCII |
case 437: return 'CP437'; break; // OEM US |
case 720: throw new PHPExcel_Exception('Code page 720 not supported.'); |
break; // OEM Arabic |
case 737: return 'CP737'; break; // OEM Greek |
case 775: return 'CP775'; break; // OEM Baltic |
case 850: return 'CP850'; break; // OEM Latin I |
case 852: return 'CP852'; break; // OEM Latin II (Central European) |
case 855: return 'CP855'; break; // OEM Cyrillic |
case 857: return 'CP857'; break; // OEM Turkish |
case 858: return 'CP858'; break; // OEM Multilingual Latin I with Euro |
case 860: return 'CP860'; break; // OEM Portugese |
case 861: return 'CP861'; break; // OEM Icelandic |
case 862: return 'CP862'; break; // OEM Hebrew |
case 863: return 'CP863'; break; // OEM Canadian (French) |
case 864: return 'CP864'; break; // OEM Arabic |
case 865: return 'CP865'; break; // OEM Nordic |
case 866: return 'CP866'; break; // OEM Cyrillic (Russian) |
case 869: return 'CP869'; break; // OEM Greek (Modern) |
case 874: return 'CP874'; break; // ANSI Thai |
case 932: return 'CP932'; break; // ANSI Japanese Shift-JIS |
case 936: return 'CP936'; break; // ANSI Chinese Simplified GBK |
case 949: return 'CP949'; break; // ANSI Korean (Wansung) |
case 950: return 'CP950'; break; // ANSI Chinese Traditional BIG5 |
case 1200: return 'UTF-16LE'; break; // UTF-16 (BIFF8) |
case 1250: return 'CP1250'; break; // ANSI Latin II (Central European) |
case 1251: return 'CP1251'; break; // ANSI Cyrillic |
case 0: // CodePage is not always correctly set when the xls file was saved by Apple's Numbers program |
case 1252: return 'CP1252'; break; // ANSI Latin I (BIFF4-BIFF7) |
case 1253: return 'CP1253'; break; // ANSI Greek |
case 1254: return 'CP1254'; break; // ANSI Turkish |
case 1255: return 'CP1255'; break; // ANSI Hebrew |
case 1256: return 'CP1256'; break; // ANSI Arabic |
case 1257: return 'CP1257'; break; // ANSI Baltic |
case 1258: return 'CP1258'; break; // ANSI Vietnamese |
case 1361: return 'CP1361'; break; // ANSI Korean (Johab) |
case 10000: return 'MAC'; break; // Apple Roman |
case 10006: return 'MACGREEK'; break; // Macintosh Greek |
case 10007: return 'MACCYRILLIC'; break; // Macintosh Cyrillic |
case 10029: return 'MACCENTRALEUROPE'; break; // Macintosh Central Europe |
case 10079: return 'MACICELAND'; break; // Macintosh Icelandic |
case 10081: return 'MACTURKISH'; break; // Macintosh Turkish |
case 32768: return 'MAC'; break; // Apple Roman |
case 32769: throw new PHPExcel_Exception('Code page 32769 not supported.'); |
break; // ANSI Latin I (BIFF2-BIFF3) |
case 65000: return 'UTF-7'; break; // Unicode (UTF-7) |
case 65001: return 'UTF-8'; break; // Unicode (UTF-8) |
} |
throw new PHPExcel_Exception('Unknown codepage: ' . $codePage); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher.php |
---|
New file |
0,0 → 1,91 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher |
{ |
/** |
* Drawing Group Container |
* |
* @var PHPExcel_Shared_Escher_DggContainer |
*/ |
private $_dggContainer; |
/** |
* Drawing Container |
* |
* @var PHPExcel_Shared_Escher_DgContainer |
*/ |
private $_dgContainer; |
/** |
* Get Drawing Group Container |
* |
* @return PHPExcel_Shared_Escher_DgContainer |
*/ |
public function getDggContainer() |
{ |
return $this->_dggContainer; |
} |
/** |
* Set Drawing Group Container |
* |
* @param PHPExcel_Shared_Escher_DggContainer $dggContainer |
*/ |
public function setDggContainer($dggContainer) |
{ |
return $this->_dggContainer = $dggContainer; |
} |
/** |
* Get Drawing Container |
* |
* @return PHPExcel_Shared_Escher_DgContainer |
*/ |
public function getDgContainer() |
{ |
return $this->_dgContainer; |
} |
/** |
* Set Drawing Container |
* |
* @param PHPExcel_Shared_Escher_DgContainer $dgContainer |
*/ |
public function setDgContainer($dgContainer) |
{ |
return $this->_dgContainer = $dgContainer; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/OLERead.php |
---|
New file |
0,0 → 1,317 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
defined('IDENTIFIER_OLE') || |
define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); |
class PHPExcel_Shared_OLERead { |
private $data = ''; |
// OLE identifier |
const IDENTIFIER_OLE = IDENTIFIER_OLE; |
// Size of a sector = 512 bytes |
const BIG_BLOCK_SIZE = 0x200; |
// Size of a short sector = 64 bytes |
const SMALL_BLOCK_SIZE = 0x40; |
// Size of a directory entry always = 128 bytes |
const PROPERTY_STORAGE_BLOCK_SIZE = 0x80; |
// Minimum size of a standard stream = 4096 bytes, streams smaller than this are stored as short streams |
const SMALL_BLOCK_THRESHOLD = 0x1000; |
// header offsets |
const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c; |
const ROOT_START_BLOCK_POS = 0x30; |
const SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c; |
const EXTENSION_BLOCK_POS = 0x44; |
const NUM_EXTENSION_BLOCK_POS = 0x48; |
const BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c; |
// property storage offsets (directory offsets) |
const SIZE_OF_NAME_POS = 0x40; |
const TYPE_POS = 0x42; |
const START_BLOCK_POS = 0x74; |
const SIZE_POS = 0x78; |
public $wrkbook = null; |
public $summaryInformation = null; |
public $documentSummaryInformation = null; |
/** |
* Read the file |
* |
* @param $sFileName string Filename |
* @throws PHPExcel_Reader_Exception |
*/ |
public function read($sFileName) |
{ |
// Check if file exists and is readable |
if(!is_readable($sFileName)) { |
throw new PHPExcel_Reader_Exception("Could not open " . $sFileName . " for reading! File does not exist, or it is not readable."); |
} |
// Get the file identifier |
// Don't bother reading the whole file until we know it's a valid OLE file |
$this->data = file_get_contents($sFileName, FALSE, NULL, 0, 8); |
// Check OLE identifier |
if ($this->data != self::IDENTIFIER_OLE) { |
throw new PHPExcel_Reader_Exception('The filename ' . $sFileName . ' is not recognised as an OLE file'); |
} |
// Get the file data |
$this->data = file_get_contents($sFileName); |
// Total number of sectors used for the SAT |
$this->numBigBlockDepotBlocks = self::_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); |
// SecID of the first sector of the directory stream |
$this->rootStartBlock = self::_GetInt4d($this->data, self::ROOT_START_BLOCK_POS); |
// SecID of the first sector of the SSAT (or -2 if not extant) |
$this->sbdStartBlock = self::_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS); |
// SecID of the first sector of the MSAT (or -2 if no additional sectors are used) |
$this->extensionBlock = self::_GetInt4d($this->data, self::EXTENSION_BLOCK_POS); |
// Total number of sectors used by MSAT |
$this->numExtensionBlocks = self::_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); |
$bigBlockDepotBlocks = array(); |
$pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS; |
$bbdBlocks = $this->numBigBlockDepotBlocks; |
if ($this->numExtensionBlocks != 0) { |
$bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS)/4; |
} |
for ($i = 0; $i < $bbdBlocks; ++$i) { |
$bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); |
$pos += 4; |
} |
for ($j = 0; $j < $this->numExtensionBlocks; ++$j) { |
$pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE; |
$blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1); |
for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) { |
$bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); |
$pos += 4; |
} |
$bbdBlocks += $blocksToRead; |
if ($bbdBlocks < $this->numBigBlockDepotBlocks) { |
$this->extensionBlock = self::_GetInt4d($this->data, $pos); |
} |
} |
$pos = 0; |
$this->bigBlockChain = ''; |
$bbs = self::BIG_BLOCK_SIZE / 4; |
for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) { |
$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE; |
$this->bigBlockChain .= substr($this->data, $pos, 4*$bbs); |
$pos += 4*$bbs; |
} |
$pos = 0; |
$sbdBlock = $this->sbdStartBlock; |
$this->smallBlockChain = ''; |
while ($sbdBlock != -2) { |
$pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; |
$this->smallBlockChain .= substr($this->data, $pos, 4*$bbs); |
$pos += 4*$bbs; |
$sbdBlock = self::_GetInt4d($this->bigBlockChain, $sbdBlock*4); |
} |
// read the directory stream |
$block = $this->rootStartBlock; |
$this->entry = $this->_readData($block); |
$this->_readPropertySets(); |
} |
/** |
* Extract binary stream data |
* |
* @return string |
*/ |
public function getStream($stream) |
{ |
if ($stream === NULL) { |
return null; |
} |
$streamData = ''; |
if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) { |
$rootdata = $this->_readData($this->props[$this->rootentry]['startBlock']); |
$block = $this->props[$stream]['startBlock']; |
while ($block != -2) { |
$pos = $block * self::SMALL_BLOCK_SIZE; |
$streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); |
$block = self::_GetInt4d($this->smallBlockChain, $block*4); |
} |
return $streamData; |
} else { |
$numBlocks = $this->props[$stream]['size'] / self::BIG_BLOCK_SIZE; |
if ($this->props[$stream]['size'] % self::BIG_BLOCK_SIZE != 0) { |
++$numBlocks; |
} |
if ($numBlocks == 0) return ''; |
$block = $this->props[$stream]['startBlock']; |
while ($block != -2) { |
$pos = ($block + 1) * self::BIG_BLOCK_SIZE; |
$streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); |
$block = self::_GetInt4d($this->bigBlockChain, $block*4); |
} |
return $streamData; |
} |
} |
/** |
* Read a standard stream (by joining sectors using information from SAT) |
* |
* @param int $bl Sector ID where the stream starts |
* @return string Data for standard stream |
*/ |
private function _readData($bl) |
{ |
$block = $bl; |
$data = ''; |
while ($block != -2) { |
$pos = ($block + 1) * self::BIG_BLOCK_SIZE; |
$data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); |
$block = self::_GetInt4d($this->bigBlockChain, $block*4); |
} |
return $data; |
} |
/** |
* Read entries in the directory stream. |
*/ |
private function _readPropertySets() { |
$offset = 0; |
// loop through entires, each entry is 128 bytes |
$entryLen = strlen($this->entry); |
while ($offset < $entryLen) { |
// entry data (128 bytes) |
$d = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE); |
// size in bytes of name |
$nameSize = ord($d[self::SIZE_OF_NAME_POS]) | (ord($d[self::SIZE_OF_NAME_POS+1]) << 8); |
// type of entry |
$type = ord($d[self::TYPE_POS]); |
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook) |
// sectorID of first sector of the short-stream container stream, if this entry is root entry |
$startBlock = self::_GetInt4d($d, self::START_BLOCK_POS); |
$size = self::_GetInt4d($d, self::SIZE_POS); |
$name = str_replace("\x00", "", substr($d,0,$nameSize)); |
$this->props[] = array ( |
'name' => $name, |
'type' => $type, |
'startBlock' => $startBlock, |
'size' => $size); |
// tmp helper to simplify checks |
$upName = strtoupper($name); |
// Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook) |
if (($upName === 'WORKBOOK') || ($upName === 'BOOK')) { |
$this->wrkbook = count($this->props) - 1; |
} |
else if ( $upName === 'ROOT ENTRY' || $upName === 'R') { |
// Root entry |
$this->rootentry = count($this->props) - 1; |
} |
// Summary information |
if ($name == chr(5) . 'SummaryInformation') { |
// echo 'Summary Information<br />'; |
$this->summaryInformation = count($this->props) - 1; |
} |
// Additional Document Summary information |
if ($name == chr(5) . 'DocumentSummaryInformation') { |
// echo 'Document Summary Information<br />'; |
$this->documentSummaryInformation = count($this->props) - 1; |
} |
$offset += self::PROPERTY_STORAGE_BLOCK_SIZE; |
} |
} |
/** |
* Read 4 bytes of data at specified position |
* |
* @param string $data |
* @param int $pos |
* @return int |
*/ |
private static function _GetInt4d($data, $pos) |
{ |
// FIX: represent numbers correctly on 64-bit system |
// http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 |
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems |
$_or_24 = ord($data[$pos + 3]); |
if ($_or_24 >= 128) { |
// negative number |
$_ord_24 = -abs((256 - $_or_24) << 24); |
} else { |
$_ord_24 = ($_or_24 & 127) << 24; |
} |
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/PCLZip/readme.txt |
---|
New file |
0,0 → 1,421 |
// -------------------------------------------------------------------------------- |
// PclZip 2.8.2 - readme.txt |
// -------------------------------------------------------------------------------- |
// License GNU/LGPL - August 2009 |
// Vincent Blavet - vincent@phpconcept.net |
// http://www.phpconcept.net |
// -------------------------------------------------------------------------------- |
// $Id: readme.txt,v 1.60 2009/09/30 20:35:21 vblavet Exp $ |
// -------------------------------------------------------------------------------- |
0 - Sommaire |
============ |
1 - Introduction |
2 - What's new |
3 - Corrected bugs |
4 - Known bugs or limitations |
5 - License |
6 - Warning |
7 - Documentation |
8 - Author |
9 - Contribute |
1 - Introduction |
================ |
PclZip is a library that allow you to manage a Zip archive. |
Full documentation about PclZip can be found here : http://www.phpconcept.net/pclzip |
2 - What's new |
============== |
Version 2.8.2 : |
- PCLZIP_CB_PRE_EXTRACT and PCLZIP_CB_POST_EXTRACT are now supported with |
extraction as a string (PCLZIP_OPT_EXTRACT_AS_STRING). The string |
can also be modified in the post-extract call back. |
**Bugs correction : |
- PCLZIP_OPT_REMOVE_ALL_PATH was not working correctly |
- Remove use of eval() and do direct call to callback functions |
- Correct support of 64bits systems (Thanks to WordPress team) |
Version 2.8.1 : |
- Move option PCLZIP_OPT_BY_EREG to PCLZIP_OPT_BY_PREG because ereg() is |
deprecated in PHP 5.3. When using option PCLZIP_OPT_BY_EREG, PclZip will |
automatically replace it by PCLZIP_OPT_BY_PREG. |
Version 2.8 : |
- Improve extraction of zip archive for large files by using temporary files |
This feature is working like the one defined in r2.7. |
Options are renamed : PCLZIP_OPT_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_OFF, |
PCLZIP_OPT_TEMP_FILE_THRESHOLD |
- Add a ratio constant PCLZIP_TEMPORARY_FILE_RATIO to configure the auto |
sense of temporary file use. |
- Bug correction : Reduce filepath in returned file list to remove ennoying |
'.//' preambule in file path. |
Version 2.7 : |
- Improve creation of zip archive for large files : |
PclZip will now autosense the configured memory and use temporary files |
when large file is suspected. |
This feature can also ne triggered by manual options in create() and add() |
methods. 'PCLZIP_OPT_ADD_TEMP_FILE_ON' force the use of temporary files, |
'PCLZIP_OPT_ADD_TEMP_FILE_OFF' disable the autosense technic, |
'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD' allow for configuration of a size |
threshold to use temporary files. |
Using "temporary files" rather than "memory" might take more time, but |
might give the ability to zip very large files : |
Tested on my win laptop with a 88Mo file : |
Zip "in-memory" : 18sec (max_execution_time=30, memory_limit=180Mo) |
Zip "tmporary-files" : 23sec (max_execution_time=30, memory_limit=30Mo) |
- Replace use of mktime() by time() to limit the E_STRICT error messages. |
- Bug correction : When adding files with full windows path (drive letter) |
PclZip is now working. Before, if the drive letter is not the default |
path, PclZip was not able to add the file. |
Version 2.6 : |
- Code optimisation |
- New attributes PCLZIP_ATT_FILE_COMMENT gives the ability to |
add a comment for a specific file. (Don't really know if this is usefull) |
- New attribute PCLZIP_ATT_FILE_CONTENT gives the ability to add a string |
as a file. |
- New attribute PCLZIP_ATT_FILE_MTIME modify the timestamp associated with |
a file. |
- Correct a bug. Files archived with a timestamp with 0h0m0s were extracted |
with current time |
- Add CRC value in the informations returned back for each file after an |
action. |
- Add missing closedir() statement. |
- When adding a folder, and removing the path of this folder, files were |
incorrectly added with a '/' at the beginning. Which means files are |
related to root in unix systems. Corrected. |
- Add conditional if before constant definition. This will allow users |
to redefine constants without changing the file, and then improve |
upgrade of pclzip code for new versions. |
Version 2.5 : |
- Introduce the ability to add file/folder with individual properties (file descriptor). |
This gives for example the ability to change the filename of a zipped file. |
. Able to add files individually |
. Able to change full name |
. Able to change short name |
. Compatible with global options |
- New attributes : PCLZIP_ATT_FILE_NAME, PCLZIP_ATT_FILE_NEW_SHORT_NAME, PCLZIP_ATT_FILE_NEW_FULL_NAME |
- New error code : PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE |
- Add a security control feature. PclZip can extract any file in any folder |
of a system. People may use this to upload a zip file and try to override |
a system file. The PCLZIP_OPT_EXTRACT_DIR_RESTRICTION will give the |
ability to forgive any directory transversal behavior. |
- New PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : check extraction path |
- New error code : PCLZIP_ERR_DIRECTORY_RESTRICTION |
- Modification in PclZipUtilPathInclusion() : dir and path beginning with ./ will be prepend |
by current path (getcwd()) |
Version 2.4 : |
- Code improvment : try to speed up the code by removing unusefull call to pack() |
- Correct bug in delete() : delete() should be called with no argument. This was not |
the case in 2.3. This is corrected in 2.4. |
- Correct a bug in path_inclusion function. When the path has several '../../', the |
result was bad. |
- Add a check for magic_quotes_runtime configuration. If enabled, PclZip will |
disable it while working and det it back to its original value. |
This resolve a lots of bad formated archive errors. |
- Bug correction : PclZip now correctly unzip file in some specific situation, |
when compressed content has same size as uncompressed content. |
- Bug correction : When selecting option 'PCLZIP_OPT_REMOVE_ALL_PATH', |
directories are not any more created. |
- Code improvment : correct unclosed opendir(), better handling of . and .. in |
loops. |
Version 2.3 : |
- Correct a bug with PHP5 : affecting the value 0xFE49FFE0 to a variable does not |
give the same result in PHP4 and PHP5 .... |
Version 2.2 : |
- Try development of PCLZIP_OPT_CRYPT ..... |
However this becomes to a stop. To crypt/decrypt I need to multiply 2 long integers, |
the result (greater than a long) is not supported by PHP. Even the use of bcmath |
functions does not help. I did not find yet a solution ...; |
- Add missing '/' at end of directory entries |
- Check is a file is encrypted or not. Returns status 'unsupported_encryption' and/or |
error code PCLZIP_ERR_UNSUPPORTED_ENCRYPTION. |
- Corrected : Bad "version need to extract" field in local file header |
- Add private method privCheckFileHeaders() in order to check local and central |
file headers. PclZip is now supporting purpose bit flag bit 3. Purpose bit flag bit 3 gives |
the ability to have a local file header without size, compressed size and crc filled. |
- Add a generic status 'error' for file status |
- Add control of compression type. PclZip only support deflate compression method. |
Before v2.2, PclZip does not check the compression method used in an archive while |
extracting. With v2.2 PclZip returns a new error status for a file using an unsupported |
compression method. New status is "unsupported_compression". New error code is |
PCLZIP_ERR_UNSUPPORTED_COMPRESSION. |
- Add optional attribute PCLZIP_OPT_STOP_ON_ERROR. This will stop the extract of files |
when errors like 'a folder with same name exists' or 'a newer file exists' or |
'a write protected file' exists, rather than set a status for the concerning file |
and resume the extract of the zip. |
- Add optional attribute PCLZIP_OPT_REPLACE_NEWER. This will force, during an extract' the |
replacement of the file, even if a newer version of the file exists. |
Note that today if a file with the same name already exists but is older it will be |
replaced by the extracted one. |
- Improve PclZipUtilOption() |
- Support of zip archive with trailing bytes. Before 2.2, PclZip checks that the central |
directory structure is the last data in the archive. Crypt encryption/decryption of |
zip archive put trailing 0 bytes after decryption. PclZip is now supporting this. |
Version 2.1 : |
- Add the ability to abort the extraction by using a user callback function. |
The user can now return the value '2' in its callback which indicates to stop the |
extraction. For a pre call-back extract is stopped before the extration of the current |
file. For a post call back, the extraction is stopped after. |
- Add the ability to extract a file (or several files) directly in the standard output. |
This is done by the new parameter PCLZIP_OPT_EXTRACT_IN_OUTPUT with method extract(). |
- Add support for parameters PCLZIP_OPT_COMMENT, PCLZIP_OPT_ADD_COMMENT, |
PCLZIP_OPT_PREPEND_COMMENT. This will create, replace, add, or prepend comments |
in the zip archive. |
- When merging two archives, the comments are not any more lost, but merged, with a |
blank space separator. |
- Corrected bug : Files are not deleted when all files are asked to be deleted. |
- Corrected bug : Folders with name '0' made PclZip to abort the create or add feature. |
Version 2.0 : |
***** Warning : Some new features may break the backward compatibility for your scripts. |
Please carefully read the readme file. |
- Add the ability to delete by Index, name and regular expression. This feature is |
performed by the method delete(), which uses the optional parameters |
PCLZIP_OPT_BY_INDEX, PCLZIP_OPT_BY_NAME, PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG. |
- Add the ability to extract by regular expression. To extract by regexp you must use the method |
extract(), with the option PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG |
(depending if you want to use ereg() or preg_match() syntax) followed by the |
regular expression pattern. |
- Add the ability to extract by index, directly with the extract() method. This is a |
code improvment of the extractByIndex() method. |
- Add the ability to extract by name. To extract by name you must use the method |
extract(), with the option PCLZIP_OPT_BY_NAME followed by the filename to |
extract or an array of filenames to extract. To extract all a folder, use the folder |
name rather than the filename with a '/' at the end. |
- Add the ability to add files without compression. This is done with a new attribute |
which is PCLZIP_OPT_NO_COMPRESSION. |
- Add the attribute PCLZIP_OPT_EXTRACT_AS_STRING, which allow to extract a file directly |
in a string without using any file (or temporary file). |
- Add constant PCLZIP_SEPARATOR for static configuration of filename separators in a single string. |
The default separator is now a comma (,) and not any more a blank space. |
THIS BREAK THE BACKWARD COMPATIBILITY : Please check if this may have an impact with |
your script. |
- Improve algorythm performance by removing the use of temporary files when adding or |
extracting files in an archive. |
- Add (correct) detection of empty filename zipping. This can occurs when the removed |
path is the same |
as a zipped dir. The dir is not zipped (['status'] = filtered), only its content. |
- Add better support for windows paths (thanks for help from manus@manusfreedom.com). |
- Corrected bug : When the archive file already exists with size=0, the add() method |
fails. Corrected in 2.0. |
- Remove the use of OS_WINDOWS constant. Use php_uname() function rather. |
- Control the order of index ranges in extract by index feature. |
- Change the internal management of folders (better handling of internal flag). |
Version 1.3 : |
- Removing the double include check. This is now done by include_once() and require_once() |
PHP directives. |
- Changing the error handling mecanism : Remove the use of an external error library. |
The former PclError...() functions are replaced by internal equivalent methods. |
By changing the environment variable PCLZIP_ERROR_EXTERNAL you can still use the former library. |
Introducing the use of constants for error codes rather than integer values. This will help |
in futur improvment. |
Introduction of error handling functions like errorCode(), errorName() and errorInfo(). |
- Remove the deprecated use of calling function with arguments passed by reference. |
- Add the calling of extract(), extractByIndex(), create() and add() functions |
with variable options rather than fixed arguments. |
- Add the ability to remove all the file path while extracting or adding, |
without any need to specify the path to remove. |
This is available for extract(), extractByIndex(), create() and add() functionS by using |
the new variable options parameters : |
- PCLZIP_OPT_REMOVE_ALL_PATH : by indicating this option while calling the fct. |
- Ability to change the mode of a file after the extraction (chmod()). |
This is available for extract() and extractByIndex() functionS by using |
the new variable options parameters. |
- PCLZIP_OPT_SET_CHMOD : by setting the value of this option. |
- Ability to definition call-back options. These call-back will be called during the adding, |
or the extracting of file (extract(), extractByIndex(), create() and add() functions) : |
- PCLZIP_CB_PRE_EXTRACT : will be called before each extraction of a file. The user |
can trigerred the change the filename of the extracted file. The user can triggered the |
skip of the extraction. This is adding a 'skipped' status in the file list result value. |
- PCLZIP_CB_POST_EXTRACT : will be called after each extraction of a file. |
Nothing can be triggered from that point. |
- PCLZIP_CB_PRE_ADD : will be called before each add of a file. The user |
can trigerred the change the stored filename of the added file. The user can triggered the |
skip of the add. This is adding a 'skipped' status in the file list result value. |
- PCLZIP_CB_POST_ADD : will be called after each add of a file. |
Nothing can be triggered from that point. |
- Two status are added in the file list returned as function result : skipped & filename_too_long |
'skipped' is used when a call-back function ask for skipping the file. |
'filename_too_long' is used while adding a file with a too long filename to archive (the file is |
not added) |
- Adding the function PclZipUtilPathInclusion(), that check the inclusion of a path into |
a directory. |
- Add a check of the presence of the archive file before some actions (like list, ...) |
- Add the initialisation of field "index" in header array. This means that by |
default index will be -1 when not explicitly set by the methods. |
Version 1.2 : |
- Adding a duplicate function. |
- Adding a merge function. The merge function is a "quick merge" function, |
it just append the content of an archive at the end of the first one. There |
is no check for duplicate files or more recent files. |
- Improve the search of the central directory end. |
Version 1.1.2 : |
- Changing the license of PclZip. PclZip is now released under the GNU / LGPL license |
(see License section). |
- Adding the optional support of a static temporary directory. You will need to configure |
the constant PCLZIP_TEMPORARY_DIR if you want to use this feature. |
- Improving the rename() function. In some cases rename() does not work (different |
Filesystems), so it will be replaced by a copy() + unlink() functions. |
Version 1.1.1 : |
- Maintenance release, no new feature. |
Version 1.1 : |
- New method Add() : adding files in the archive |
- New method ExtractByIndex() : partial extract of the archive, files are identified by |
their index in the archive |
- New method DeleteByIndex() : delete some files/folder entries from the archive, |
files are identified by their index in the archive. |
- Adding a test of the zlib extension presence. If not present abort the script. |
Version 1.0.1 : |
- No new feature |
3 - Corrected bugs |
================== |
Corrected in Version 2.0 : |
- Corrected : During an extraction, if a call-back fucntion is used and try to skip |
a file, all the extraction process is stopped. |
Corrected in Version 1.3 : |
- Corrected : Support of static synopsis for method extract() is broken. |
- Corrected : invalid size of archive content field (0xFF) should be (0xFFFF). |
- Corrected : When an extract is done with a remove_path parameter, the entry for |
the directory with exactly the same path is not skipped/filtered. |
- Corrected : extractByIndex() and deleteByIndex() were not managing index in the |
right way. For example indexes '1,3-5,11' will only extract files 1 and 11. This |
is due to a sort of the index resulting table that puts 11 before 3-5 (sort on |
string and not interger). The sort is temporarilly removed, this means that |
you must provide a sorted list of index ranges. |
Corrected in Version 1.2 : |
- Nothing. |
Corrected in Version 1.1.2 : |
- Corrected : Winzip is unable to delete or add new files in a PclZip created archives. |
Corrected in Version 1.1.1 : |
- Corrected : When archived file is not compressed (0% compression), the |
extract method fails. |
Corrected in Version 1.1 : |
- Corrected : Adding a complete tree of folder may result in a bad archive |
creation. |
Corrected in Version 1.0.1 : |
- Corrected : Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024). |
4 - Known bugs or limitations |
============================= |
Please publish bugs reports in SourceForge : |
http://sourceforge.net/tracker/?group_id=40254&atid=427564 |
In Version 2.x : |
- PclZip does only support file uncompressed or compressed with deflate (compression method 8) |
- PclZip does not support password protected zip archive |
- Some concern were seen when changing mtime of a file while archiving. |
Seems to be linked to Daylight Saving Time (PclTest_changing_mtime). |
In Version 1.2 : |
- merge() methods does not check for duplicate files or last date of modifications. |
In Version 1.1 : |
- Limitation : Using 'extract' fields in the file header in the zip archive is not supported. |
- WinZip is unable to delete a single file in a PclZip created archive. It is also unable to |
add a file in a PclZip created archive. (Corrected in v.1.2) |
In Version 1.0.1 : |
- Adding a complete tree of folder may result in a bad archive |
creation. (Corrected in V.1.1). |
- Path given to methods must be in the unix format (/) and not the Windows format (\). |
Workaround : Use only / directory separators. |
- PclZip is using temporary files that are sometime the name of the file with a .tmp or .gz |
added suffix. Files with these names may already exist and may be overwritten. |
Workaround : none. |
- PclZip does not check if the zlib extension is present. If it is absent, the zip |
file is not created and the lib abort without warning. |
Workaround : enable the zlib extension on the php install |
In Version 1.0 : |
- Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024). |
(Corrected in v.1.0.1) |
- Limitation : Multi-disk zip archive are not supported. |
5 - License |
=========== |
Since version 1.1.2, PclZip Library is released under GNU/LGPL license. |
This library is free, so you can use it at no cost. |
HOWEVER, if you release a script, an application, a library or any kind of |
code using PclZip library (or a part of it), YOU MUST : |
- Indicate in the documentation (or a readme file), that your work |
uses PclZip Library, and make a reference to the author and the web site |
http://www.phpconcept.net |
- Gives the ability to the final user to update the PclZip libary. |
I will also appreciate that you send me a mail (vincent@phpconcept.net), just to |
be aware that someone is using PclZip. |
For more information about GNU/LGPL license : http://www.gnu.org |
6 - Warning |
================= |
This library and the associated files are non commercial, non professional work. |
It should not have unexpected results. However if any damage is caused by this software |
the author can not be responsible. |
The use of this software is at the risk of the user. |
7 - Documentation |
================= |
PclZip User Manuel is available in English on PhpConcept : http://www.phpconcept.net/pclzip/man/en/index.php |
A Russian translation was done by Feskov Kuzma : http://php.russofile.ru/ru/authors/unsort/zip/ |
8 - Author |
========== |
This software was written by Vincent Blavet (vincent@phpconcept.net) on its leasure time. |
9 - Contribute |
============== |
If you want to contribute to the development of PclZip, please contact vincent@phpconcept.net. |
If you can help in financing PhpConcept hosting service, please go to |
http://www.phpconcept.net/soutien.php |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/PCLZip/pclzip.lib.php |
---|
New file |
0,0 → 1,5694 |
<?php |
// -------------------------------------------------------------------------------- |
// PhpConcept Library - Zip Module 2.8.2 |
// -------------------------------------------------------------------------------- |
// License GNU/LGPL - Vincent Blavet - August 2009 |
// http://www.phpconcept.net |
// -------------------------------------------------------------------------------- |
// |
// Presentation : |
// PclZip is a PHP library that manage ZIP archives. |
// So far tests show that archives generated by PclZip are readable by |
// WinZip application and other tools. |
// |
// Description : |
// See readme.txt and http://www.phpconcept.net |
// |
// Warning : |
// This library and the associated files are non commercial, non professional |
// work. |
// It should not have unexpected results. However if any damage is caused by |
// this software the author can not be responsible. |
// The use of this software is at the risk of the user. |
// |
// -------------------------------------------------------------------------------- |
// $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $ |
// -------------------------------------------------------------------------------- |
// ----- Constants |
if (!defined('PCLZIP_READ_BLOCK_SIZE')) { |
define( 'PCLZIP_READ_BLOCK_SIZE', 2048 ); |
} |
// ----- File list separator |
// In version 1.x of PclZip, the separator for file list is a space |
// (which is not a very smart choice, specifically for windows paths !). |
// A better separator should be a comma (,). This constant gives you the |
// abilty to change that. |
// However notice that changing this value, may have impact on existing |
// scripts, using space separated filenames. |
// Recommanded values for compatibility with older versions : |
//define( 'PCLZIP_SEPARATOR', ' ' ); |
// Recommanded values for smart separation of filenames. |
if (!defined('PCLZIP_SEPARATOR')) { |
define( 'PCLZIP_SEPARATOR', ',' ); |
} |
// ----- Error configuration |
// 0 : PclZip Class integrated error handling |
// 1 : PclError external library error handling. By enabling this |
// you must ensure that you have included PclError library. |
// [2,...] : reserved for futur use |
if (!defined('PCLZIP_ERROR_EXTERNAL')) { |
define( 'PCLZIP_ERROR_EXTERNAL', 0 ); |
} |
// ----- Optional static temporary directory |
// By default temporary files are generated in the script current |
// path. |
// If defined : |
// - MUST BE terminated by a '/'. |
// - MUST be a valid, already created directory |
// Samples : |
// define( 'PCLZIP_TEMPORARY_DIR', '/temp/' ); |
// define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' ); |
if (!defined('PCLZIP_TEMPORARY_DIR')) { |
define( 'PCLZIP_TEMPORARY_DIR', '' ); |
} |
// ----- Optional threshold ratio for use of temporary files |
// Pclzip sense the size of the file to add/extract and decide to |
// use or not temporary file. The algorythm is looking for |
// memory_limit of PHP and apply a ratio. |
// threshold = memory_limit * ratio. |
// Recommended values are under 0.5. Default 0.47. |
// Samples : |
// define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 ); |
if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) { |
define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 ); |
} |
// -------------------------------------------------------------------------------- |
// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED ***** |
// -------------------------------------------------------------------------------- |
// ----- Global variables |
$g_pclzip_version = "2.8.2"; |
// ----- Error codes |
// -1 : Unable to open file in binary write mode |
// -2 : Unable to open file in binary read mode |
// -3 : Invalid parameters |
// -4 : File does not exist |
// -5 : Filename is too long (max. 255) |
// -6 : Not a valid zip file |
// -7 : Invalid extracted file size |
// -8 : Unable to create directory |
// -9 : Invalid archive extension |
// -10 : Invalid archive format |
// -11 : Unable to delete file (unlink) |
// -12 : Unable to rename file (rename) |
// -13 : Invalid header checksum |
// -14 : Invalid archive size |
define( 'PCLZIP_ERR_USER_ABORTED', 2 ); |
define( 'PCLZIP_ERR_NO_ERROR', 0 ); |
define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 ); |
define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 ); |
define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 ); |
define( 'PCLZIP_ERR_MISSING_FILE', -4 ); |
define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 ); |
define( 'PCLZIP_ERR_INVALID_ZIP', -6 ); |
define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 ); |
define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 ); |
define( 'PCLZIP_ERR_BAD_EXTENSION', -9 ); |
define( 'PCLZIP_ERR_BAD_FORMAT', -10 ); |
define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 ); |
define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 ); |
define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 ); |
define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 ); |
define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 ); |
define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 ); |
define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 ); |
define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 ); |
define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 ); |
define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 ); |
define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 ); |
// ----- Options values |
define( 'PCLZIP_OPT_PATH', 77001 ); |
define( 'PCLZIP_OPT_ADD_PATH', 77002 ); |
define( 'PCLZIP_OPT_REMOVE_PATH', 77003 ); |
define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 ); |
define( 'PCLZIP_OPT_SET_CHMOD', 77005 ); |
define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 ); |
define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 ); |
define( 'PCLZIP_OPT_BY_NAME', 77008 ); |
define( 'PCLZIP_OPT_BY_INDEX', 77009 ); |
define( 'PCLZIP_OPT_BY_EREG', 77010 ); |
define( 'PCLZIP_OPT_BY_PREG', 77011 ); |
define( 'PCLZIP_OPT_COMMENT', 77012 ); |
define( 'PCLZIP_OPT_ADD_COMMENT', 77013 ); |
define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 ); |
define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 ); |
define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 ); |
define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 ); |
// Having big trouble with crypt. Need to multiply 2 long int |
// which is not correctly supported by PHP ... |
//define( 'PCLZIP_OPT_CRYPT', 77018 ); |
define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 ); |
define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 ); |
define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias |
define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 ); |
define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias |
define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 ); |
define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias |
// ----- File description attributes |
define( 'PCLZIP_ATT_FILE_NAME', 79001 ); |
define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 ); |
define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 ); |
define( 'PCLZIP_ATT_FILE_MTIME', 79004 ); |
define( 'PCLZIP_ATT_FILE_CONTENT', 79005 ); |
define( 'PCLZIP_ATT_FILE_COMMENT', 79006 ); |
// ----- Call backs values |
define( 'PCLZIP_CB_PRE_EXTRACT', 78001 ); |
define( 'PCLZIP_CB_POST_EXTRACT', 78002 ); |
define( 'PCLZIP_CB_PRE_ADD', 78003 ); |
define( 'PCLZIP_CB_POST_ADD', 78004 ); |
/* For futur use |
define( 'PCLZIP_CB_PRE_LIST', 78005 ); |
define( 'PCLZIP_CB_POST_LIST', 78006 ); |
define( 'PCLZIP_CB_PRE_DELETE', 78007 ); |
define( 'PCLZIP_CB_POST_DELETE', 78008 ); |
*/ |
// -------------------------------------------------------------------------------- |
// Class : PclZip |
// Description : |
// PclZip is the class that represent a Zip archive. |
// The public methods allow the manipulation of the archive. |
// Attributes : |
// Attributes must not be accessed directly. |
// Methods : |
// PclZip() : Object creator |
// create() : Creates the Zip archive |
// listContent() : List the content of the Zip archive |
// extract() : Extract the content of the archive |
// properties() : List the properties of the archive |
// -------------------------------------------------------------------------------- |
class PclZip |
{ |
// ----- Filename of the zip file |
var $zipname = ''; |
// ----- File descriptor of the zip file |
var $zip_fd = 0; |
// ----- Internal error handling |
var $error_code = 1; |
var $error_string = ''; |
// ----- Current status of the magic_quotes_runtime |
// This value store the php configuration for magic_quotes |
// The class can then disable the magic_quotes and reset it after |
var $magic_quotes_status; |
// -------------------------------------------------------------------------------- |
// Function : PclZip() |
// Description : |
// Creates a PclZip object and set the name of the associated Zip archive |
// filename. |
// Note that no real action is taken, if the archive does not exist it is not |
// created. Use create() for that. |
// -------------------------------------------------------------------------------- |
function PclZip($p_zipname) |
{ |
// ----- Tests the zlib |
if (!function_exists('gzopen')) |
{ |
die('Abort '.basename(__FILE__).' : Missing zlib extensions'); |
} |
// ----- Set the attributes |
$this->zipname = $p_zipname; |
$this->zip_fd = 0; |
$this->magic_quotes_status = -1; |
// ----- Return |
return; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : |
// create($p_filelist, $p_add_dir="", $p_remove_dir="") |
// create($p_filelist, $p_option, $p_option_value, ...) |
// Description : |
// This method supports two different synopsis. The first one is historical. |
// This method creates a Zip Archive. The Zip file is created in the |
// filesystem. The files and directories indicated in $p_filelist |
// are added in the archive. See the parameters description for the |
// supported format of $p_filelist. |
// When a directory is in the list, the directory and its content is added |
// in the archive. |
// In this synopsis, the function takes an optional variable list of |
// options. See bellow the supported options. |
// Parameters : |
// $p_filelist : An array containing file or directory names, or |
// a string containing one filename or one directory name, or |
// a string containing a list of filenames and/or directory |
// names separated by spaces. |
// $p_add_dir : A path to add before the real path of the archived file, |
// in order to have it memorized in the archive. |
// $p_remove_dir : A path to remove from the real path of the file to archive, |
// in order to have a shorter path memorized in the archive. |
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir |
// is removed first, before $p_add_dir is added. |
// Options : |
// PCLZIP_OPT_ADD_PATH : |
// PCLZIP_OPT_REMOVE_PATH : |
// PCLZIP_OPT_REMOVE_ALL_PATH : |
// PCLZIP_OPT_COMMENT : |
// PCLZIP_CB_PRE_ADD : |
// PCLZIP_CB_POST_ADD : |
// Return Values : |
// 0 on failure, |
// The list of the added files, with a status of the add action. |
// (see PclZip::listContent() for list entry format) |
// -------------------------------------------------------------------------------- |
function create($p_filelist) |
{ |
$v_result=1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Set default values |
$v_options = array(); |
$v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; |
// ----- Look for variable options arguments |
$v_size = func_num_args(); |
// ----- Look for arguments |
if ($v_size > 1) { |
// ----- Get the arguments |
$v_arg_list = func_get_args(); |
// ----- Remove from the options list the first argument |
array_shift($v_arg_list); |
$v_size--; |
// ----- Look for first arg |
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { |
// ----- Parse the options |
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, |
array (PCLZIP_OPT_REMOVE_PATH => 'optional', |
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', |
PCLZIP_OPT_ADD_PATH => 'optional', |
PCLZIP_CB_PRE_ADD => 'optional', |
PCLZIP_CB_POST_ADD => 'optional', |
PCLZIP_OPT_NO_COMPRESSION => 'optional', |
PCLZIP_OPT_COMMENT => 'optional', |
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', |
PCLZIP_OPT_TEMP_FILE_ON => 'optional', |
PCLZIP_OPT_TEMP_FILE_OFF => 'optional' |
//, PCLZIP_OPT_CRYPT => 'optional' |
)); |
if ($v_result != 1) { |
return 0; |
} |
} |
// ----- Look for 2 args |
// Here we need to support the first historic synopsis of the |
// method. |
else { |
// ----- Get the first argument |
$v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0]; |
// ----- Look for the optional second argument |
if ($v_size == 2) { |
$v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; |
} |
else if ($v_size > 2) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, |
"Invalid number / type of arguments"); |
return 0; |
} |
} |
} |
// ----- Look for default option values |
$this->privOptionDefaultThreshold($v_options); |
// ----- Init |
$v_string_list = array(); |
$v_att_list = array(); |
$v_filedescr_list = array(); |
$p_result_list = array(); |
// ----- Look if the $p_filelist is really an array |
if (is_array($p_filelist)) { |
// ----- Look if the first element is also an array |
// This will mean that this is a file description entry |
if (isset($p_filelist[0]) && is_array($p_filelist[0])) { |
$v_att_list = $p_filelist; |
} |
// ----- The list is a list of string names |
else { |
$v_string_list = $p_filelist; |
} |
} |
// ----- Look if the $p_filelist is a string |
else if (is_string($p_filelist)) { |
// ----- Create a list from the string |
$v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); |
} |
// ----- Invalid variable type for $p_filelist |
else { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist"); |
return 0; |
} |
// ----- Reformat the string list |
if (sizeof($v_string_list) != 0) { |
foreach ($v_string_list as $v_string) { |
if ($v_string != '') { |
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; |
} |
else { |
} |
} |
} |
// ----- For each file in the list check the attributes |
$v_supported_attributes |
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory' |
,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' |
,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' |
,PCLZIP_ATT_FILE_MTIME => 'optional' |
,PCLZIP_ATT_FILE_CONTENT => 'optional' |
,PCLZIP_ATT_FILE_COMMENT => 'optional' |
); |
foreach ($v_att_list as $v_entry) { |
$v_result = $this->privFileDescrParseAtt($v_entry, |
$v_filedescr_list[], |
$v_options, |
$v_supported_attributes); |
if ($v_result != 1) { |
return 0; |
} |
} |
// ----- Expand the filelist (expand directories) |
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); |
if ($v_result != 1) { |
return 0; |
} |
// ----- Call the create fct |
$v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options); |
if ($v_result != 1) { |
return 0; |
} |
// ----- Return |
return $p_result_list; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : |
// add($p_filelist, $p_add_dir="", $p_remove_dir="") |
// add($p_filelist, $p_option, $p_option_value, ...) |
// Description : |
// This method supports two synopsis. The first one is historical. |
// This methods add the list of files in an existing archive. |
// If a file with the same name already exists, it is added at the end of the |
// archive, the first one is still present. |
// If the archive does not exist, it is created. |
// Parameters : |
// $p_filelist : An array containing file or directory names, or |
// a string containing one filename or one directory name, or |
// a string containing a list of filenames and/or directory |
// names separated by spaces. |
// $p_add_dir : A path to add before the real path of the archived file, |
// in order to have it memorized in the archive. |
// $p_remove_dir : A path to remove from the real path of the file to archive, |
// in order to have a shorter path memorized in the archive. |
// When $p_add_dir and $p_remove_dir are set, $p_remove_dir |
// is removed first, before $p_add_dir is added. |
// Options : |
// PCLZIP_OPT_ADD_PATH : |
// PCLZIP_OPT_REMOVE_PATH : |
// PCLZIP_OPT_REMOVE_ALL_PATH : |
// PCLZIP_OPT_COMMENT : |
// PCLZIP_OPT_ADD_COMMENT : |
// PCLZIP_OPT_PREPEND_COMMENT : |
// PCLZIP_CB_PRE_ADD : |
// PCLZIP_CB_POST_ADD : |
// Return Values : |
// 0 on failure, |
// The list of the added files, with a status of the add action. |
// (see PclZip::listContent() for list entry format) |
// -------------------------------------------------------------------------------- |
function add($p_filelist) |
{ |
$v_result=1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Set default values |
$v_options = array(); |
$v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; |
// ----- Look for variable options arguments |
$v_size = func_num_args(); |
// ----- Look for arguments |
if ($v_size > 1) { |
// ----- Get the arguments |
$v_arg_list = func_get_args(); |
// ----- Remove form the options list the first argument |
array_shift($v_arg_list); |
$v_size--; |
// ----- Look for first arg |
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { |
// ----- Parse the options |
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, |
array (PCLZIP_OPT_REMOVE_PATH => 'optional', |
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', |
PCLZIP_OPT_ADD_PATH => 'optional', |
PCLZIP_CB_PRE_ADD => 'optional', |
PCLZIP_CB_POST_ADD => 'optional', |
PCLZIP_OPT_NO_COMPRESSION => 'optional', |
PCLZIP_OPT_COMMENT => 'optional', |
PCLZIP_OPT_ADD_COMMENT => 'optional', |
PCLZIP_OPT_PREPEND_COMMENT => 'optional', |
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', |
PCLZIP_OPT_TEMP_FILE_ON => 'optional', |
PCLZIP_OPT_TEMP_FILE_OFF => 'optional' |
//, PCLZIP_OPT_CRYPT => 'optional' |
)); |
if ($v_result != 1) { |
return 0; |
} |
} |
// ----- Look for 2 args |
// Here we need to support the first historic synopsis of the |
// method. |
else { |
// ----- Get the first argument |
$v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0]; |
// ----- Look for the optional second argument |
if ($v_size == 2) { |
$v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; |
} |
else if ($v_size > 2) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); |
// ----- Return |
return 0; |
} |
} |
} |
// ----- Look for default option values |
$this->privOptionDefaultThreshold($v_options); |
// ----- Init |
$v_string_list = array(); |
$v_att_list = array(); |
$v_filedescr_list = array(); |
$p_result_list = array(); |
// ----- Look if the $p_filelist is really an array |
if (is_array($p_filelist)) { |
// ----- Look if the first element is also an array |
// This will mean that this is a file description entry |
if (isset($p_filelist[0]) && is_array($p_filelist[0])) { |
$v_att_list = $p_filelist; |
} |
// ----- The list is a list of string names |
else { |
$v_string_list = $p_filelist; |
} |
} |
// ----- Look if the $p_filelist is a string |
else if (is_string($p_filelist)) { |
// ----- Create a list from the string |
$v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); |
} |
// ----- Invalid variable type for $p_filelist |
else { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist"); |
return 0; |
} |
// ----- Reformat the string list |
if (sizeof($v_string_list) != 0) { |
foreach ($v_string_list as $v_string) { |
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; |
} |
} |
// ----- For each file in the list check the attributes |
$v_supported_attributes |
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory' |
,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' |
,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' |
,PCLZIP_ATT_FILE_MTIME => 'optional' |
,PCLZIP_ATT_FILE_CONTENT => 'optional' |
,PCLZIP_ATT_FILE_COMMENT => 'optional' |
); |
foreach ($v_att_list as $v_entry) { |
$v_result = $this->privFileDescrParseAtt($v_entry, |
$v_filedescr_list[], |
$v_options, |
$v_supported_attributes); |
if ($v_result != 1) { |
return 0; |
} |
} |
// ----- Expand the filelist (expand directories) |
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); |
if ($v_result != 1) { |
return 0; |
} |
// ----- Call the create fct |
$v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options); |
if ($v_result != 1) { |
return 0; |
} |
// ----- Return |
return $p_result_list; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : listContent() |
// Description : |
// This public method, gives the list of the files and directories, with their |
// properties. |
// The properties of each entries in the list are (used also in other functions) : |
// filename : Name of the file. For a create or add action it is the filename |
// given by the user. For an extract function it is the filename |
// of the extracted file. |
// stored_filename : Name of the file / directory stored in the archive. |
// size : Size of the stored file. |
// compressed_size : Size of the file's data compressed in the archive |
// (without the headers overhead) |
// mtime : Last known modification date of the file (UNIX timestamp) |
// comment : Comment associated with the file |
// folder : true | false |
// index : index of the file in the archive |
// status : status of the action (depending of the action) : |
// Values are : |
// ok : OK ! |
// filtered : the file / dir is not extracted (filtered by user) |
// already_a_directory : the file can not be extracted because a |
// directory with the same name already exists |
// write_protected : the file can not be extracted because a file |
// with the same name already exists and is |
// write protected |
// newer_exist : the file was not extracted because a newer file exists |
// path_creation_fail : the file is not extracted because the folder |
// does not exist and can not be created |
// write_error : the file was not extracted because there was a |
// error while writing the file |
// read_error : the file was not extracted because there was a error |
// while reading the file |
// invalid_header : the file was not extracted because of an archive |
// format error (bad file header) |
// Note that each time a method can continue operating when there |
// is an action error on a file, the error is only logged in the file status. |
// Return Values : |
// 0 on an unrecoverable failure, |
// The list of the files in the archive. |
// -------------------------------------------------------------------------------- |
function listContent() |
{ |
$v_result=1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Check archive |
if (!$this->privCheckFormat()) { |
return(0); |
} |
// ----- Call the extracting fct |
$p_list = array(); |
if (($v_result = $this->privList($p_list)) != 1) |
{ |
unset($p_list); |
return(0); |
} |
// ----- Return |
return $p_list; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : |
// extract($p_path="./", $p_remove_path="") |
// extract([$p_option, $p_option_value, ...]) |
// Description : |
// This method supports two synopsis. The first one is historical. |
// This method extract all the files / directories from the archive to the |
// folder indicated in $p_path. |
// If you want to ignore the 'root' part of path of the memorized files |
// you can indicate this in the optional $p_remove_path parameter. |
// By default, if a newer file with the same name already exists, the |
// file is not extracted. |
// |
// If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions |
// are used, the path indicated in PCLZIP_OPT_ADD_PATH is append |
// at the end of the path value of PCLZIP_OPT_PATH. |
// Parameters : |
// $p_path : Path where the files and directories are to be extracted |
// $p_remove_path : First part ('root' part) of the memorized path |
// (if any similar) to remove while extracting. |
// Options : |
// PCLZIP_OPT_PATH : |
// PCLZIP_OPT_ADD_PATH : |
// PCLZIP_OPT_REMOVE_PATH : |
// PCLZIP_OPT_REMOVE_ALL_PATH : |
// PCLZIP_CB_PRE_EXTRACT : |
// PCLZIP_CB_POST_EXTRACT : |
// Return Values : |
// 0 or a negative value on failure, |
// The list of the extracted files, with a status of the action. |
// (see PclZip::listContent() for list entry format) |
// -------------------------------------------------------------------------------- |
function extract() |
{ |
$v_result=1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Check archive |
if (!$this->privCheckFormat()) { |
return(0); |
} |
// ----- Set default values |
$v_options = array(); |
// $v_path = "./"; |
$v_path = ''; |
$v_remove_path = ""; |
$v_remove_all_path = false; |
// ----- Look for variable options arguments |
$v_size = func_num_args(); |
// ----- Default values for option |
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; |
// ----- Look for arguments |
if ($v_size > 0) { |
// ----- Get the arguments |
$v_arg_list = func_get_args(); |
// ----- Look for first arg |
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { |
// ----- Parse the options |
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, |
array (PCLZIP_OPT_PATH => 'optional', |
PCLZIP_OPT_REMOVE_PATH => 'optional', |
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', |
PCLZIP_OPT_ADD_PATH => 'optional', |
PCLZIP_CB_PRE_EXTRACT => 'optional', |
PCLZIP_CB_POST_EXTRACT => 'optional', |
PCLZIP_OPT_SET_CHMOD => 'optional', |
PCLZIP_OPT_BY_NAME => 'optional', |
PCLZIP_OPT_BY_EREG => 'optional', |
PCLZIP_OPT_BY_PREG => 'optional', |
PCLZIP_OPT_BY_INDEX => 'optional', |
PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', |
PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional', |
PCLZIP_OPT_REPLACE_NEWER => 'optional' |
,PCLZIP_OPT_STOP_ON_ERROR => 'optional' |
,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', |
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', |
PCLZIP_OPT_TEMP_FILE_ON => 'optional', |
PCLZIP_OPT_TEMP_FILE_OFF => 'optional' |
)); |
if ($v_result != 1) { |
return 0; |
} |
// ----- Set the arguments |
if (isset($v_options[PCLZIP_OPT_PATH])) { |
$v_path = $v_options[PCLZIP_OPT_PATH]; |
} |
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { |
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; |
} |
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { |
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; |
} |
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { |
// ----- Check for '/' in last path char |
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { |
$v_path .= '/'; |
} |
$v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; |
} |
} |
// ----- Look for 2 args |
// Here we need to support the first historic synopsis of the |
// method. |
else { |
// ----- Get the first argument |
$v_path = $v_arg_list[0]; |
// ----- Look for the optional second argument |
if ($v_size == 2) { |
$v_remove_path = $v_arg_list[1]; |
} |
else if ($v_size > 2) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); |
// ----- Return |
return 0; |
} |
} |
} |
// ----- Look for default option values |
$this->privOptionDefaultThreshold($v_options); |
// ----- Trace |
// ----- Call the extracting fct |
$p_list = array(); |
$v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, |
$v_remove_all_path, $v_options); |
if ($v_result < 1) { |
unset($p_list); |
return(0); |
} |
// ----- Return |
return $p_list; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : |
// extractByIndex($p_index, $p_path="./", $p_remove_path="") |
// extractByIndex($p_index, [$p_option, $p_option_value, ...]) |
// Description : |
// This method supports two synopsis. The first one is historical. |
// This method is doing a partial extract of the archive. |
// The extracted files or folders are identified by their index in the |
// archive (from 0 to n). |
// Note that if the index identify a folder, only the folder entry is |
// extracted, not all the files included in the archive. |
// Parameters : |
// $p_index : A single index (integer) or a string of indexes of files to |
// extract. The form of the string is "0,4-6,8-12" with only numbers |
// and '-' for range or ',' to separate ranges. No spaces or ';' |
// are allowed. |
// $p_path : Path where the files and directories are to be extracted |
// $p_remove_path : First part ('root' part) of the memorized path |
// (if any similar) to remove while extracting. |
// Options : |
// PCLZIP_OPT_PATH : |
// PCLZIP_OPT_ADD_PATH : |
// PCLZIP_OPT_REMOVE_PATH : |
// PCLZIP_OPT_REMOVE_ALL_PATH : |
// PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and |
// not as files. |
// The resulting content is in a new field 'content' in the file |
// structure. |
// This option must be used alone (any other options are ignored). |
// PCLZIP_CB_PRE_EXTRACT : |
// PCLZIP_CB_POST_EXTRACT : |
// Return Values : |
// 0 on failure, |
// The list of the extracted files, with a status of the action. |
// (see PclZip::listContent() for list entry format) |
// -------------------------------------------------------------------------------- |
//function extractByIndex($p_index, options...) |
function extractByIndex($p_index) |
{ |
$v_result=1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Check archive |
if (!$this->privCheckFormat()) { |
return(0); |
} |
// ----- Set default values |
$v_options = array(); |
// $v_path = "./"; |
$v_path = ''; |
$v_remove_path = ""; |
$v_remove_all_path = false; |
// ----- Look for variable options arguments |
$v_size = func_num_args(); |
// ----- Default values for option |
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; |
// ----- Look for arguments |
if ($v_size > 1) { |
// ----- Get the arguments |
$v_arg_list = func_get_args(); |
// ----- Remove form the options list the first argument |
array_shift($v_arg_list); |
$v_size--; |
// ----- Look for first arg |
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { |
// ----- Parse the options |
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, |
array (PCLZIP_OPT_PATH => 'optional', |
PCLZIP_OPT_REMOVE_PATH => 'optional', |
PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', |
PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', |
PCLZIP_OPT_ADD_PATH => 'optional', |
PCLZIP_CB_PRE_EXTRACT => 'optional', |
PCLZIP_CB_POST_EXTRACT => 'optional', |
PCLZIP_OPT_SET_CHMOD => 'optional', |
PCLZIP_OPT_REPLACE_NEWER => 'optional' |
,PCLZIP_OPT_STOP_ON_ERROR => 'optional' |
,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', |
PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', |
PCLZIP_OPT_TEMP_FILE_ON => 'optional', |
PCLZIP_OPT_TEMP_FILE_OFF => 'optional' |
)); |
if ($v_result != 1) { |
return 0; |
} |
// ----- Set the arguments |
if (isset($v_options[PCLZIP_OPT_PATH])) { |
$v_path = $v_options[PCLZIP_OPT_PATH]; |
} |
if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { |
$v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; |
} |
if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { |
$v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; |
} |
if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { |
// ----- Check for '/' in last path char |
if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { |
$v_path .= '/'; |
} |
$v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; |
} |
if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) { |
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; |
} |
else { |
} |
} |
// ----- Look for 2 args |
// Here we need to support the first historic synopsis of the |
// method. |
else { |
// ----- Get the first argument |
$v_path = $v_arg_list[0]; |
// ----- Look for the optional second argument |
if ($v_size == 2) { |
$v_remove_path = $v_arg_list[1]; |
} |
else if ($v_size > 2) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); |
// ----- Return |
return 0; |
} |
} |
} |
// ----- Trace |
// ----- Trick |
// Here I want to reuse extractByRule(), so I need to parse the $p_index |
// with privParseOptions() |
$v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index); |
$v_options_trick = array(); |
$v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, |
array (PCLZIP_OPT_BY_INDEX => 'optional' )); |
if ($v_result != 1) { |
return 0; |
} |
$v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX]; |
// ----- Look for default option values |
$this->privOptionDefaultThreshold($v_options); |
// ----- Call the extracting fct |
if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) { |
return(0); |
} |
// ----- Return |
return $p_list; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : |
// delete([$p_option, $p_option_value, ...]) |
// Description : |
// This method removes files from the archive. |
// If no parameters are given, then all the archive is emptied. |
// Parameters : |
// None or optional arguments. |
// Options : |
// PCLZIP_OPT_BY_INDEX : |
// PCLZIP_OPT_BY_NAME : |
// PCLZIP_OPT_BY_EREG : |
// PCLZIP_OPT_BY_PREG : |
// Return Values : |
// 0 on failure, |
// The list of the files which are still present in the archive. |
// (see PclZip::listContent() for list entry format) |
// -------------------------------------------------------------------------------- |
function delete() |
{ |
$v_result=1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Check archive |
if (!$this->privCheckFormat()) { |
return(0); |
} |
// ----- Set default values |
$v_options = array(); |
// ----- Look for variable options arguments |
$v_size = func_num_args(); |
// ----- Look for arguments |
if ($v_size > 0) { |
// ----- Get the arguments |
$v_arg_list = func_get_args(); |
// ----- Parse the options |
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, |
array (PCLZIP_OPT_BY_NAME => 'optional', |
PCLZIP_OPT_BY_EREG => 'optional', |
PCLZIP_OPT_BY_PREG => 'optional', |
PCLZIP_OPT_BY_INDEX => 'optional' )); |
if ($v_result != 1) { |
return 0; |
} |
} |
// ----- Magic quotes trick |
$this->privDisableMagicQuotes(); |
// ----- Call the delete fct |
$v_list = array(); |
if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) { |
$this->privSwapBackMagicQuotes(); |
unset($v_list); |
return(0); |
} |
// ----- Magic quotes trick |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_list; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : deleteByIndex() |
// Description : |
// ***** Deprecated ***** |
// delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered. |
// -------------------------------------------------------------------------------- |
function deleteByIndex($p_index) |
{ |
$p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index); |
// ----- Return |
return $p_list; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : properties() |
// Description : |
// This method gives the properties of the archive. |
// The properties are : |
// nb : Number of files in the archive |
// comment : Comment associated with the archive file |
// status : not_exist, ok |
// Parameters : |
// None |
// Return Values : |
// 0 on failure, |
// An array with the archive properties. |
// -------------------------------------------------------------------------------- |
function properties() |
{ |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Magic quotes trick |
$this->privDisableMagicQuotes(); |
// ----- Check archive |
if (!$this->privCheckFormat()) { |
$this->privSwapBackMagicQuotes(); |
return(0); |
} |
// ----- Default properties |
$v_prop = array(); |
$v_prop['comment'] = ''; |
$v_prop['nb'] = 0; |
$v_prop['status'] = 'not_exist'; |
// ----- Look if file exists |
if (@is_file($this->zipname)) |
{ |
// ----- Open the zip file |
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) |
{ |
$this->privSwapBackMagicQuotes(); |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); |
// ----- Return |
return 0; |
} |
// ----- Read the central directory informations |
$v_central_dir = array(); |
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) |
{ |
$this->privSwapBackMagicQuotes(); |
return 0; |
} |
// ----- Close the zip file |
$this->privCloseFd(); |
// ----- Set the user attributes |
$v_prop['comment'] = $v_central_dir['comment']; |
$v_prop['nb'] = $v_central_dir['entries']; |
$v_prop['status'] = 'ok'; |
} |
// ----- Magic quotes trick |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_prop; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : duplicate() |
// Description : |
// This method creates an archive by copying the content of an other one. If |
// the archive already exist, it is replaced by the new one without any warning. |
// Parameters : |
// $p_archive : The filename of a valid archive, or |
// a valid PclZip object. |
// Return Values : |
// 1 on success. |
// 0 or a negative value on error (error code). |
// -------------------------------------------------------------------------------- |
function duplicate($p_archive) |
{ |
$v_result = 1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Look if the $p_archive is a PclZip object |
if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) |
{ |
// ----- Duplicate the archive |
$v_result = $this->privDuplicate($p_archive->zipname); |
} |
// ----- Look if the $p_archive is a string (so a filename) |
else if (is_string($p_archive)) |
{ |
// ----- Check that $p_archive is a valid zip file |
// TBC : Should also check the archive format |
if (!is_file($p_archive)) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'"); |
$v_result = PCLZIP_ERR_MISSING_FILE; |
} |
else { |
// ----- Duplicate the archive |
$v_result = $this->privDuplicate($p_archive); |
} |
} |
// ----- Invalid variable |
else |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); |
$v_result = PCLZIP_ERR_INVALID_PARAMETER; |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : merge() |
// Description : |
// This method merge the $p_archive_to_add archive at the end of the current |
// one ($this). |
// If the archive ($this) does not exist, the merge becomes a duplicate. |
// If the $p_archive_to_add archive does not exist, the merge is a success. |
// Parameters : |
// $p_archive_to_add : It can be directly the filename of a valid zip archive, |
// or a PclZip object archive. |
// Return Values : |
// 1 on success, |
// 0 or negative values on error (see below). |
// -------------------------------------------------------------------------------- |
function merge($p_archive_to_add) |
{ |
$v_result = 1; |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Check archive |
if (!$this->privCheckFormat()) { |
return(0); |
} |
// ----- Look if the $p_archive_to_add is a PclZip object |
if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) |
{ |
// ----- Merge the archive |
$v_result = $this->privMerge($p_archive_to_add); |
} |
// ----- Look if the $p_archive_to_add is a string (so a filename) |
else if (is_string($p_archive_to_add)) |
{ |
// ----- Create a temporary archive |
$v_object_archive = new PclZip($p_archive_to_add); |
// ----- Merge the archive |
$v_result = $this->privMerge($v_object_archive); |
} |
// ----- Invalid variable |
else |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); |
$v_result = PCLZIP_ERR_INVALID_PARAMETER; |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : errorCode() |
// Description : |
// Parameters : |
// -------------------------------------------------------------------------------- |
function errorCode() |
{ |
if (PCLZIP_ERROR_EXTERNAL == 1) { |
return(PclErrorCode()); |
} |
else { |
return($this->error_code); |
} |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : errorName() |
// Description : |
// Parameters : |
// -------------------------------------------------------------------------------- |
function errorName($p_with_code=false) |
{ |
$v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR', |
PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL', |
PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL', |
PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER', |
PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE', |
PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG', |
PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP', |
PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE', |
PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL', |
PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION', |
PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT', |
PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL', |
PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL', |
PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM', |
PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', |
PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE', |
PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE', |
PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', |
PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION' |
,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE' |
,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION' |
); |
if (isset($v_name[$this->error_code])) { |
$v_value = $v_name[$this->error_code]; |
} |
else { |
$v_value = 'NoName'; |
} |
if ($p_with_code) { |
return($v_value.' ('.$this->error_code.')'); |
} |
else { |
return($v_value); |
} |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : errorInfo() |
// Description : |
// Parameters : |
// -------------------------------------------------------------------------------- |
function errorInfo($p_full=false) |
{ |
if (PCLZIP_ERROR_EXTERNAL == 1) { |
return(PclErrorString()); |
} |
else { |
if ($p_full) { |
return($this->errorName(true)." : ".$this->error_string); |
} |
else { |
return($this->error_string." [code ".$this->error_code."]"); |
} |
} |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** |
// ***** ***** |
// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privCheckFormat() |
// Description : |
// This method check that the archive exists and is a valid zip archive. |
// Several level of check exists. (futur) |
// Parameters : |
// $p_level : Level of check. Default 0. |
// 0 : Check the first bytes (magic codes) (default value)) |
// 1 : 0 + Check the central directory (futur) |
// 2 : 1 + Check each file header (futur) |
// Return Values : |
// true on success, |
// false on error, the error code is set. |
// -------------------------------------------------------------------------------- |
function privCheckFormat($p_level=0) |
{ |
$v_result = true; |
// ----- Reset the file system cache |
clearstatcache(); |
// ----- Reset the error handler |
$this->privErrorReset(); |
// ----- Look if the file exits |
if (!is_file($this->zipname)) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'"); |
return(false); |
} |
// ----- Check that the file is readeable |
if (!is_readable($this->zipname)) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'"); |
return(false); |
} |
// ----- Check the magic code |
// TBC |
// ----- Check the central header |
// TBC |
// ----- Check each file header |
// TBC |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privParseOptions() |
// Description : |
// This internal methods reads the variable list of arguments ($p_options_list, |
// $p_size) and generate an array with the options and values ($v_result_list). |
// $v_requested_options contains the options that can be present and those that |
// must be present. |
// $v_requested_options is an array, with the option value as key, and 'optional', |
// or 'mandatory' as value. |
// Parameters : |
// See above. |
// Return Values : |
// 1 on success. |
// 0 on failure. |
// -------------------------------------------------------------------------------- |
function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false) |
{ |
$v_result=1; |
// ----- Read the options |
$i=0; |
while ($i<$p_size) { |
// ----- Check if the option is supported |
if (!isset($v_requested_options[$p_options_list[$i]])) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Look for next option |
switch ($p_options_list[$i]) { |
// ----- Look for options that request a path value |
case PCLZIP_OPT_PATH : |
case PCLZIP_OPT_REMOVE_PATH : |
case PCLZIP_OPT_ADD_PATH : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
$v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); |
$i++; |
break; |
case PCLZIP_OPT_TEMP_FILE_THRESHOLD : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
return PclZip::errorCode(); |
} |
// ----- Check for incompatible options |
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); |
return PclZip::errorCode(); |
} |
// ----- Check the value |
$v_value = $p_options_list[$i+1]; |
if ((!is_integer($v_value)) || ($v_value<0)) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
return PclZip::errorCode(); |
} |
// ----- Get the value (and convert it in bytes) |
$v_result_list[$p_options_list[$i]] = $v_value*1048576; |
$i++; |
break; |
case PCLZIP_OPT_TEMP_FILE_ON : |
// ----- Check for incompatible options |
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); |
return PclZip::errorCode(); |
} |
$v_result_list[$p_options_list[$i]] = true; |
break; |
case PCLZIP_OPT_TEMP_FILE_OFF : |
// ----- Check for incompatible options |
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'"); |
return PclZip::errorCode(); |
} |
// ----- Check for incompatible options |
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'"); |
return PclZip::errorCode(); |
} |
$v_result_list[$p_options_list[$i]] = true; |
break; |
case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
if ( is_string($p_options_list[$i+1]) |
&& ($p_options_list[$i+1] != '')) { |
$v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); |
$i++; |
} |
else { |
} |
break; |
// ----- Look for options that request an array of string for value |
case PCLZIP_OPT_BY_NAME : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
if (is_string($p_options_list[$i+1])) { |
$v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1]; |
} |
else if (is_array($p_options_list[$i+1])) { |
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; |
} |
else { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
$i++; |
break; |
// ----- Look for options that request an EREG or PREG expression |
case PCLZIP_OPT_BY_EREG : |
// ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG |
// to PCLZIP_OPT_BY_PREG |
$p_options_list[$i] = PCLZIP_OPT_BY_PREG; |
case PCLZIP_OPT_BY_PREG : |
//case PCLZIP_OPT_CRYPT : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
if (is_string($p_options_list[$i+1])) { |
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; |
} |
else { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
$i++; |
break; |
// ----- Look for options that takes a string |
case PCLZIP_OPT_COMMENT : |
case PCLZIP_OPT_ADD_COMMENT : |
case PCLZIP_OPT_PREPEND_COMMENT : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, |
"Missing parameter value for option '" |
.PclZipUtilOptionText($p_options_list[$i]) |
."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
if (is_string($p_options_list[$i+1])) { |
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; |
} |
else { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, |
"Wrong parameter value for option '" |
.PclZipUtilOptionText($p_options_list[$i]) |
."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
$i++; |
break; |
// ----- Look for options that request an array of index |
case PCLZIP_OPT_BY_INDEX : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
$v_work_list = array(); |
if (is_string($p_options_list[$i+1])) { |
// ----- Remove spaces |
$p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', ''); |
// ----- Parse items |
$v_work_list = explode(",", $p_options_list[$i+1]); |
} |
else if (is_integer($p_options_list[$i+1])) { |
$v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1]; |
} |
else if (is_array($p_options_list[$i+1])) { |
$v_work_list = $p_options_list[$i+1]; |
} |
else { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Reduce the index list |
// each index item in the list must be a couple with a start and |
// an end value : [0,3], [5-5], [8-10], ... |
// ----- Check the format of each item |
$v_sort_flag=false; |
$v_sort_value=0; |
for ($j=0; $j<sizeof($v_work_list); $j++) { |
// ----- Explode the item |
$v_item_list = explode("-", $v_work_list[$j]); |
$v_size_item_list = sizeof($v_item_list); |
// ----- TBC : Here we might check that each item is a |
// real integer ... |
// ----- Look for single value |
if ($v_size_item_list == 1) { |
// ----- Set the option value |
$v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0]; |
$v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0]; |
} |
elseif ($v_size_item_list == 2) { |
// ----- Set the option value |
$v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0]; |
$v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1]; |
} |
else { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Look for list sort |
if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) { |
$v_sort_flag=true; |
// ----- TBC : An automatic sort should be writen ... |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
$v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start']; |
} |
// ----- Sort the items |
if ($v_sort_flag) { |
// TBC : To Be Completed |
} |
// ----- Next option |
$i++; |
break; |
// ----- Look for options that request no value |
case PCLZIP_OPT_REMOVE_ALL_PATH : |
case PCLZIP_OPT_EXTRACT_AS_STRING : |
case PCLZIP_OPT_NO_COMPRESSION : |
case PCLZIP_OPT_EXTRACT_IN_OUTPUT : |
case PCLZIP_OPT_REPLACE_NEWER : |
case PCLZIP_OPT_STOP_ON_ERROR : |
$v_result_list[$p_options_list[$i]] = true; |
break; |
// ----- Look for options that request an octal value |
case PCLZIP_OPT_SET_CHMOD : |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; |
$i++; |
break; |
// ----- Look for options that request a call-back |
case PCLZIP_CB_PRE_EXTRACT : |
case PCLZIP_CB_POST_EXTRACT : |
case PCLZIP_CB_PRE_ADD : |
case PCLZIP_CB_POST_ADD : |
/* for futur use |
case PCLZIP_CB_PRE_DELETE : |
case PCLZIP_CB_POST_DELETE : |
case PCLZIP_CB_PRE_LIST : |
case PCLZIP_CB_POST_LIST : |
*/ |
// ----- Check the number of parameters |
if (($i+1) >= $p_size) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Get the value |
$v_function_name = $p_options_list[$i+1]; |
// ----- Check that the value is a valid existing function |
if (!function_exists($v_function_name)) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Set the attribute |
$v_result_list[$p_options_list[$i]] = $v_function_name; |
$i++; |
break; |
default : |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, |
"Unknown parameter '" |
.$p_options_list[$i]."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Next options |
$i++; |
} |
// ----- Look for mandatory options |
if ($v_requested_options !== false) { |
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { |
// ----- Look for mandatory option |
if ($v_requested_options[$key] == 'mandatory') { |
// ----- Look if present |
if (!isset($v_result_list[$key])) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); |
// ----- Return |
return PclZip::errorCode(); |
} |
} |
} |
} |
// ----- Look for default values |
if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privOptionDefaultThreshold() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privOptionDefaultThreshold(&$p_options) |
{ |
$v_result=1; |
if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) |
|| isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) { |
return $v_result; |
} |
// ----- Get 'memory_limit' configuration value |
$v_memory_limit = ini_get('memory_limit'); |
$v_memory_limit = trim($v_memory_limit); |
$last = strtolower(substr($v_memory_limit, -1)); |
if($last == 'g') |
//$v_memory_limit = $v_memory_limit*1024*1024*1024; |
$v_memory_limit = $v_memory_limit*1073741824; |
if($last == 'm') |
//$v_memory_limit = $v_memory_limit*1024*1024; |
$v_memory_limit = $v_memory_limit*1048576; |
if($last == 'k') |
$v_memory_limit = $v_memory_limit*1024; |
$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO); |
// ----- Sanity check : No threshold if value lower than 1M |
if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) { |
unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privFileDescrParseAtt() |
// Description : |
// Parameters : |
// Return Values : |
// 1 on success. |
// 0 on failure. |
// -------------------------------------------------------------------------------- |
function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false) |
{ |
$v_result=1; |
// ----- For each file in the list check the attributes |
foreach ($p_file_list as $v_key => $v_value) { |
// ----- Check if the option is supported |
if (!isset($v_requested_options[$v_key])) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Look for attribute |
switch ($v_key) { |
case PCLZIP_ATT_FILE_NAME : |
if (!is_string($v_value)) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
$p_filedescr['filename'] = PclZipUtilPathReduction($v_value); |
if ($p_filedescr['filename'] == '') { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
break; |
case PCLZIP_ATT_FILE_NEW_SHORT_NAME : |
if (!is_string($v_value)) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
$p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value); |
if ($p_filedescr['new_short_name'] == '') { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
break; |
case PCLZIP_ATT_FILE_NEW_FULL_NAME : |
if (!is_string($v_value)) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
$p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value); |
if ($p_filedescr['new_full_name'] == '') { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
break; |
// ----- Look for options that takes a string |
case PCLZIP_ATT_FILE_COMMENT : |
if (!is_string($v_value)) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
$p_filedescr['comment'] = $v_value; |
break; |
case PCLZIP_ATT_FILE_MTIME : |
if (!is_integer($v_value)) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'"); |
return PclZip::errorCode(); |
} |
$p_filedescr['mtime'] = $v_value; |
break; |
case PCLZIP_ATT_FILE_CONTENT : |
$p_filedescr['content'] = $v_value; |
break; |
default : |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, |
"Unknown parameter '".$v_key."'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Look for mandatory options |
if ($v_requested_options !== false) { |
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { |
// ----- Look for mandatory option |
if ($v_requested_options[$key] == 'mandatory') { |
// ----- Look if present |
if (!isset($p_file_list[$key])) { |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); |
return PclZip::errorCode(); |
} |
} |
} |
} |
// end foreach |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privFileDescrExpand() |
// Description : |
// This method look for each item of the list to see if its a file, a folder |
// or a string to be added as file. For any other type of files (link, other) |
// just ignore the item. |
// Then prepare the information that will be stored for that file. |
// When its a folder, expand the folder with all the files that are in that |
// folder (recursively). |
// Parameters : |
// Return Values : |
// 1 on success. |
// 0 on failure. |
// -------------------------------------------------------------------------------- |
function privFileDescrExpand(&$p_filedescr_list, &$p_options) |
{ |
$v_result=1; |
// ----- Create a result list |
$v_result_list = array(); |
// ----- Look each entry |
for ($i=0; $i<sizeof($p_filedescr_list); $i++) { |
// ----- Get filedescr |
$v_descr = $p_filedescr_list[$i]; |
// ----- Reduce the filename |
$v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false); |
$v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']); |
// ----- Look for real file or folder |
if (file_exists($v_descr['filename'])) { |
if (@is_file($v_descr['filename'])) { |
$v_descr['type'] = 'file'; |
} |
else if (@is_dir($v_descr['filename'])) { |
$v_descr['type'] = 'folder'; |
} |
else if (@is_link($v_descr['filename'])) { |
// skip |
continue; |
} |
else { |
// skip |
continue; |
} |
} |
// ----- Look for string added as file |
else if (isset($v_descr['content'])) { |
$v_descr['type'] = 'virtual_file'; |
} |
// ----- Missing file |
else { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Calculate the stored filename |
$this->privCalculateStoredFilename($v_descr, $p_options); |
// ----- Add the descriptor in result list |
$v_result_list[sizeof($v_result_list)] = $v_descr; |
// ----- Look for folder |
if ($v_descr['type'] == 'folder') { |
// ----- List of items in folder |
$v_dirlist_descr = array(); |
$v_dirlist_nb = 0; |
if ($v_folder_handler = @opendir($v_descr['filename'])) { |
while (($v_item_handler = @readdir($v_folder_handler)) !== false) { |
// ----- Skip '.' and '..' |
if (($v_item_handler == '.') || ($v_item_handler == '..')) { |
continue; |
} |
// ----- Compose the full filename |
$v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler; |
// ----- Look for different stored filename |
// Because the name of the folder was changed, the name of the |
// files/sub-folders also change |
if (($v_descr['stored_filename'] != $v_descr['filename']) |
&& (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) { |
if ($v_descr['stored_filename'] != '') { |
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler; |
} |
else { |
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler; |
} |
} |
$v_dirlist_nb++; |
} |
@closedir($v_folder_handler); |
} |
else { |
// TBC : unable to open folder in read mode |
} |
// ----- Expand each element of the list |
if ($v_dirlist_nb != 0) { |
// ----- Expand |
if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) { |
return $v_result; |
} |
// ----- Concat the resulting list |
$v_result_list = array_merge($v_result_list, $v_dirlist_descr); |
} |
else { |
} |
// ----- Free local array |
unset($v_dirlist_descr); |
} |
} |
// ----- Get the result list |
$p_filedescr_list = $v_result_list; |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privCreate() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privCreate($p_filedescr_list, &$p_result_list, &$p_options) |
{ |
$v_result=1; |
$v_list_detail = array(); |
// ----- Magic quotes trick |
$this->privDisableMagicQuotes(); |
// ----- Open the file in write mode |
if (($v_result = $this->privOpenFd('wb')) != 1) |
{ |
// ----- Return |
return $v_result; |
} |
// ----- Add the list of files |
$v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options); |
// ----- Close |
$this->privCloseFd(); |
// ----- Magic quotes trick |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privAdd() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privAdd($p_filedescr_list, &$p_result_list, &$p_options) |
{ |
$v_result=1; |
$v_list_detail = array(); |
// ----- Look if the archive exists or is empty |
if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) |
{ |
// ----- Do a create |
$v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options); |
// ----- Return |
return $v_result; |
} |
// ----- Magic quotes trick |
$this->privDisableMagicQuotes(); |
// ----- Open the zip file |
if (($v_result=$this->privOpenFd('rb')) != 1) |
{ |
// ----- Magic quotes trick |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_result; |
} |
// ----- Read the central directory informations |
$v_central_dir = array(); |
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) |
{ |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Go to beginning of File |
@rewind($this->zip_fd); |
// ----- Creates a temporay file |
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; |
// ----- Open the temporary file in write mode |
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) |
{ |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Copy the files from the archive to the temporary file |
// TBC : Here I should better append the file and go back to erase the central dir |
$v_size = $v_central_dir['offset']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = fread($this->zip_fd, $v_read_size); |
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Swap the file descriptor |
// Here is a trick : I swap the temporary fd with the zip fd, in order to use |
// the following methods on the temporary fil and not the real archive |
$v_swap = $this->zip_fd; |
$this->zip_fd = $v_zip_temp_fd; |
$v_zip_temp_fd = $v_swap; |
// ----- Add the files |
$v_header_list = array(); |
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) |
{ |
fclose($v_zip_temp_fd); |
$this->privCloseFd(); |
@unlink($v_zip_temp_name); |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_result; |
} |
// ----- Store the offset of the central dir |
$v_offset = @ftell($this->zip_fd); |
// ----- Copy the block of file headers from the old archive |
$v_size = $v_central_dir['size']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($v_zip_temp_fd, $v_read_size); |
@fwrite($this->zip_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Create the Central Dir files header |
for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++) |
{ |
// ----- Create the file header |
if ($v_header_list[$i]['status'] == 'ok') { |
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) { |
fclose($v_zip_temp_fd); |
$this->privCloseFd(); |
@unlink($v_zip_temp_name); |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_result; |
} |
$v_count++; |
} |
// ----- Transform the header to a 'usable' info |
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
} |
// ----- Zip file comment |
$v_comment = $v_central_dir['comment']; |
if (isset($p_options[PCLZIP_OPT_COMMENT])) { |
$v_comment = $p_options[PCLZIP_OPT_COMMENT]; |
} |
if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) { |
$v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT]; |
} |
if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) { |
$v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment; |
} |
// ----- Calculate the size of the central header |
$v_size = @ftell($this->zip_fd)-$v_offset; |
// ----- Create the central dir footer |
if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) |
{ |
// ----- Reset the file list |
unset($v_header_list); |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_result; |
} |
// ----- Swap back the file descriptor |
$v_swap = $this->zip_fd; |
$this->zip_fd = $v_zip_temp_fd; |
$v_zip_temp_fd = $v_swap; |
// ----- Close |
$this->privCloseFd(); |
// ----- Close the temporary file |
@fclose($v_zip_temp_fd); |
// ----- Magic quotes trick |
$this->privSwapBackMagicQuotes(); |
// ----- Delete the zip file |
// TBC : I should test the result ... |
@unlink($this->zipname); |
// ----- Rename the temporary file |
// TBC : I should test the result ... |
//@rename($v_zip_temp_name, $this->zipname); |
PclZipUtilRename($v_zip_temp_name, $this->zipname); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privOpenFd() |
// Description : |
// Parameters : |
// -------------------------------------------------------------------------------- |
function privOpenFd($p_mode) |
{ |
$v_result=1; |
// ----- Look if already open |
if ($this->zip_fd != 0) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Open the zip file |
if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privCloseFd() |
// Description : |
// Parameters : |
// -------------------------------------------------------------------------------- |
function privCloseFd() |
{ |
$v_result=1; |
if ($this->zip_fd != 0) |
@fclose($this->zip_fd); |
$this->zip_fd = 0; |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privAddList() |
// Description : |
// $p_add_dir and $p_remove_dir will give the ability to memorize a path which is |
// different from the real path of the file. This is usefull if you want to have PclTar |
// running in any directory, and memorize relative path from an other directory. |
// Parameters : |
// $p_list : An array containing the file or directory names to add in the tar |
// $p_result_list : list of added files with their properties (specially the status field) |
// $p_add_dir : Path to add in the filename path archived |
// $p_remove_dir : Path to remove in the filename path archived |
// Return Values : |
// -------------------------------------------------------------------------------- |
// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options) |
function privAddList($p_filedescr_list, &$p_result_list, &$p_options) |
{ |
$v_result=1; |
// ----- Add the files |
$v_header_list = array(); |
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) |
{ |
// ----- Return |
return $v_result; |
} |
// ----- Store the offset of the central dir |
$v_offset = @ftell($this->zip_fd); |
// ----- Create the Central Dir files header |
for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++) |
{ |
// ----- Create the file header |
if ($v_header_list[$i]['status'] == 'ok') { |
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) { |
// ----- Return |
return $v_result; |
} |
$v_count++; |
} |
// ----- Transform the header to a 'usable' info |
$this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
} |
// ----- Zip file comment |
$v_comment = ''; |
if (isset($p_options[PCLZIP_OPT_COMMENT])) { |
$v_comment = $p_options[PCLZIP_OPT_COMMENT]; |
} |
// ----- Calculate the size of the central header |
$v_size = @ftell($this->zip_fd)-$v_offset; |
// ----- Create the central dir footer |
if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) |
{ |
// ----- Reset the file list |
unset($v_header_list); |
// ----- Return |
return $v_result; |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privAddFileList() |
// Description : |
// Parameters : |
// $p_filedescr_list : An array containing the file description |
// or directory names to add in the zip |
// $p_result_list : list of added files with their properties (specially the status field) |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) |
{ |
$v_result=1; |
$v_header = array(); |
// ----- Recuperate the current number of elt in list |
$v_nb = sizeof($p_result_list); |
// ----- Loop on the files |
for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) { |
// ----- Format the filename |
$p_filedescr_list[$j]['filename'] |
= PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false); |
// ----- Skip empty file names |
// TBC : Can this be possible ? not checked in DescrParseAtt ? |
if ($p_filedescr_list[$j]['filename'] == "") { |
continue; |
} |
// ----- Check the filename |
if ( ($p_filedescr_list[$j]['type'] != 'virtual_file') |
&& (!file_exists($p_filedescr_list[$j]['filename']))) { |
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist"); |
return PclZip::errorCode(); |
} |
// ----- Look if it is a file or a dir with no all path remove option |
// or a dir with all its path removed |
// if ( (is_file($p_filedescr_list[$j]['filename'])) |
// || ( is_dir($p_filedescr_list[$j]['filename']) |
if ( ($p_filedescr_list[$j]['type'] == 'file') |
|| ($p_filedescr_list[$j]['type'] == 'virtual_file') |
|| ( ($p_filedescr_list[$j]['type'] == 'folder') |
&& ( !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]) |
|| !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) |
) { |
// ----- Add the file |
$v_result = $this->privAddFile($p_filedescr_list[$j], $v_header, |
$p_options); |
if ($v_result != 1) { |
return $v_result; |
} |
// ----- Store the file infos |
$p_result_list[$v_nb++] = $v_header; |
} |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privAddFile() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privAddFile($p_filedescr, &$p_header, &$p_options) |
{ |
$v_result=1; |
// ----- Working variable |
$p_filename = $p_filedescr['filename']; |
// TBC : Already done in the fileAtt check ... ? |
if ($p_filename == "") { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Look for a stored different filename |
/* TBC : Removed |
if (isset($p_filedescr['stored_filename'])) { |
$v_stored_filename = $p_filedescr['stored_filename']; |
} |
else { |
$v_stored_filename = $p_filedescr['stored_filename']; |
} |
*/ |
// ----- Set the file properties |
clearstatcache(); |
$p_header['version'] = 20; |
$p_header['version_extracted'] = 10; |
$p_header['flag'] = 0; |
$p_header['compression'] = 0; |
$p_header['crc'] = 0; |
$p_header['compressed_size'] = 0; |
$p_header['filename_len'] = strlen($p_filename); |
$p_header['extra_len'] = 0; |
$p_header['disk'] = 0; |
$p_header['internal'] = 0; |
$p_header['offset'] = 0; |
$p_header['filename'] = $p_filename; |
// TBC : Removed $p_header['stored_filename'] = $v_stored_filename; |
$p_header['stored_filename'] = $p_filedescr['stored_filename']; |
$p_header['extra'] = ''; |
$p_header['status'] = 'ok'; |
$p_header['index'] = -1; |
// ----- Look for regular file |
if ($p_filedescr['type']=='file') { |
$p_header['external'] = 0x00000000; |
$p_header['size'] = filesize($p_filename); |
} |
// ----- Look for regular folder |
else if ($p_filedescr['type']=='folder') { |
$p_header['external'] = 0x00000010; |
$p_header['mtime'] = filemtime($p_filename); |
$p_header['size'] = filesize($p_filename); |
} |
// ----- Look for virtual file |
else if ($p_filedescr['type'] == 'virtual_file') { |
$p_header['external'] = 0x00000000; |
$p_header['size'] = strlen($p_filedescr['content']); |
} |
// ----- Look for filetime |
if (isset($p_filedescr['mtime'])) { |
$p_header['mtime'] = $p_filedescr['mtime']; |
} |
else if ($p_filedescr['type'] == 'virtual_file') { |
$p_header['mtime'] = time(); |
} |
else { |
$p_header['mtime'] = filemtime($p_filename); |
} |
// ------ Look for file comment |
if (isset($p_filedescr['comment'])) { |
$p_header['comment_len'] = strlen($p_filedescr['comment']); |
$p_header['comment'] = $p_filedescr['comment']; |
} |
else { |
$p_header['comment_len'] = 0; |
$p_header['comment'] = ''; |
} |
// ----- Look for pre-add callback |
if (isset($p_options[PCLZIP_CB_PRE_ADD])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_header, $v_local_header); |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header); |
if ($v_result == 0) { |
// ----- Change the file status |
$p_header['status'] = "skipped"; |
$v_result = 1; |
} |
// ----- Update the informations |
// Only some fields can be modified |
if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { |
$p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']); |
} |
} |
// ----- Look for empty stored filename |
if ($p_header['stored_filename'] == "") { |
$p_header['status'] = "filtered"; |
} |
// ----- Check the path length |
if (strlen($p_header['stored_filename']) > 0xFF) { |
$p_header['status'] = 'filename_too_long'; |
} |
// ----- Look if no error, or file not skipped |
if ($p_header['status'] == 'ok') { |
// ----- Look for a file |
if ($p_filedescr['type'] == 'file') { |
// ----- Look for using temporary file to zip |
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) |
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) |
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) |
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) { |
$v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options); |
if ($v_result < PCLZIP_ERR_NO_ERROR) { |
return $v_result; |
} |
} |
// ----- Use "in memory" zip algo |
else { |
// ----- Open the source file |
if (($v_file = @fopen($p_filename, "rb")) == 0) { |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); |
return PclZip::errorCode(); |
} |
// ----- Read the file content |
$v_content = @fread($v_file, $p_header['size']); |
// ----- Close the file |
@fclose($v_file); |
// ----- Calculate the CRC |
$p_header['crc'] = @crc32($v_content); |
// ----- Look for no compression |
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { |
// ----- Set header parameters |
$p_header['compressed_size'] = $p_header['size']; |
$p_header['compression'] = 0; |
} |
// ----- Look for normal compression |
else { |
// ----- Compress the content |
$v_content = @gzdeflate($v_content); |
// ----- Set header parameters |
$p_header['compressed_size'] = strlen($v_content); |
$p_header['compression'] = 8; |
} |
// ----- Call the header generation |
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { |
@fclose($v_file); |
return $v_result; |
} |
// ----- Write the compressed (or not) content |
@fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); |
} |
} |
// ----- Look for a virtual file (a file from string) |
else if ($p_filedescr['type'] == 'virtual_file') { |
$v_content = $p_filedescr['content']; |
// ----- Calculate the CRC |
$p_header['crc'] = @crc32($v_content); |
// ----- Look for no compression |
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { |
// ----- Set header parameters |
$p_header['compressed_size'] = $p_header['size']; |
$p_header['compression'] = 0; |
} |
// ----- Look for normal compression |
else { |
// ----- Compress the content |
$v_content = @gzdeflate($v_content); |
// ----- Set header parameters |
$p_header['compressed_size'] = strlen($v_content); |
$p_header['compression'] = 8; |
} |
// ----- Call the header generation |
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { |
@fclose($v_file); |
return $v_result; |
} |
// ----- Write the compressed (or not) content |
@fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); |
} |
// ----- Look for a directory |
else if ($p_filedescr['type'] == 'folder') { |
// ----- Look for directory last '/' |
if (@substr($p_header['stored_filename'], -1) != '/') { |
$p_header['stored_filename'] .= '/'; |
} |
// ----- Set the file properties |
$p_header['size'] = 0; |
//$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked |
$p_header['external'] = 0x00000010; // Value for a folder : to be checked |
// ----- Call the header generation |
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) |
{ |
return $v_result; |
} |
} |
} |
// ----- Look for post-add callback |
if (isset($p_options[PCLZIP_CB_POST_ADD])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_header, $v_local_header); |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header); |
if ($v_result == 0) { |
// ----- Ignored |
$v_result = 1; |
} |
// ----- Update the informations |
// Nothing can be modified |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privAddFileUsingTempFile() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options) |
{ |
$v_result=PCLZIP_ERR_NO_ERROR; |
// ----- Working variable |
$p_filename = $p_filedescr['filename']; |
// ----- Open the source file |
if (($v_file = @fopen($p_filename, "rb")) == 0) { |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); |
return PclZip::errorCode(); |
} |
// ----- Creates a compressed temporary file |
$v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; |
if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) { |
fclose($v_file); |
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); |
return PclZip::errorCode(); |
} |
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks |
$v_size = filesize($p_filename); |
while ($v_size != 0) { |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($v_file, $v_read_size); |
//$v_binary_data = pack('a'.$v_read_size, $v_buffer); |
@gzputs($v_file_compressed, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Close the file |
@fclose($v_file); |
@gzclose($v_file_compressed); |
// ----- Check the minimum file size |
if (filesize($v_gzip_temp_name) < 18) { |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes'); |
return PclZip::errorCode(); |
} |
// ----- Extract the compressed attributes |
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) { |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); |
return PclZip::errorCode(); |
} |
// ----- Read the gzip file header |
$v_binary_data = @fread($v_file_compressed, 10); |
$v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data); |
// ----- Check some parameters |
$v_data_header['os'] = bin2hex($v_data_header['os']); |
// ----- Read the gzip file footer |
@fseek($v_file_compressed, filesize($v_gzip_temp_name)-8); |
$v_binary_data = @fread($v_file_compressed, 8); |
$v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data); |
// ----- Set the attributes |
$p_header['compression'] = ord($v_data_header['cm']); |
//$p_header['mtime'] = $v_data_header['mtime']; |
$p_header['crc'] = $v_data_footer['crc']; |
$p_header['compressed_size'] = filesize($v_gzip_temp_name)-18; |
// ----- Close the file |
@fclose($v_file_compressed); |
// ----- Call the header generation |
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { |
return $v_result; |
} |
// ----- Add the compressed data |
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) |
{ |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); |
return PclZip::errorCode(); |
} |
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks |
fseek($v_file_compressed, 10); |
$v_size = $p_header['compressed_size']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($v_file_compressed, $v_read_size); |
//$v_binary_data = pack('a'.$v_read_size, $v_buffer); |
@fwrite($this->zip_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Close the file |
@fclose($v_file_compressed); |
// ----- Unlink the temporary file |
@unlink($v_gzip_temp_name); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privCalculateStoredFilename() |
// Description : |
// Based on file descriptor properties and global options, this method |
// calculate the filename that will be stored in the archive. |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privCalculateStoredFilename(&$p_filedescr, &$p_options) |
{ |
$v_result=1; |
// ----- Working variables |
$p_filename = $p_filedescr['filename']; |
if (isset($p_options[PCLZIP_OPT_ADD_PATH])) { |
$p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH]; |
} |
else { |
$p_add_dir = ''; |
} |
if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) { |
$p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH]; |
} |
else { |
$p_remove_dir = ''; |
} |
if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { |
$p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH]; |
} |
else { |
$p_remove_all_dir = 0; |
} |
// ----- Look for full name change |
if (isset($p_filedescr['new_full_name'])) { |
// ----- Remove drive letter if any |
$v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']); |
} |
// ----- Look for path and/or short name change |
else { |
// ----- Look for short name change |
// Its when we cahnge just the filename but not the path |
if (isset($p_filedescr['new_short_name'])) { |
$v_path_info = pathinfo($p_filename); |
$v_dir = ''; |
if ($v_path_info['dirname'] != '') { |
$v_dir = $v_path_info['dirname'].'/'; |
} |
$v_stored_filename = $v_dir.$p_filedescr['new_short_name']; |
} |
else { |
// ----- Calculate the stored filename |
$v_stored_filename = $p_filename; |
} |
// ----- Look for all path to remove |
if ($p_remove_all_dir) { |
$v_stored_filename = basename($p_filename); |
} |
// ----- Look for partial path remove |
else if ($p_remove_dir != "") { |
if (substr($p_remove_dir, -1) != '/') |
$p_remove_dir .= "/"; |
if ( (substr($p_filename, 0, 2) == "./") |
|| (substr($p_remove_dir, 0, 2) == "./")) { |
if ( (substr($p_filename, 0, 2) == "./") |
&& (substr($p_remove_dir, 0, 2) != "./")) { |
$p_remove_dir = "./".$p_remove_dir; |
} |
if ( (substr($p_filename, 0, 2) != "./") |
&& (substr($p_remove_dir, 0, 2) == "./")) { |
$p_remove_dir = substr($p_remove_dir, 2); |
} |
} |
$v_compare = PclZipUtilPathInclusion($p_remove_dir, |
$v_stored_filename); |
if ($v_compare > 0) { |
if ($v_compare == 2) { |
$v_stored_filename = ""; |
} |
else { |
$v_stored_filename = substr($v_stored_filename, |
strlen($p_remove_dir)); |
} |
} |
} |
// ----- Remove drive letter if any |
$v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename); |
// ----- Look for path to add |
if ($p_add_dir != "") { |
if (substr($p_add_dir, -1) == "/") |
$v_stored_filename = $p_add_dir.$v_stored_filename; |
else |
$v_stored_filename = $p_add_dir."/".$v_stored_filename; |
} |
} |
// ----- Filename (reduce the path of stored name) |
$v_stored_filename = PclZipUtilPathReduction($v_stored_filename); |
$p_filedescr['stored_filename'] = $v_stored_filename; |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privWriteFileHeader() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privWriteFileHeader(&$p_header) |
{ |
$v_result=1; |
// ----- Store the offset position of the file |
$p_header['offset'] = ftell($this->zip_fd); |
// ----- Transform UNIX mtime to DOS format mdate/mtime |
$v_date = getdate($p_header['mtime']); |
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; |
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; |
// ----- Packed data |
$v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, |
$p_header['version_extracted'], $p_header['flag'], |
$p_header['compression'], $v_mtime, $v_mdate, |
$p_header['crc'], $p_header['compressed_size'], |
$p_header['size'], |
strlen($p_header['stored_filename']), |
$p_header['extra_len']); |
// ----- Write the first 148 bytes of the header in the archive |
fputs($this->zip_fd, $v_binary_data, 30); |
// ----- Write the variable fields |
if (strlen($p_header['stored_filename']) != 0) |
{ |
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); |
} |
if ($p_header['extra_len'] != 0) |
{ |
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privWriteCentralFileHeader() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privWriteCentralFileHeader(&$p_header) |
{ |
$v_result=1; |
// TBC |
//for(reset($p_header); $key = key($p_header); next($p_header)) { |
//} |
// ----- Transform UNIX mtime to DOS format mdate/mtime |
$v_date = getdate($p_header['mtime']); |
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; |
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; |
// ----- Packed data |
$v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, |
$p_header['version'], $p_header['version_extracted'], |
$p_header['flag'], $p_header['compression'], |
$v_mtime, $v_mdate, $p_header['crc'], |
$p_header['compressed_size'], $p_header['size'], |
strlen($p_header['stored_filename']), |
$p_header['extra_len'], $p_header['comment_len'], |
$p_header['disk'], $p_header['internal'], |
$p_header['external'], $p_header['offset']); |
// ----- Write the 42 bytes of the header in the zip file |
fputs($this->zip_fd, $v_binary_data, 46); |
// ----- Write the variable fields |
if (strlen($p_header['stored_filename']) != 0) |
{ |
fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); |
} |
if ($p_header['extra_len'] != 0) |
{ |
fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); |
} |
if ($p_header['comment_len'] != 0) |
{ |
fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privWriteCentralHeader() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) |
{ |
$v_result=1; |
// ----- Packed data |
$v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, |
$p_nb_entries, $p_size, |
$p_offset, strlen($p_comment)); |
// ----- Write the 22 bytes of the header in the zip file |
fputs($this->zip_fd, $v_binary_data, 22); |
// ----- Write the variable fields |
if (strlen($p_comment) != 0) |
{ |
fputs($this->zip_fd, $p_comment, strlen($p_comment)); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privList() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privList(&$p_list) |
{ |
$v_result=1; |
// ----- Magic quotes trick |
$this->privDisableMagicQuotes(); |
// ----- Open the zip file |
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) |
{ |
// ----- Magic quotes trick |
$this->privSwapBackMagicQuotes(); |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read the central directory informations |
$v_central_dir = array(); |
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) |
{ |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Go to beginning of Central Dir |
@rewind($this->zip_fd); |
if (@fseek($this->zip_fd, $v_central_dir['offset'])) |
{ |
$this->privSwapBackMagicQuotes(); |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read each entry |
for ($i=0; $i<$v_central_dir['entries']; $i++) |
{ |
// ----- Read the file header |
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) |
{ |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
$v_header['index'] = $i; |
// ----- Get the only interesting attributes |
$this->privConvertHeader2FileInfo($v_header, $p_list[$i]); |
unset($v_header); |
} |
// ----- Close the zip file |
$this->privCloseFd(); |
// ----- Magic quotes trick |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privConvertHeader2FileInfo() |
// Description : |
// This function takes the file informations from the central directory |
// entries and extract the interesting parameters that will be given back. |
// The resulting file infos are set in the array $p_info |
// $p_info['filename'] : Filename with full path. Given by user (add), |
// extracted in the filesystem (extract). |
// $p_info['stored_filename'] : Stored filename in the archive. |
// $p_info['size'] = Size of the file. |
// $p_info['compressed_size'] = Compressed size of the file. |
// $p_info['mtime'] = Last modification date of the file. |
// $p_info['comment'] = Comment associated with the file. |
// $p_info['folder'] = true/false : indicates if the entry is a folder or not. |
// $p_info['status'] = status of the action on the file. |
// $p_info['crc'] = CRC of the file content. |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privConvertHeader2FileInfo($p_header, &$p_info) |
{ |
$v_result=1; |
// ----- Get the interesting attributes |
$v_temp_path = PclZipUtilPathReduction($p_header['filename']); |
$p_info['filename'] = $v_temp_path; |
$v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']); |
$p_info['stored_filename'] = $v_temp_path; |
$p_info['size'] = $p_header['size']; |
$p_info['compressed_size'] = $p_header['compressed_size']; |
$p_info['mtime'] = $p_header['mtime']; |
$p_info['comment'] = $p_header['comment']; |
$p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); |
$p_info['index'] = $p_header['index']; |
$p_info['status'] = $p_header['status']; |
$p_info['crc'] = $p_header['crc']; |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privExtractByRule() |
// Description : |
// Extract a file or directory depending of rules (by index, by name, ...) |
// Parameters : |
// $p_file_list : An array where will be placed the properties of each |
// extracted file |
// $p_path : Path to add while writing the extracted files |
// $p_remove_path : Path to remove (from the file memorized path) while writing the |
// extracted files. If the path does not match the file path, |
// the file is extracted with its memorized path. |
// $p_remove_path does not apply to 'list' mode. |
// $p_path and $p_remove_path are commulative. |
// Return Values : |
// 1 on success,0 or less on error (see error code list) |
// -------------------------------------------------------------------------------- |
function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) |
{ |
$v_result=1; |
// ----- Magic quotes trick |
$this->privDisableMagicQuotes(); |
// ----- Check the path |
if ( ($p_path == "") |
|| ( (substr($p_path, 0, 1) != "/") |
&& (substr($p_path, 0, 3) != "../") |
&& (substr($p_path,1,2)!=":/"))) |
$p_path = "./".$p_path; |
// ----- Reduce the path last (and duplicated) '/' |
if (($p_path != "./") && ($p_path != "/")) |
{ |
// ----- Look for the path end '/' |
while (substr($p_path, -1) == "/") |
{ |
$p_path = substr($p_path, 0, strlen($p_path)-1); |
} |
} |
// ----- Look for path to remove format (should end by /) |
if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) |
{ |
$p_remove_path .= '/'; |
} |
$p_remove_path_size = strlen($p_remove_path); |
// ----- Open the zip file |
if (($v_result = $this->privOpenFd('rb')) != 1) |
{ |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Read the central directory informations |
$v_central_dir = array(); |
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Start at beginning of Central Dir |
$v_pos_entry = $v_central_dir['offset']; |
// ----- Read each entry |
$j_start = 0; |
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) |
{ |
// ----- Read next Central dir entry |
@rewind($this->zip_fd); |
if (@fseek($this->zip_fd, $v_pos_entry)) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read the file header |
$v_header = array(); |
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Store the index |
$v_header['index'] = $i; |
// ----- Store the file position |
$v_pos_entry = ftell($this->zip_fd); |
// ----- Look for the specific extract rules |
$v_extract = false; |
// ----- Look for extract by name rule |
if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) |
&& ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { |
// ----- Look if the filename is in the list |
for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) { |
// ----- Look for a directory |
if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") { |
// ----- Look if the directory is in the filename path |
if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) |
&& (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { |
$v_extract = true; |
} |
} |
// ----- Look for a filename |
elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { |
$v_extract = true; |
} |
} |
} |
// ----- Look for extract by ereg rule |
// ereg() is deprecated with PHP 5.3 |
/* |
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) |
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) { |
if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) { |
$v_extract = true; |
} |
} |
*/ |
// ----- Look for extract by preg rule |
else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) |
&& ($p_options[PCLZIP_OPT_BY_PREG] != "")) { |
if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) { |
$v_extract = true; |
} |
} |
// ----- Look for extract by index rule |
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) |
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { |
// ----- Look if the index is in the list |
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) { |
if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { |
$v_extract = true; |
} |
if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { |
$j_start = $j+1; |
} |
if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { |
break; |
} |
} |
} |
// ----- Look for no rule, which means extract all the archive |
else { |
$v_extract = true; |
} |
// ----- Check compression method |
if ( ($v_extract) |
&& ( ($v_header['compression'] != 8) |
&& ($v_header['compression'] != 0))) { |
$v_header['status'] = 'unsupported_compression'; |
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR |
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) |
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { |
$this->privSwapBackMagicQuotes(); |
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION, |
"Filename '".$v_header['stored_filename']."' is " |
."compressed by an unsupported compression " |
."method (".$v_header['compression'].") "); |
return PclZip::errorCode(); |
} |
} |
// ----- Check encrypted files |
if (($v_extract) && (($v_header['flag'] & 1) == 1)) { |
$v_header['status'] = 'unsupported_encryption'; |
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR |
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) |
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { |
$this->privSwapBackMagicQuotes(); |
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, |
"Unsupported encryption for " |
." filename '".$v_header['stored_filename'] |
."'"); |
return PclZip::errorCode(); |
} |
} |
// ----- Look for real extraction |
if (($v_extract) && ($v_header['status'] != 'ok')) { |
$v_result = $this->privConvertHeader2FileInfo($v_header, |
$p_file_list[$v_nb_extracted++]); |
if ($v_result != 1) { |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
$v_extract = false; |
} |
// ----- Look for real extraction |
if ($v_extract) |
{ |
// ----- Go to the file position |
@rewind($this->zip_fd); |
if (@fseek($this->zip_fd, $v_header['offset'])) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Look for extraction as string |
if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) { |
$v_string = ''; |
// ----- Extracting the file |
$v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options); |
if ($v_result1 < 1) { |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result1; |
} |
// ----- Get the only interesting attributes |
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Set the file content |
$p_file_list[$v_nb_extracted]['content'] = $v_string; |
// ----- Next extracted file |
$v_nb_extracted++; |
// ----- Look for user callback abort |
if ($v_result1 == 2) { |
break; |
} |
} |
// ----- Look for extraction in standard output |
elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) |
&& ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) { |
// ----- Extracting the file in standard output |
$v_result1 = $this->privExtractFileInOutput($v_header, $p_options); |
if ($v_result1 < 1) { |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result1; |
} |
// ----- Get the only interesting attributes |
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Look for user callback abort |
if ($v_result1 == 2) { |
break; |
} |
} |
// ----- Look for normal extraction |
else { |
// ----- Extracting the file |
$v_result1 = $this->privExtractFile($v_header, |
$p_path, $p_remove_path, |
$p_remove_all_path, |
$p_options); |
if ($v_result1 < 1) { |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result1; |
} |
// ----- Get the only interesting attributes |
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
return $v_result; |
} |
// ----- Look for user callback abort |
if ($v_result1 == 2) { |
break; |
} |
} |
} |
} |
// ----- Close the zip file |
$this->privCloseFd(); |
$this->privSwapBackMagicQuotes(); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privExtractFile() |
// Description : |
// Parameters : |
// Return Values : |
// |
// 1 : ... ? |
// PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback |
// -------------------------------------------------------------------------------- |
function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) |
{ |
$v_result=1; |
// ----- Read the file header |
if (($v_result = $this->privReadFileHeader($v_header)) != 1) |
{ |
// ----- Return |
return $v_result; |
} |
// ----- Check that the file header is coherent with $p_entry info |
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { |
// TBC |
} |
// ----- Look for all path to remove |
if ($p_remove_all_path == true) { |
// ----- Look for folder entry that not need to be extracted |
if (($p_entry['external']&0x00000010)==0x00000010) { |
$p_entry['status'] = "filtered"; |
return $v_result; |
} |
// ----- Get the basename of the path |
$p_entry['filename'] = basename($p_entry['filename']); |
} |
// ----- Look for path to remove |
else if ($p_remove_path != "") |
{ |
if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) |
{ |
// ----- Change the file status |
$p_entry['status'] = "filtered"; |
// ----- Return |
return $v_result; |
} |
$p_remove_path_size = strlen($p_remove_path); |
if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) |
{ |
// ----- Remove the path |
$p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); |
} |
} |
// ----- Add the path |
if ($p_path != '') { |
$p_entry['filename'] = $p_path."/".$p_entry['filename']; |
} |
// ----- Check a base_dir_restriction |
if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) { |
$v_inclusion |
= PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], |
$p_entry['filename']); |
if ($v_inclusion == 0) { |
PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION, |
"Filename '".$p_entry['filename']."' is " |
."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION"); |
return PclZip::errorCode(); |
} |
} |
// ----- Look for pre-extract callback |
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_entry, $v_local_header); |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); |
if ($v_result == 0) { |
// ----- Change the file status |
$p_entry['status'] = "skipped"; |
$v_result = 1; |
} |
// ----- Look for abort result |
if ($v_result == 2) { |
// ----- This status is internal and will be changed in 'skipped' |
$p_entry['status'] = "aborted"; |
$v_result = PCLZIP_ERR_USER_ABORTED; |
} |
// ----- Update the informations |
// Only some fields can be modified |
$p_entry['filename'] = $v_local_header['filename']; |
} |
// ----- Look if extraction should be done |
if ($p_entry['status'] == 'ok') { |
// ----- Look for specific actions while the file exist |
if (file_exists($p_entry['filename'])) |
{ |
// ----- Look if file is a directory |
if (is_dir($p_entry['filename'])) |
{ |
// ----- Change the file status |
$p_entry['status'] = "already_a_directory"; |
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR |
// For historical reason first PclZip implementation does not stop |
// when this kind of error occurs. |
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) |
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { |
PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY, |
"Filename '".$p_entry['filename']."' is " |
."already used by an existing directory"); |
return PclZip::errorCode(); |
} |
} |
// ----- Look if file is write protected |
else if (!is_writeable($p_entry['filename'])) |
{ |
// ----- Change the file status |
$p_entry['status'] = "write_protected"; |
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR |
// For historical reason first PclZip implementation does not stop |
// when this kind of error occurs. |
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) |
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { |
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, |
"Filename '".$p_entry['filename']."' exists " |
."and is write protected"); |
return PclZip::errorCode(); |
} |
} |
// ----- Look if the extracted file is older |
else if (filemtime($p_entry['filename']) > $p_entry['mtime']) |
{ |
// ----- Change the file status |
if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER])) |
&& ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) { |
} |
else { |
$p_entry['status'] = "newer_exist"; |
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR |
// For historical reason first PclZip implementation does not stop |
// when this kind of error occurs. |
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) |
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { |
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, |
"Newer version of '".$p_entry['filename']."' exists " |
."and option PCLZIP_OPT_REPLACE_NEWER is not selected"); |
return PclZip::errorCode(); |
} |
} |
} |
else { |
} |
} |
// ----- Check the directory availability and create it if necessary |
else { |
if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) |
$v_dir_to_check = $p_entry['filename']; |
else if (!strstr($p_entry['filename'], "/")) |
$v_dir_to_check = ""; |
else |
$v_dir_to_check = dirname($p_entry['filename']); |
if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) { |
// ----- Change the file status |
$p_entry['status'] = "path_creation_fail"; |
// ----- Return |
//return $v_result; |
$v_result = 1; |
} |
} |
} |
// ----- Look if extraction should be done |
if ($p_entry['status'] == 'ok') { |
// ----- Do the extraction (if not a folder) |
if (!(($p_entry['external']&0x00000010)==0x00000010)) |
{ |
// ----- Look for not compressed file |
if ($p_entry['compression'] == 0) { |
// ----- Opening destination file |
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) |
{ |
// ----- Change the file status |
$p_entry['status'] = "write_error"; |
// ----- Return |
return $v_result; |
} |
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks |
$v_size = $p_entry['compressed_size']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($this->zip_fd, $v_read_size); |
/* Try to speed up the code |
$v_binary_data = pack('a'.$v_read_size, $v_buffer); |
@fwrite($v_dest_file, $v_binary_data, $v_read_size); |
*/ |
@fwrite($v_dest_file, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Closing the destination file |
fclose($v_dest_file); |
// ----- Change the file mtime |
touch($p_entry['filename'], $p_entry['mtime']); |
} |
else { |
// ----- TBC |
// Need to be finished |
if (($p_entry['flag'] & 1) == 1) { |
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.'); |
return PclZip::errorCode(); |
} |
// ----- Look for using temporary file to unzip |
if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) |
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) |
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) |
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) { |
$v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options); |
if ($v_result < PCLZIP_ERR_NO_ERROR) { |
return $v_result; |
} |
} |
// ----- Look for extract in memory |
else { |
// ----- Read the compressed file in a buffer (one shot) |
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); |
// ----- Decompress the file |
$v_file_content = @gzinflate($v_buffer); |
unset($v_buffer); |
if ($v_file_content === FALSE) { |
// ----- Change the file status |
// TBC |
$p_entry['status'] = "error"; |
return $v_result; |
} |
// ----- Opening destination file |
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { |
// ----- Change the file status |
$p_entry['status'] = "write_error"; |
return $v_result; |
} |
// ----- Write the uncompressed data |
@fwrite($v_dest_file, $v_file_content, $p_entry['size']); |
unset($v_file_content); |
// ----- Closing the destination file |
@fclose($v_dest_file); |
} |
// ----- Change the file mtime |
@touch($p_entry['filename'], $p_entry['mtime']); |
} |
// ----- Look for chmod option |
if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) { |
// ----- Change the mode of the file |
@chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]); |
} |
} |
} |
// ----- Change abort status |
if ($p_entry['status'] == "aborted") { |
$p_entry['status'] = "skipped"; |
} |
// ----- Look for post-extract callback |
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_entry, $v_local_header); |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); |
// ----- Look for abort result |
if ($v_result == 2) { |
$v_result = PCLZIP_ERR_USER_ABORTED; |
} |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privExtractFileUsingTempFile() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privExtractFileUsingTempFile(&$p_entry, &$p_options) |
{ |
$v_result=1; |
// ----- Creates a temporary file |
$v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; |
if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) { |
fclose($v_file); |
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); |
return PclZip::errorCode(); |
} |
// ----- Write gz file format header |
$v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3)); |
@fwrite($v_dest_file, $v_binary_data, 10); |
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks |
$v_size = $p_entry['compressed_size']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($this->zip_fd, $v_read_size); |
//$v_binary_data = pack('a'.$v_read_size, $v_buffer); |
@fwrite($v_dest_file, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Write gz file format footer |
$v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']); |
@fwrite($v_dest_file, $v_binary_data, 8); |
// ----- Close the temporary file |
@fclose($v_dest_file); |
// ----- Opening destination file |
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { |
$p_entry['status'] = "write_error"; |
return $v_result; |
} |
// ----- Open the temporary gz file |
if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) { |
@fclose($v_dest_file); |
$p_entry['status'] = "read_error"; |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); |
return PclZip::errorCode(); |
} |
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks |
$v_size = $p_entry['size']; |
while ($v_size != 0) { |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @gzread($v_src_file, $v_read_size); |
//$v_binary_data = pack('a'.$v_read_size, $v_buffer); |
@fwrite($v_dest_file, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
@fclose($v_dest_file); |
@gzclose($v_src_file); |
// ----- Delete the temporary file |
@unlink($v_gzip_temp_name); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privExtractFileInOutput() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privExtractFileInOutput(&$p_entry, &$p_options) |
{ |
$v_result=1; |
// ----- Read the file header |
if (($v_result = $this->privReadFileHeader($v_header)) != 1) { |
return $v_result; |
} |
// ----- Check that the file header is coherent with $p_entry info |
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { |
// TBC |
} |
// ----- Look for pre-extract callback |
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_entry, $v_local_header); |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); |
if ($v_result == 0) { |
// ----- Change the file status |
$p_entry['status'] = "skipped"; |
$v_result = 1; |
} |
// ----- Look for abort result |
if ($v_result == 2) { |
// ----- This status is internal and will be changed in 'skipped' |
$p_entry['status'] = "aborted"; |
$v_result = PCLZIP_ERR_USER_ABORTED; |
} |
// ----- Update the informations |
// Only some fields can be modified |
$p_entry['filename'] = $v_local_header['filename']; |
} |
// ----- Trace |
// ----- Look if extraction should be done |
if ($p_entry['status'] == 'ok') { |
// ----- Do the extraction (if not a folder) |
if (!(($p_entry['external']&0x00000010)==0x00000010)) { |
// ----- Look for not compressed file |
if ($p_entry['compressed_size'] == $p_entry['size']) { |
// ----- Read the file in a buffer (one shot) |
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); |
// ----- Send the file to the output |
echo $v_buffer; |
unset($v_buffer); |
} |
else { |
// ----- Read the compressed file in a buffer (one shot) |
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); |
// ----- Decompress the file |
$v_file_content = gzinflate($v_buffer); |
unset($v_buffer); |
// ----- Send the file to the output |
echo $v_file_content; |
unset($v_file_content); |
} |
} |
} |
// ----- Change abort status |
if ($p_entry['status'] == "aborted") { |
$p_entry['status'] = "skipped"; |
} |
// ----- Look for post-extract callback |
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_entry, $v_local_header); |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); |
// ----- Look for abort result |
if ($v_result == 2) { |
$v_result = PCLZIP_ERR_USER_ABORTED; |
} |
} |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privExtractFileAsString() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privExtractFileAsString(&$p_entry, &$p_string, &$p_options) |
{ |
$v_result=1; |
// ----- Read the file header |
$v_header = array(); |
if (($v_result = $this->privReadFileHeader($v_header)) != 1) |
{ |
// ----- Return |
return $v_result; |
} |
// ----- Check that the file header is coherent with $p_entry info |
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { |
// TBC |
} |
// ----- Look for pre-extract callback |
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_entry, $v_local_header); |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); |
if ($v_result == 0) { |
// ----- Change the file status |
$p_entry['status'] = "skipped"; |
$v_result = 1; |
} |
// ----- Look for abort result |
if ($v_result == 2) { |
// ----- This status is internal and will be changed in 'skipped' |
$p_entry['status'] = "aborted"; |
$v_result = PCLZIP_ERR_USER_ABORTED; |
} |
// ----- Update the informations |
// Only some fields can be modified |
$p_entry['filename'] = $v_local_header['filename']; |
} |
// ----- Look if extraction should be done |
if ($p_entry['status'] == 'ok') { |
// ----- Do the extraction (if not a folder) |
if (!(($p_entry['external']&0x00000010)==0x00000010)) { |
// ----- Look for not compressed file |
// if ($p_entry['compressed_size'] == $p_entry['size']) |
if ($p_entry['compression'] == 0) { |
// ----- Reading the file |
$p_string = @fread($this->zip_fd, $p_entry['compressed_size']); |
} |
else { |
// ----- Reading the file |
$v_data = @fread($this->zip_fd, $p_entry['compressed_size']); |
// ----- Decompress the file |
if (($p_string = @gzinflate($v_data)) === FALSE) { |
// TBC |
} |
} |
// ----- Trace |
} |
else { |
// TBC : error : can not extract a folder in a string |
} |
} |
// ----- Change abort status |
if ($p_entry['status'] == "aborted") { |
$p_entry['status'] = "skipped"; |
} |
// ----- Look for post-extract callback |
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { |
// ----- Generate a local information |
$v_local_header = array(); |
$this->privConvertHeader2FileInfo($p_entry, $v_local_header); |
// ----- Swap the content to header |
$v_local_header['content'] = $p_string; |
$p_string = ''; |
// ----- Call the callback |
// Here I do not use call_user_func() because I need to send a reference to the |
// header. |
// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); |
$v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); |
// ----- Swap back the content to header |
$p_string = $v_local_header['content']; |
unset($v_local_header['content']); |
// ----- Look for abort result |
if ($v_result == 2) { |
$v_result = PCLZIP_ERR_USER_ABORTED; |
} |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privReadFileHeader() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privReadFileHeader(&$p_header) |
{ |
$v_result=1; |
// ----- Read the 4 bytes signature |
$v_binary_data = @fread($this->zip_fd, 4); |
$v_data = unpack('Vid', $v_binary_data); |
// ----- Check signature |
if ($v_data['id'] != 0x04034b50) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read the first 42 bytes of the header |
$v_binary_data = fread($this->zip_fd, 26); |
// ----- Look for invalid block size |
if (strlen($v_binary_data) != 26) |
{ |
$p_header['filename'] = ""; |
$p_header['status'] = "invalid_header"; |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Extract the values |
$v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); |
// ----- Get filename |
$p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']); |
// ----- Get extra_fields |
if ($v_data['extra_len'] != 0) { |
$p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']); |
} |
else { |
$p_header['extra'] = ''; |
} |
// ----- Extract properties |
$p_header['version_extracted'] = $v_data['version']; |
$p_header['compression'] = $v_data['compression']; |
$p_header['size'] = $v_data['size']; |
$p_header['compressed_size'] = $v_data['compressed_size']; |
$p_header['crc'] = $v_data['crc']; |
$p_header['flag'] = $v_data['flag']; |
$p_header['filename_len'] = $v_data['filename_len']; |
// ----- Recuperate date in UNIX format |
$p_header['mdate'] = $v_data['mdate']; |
$p_header['mtime'] = $v_data['mtime']; |
if ($p_header['mdate'] && $p_header['mtime']) |
{ |
// ----- Extract time |
$v_hour = ($p_header['mtime'] & 0xF800) >> 11; |
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5; |
$v_seconde = ($p_header['mtime'] & 0x001F)*2; |
// ----- Extract date |
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; |
$v_month = ($p_header['mdate'] & 0x01E0) >> 5; |
$v_day = $p_header['mdate'] & 0x001F; |
// ----- Get UNIX date format |
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); |
} |
else |
{ |
$p_header['mtime'] = time(); |
} |
// TBC |
//for(reset($v_data); $key = key($v_data); next($v_data)) { |
//} |
// ----- Set the stored filename |
$p_header['stored_filename'] = $p_header['filename']; |
// ----- Set the status field |
$p_header['status'] = "ok"; |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privReadCentralFileHeader() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privReadCentralFileHeader(&$p_header) |
{ |
$v_result=1; |
// ----- Read the 4 bytes signature |
$v_binary_data = @fread($this->zip_fd, 4); |
$v_data = unpack('Vid', $v_binary_data); |
// ----- Check signature |
if ($v_data['id'] != 0x02014b50) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read the first 42 bytes of the header |
$v_binary_data = fread($this->zip_fd, 42); |
// ----- Look for invalid block size |
if (strlen($v_binary_data) != 42) |
{ |
$p_header['filename'] = ""; |
$p_header['status'] = "invalid_header"; |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Extract the values |
$p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); |
// ----- Get filename |
if ($p_header['filename_len'] != 0) |
$p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']); |
else |
$p_header['filename'] = ''; |
// ----- Get extra |
if ($p_header['extra_len'] != 0) |
$p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']); |
else |
$p_header['extra'] = ''; |
// ----- Get comment |
if ($p_header['comment_len'] != 0) |
$p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']); |
else |
$p_header['comment'] = ''; |
// ----- Extract properties |
// ----- Recuperate date in UNIX format |
//if ($p_header['mdate'] && $p_header['mtime']) |
// TBC : bug : this was ignoring time with 0/0/0 |
if (1) |
{ |
// ----- Extract time |
$v_hour = ($p_header['mtime'] & 0xF800) >> 11; |
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5; |
$v_seconde = ($p_header['mtime'] & 0x001F)*2; |
// ----- Extract date |
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; |
$v_month = ($p_header['mdate'] & 0x01E0) >> 5; |
$v_day = $p_header['mdate'] & 0x001F; |
// ----- Get UNIX date format |
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); |
} |
else |
{ |
$p_header['mtime'] = time(); |
} |
// ----- Set the stored filename |
$p_header['stored_filename'] = $p_header['filename']; |
// ----- Set default status to ok |
$p_header['status'] = 'ok'; |
// ----- Look if it is a directory |
if (substr($p_header['filename'], -1) == '/') { |
//$p_header['external'] = 0x41FF0010; |
$p_header['external'] = 0x00000010; |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privCheckFileHeaders() |
// Description : |
// Parameters : |
// Return Values : |
// 1 on success, |
// 0 on error; |
// -------------------------------------------------------------------------------- |
function privCheckFileHeaders(&$p_local_header, &$p_central_header) |
{ |
$v_result=1; |
// ----- Check the static values |
// TBC |
if ($p_local_header['filename'] != $p_central_header['filename']) { |
} |
if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) { |
} |
if ($p_local_header['flag'] != $p_central_header['flag']) { |
} |
if ($p_local_header['compression'] != $p_central_header['compression']) { |
} |
if ($p_local_header['mtime'] != $p_central_header['mtime']) { |
} |
if ($p_local_header['filename_len'] != $p_central_header['filename_len']) { |
} |
// ----- Look for flag bit 3 |
if (($p_local_header['flag'] & 8) == 8) { |
$p_local_header['size'] = $p_central_header['size']; |
$p_local_header['compressed_size'] = $p_central_header['compressed_size']; |
$p_local_header['crc'] = $p_central_header['crc']; |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privReadEndCentralDir() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privReadEndCentralDir(&$p_central_dir) |
{ |
$v_result=1; |
// ----- Go to the end of the zip file |
$v_size = filesize($this->zipname); |
@fseek($this->zip_fd, $v_size); |
if (@ftell($this->zip_fd) != $v_size) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\''); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- First try : look if this is an archive with no commentaries (most of the time) |
// in this case the end of central dir is at 22 bytes of the file end |
$v_found = 0; |
if ($v_size > 26) { |
@fseek($this->zip_fd, $v_size-22); |
if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22)) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read for bytes |
$v_binary_data = @fread($this->zip_fd, 4); |
$v_data = @unpack('Vid', $v_binary_data); |
// ----- Check signature |
if ($v_data['id'] == 0x06054b50) { |
$v_found = 1; |
} |
$v_pos = ftell($this->zip_fd); |
} |
// ----- Go back to the maximum possible size of the Central Dir End Record |
if (!$v_found) { |
$v_maximum_size = 65557; // 0xFFFF + 22; |
if ($v_maximum_size > $v_size) |
$v_maximum_size = $v_size; |
@fseek($this->zip_fd, $v_size-$v_maximum_size); |
if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size)) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read byte per byte in order to find the signature |
$v_pos = ftell($this->zip_fd); |
$v_bytes = 0x00000000; |
while ($v_pos < $v_size) |
{ |
// ----- Read a byte |
$v_byte = @fread($this->zip_fd, 1); |
// ----- Add the byte |
//$v_bytes = ($v_bytes << 8) | Ord($v_byte); |
// Note we mask the old value down such that once shifted we can never end up with more than a 32bit number |
// Otherwise on systems where we have 64bit integers the check below for the magic number will fail. |
$v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte); |
// ----- Compare the bytes |
if ($v_bytes == 0x504b0506) |
{ |
$v_pos++; |
break; |
} |
$v_pos++; |
} |
// ----- Look if not found end of central dir |
if ($v_pos == $v_size) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature"); |
// ----- Return |
return PclZip::errorCode(); |
} |
} |
// ----- Read the first 18 bytes of the header |
$v_binary_data = fread($this->zip_fd, 18); |
// ----- Look for invalid block size |
if (strlen($v_binary_data) != 18) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data)); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Extract the values |
$v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); |
// ----- Check the global size |
if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { |
// ----- Removed in release 2.2 see readme file |
// The check of the file size is a little too strict. |
// Some bugs where found when a zip is encrypted/decrypted with 'crypt'. |
// While decrypted, zip has training 0 bytes |
if (0) { |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, |
'The central dir is not at the end of the archive.' |
.' Some trailing bytes exists after the archive.'); |
// ----- Return |
return PclZip::errorCode(); |
} |
} |
// ----- Get comment |
if ($v_data['comment_size'] != 0) { |
$p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']); |
} |
else |
$p_central_dir['comment'] = ''; |
$p_central_dir['entries'] = $v_data['entries']; |
$p_central_dir['disk_entries'] = $v_data['disk_entries']; |
$p_central_dir['offset'] = $v_data['offset']; |
$p_central_dir['size'] = $v_data['size']; |
$p_central_dir['disk'] = $v_data['disk']; |
$p_central_dir['disk_start'] = $v_data['disk_start']; |
// TBC |
//for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) { |
//} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privDeleteByRule() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privDeleteByRule(&$p_result_list, &$p_options) |
{ |
$v_result=1; |
$v_list_detail = array(); |
// ----- Open the zip file |
if (($v_result=$this->privOpenFd('rb')) != 1) |
{ |
// ----- Return |
return $v_result; |
} |
// ----- Read the central directory informations |
$v_central_dir = array(); |
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) |
{ |
$this->privCloseFd(); |
return $v_result; |
} |
// ----- Go to beginning of File |
@rewind($this->zip_fd); |
// ----- Scan all the files |
// ----- Start at beginning of Central Dir |
$v_pos_entry = $v_central_dir['offset']; |
@rewind($this->zip_fd); |
if (@fseek($this->zip_fd, $v_pos_entry)) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read each entry |
$v_header_list = array(); |
$j_start = 0; |
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) |
{ |
// ----- Read the file header |
$v_header_list[$v_nb_extracted] = array(); |
if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1) |
{ |
// ----- Close the zip file |
$this->privCloseFd(); |
return $v_result; |
} |
// ----- Store the index |
$v_header_list[$v_nb_extracted]['index'] = $i; |
// ----- Look for the specific extract rules |
$v_found = false; |
// ----- Look for extract by name rule |
if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) |
&& ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { |
// ----- Look if the filename is in the list |
for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) { |
// ----- Look for a directory |
if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") { |
// ----- Look if the directory is in the filename path |
if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) |
&& (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { |
$v_found = true; |
} |
elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ |
&& ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) { |
$v_found = true; |
} |
} |
// ----- Look for a filename |
elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { |
$v_found = true; |
} |
} |
} |
// ----- Look for extract by ereg rule |
// ereg() is deprecated with PHP 5.3 |
/* |
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) |
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) { |
if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { |
$v_found = true; |
} |
} |
*/ |
// ----- Look for extract by preg rule |
else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) |
&& ($p_options[PCLZIP_OPT_BY_PREG] != "")) { |
if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { |
$v_found = true; |
} |
} |
// ----- Look for extract by index rule |
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) |
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { |
// ----- Look if the index is in the list |
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) { |
if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { |
$v_found = true; |
} |
if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { |
$j_start = $j+1; |
} |
if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { |
break; |
} |
} |
} |
else { |
$v_found = true; |
} |
// ----- Look for deletion |
if ($v_found) |
{ |
unset($v_header_list[$v_nb_extracted]); |
} |
else |
{ |
$v_nb_extracted++; |
} |
} |
// ----- Look if something need to be deleted |
if ($v_nb_extracted > 0) { |
// ----- Creates a temporay file |
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; |
// ----- Creates a temporary zip archive |
$v_temp_zip = new PclZip($v_zip_temp_name); |
// ----- Open the temporary zip file in write mode |
if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) { |
$this->privCloseFd(); |
// ----- Return |
return $v_result; |
} |
// ----- Look which file need to be kept |
for ($i=0; $i<sizeof($v_header_list); $i++) { |
// ----- Calculate the position of the header |
@rewind($this->zip_fd); |
if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) { |
// ----- Close the zip file |
$this->privCloseFd(); |
$v_temp_zip->privCloseFd(); |
@unlink($v_zip_temp_name); |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Read the file header |
$v_local_header = array(); |
if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) { |
// ----- Close the zip file |
$this->privCloseFd(); |
$v_temp_zip->privCloseFd(); |
@unlink($v_zip_temp_name); |
// ----- Return |
return $v_result; |
} |
// ----- Check that local file header is same as central file header |
if ($this->privCheckFileHeaders($v_local_header, |
$v_header_list[$i]) != 1) { |
// TBC |
} |
unset($v_local_header); |
// ----- Write the file header |
if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) { |
// ----- Close the zip file |
$this->privCloseFd(); |
$v_temp_zip->privCloseFd(); |
@unlink($v_zip_temp_name); |
// ----- Return |
return $v_result; |
} |
// ----- Read/write the data block |
if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) { |
// ----- Close the zip file |
$this->privCloseFd(); |
$v_temp_zip->privCloseFd(); |
@unlink($v_zip_temp_name); |
// ----- Return |
return $v_result; |
} |
} |
// ----- Store the offset of the central dir |
$v_offset = @ftell($v_temp_zip->zip_fd); |
// ----- Re-Create the Central Dir files header |
for ($i=0; $i<sizeof($v_header_list); $i++) { |
// ----- Create the file header |
if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) { |
$v_temp_zip->privCloseFd(); |
$this->privCloseFd(); |
@unlink($v_zip_temp_name); |
// ----- Return |
return $v_result; |
} |
// ----- Transform the header to a 'usable' info |
$v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
} |
// ----- Zip file comment |
$v_comment = ''; |
if (isset($p_options[PCLZIP_OPT_COMMENT])) { |
$v_comment = $p_options[PCLZIP_OPT_COMMENT]; |
} |
// ----- Calculate the size of the central header |
$v_size = @ftell($v_temp_zip->zip_fd)-$v_offset; |
// ----- Create the central dir footer |
if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) { |
// ----- Reset the file list |
unset($v_header_list); |
$v_temp_zip->privCloseFd(); |
$this->privCloseFd(); |
@unlink($v_zip_temp_name); |
// ----- Return |
return $v_result; |
} |
// ----- Close |
$v_temp_zip->privCloseFd(); |
$this->privCloseFd(); |
// ----- Delete the zip file |
// TBC : I should test the result ... |
@unlink($this->zipname); |
// ----- Rename the temporary file |
// TBC : I should test the result ... |
//@rename($v_zip_temp_name, $this->zipname); |
PclZipUtilRename($v_zip_temp_name, $this->zipname); |
// ----- Destroy the temporary archive |
unset($v_temp_zip); |
} |
// ----- Remove every files : reset the file |
else if ($v_central_dir['entries'] != 0) { |
$this->privCloseFd(); |
if (($v_result = $this->privOpenFd('wb')) != 1) { |
return $v_result; |
} |
if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) { |
return $v_result; |
} |
$this->privCloseFd(); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privDirCheck() |
// Description : |
// Check if a directory exists, if not it creates it and all the parents directory |
// which may be useful. |
// Parameters : |
// $p_dir : Directory path to check. |
// Return Values : |
// 1 : OK |
// -1 : Unable to create directory |
// -------------------------------------------------------------------------------- |
function privDirCheck($p_dir, $p_is_dir=false) |
{ |
$v_result = 1; |
// ----- Remove the final '/' |
if (($p_is_dir) && (substr($p_dir, -1)=='/')) |
{ |
$p_dir = substr($p_dir, 0, strlen($p_dir)-1); |
} |
// ----- Check the directory availability |
if ((is_dir($p_dir)) || ($p_dir == "")) |
{ |
return 1; |
} |
// ----- Extract parent directory |
$p_parent_dir = dirname($p_dir); |
// ----- Just a check |
if ($p_parent_dir != $p_dir) |
{ |
// ----- Look for parent directory |
if ($p_parent_dir != "") |
{ |
if (($v_result = $this->privDirCheck($p_parent_dir)) != 1) |
{ |
return $v_result; |
} |
} |
} |
// ----- Create the directory |
if (!@mkdir($p_dir, 0777)) |
{ |
// ----- Error log |
PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'"); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privMerge() |
// Description : |
// If $p_archive_to_add does not exist, the function exit with a success result. |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privMerge(&$p_archive_to_add) |
{ |
$v_result=1; |
// ----- Look if the archive_to_add exists |
if (!is_file($p_archive_to_add->zipname)) |
{ |
// ----- Nothing to merge, so merge is a success |
$v_result = 1; |
// ----- Return |
return $v_result; |
} |
// ----- Look if the archive exists |
if (!is_file($this->zipname)) |
{ |
// ----- Do a duplicate |
$v_result = $this->privDuplicate($p_archive_to_add->zipname); |
// ----- Return |
return $v_result; |
} |
// ----- Open the zip file |
if (($v_result=$this->privOpenFd('rb')) != 1) |
{ |
// ----- Return |
return $v_result; |
} |
// ----- Read the central directory informations |
$v_central_dir = array(); |
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) |
{ |
$this->privCloseFd(); |
return $v_result; |
} |
// ----- Go to beginning of File |
@rewind($this->zip_fd); |
// ----- Open the archive_to_add file |
if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1) |
{ |
$this->privCloseFd(); |
// ----- Return |
return $v_result; |
} |
// ----- Read the central directory informations |
$v_central_dir_to_add = array(); |
if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1) |
{ |
$this->privCloseFd(); |
$p_archive_to_add->privCloseFd(); |
return $v_result; |
} |
// ----- Go to beginning of File |
@rewind($p_archive_to_add->zip_fd); |
// ----- Creates a temporay file |
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; |
// ----- Open the temporary file in write mode |
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) |
{ |
$this->privCloseFd(); |
$p_archive_to_add->privCloseFd(); |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Copy the files from the archive to the temporary file |
// TBC : Here I should better append the file and go back to erase the central dir |
$v_size = $v_central_dir['offset']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = fread($this->zip_fd, $v_read_size); |
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Copy the files from the archive_to_add into the temporary file |
$v_size = $v_central_dir_to_add['offset']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size); |
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Store the offset of the central dir |
$v_offset = @ftell($v_zip_temp_fd); |
// ----- Copy the block of file headers from the old archive |
$v_size = $v_central_dir['size']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($this->zip_fd, $v_read_size); |
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Copy the block of file headers from the archive_to_add |
$v_size = $v_central_dir_to_add['size']; |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size); |
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Merge the file comments |
$v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment']; |
// ----- Calculate the size of the (new) central header |
$v_size = @ftell($v_zip_temp_fd)-$v_offset; |
// ----- Swap the file descriptor |
// Here is a trick : I swap the temporary fd with the zip fd, in order to use |
// the following methods on the temporary fil and not the real archive fd |
$v_swap = $this->zip_fd; |
$this->zip_fd = $v_zip_temp_fd; |
$v_zip_temp_fd = $v_swap; |
// ----- Create the central dir footer |
if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) |
{ |
$this->privCloseFd(); |
$p_archive_to_add->privCloseFd(); |
@fclose($v_zip_temp_fd); |
$this->zip_fd = null; |
// ----- Reset the file list |
unset($v_header_list); |
// ----- Return |
return $v_result; |
} |
// ----- Swap back the file descriptor |
$v_swap = $this->zip_fd; |
$this->zip_fd = $v_zip_temp_fd; |
$v_zip_temp_fd = $v_swap; |
// ----- Close |
$this->privCloseFd(); |
$p_archive_to_add->privCloseFd(); |
// ----- Close the temporary file |
@fclose($v_zip_temp_fd); |
// ----- Delete the zip file |
// TBC : I should test the result ... |
@unlink($this->zipname); |
// ----- Rename the temporary file |
// TBC : I should test the result ... |
//@rename($v_zip_temp_name, $this->zipname); |
PclZipUtilRename($v_zip_temp_name, $this->zipname); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privDuplicate() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privDuplicate($p_archive_filename) |
{ |
$v_result=1; |
// ----- Look if the $p_archive_filename exists |
if (!is_file($p_archive_filename)) |
{ |
// ----- Nothing to duplicate, so duplicate is a success. |
$v_result = 1; |
// ----- Return |
return $v_result; |
} |
// ----- Open the zip file |
if (($v_result=$this->privOpenFd('wb')) != 1) |
{ |
// ----- Return |
return $v_result; |
} |
// ----- Open the temporary file in write mode |
if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) |
{ |
$this->privCloseFd(); |
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode'); |
// ----- Return |
return PclZip::errorCode(); |
} |
// ----- Copy the files from the archive to the temporary file |
// TBC : Here I should better append the file and go back to erase the central dir |
$v_size = filesize($p_archive_filename); |
while ($v_size != 0) |
{ |
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = fread($v_zip_temp_fd, $v_read_size); |
@fwrite($this->zip_fd, $v_buffer, $v_read_size); |
$v_size -= $v_read_size; |
} |
// ----- Close |
$this->privCloseFd(); |
// ----- Close the temporary file |
@fclose($v_zip_temp_fd); |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privErrorLog() |
// Description : |
// Parameters : |
// -------------------------------------------------------------------------------- |
function privErrorLog($p_error_code=0, $p_error_string='') |
{ |
if (PCLZIP_ERROR_EXTERNAL == 1) { |
PclError($p_error_code, $p_error_string); |
} |
else { |
$this->error_code = $p_error_code; |
$this->error_string = $p_error_string; |
} |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privErrorReset() |
// Description : |
// Parameters : |
// -------------------------------------------------------------------------------- |
function privErrorReset() |
{ |
if (PCLZIP_ERROR_EXTERNAL == 1) { |
PclErrorReset(); |
} |
else { |
$this->error_code = 0; |
$this->error_string = ''; |
} |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privDisableMagicQuotes() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privDisableMagicQuotes() |
{ |
$v_result=1; |
// ----- Look if function exists |
if ( (!function_exists("get_magic_quotes_runtime")) |
|| (!function_exists("set_magic_quotes_runtime"))) { |
return $v_result; |
} |
// ----- Look if already done |
if ($this->magic_quotes_status != -1) { |
return $v_result; |
} |
// ----- Get and memorize the magic_quote value |
$this->magic_quotes_status = @get_magic_quotes_runtime(); |
// ----- Disable magic_quotes |
if ($this->magic_quotes_status == 1) { |
@set_magic_quotes_runtime(0); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : privSwapBackMagicQuotes() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function privSwapBackMagicQuotes() |
{ |
$v_result=1; |
// ----- Look if function exists |
if ( (!function_exists("get_magic_quotes_runtime")) |
|| (!function_exists("set_magic_quotes_runtime"))) { |
return $v_result; |
} |
// ----- Look if something to do |
if ($this->magic_quotes_status != -1) { |
return $v_result; |
} |
// ----- Swap back magic_quotes |
if ($this->magic_quotes_status == 1) { |
@set_magic_quotes_runtime($this->magic_quotes_status); |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
} |
// End of class |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : PclZipUtilPathReduction() |
// Description : |
// Parameters : |
// Return Values : |
// -------------------------------------------------------------------------------- |
function PclZipUtilPathReduction($p_dir) |
{ |
$v_result = ""; |
// ----- Look for not empty path |
if ($p_dir != "") { |
// ----- Explode path by directory names |
$v_list = explode("/", $p_dir); |
// ----- Study directories from last to first |
$v_skip = 0; |
for ($i=sizeof($v_list)-1; $i>=0; $i--) { |
// ----- Look for current path |
if ($v_list[$i] == ".") { |
// ----- Ignore this directory |
// Should be the first $i=0, but no check is done |
} |
else if ($v_list[$i] == "..") { |
$v_skip++; |
} |
else if ($v_list[$i] == "") { |
// ----- First '/' i.e. root slash |
if ($i == 0) { |
$v_result = "/".$v_result; |
if ($v_skip > 0) { |
// ----- It is an invalid path, so the path is not modified |
// TBC |
$v_result = $p_dir; |
$v_skip = 0; |
} |
} |
// ----- Last '/' i.e. indicates a directory |
else if ($i == (sizeof($v_list)-1)) { |
$v_result = $v_list[$i]; |
} |
// ----- Double '/' inside the path |
else { |
// ----- Ignore only the double '//' in path, |
// but not the first and last '/' |
} |
} |
else { |
// ----- Look for item to skip |
if ($v_skip > 0) { |
$v_skip--; |
} |
else { |
$v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:""); |
} |
} |
} |
// ----- Look for skip |
if ($v_skip > 0) { |
while ($v_skip > 0) { |
$v_result = '../'.$v_result; |
$v_skip--; |
} |
} |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : PclZipUtilPathInclusion() |
// Description : |
// This function indicates if the path $p_path is under the $p_dir tree. Or, |
// said in an other way, if the file or sub-dir $p_path is inside the dir |
// $p_dir. |
// The function indicates also if the path is exactly the same as the dir. |
// This function supports path with duplicated '/' like '//', but does not |
// support '.' or '..' statements. |
// Parameters : |
// Return Values : |
// 0 if $p_path is not inside directory $p_dir |
// 1 if $p_path is inside directory $p_dir |
// 2 if $p_path is exactly the same as $p_dir |
// -------------------------------------------------------------------------------- |
function PclZipUtilPathInclusion($p_dir, $p_path) |
{ |
$v_result = 1; |
// ----- Look for path beginning by ./ |
if ( ($p_dir == '.') |
|| ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) { |
$p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1); |
} |
if ( ($p_path == '.') |
|| ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) { |
$p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1); |
} |
// ----- Explode dir and path by directory separator |
$v_list_dir = explode("/", $p_dir); |
$v_list_dir_size = sizeof($v_list_dir); |
$v_list_path = explode("/", $p_path); |
$v_list_path_size = sizeof($v_list_path); |
// ----- Study directories paths |
$i = 0; |
$j = 0; |
while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) { |
// ----- Look for empty dir (path reduction) |
if ($v_list_dir[$i] == '') { |
$i++; |
continue; |
} |
if ($v_list_path[$j] == '') { |
$j++; |
continue; |
} |
// ----- Compare the items |
if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) { |
$v_result = 0; |
} |
// ----- Next items |
$i++; |
$j++; |
} |
// ----- Look if everything seems to be the same |
if ($v_result) { |
// ----- Skip all the empty items |
while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++; |
while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++; |
if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { |
// ----- There are exactly the same |
$v_result = 2; |
} |
else if ($i < $v_list_dir_size) { |
// ----- The path is shorter than the dir |
$v_result = 0; |
} |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : PclZipUtilCopyBlock() |
// Description : |
// Parameters : |
// $p_mode : read/write compression mode |
// 0 : src & dest normal |
// 1 : src gzip, dest normal |
// 2 : src normal, dest gzip |
// 3 : src & dest gzip |
// Return Values : |
// -------------------------------------------------------------------------------- |
function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0) |
{ |
$v_result = 1; |
if ($p_mode==0) |
{ |
while ($p_size != 0) |
{ |
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($p_src, $v_read_size); |
@fwrite($p_dest, $v_buffer, $v_read_size); |
$p_size -= $v_read_size; |
} |
} |
else if ($p_mode==1) |
{ |
while ($p_size != 0) |
{ |
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @gzread($p_src, $v_read_size); |
@fwrite($p_dest, $v_buffer, $v_read_size); |
$p_size -= $v_read_size; |
} |
} |
else if ($p_mode==2) |
{ |
while ($p_size != 0) |
{ |
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @fread($p_src, $v_read_size); |
@gzwrite($p_dest, $v_buffer, $v_read_size); |
$p_size -= $v_read_size; |
} |
} |
else if ($p_mode==3) |
{ |
while ($p_size != 0) |
{ |
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); |
$v_buffer = @gzread($p_src, $v_read_size); |
@gzwrite($p_dest, $v_buffer, $v_read_size); |
$p_size -= $v_read_size; |
} |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : PclZipUtilRename() |
// Description : |
// This function tries to do a simple rename() function. If it fails, it |
// tries to copy the $p_src file in a new $p_dest file and then unlink the |
// first one. |
// Parameters : |
// $p_src : Old filename |
// $p_dest : New filename |
// Return Values : |
// 1 on success, 0 on failure. |
// -------------------------------------------------------------------------------- |
function PclZipUtilRename($p_src, $p_dest) |
{ |
$v_result = 1; |
// ----- Try to rename the files |
if (!@rename($p_src, $p_dest)) { |
// ----- Try to copy & unlink the src |
if (!@copy($p_src, $p_dest)) { |
$v_result = 0; |
} |
else if (!@unlink($p_src)) { |
$v_result = 0; |
} |
} |
// ----- Return |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : PclZipUtilOptionText() |
// Description : |
// Translate option value in text. Mainly for debug purpose. |
// Parameters : |
// $p_option : the option value. |
// Return Values : |
// The option text value. |
// -------------------------------------------------------------------------------- |
function PclZipUtilOptionText($p_option) |
{ |
$v_list = get_defined_constants(); |
for (reset($v_list); $v_key = key($v_list); next($v_list)) { |
$v_prefix = substr($v_key, 0, 10); |
if (( ($v_prefix == 'PCLZIP_OPT') |
|| ($v_prefix == 'PCLZIP_CB_') |
|| ($v_prefix == 'PCLZIP_ATT')) |
&& ($v_list[$v_key] == $p_option)) { |
return $v_key; |
} |
} |
$v_result = 'Unknown'; |
return $v_result; |
} |
// -------------------------------------------------------------------------------- |
// -------------------------------------------------------------------------------- |
// Function : PclZipUtilTranslateWinPath() |
// Description : |
// Translate windows path by replacing '\' by '/' and optionally removing |
// drive letter. |
// Parameters : |
// $p_path : path to translate. |
// $p_remove_disk_letter : true | false |
// Return Values : |
// The path translated. |
// -------------------------------------------------------------------------------- |
function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true) |
{ |
if (stristr(php_uname(), 'windows')) { |
// ----- Look for potential disk letter |
if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { |
$p_path = substr($p_path, $v_position+1); |
} |
// ----- Change potential windows directory separator |
if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { |
$p_path = strtr($p_path, '\\', '/'); |
} |
} |
return $p_path; |
} |
// -------------------------------------------------------------------------------- |
?> |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/PCLZip/gnu-lgpl.txt |
---|
New file |
0,0 → 1,504 |
GNU LESSER GENERAL PUBLIC LICENSE |
Version 2.1, February 1999 |
Copyright (C) 1991, 1999 Free Software Foundation, Inc. |
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
[This is the first released version of the Lesser GPL. It also counts |
as the successor of the GNU Library Public License, version 2, hence |
the version number 2.1.] |
Preamble |
The licenses for most software are designed to take away your |
freedom to share and change it. By contrast, the GNU General Public |
Licenses are intended to guarantee your freedom to share and change |
free software--to make sure the software is free for all its users. |
This license, the Lesser General Public License, applies to some |
specially designated software packages--typically libraries--of the |
Free Software Foundation and other authors who decide to use it. You |
can use it too, but we suggest you first think carefully about whether |
this license or the ordinary General Public License is the better |
strategy to use in any particular case, based on the explanations below. |
When we speak of free software, we are referring to freedom of use, |
not price. Our General Public Licenses are designed to make sure that |
you have the freedom to distribute copies of free software (and charge |
for this service if you wish); that you receive source code or can get |
it if you want it; that you can change the software and use pieces of |
it in new free programs; and that you are informed that you can do |
these things. |
To protect your rights, we need to make restrictions that forbid |
distributors to deny you these rights or to ask you to surrender these |
rights. These restrictions translate to certain responsibilities for |
you if you distribute copies of the library or if you modify it. |
For example, if you distribute copies of the library, whether gratis |
or for a fee, you must give the recipients all the rights that we gave |
you. You must make sure that they, too, receive or can get the source |
code. If you link other code with the library, you must provide |
complete object files to the recipients, so that they can relink them |
with the library after making changes to the library and recompiling |
it. And you must show them these terms so they know their rights. |
We protect your rights with a two-step method: (1) we copyright the |
library, and (2) we offer you this license, which gives you legal |
permission to copy, distribute and/or modify the library. |
To protect each distributor, we want to make it very clear that |
there is no warranty for the free library. Also, if the library is |
modified by someone else and passed on, the recipients should know |
that what they have is not the original version, so that the original |
author's reputation will not be affected by problems that might be |
introduced by others. |
Finally, software patents pose a constant threat to the existence of |
any free program. We wish to make sure that a company cannot |
effectively restrict the users of a free program by obtaining a |
restrictive license from a patent holder. Therefore, we insist that |
any patent license obtained for a version of the library must be |
consistent with the full freedom of use specified in this license. |
Most GNU software, including some libraries, is covered by the |
ordinary GNU General Public License. This license, the GNU Lesser |
General Public License, applies to certain designated libraries, and |
is quite different from the ordinary General Public License. We use |
this license for certain libraries in order to permit linking those |
libraries into non-free programs. |
When a program is linked with a library, whether statically or using |
a shared library, the combination of the two is legally speaking a |
combined work, a derivative of the original library. The ordinary |
General Public License therefore permits such linking only if the |
entire combination fits its criteria of freedom. The Lesser General |
Public License permits more lax criteria for linking other code with |
the library. |
We call this license the "Lesser" General Public License because it |
does Less to protect the user's freedom than the ordinary General |
Public License. It also provides other free software developers Less |
of an advantage over competing non-free programs. These disadvantages |
are the reason we use the ordinary General Public License for many |
libraries. However, the Lesser license provides advantages in certain |
special circumstances. |
For example, on rare occasions, there may be a special need to |
encourage the widest possible use of a certain library, so that it becomes |
a de-facto standard. To achieve this, non-free programs must be |
allowed to use the library. A more frequent case is that a free |
library does the same job as widely used non-free libraries. In this |
case, there is little to gain by limiting the free library to free |
software only, so we use the Lesser General Public License. |
In other cases, permission to use a particular library in non-free |
programs enables a greater number of people to use a large body of |
free software. For example, permission to use the GNU C Library in |
non-free programs enables many more people to use the whole GNU |
operating system, as well as its variant, the GNU/Linux operating |
system. |
Although the Lesser General Public License is Less protective of the |
users' freedom, it does ensure that the user of a program that is |
linked with the Library has the freedom and the wherewithal to run |
that program using a modified version of the Library. |
The precise terms and conditions for copying, distribution and |
modification follow. Pay close attention to the difference between a |
"work based on the library" and a "work that uses the library". The |
former contains code derived from the library, whereas the latter must |
be combined with the library in order to run. |
GNU LESSER GENERAL PUBLIC LICENSE |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
0. This License Agreement applies to any software library or other |
program which contains a notice placed by the copyright holder or |
other authorized party saying it may be distributed under the terms of |
this Lesser General Public License (also called "this License"). |
Each licensee is addressed as "you". |
A "library" means a collection of software functions and/or data |
prepared so as to be conveniently linked with application programs |
(which use some of those functions and data) to form executables. |
The "Library", below, refers to any such software library or work |
which has been distributed under these terms. A "work based on the |
Library" means either the Library or any derivative work under |
copyright law: that is to say, a work containing the Library or a |
portion of it, either verbatim or with modifications and/or translated |
straightforwardly into another language. (Hereinafter, translation is |
included without limitation in the term "modification".) |
"Source code" for a work means the preferred form of the work for |
making modifications to it. For a library, complete source code means |
all the source code for all modules it contains, plus any associated |
interface definition files, plus the scripts used to control compilation |
and installation of the library. |
Activities other than copying, distribution and modification are not |
covered by this License; they are outside its scope. The act of |
running a program using the Library is not restricted, and output from |
such a program is covered only if its contents constitute a work based |
on the Library (independent of the use of the Library in a tool for |
writing it). Whether that is true depends on what the Library does |
and what the program that uses the Library does. |
1. You may copy and distribute verbatim copies of the Library's |
complete source code as you receive it, in any medium, provided that |
you conspicuously and appropriately publish on each copy an |
appropriate copyright notice and disclaimer of warranty; keep intact |
all the notices that refer to this License and to the absence of any |
warranty; and distribute a copy of this License along with the |
Library. |
You may charge a fee for the physical act of transferring a copy, |
and you may at your option offer warranty protection in exchange for a |
fee. |
2. You may modify your copy or copies of the Library or any portion |
of it, thus forming a work based on the Library, and copy and |
distribute such modifications or work under the terms of Section 1 |
above, provided that you also meet all of these conditions: |
a) The modified work must itself be a software library. |
b) You must cause the files modified to carry prominent notices |
stating that you changed the files and the date of any change. |
c) You must cause the whole of the work to be licensed at no |
charge to all third parties under the terms of this License. |
d) If a facility in the modified Library refers to a function or a |
table of data to be supplied by an application program that uses |
the facility, other than as an argument passed when the facility |
is invoked, then you must make a good faith effort to ensure that, |
in the event an application does not supply such function or |
table, the facility still operates, and performs whatever part of |
its purpose remains meaningful. |
(For example, a function in a library to compute square roots has |
a purpose that is entirely well-defined independent of the |
application. Therefore, Subsection 2d requires that any |
application-supplied function or table used by this function must |
be optional: if the application does not supply it, the square |
root function must still compute square roots.) |
These requirements apply to the modified work as a whole. If |
identifiable sections of that work are not derived from the Library, |
and can be reasonably considered independent and separate works in |
themselves, then this License, and its terms, do not apply to those |
sections when you distribute them as separate works. But when you |
distribute the same sections as part of a whole which is a work based |
on the Library, the distribution of the whole must be on the terms of |
this License, whose permissions for other licensees extend to the |
entire whole, and thus to each and every part regardless of who wrote |
it. |
Thus, it is not the intent of this section to claim rights or contest |
your rights to work written entirely by you; rather, the intent is to |
exercise the right to control the distribution of derivative or |
collective works based on the Library. |
In addition, mere aggregation of another work not based on the Library |
with the Library (or with a work based on the Library) on a volume of |
a storage or distribution medium does not bring the other work under |
the scope of this License. |
3. You may opt to apply the terms of the ordinary GNU General Public |
License instead of this License to a given copy of the Library. To do |
this, you must alter all the notices that refer to this License, so |
that they refer to the ordinary GNU General Public License, version 2, |
instead of to this License. (If a newer version than version 2 of the |
ordinary GNU General Public License has appeared, then you can specify |
that version instead if you wish.) Do not make any other change in |
these notices. |
Once this change is made in a given copy, it is irreversible for |
that copy, so the ordinary GNU General Public License applies to all |
subsequent copies and derivative works made from that copy. |
This option is useful when you wish to copy part of the code of |
the Library into a program that is not a library. |
4. You may copy and distribute the Library (or a portion or |
derivative of it, under Section 2) in object code or executable form |
under the terms of Sections 1 and 2 above provided that you accompany |
it with the complete corresponding machine-readable source code, which |
must be distributed under the terms of Sections 1 and 2 above on a |
medium customarily used for software interchange. |
If distribution of object code is made by offering access to copy |
from a designated place, then offering equivalent access to copy the |
source code from the same place satisfies the requirement to |
distribute the source code, even though third parties are not |
compelled to copy the source along with the object code. |
5. A program that contains no derivative of any portion of the |
Library, but is designed to work with the Library by being compiled or |
linked with it, is called a "work that uses the Library". Such a |
work, in isolation, is not a derivative work of the Library, and |
therefore falls outside the scope of this License. |
However, linking a "work that uses the Library" with the Library |
creates an executable that is a derivative of the Library (because it |
contains portions of the Library), rather than a "work that uses the |
library". The executable is therefore covered by this License. |
Section 6 states terms for distribution of such executables. |
When a "work that uses the Library" uses material from a header file |
that is part of the Library, the object code for the work may be a |
derivative work of the Library even though the source code is not. |
Whether this is true is especially significant if the work can be |
linked without the Library, or if the work is itself a library. The |
threshold for this to be true is not precisely defined by law. |
If such an object file uses only numerical parameters, data |
structure layouts and accessors, and small macros and small inline |
functions (ten lines or less in length), then the use of the object |
file is unrestricted, regardless of whether it is legally a derivative |
work. (Executables containing this object code plus portions of the |
Library will still fall under Section 6.) |
Otherwise, if the work is a derivative of the Library, you may |
distribute the object code for the work under the terms of Section 6. |
Any executables containing that work also fall under Section 6, |
whether or not they are linked directly with the Library itself. |
6. As an exception to the Sections above, you may also combine or |
link a "work that uses the Library" with the Library to produce a |
work containing portions of the Library, and distribute that work |
under terms of your choice, provided that the terms permit |
modification of the work for the customer's own use and reverse |
engineering for debugging such modifications. |
You must give prominent notice with each copy of the work that the |
Library is used in it and that the Library and its use are covered by |
this License. You must supply a copy of this License. If the work |
during execution displays copyright notices, you must include the |
copyright notice for the Library among them, as well as a reference |
directing the user to the copy of this License. Also, you must do one |
of these things: |
a) Accompany the work with the complete corresponding |
machine-readable source code for the Library including whatever |
changes were used in the work (which must be distributed under |
Sections 1 and 2 above); and, if the work is an executable linked |
with the Library, with the complete machine-readable "work that |
uses the Library", as object code and/or source code, so that the |
user can modify the Library and then relink to produce a modified |
executable containing the modified Library. (It is understood |
that the user who changes the contents of definitions files in the |
Library will not necessarily be able to recompile the application |
to use the modified definitions.) |
b) Use a suitable shared library mechanism for linking with the |
Library. A suitable mechanism is one that (1) uses at run time a |
copy of the library already present on the user's computer system, |
rather than copying library functions into the executable, and (2) |
will operate properly with a modified version of the library, if |
the user installs one, as long as the modified version is |
interface-compatible with the version that the work was made with. |
c) Accompany the work with a written offer, valid for at |
least three years, to give the same user the materials |
specified in Subsection 6a, above, for a charge no more |
than the cost of performing this distribution. |
d) If distribution of the work is made by offering access to copy |
from a designated place, offer equivalent access to copy the above |
specified materials from the same place. |
e) Verify that the user has already received a copy of these |
materials or that you have already sent this user a copy. |
For an executable, the required form of the "work that uses the |
Library" must include any data and utility programs needed for |
reproducing the executable from it. However, as a special exception, |
the materials to be distributed need not include anything that is |
normally distributed (in either source or binary form) with the major |
components (compiler, kernel, and so on) of the operating system on |
which the executable runs, unless that component itself accompanies |
the executable. |
It may happen that this requirement contradicts the license |
restrictions of other proprietary libraries that do not normally |
accompany the operating system. Such a contradiction means you cannot |
use both them and the Library together in an executable that you |
distribute. |
7. You may place library facilities that are a work based on the |
Library side-by-side in a single library together with other library |
facilities not covered by this License, and distribute such a combined |
library, provided that the separate distribution of the work based on |
the Library and of the other library facilities is otherwise |
permitted, and provided that you do these two things: |
a) Accompany the combined library with a copy of the same work |
based on the Library, uncombined with any other library |
facilities. This must be distributed under the terms of the |
Sections above. |
b) Give prominent notice with the combined library of the fact |
that part of it is a work based on the Library, and explaining |
where to find the accompanying uncombined form of the same work. |
8. You may not copy, modify, sublicense, link with, or distribute |
the Library except as expressly provided under this License. Any |
attempt otherwise to copy, modify, sublicense, link with, or |
distribute the Library is void, and will automatically terminate your |
rights under this License. However, parties who have received copies, |
or rights, from you under this License will not have their licenses |
terminated so long as such parties remain in full compliance. |
9. You are not required to accept this License, since you have not |
signed it. However, nothing else grants you permission to modify or |
distribute the Library or its derivative works. These actions are |
prohibited by law if you do not accept this License. Therefore, by |
modifying or distributing the Library (or any work based on the |
Library), you indicate your acceptance of this License to do so, and |
all its terms and conditions for copying, distributing or modifying |
the Library or works based on it. |
10. Each time you redistribute the Library (or any work based on the |
Library), the recipient automatically receives a license from the |
original licensor to copy, distribute, link with or modify the Library |
subject to these terms and conditions. You may not impose any further |
restrictions on the recipients' exercise of the rights granted herein. |
You are not responsible for enforcing compliance by third parties with |
this License. |
11. If, as a consequence of a court judgment or allegation of patent |
infringement or for any other reason (not limited to patent issues), |
conditions are imposed on you (whether by court order, agreement or |
otherwise) that contradict the conditions of this License, they do not |
excuse you from the conditions of this License. If you cannot |
distribute so as to satisfy simultaneously your obligations under this |
License and any other pertinent obligations, then as a consequence you |
may not distribute the Library at all. For example, if a patent |
license would not permit royalty-free redistribution of the Library by |
all those who receive copies directly or indirectly through you, then |
the only way you could satisfy both it and this License would be to |
refrain entirely from distribution of the Library. |
If any portion of this section is held invalid or unenforceable under any |
particular circumstance, the balance of the section is intended to apply, |
and the section as a whole is intended to apply in other circumstances. |
It is not the purpose of this section to induce you to infringe any |
patents or other property right claims or to contest validity of any |
such claims; this section has the sole purpose of protecting the |
integrity of the free software distribution system which is |
implemented by public license practices. Many people have made |
generous contributions to the wide range of software distributed |
through that system in reliance on consistent application of that |
system; it is up to the author/donor to decide if he or she is willing |
to distribute software through any other system and a licensee cannot |
impose that choice. |
This section is intended to make thoroughly clear what is believed to |
be a consequence of the rest of this License. |
12. If the distribution and/or use of the Library is restricted in |
certain countries either by patents or by copyrighted interfaces, the |
original copyright holder who places the Library under this License may add |
an explicit geographical distribution limitation excluding those countries, |
so that distribution is permitted only in or among countries not thus |
excluded. In such case, this License incorporates the limitation as if |
written in the body of this License. |
13. The Free Software Foundation may publish revised and/or new |
versions of the Lesser General Public License from time to time. |
Such new versions will be similar in spirit to the present version, |
but may differ in detail to address new problems or concerns. |
Each version is given a distinguishing version number. If the Library |
specifies a version number of this License which applies to it and |
"any later version", you have the option of following the terms and |
conditions either of that version or of any later version published by |
the Free Software Foundation. If the Library does not specify a |
license version number, you may choose any version ever published by |
the Free Software Foundation. |
14. If you wish to incorporate parts of the Library into other free |
programs whose distribution conditions are incompatible with these, |
write to the author to ask for permission. For software which is |
copyrighted by the Free Software Foundation, write to the Free |
Software Foundation; we sometimes make exceptions for this. Our |
decision will be guided by the two goals of preserving the free status |
of all derivatives of our free software and of promoting the sharing |
and reuse of software generally. |
NO WARRANTY |
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO |
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. |
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR |
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY |
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE |
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME |
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN |
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY |
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU |
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE |
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING |
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A |
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF |
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
DAMAGES. |
END OF TERMS AND CONDITIONS |
How to Apply These Terms to Your New Libraries |
If you develop a new library, and you want it to be of the greatest |
possible use to the public, we recommend making it free software that |
everyone can redistribute and change. You can do so by permitting |
redistribution under these terms (or, alternatively, under the terms of the |
ordinary General Public License). |
To apply these terms, attach the following notices to the library. It is |
safest to attach them to the start of each source file to most effectively |
convey the exclusion of warranty; and each file should have at least the |
"copyright" line and a pointer to where the full notice is found. |
<one line to give the library's name and a brief idea of what it does.> |
Copyright (C) <year> <name of author> |
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Also add information on how to contact you by electronic and paper mail. |
You should also get your employer (if you work as a programmer) or your |
school, if any, to sign a "copyright disclaimer" for the library, if |
necessary. Here is a sample; alter the names: |
Yoyodyne, Inc., hereby disclaims all copyright interest in the |
library `Frob' (a library for tweaking knobs) written by James Random Hacker. |
<signature of Ty Coon>, 1 April 1990 |
Ty Coon, President of Vice |
That's all there is to it! |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Date.php |
---|
New file |
0,0 → 1,390 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Date |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Date |
{ |
/** constants */ |
const CALENDAR_WINDOWS_1900 = 1900; // Base date of 1st Jan 1900 = 1.0 |
const CALENDAR_MAC_1904 = 1904; // Base date of 2nd Jan 1904 = 1.0 |
/* |
* Names of the months of the year, indexed by shortname |
* Planned usage for locale settings |
* |
* @public |
* @var string[] |
*/ |
public static $_monthNames = array( 'Jan' => 'January', |
'Feb' => 'February', |
'Mar' => 'March', |
'Apr' => 'April', |
'May' => 'May', |
'Jun' => 'June', |
'Jul' => 'July', |
'Aug' => 'August', |
'Sep' => 'September', |
'Oct' => 'October', |
'Nov' => 'November', |
'Dec' => 'December', |
); |
/* |
* Names of the months of the year, indexed by shortname |
* Planned usage for locale settings |
* |
* @public |
* @var string[] |
*/ |
public static $_numberSuffixes = array( 'st', |
'nd', |
'rd', |
'th', |
); |
/* |
* Base calendar year to use for calculations |
* |
* @private |
* @var int |
*/ |
protected static $_excelBaseDate = self::CALENDAR_WINDOWS_1900; |
/** |
* Set the Excel calendar (Windows 1900 or Mac 1904) |
* |
* @param integer $baseDate Excel base date (1900 or 1904) |
* @return boolean Success or failure |
*/ |
public static function setExcelCalendar($baseDate) { |
if (($baseDate == self::CALENDAR_WINDOWS_1900) || |
($baseDate == self::CALENDAR_MAC_1904)) { |
self::$_excelBaseDate = $baseDate; |
return TRUE; |
} |
return FALSE; |
} // function setExcelCalendar() |
/** |
* Return the Excel calendar (Windows 1900 or Mac 1904) |
* |
* @return integer Excel base date (1900 or 1904) |
*/ |
public static function getExcelCalendar() { |
return self::$_excelBaseDate; |
} // function getExcelCalendar() |
/** |
* Convert a date from Excel to PHP |
* |
* @param long $dateValue Excel date/time value |
* @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as |
* a UST timestamp, or adjusted to UST |
* @param string $timezone The timezone for finding the adjustment from UST |
* @return long PHP serialized date/time |
*/ |
public static function ExcelToPHP($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL) { |
if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) { |
$my_excelBaseDate = 25569; |
// Adjust for the spurious 29-Feb-1900 (Day 60) |
if ($dateValue < 60) { |
--$my_excelBaseDate; |
} |
} else { |
$my_excelBaseDate = 24107; |
} |
// Perform conversion |
if ($dateValue >= 1) { |
$utcDays = $dateValue - $my_excelBaseDate; |
$returnValue = round($utcDays * 86400); |
if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) { |
$returnValue = (integer) $returnValue; |
} |
} else { |
$hours = round($dateValue * 24); |
$mins = round($dateValue * 1440) - round($hours * 60); |
$secs = round($dateValue * 86400) - round($hours * 3600) - round($mins * 60); |
$returnValue = (integer) gmmktime($hours, $mins, $secs); |
} |
$timezoneAdjustment = ($adjustToTimezone) ? |
PHPExcel_Shared_TimeZone::getTimezoneAdjustment($timezone, $returnValue) : |
0; |
// Return |
return $returnValue + $timezoneAdjustment; |
} // function ExcelToPHP() |
/** |
* Convert a date from Excel to a PHP Date/Time object |
* |
* @param integer $dateValue Excel date/time value |
* @return integer PHP date/time object |
*/ |
public static function ExcelToPHPObject($dateValue = 0) { |
$dateTime = self::ExcelToPHP($dateValue); |
$days = floor($dateTime / 86400); |
$time = round((($dateTime / 86400) - $days) * 86400); |
$hours = round($time / 3600); |
$minutes = round($time / 60) - ($hours * 60); |
$seconds = round($time) - ($hours * 3600) - ($minutes * 60); |
$dateObj = date_create('1-Jan-1970+'.$days.' days'); |
$dateObj->setTime($hours,$minutes,$seconds); |
return $dateObj; |
} // function ExcelToPHPObject() |
/** |
* Convert a date from PHP to Excel |
* |
* @param mixed $dateValue PHP serialized date/time or date object |
* @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as |
* a UST timestamp, or adjusted to UST |
* @param string $timezone The timezone for finding the adjustment from UST |
* @return mixed Excel date/time value |
* or boolean FALSE on failure |
*/ |
public static function PHPToExcel($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL) { |
$saveTimeZone = date_default_timezone_get(); |
date_default_timezone_set('UTC'); |
$retValue = FALSE; |
if ((is_object($dateValue)) && ($dateValue instanceof DateTime)) { |
$retValue = self::FormattedPHPToExcel( $dateValue->format('Y'), $dateValue->format('m'), $dateValue->format('d'), |
$dateValue->format('H'), $dateValue->format('i'), $dateValue->format('s') |
); |
} elseif (is_numeric($dateValue)) { |
$retValue = self::FormattedPHPToExcel( date('Y',$dateValue), date('m',$dateValue), date('d',$dateValue), |
date('H',$dateValue), date('i',$dateValue), date('s',$dateValue) |
); |
} |
date_default_timezone_set($saveTimeZone); |
return $retValue; |
} // function PHPToExcel() |
/** |
* FormattedPHPToExcel |
* |
* @param long $year |
* @param long $month |
* @param long $day |
* @param long $hours |
* @param long $minutes |
* @param long $seconds |
* @return long Excel date/time value |
*/ |
public static function FormattedPHPToExcel($year, $month, $day, $hours=0, $minutes=0, $seconds=0) { |
if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) { |
// |
// Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel |
// This affects every date following 28th February 1900 |
// |
$excel1900isLeapYear = TRUE; |
if (($year == 1900) && ($month <= 2)) { $excel1900isLeapYear = FALSE; } |
$my_excelBaseDate = 2415020; |
} else { |
$my_excelBaseDate = 2416481; |
$excel1900isLeapYear = FALSE; |
} |
// Julian base date Adjustment |
if ($month > 2) { |
$month -= 3; |
} else { |
$month += 9; |
--$year; |
} |
// Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0) |
$century = substr($year,0,2); |
$decade = substr($year,2,2); |
$excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $my_excelBaseDate + $excel1900isLeapYear; |
$excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400; |
return (float) $excelDate + $excelTime; |
} // function FormattedPHPToExcel() |
/** |
* Is a given cell a date/time? |
* |
* @param PHPExcel_Cell $pCell |
* @return boolean |
*/ |
public static function isDateTime(PHPExcel_Cell $pCell) { |
return self::isDateTimeFormat( |
$pCell->getWorksheet()->getStyle( |
$pCell->getCoordinate() |
)->getNumberFormat() |
); |
} // function isDateTime() |
/** |
* Is a given number format a date/time? |
* |
* @param PHPExcel_Style_NumberFormat $pFormat |
* @return boolean |
*/ |
public static function isDateTimeFormat(PHPExcel_Style_NumberFormat $pFormat) { |
return self::isDateTimeFormatCode($pFormat->getFormatCode()); |
} // function isDateTimeFormat() |
private static $possibleDateFormatCharacters = 'eymdHs'; |
/** |
* Is a given number format code a date/time? |
* |
* @param string $pFormatCode |
* @return boolean |
*/ |
public static function isDateTimeFormatCode($pFormatCode = '') { |
// Switch on formatcode |
switch ($pFormatCode) { |
// General contains an epoch letter 'e', so we trap for it explicitly here |
case PHPExcel_Style_NumberFormat::FORMAT_GENERAL: |
return FALSE; |
// Explicitly defined date formats |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYSLASH: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYMINUS: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMMINUS: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_MYMINUS: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_DATETIME: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME1: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME2: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME5: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME6: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME7: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME8: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDDSLASH: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX16: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX17: |
case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX22: |
return TRUE; |
} |
// Typically number, currency or accounting (or occasionally fraction) formats |
if ((substr($pFormatCode,0,1) == '_') || (substr($pFormatCode,0,2) == '0 ')) { |
return FALSE; |
} |
// Try checking for any of the date formatting characters that don't appear within square braces |
if (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$pFormatCode)) { |
// We might also have a format mask containing quoted strings... |
// we don't want to test for any of our characters within the quoted blocks |
if (strpos($pFormatCode,'"') !== FALSE) { |
$segMatcher = FALSE; |
foreach(explode('"',$pFormatCode) as $subVal) { |
// Only test in alternate array entries (the non-quoted blocks) |
if (($segMatcher = !$segMatcher) && |
(preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$subVal))) { |
return TRUE; |
} |
} |
return FALSE; |
} |
return TRUE; |
} |
// No date... |
return FALSE; |
} // function isDateTimeFormatCode() |
/** |
* Convert a date/time string to Excel time |
* |
* @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10' |
* @return float|FALSE Excel date/time serial value |
*/ |
public static function stringToExcel($dateValue = '') { |
if (strlen($dateValue) < 2) |
return FALSE; |
if (!preg_match('/^(\d{1,4}[ \.\/\-][A-Z]{3,9}([ \.\/\-]\d{1,4})?|[A-Z]{3,9}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?|\d{1,4}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?)( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/iu', $dateValue)) |
return FALSE; |
$dateValueNew = PHPExcel_Calculation_DateTime::DATEVALUE($dateValue); |
if ($dateValueNew === PHPExcel_Calculation_Functions::VALUE()) { |
return FALSE; |
} else { |
if (strpos($dateValue, ':') !== FALSE) { |
$timeValue = PHPExcel_Calculation_DateTime::TIMEVALUE($dateValue); |
if ($timeValue === PHPExcel_Calculation_Functions::VALUE()) { |
return FALSE; |
} |
$dateValueNew += $timeValue; |
} |
return $dateValueNew; |
} |
} |
public static function monthStringToNumber($month) { |
$monthIndex = 1; |
foreach(self::$_monthNames as $shortMonthName => $longMonthName) { |
if (($month === $longMonthName) || ($month === $shortMonthName)) { |
return $monthIndex; |
} |
++$monthIndex; |
} |
return $month; |
} |
public static function dayStringToNumber($day) { |
$strippedDayValue = (str_replace(self::$_numberSuffixes,'',$day)); |
if (is_numeric($strippedDayValue)) { |
return $strippedDayValue; |
} |
return $day; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/ZipStreamWrapper.php |
---|
New file |
0,0 → 1,201 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_ZipStreamWrapper |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_ZipStreamWrapper { |
/** |
* Internal ZipAcrhive |
* |
* @var ZipAcrhive |
*/ |
private $_archive; |
/** |
* Filename in ZipAcrhive |
* |
* @var string |
*/ |
private $_fileNameInArchive = ''; |
/** |
* Position in file |
* |
* @var int |
*/ |
private $_position = 0; |
/** |
* Data |
* |
* @var mixed |
*/ |
private $_data = ''; |
/** |
* Register wrapper |
*/ |
public static function register() { |
@stream_wrapper_unregister("zip"); |
@stream_wrapper_register("zip", __CLASS__); |
} |
/** |
* Implements support for fopen(). |
* |
* @param string $path resource name including scheme, e.g. |
* @param string $mode only "r" is supported |
* @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH |
* @param string &$openedPath absolute path of the opened stream (out parameter) |
* @return bool true on success |
*/ |
public function stream_open($path, $mode, $options, &$opened_path) { |
// Check for mode |
if ($mode{0} != 'r') { |
throw new PHPExcel_Reader_Exception('Mode ' . $mode . ' is not supported. Only read mode is supported.'); |
} |
$pos = strrpos($path, '#'); |
$url['host'] = substr($path, 6, $pos - 6); // 6: strlen('zip://') |
$url['fragment'] = substr($path, $pos + 1); |
// Open archive |
$this->_archive = new ZipArchive(); |
$this->_archive->open($url['host']); |
$this->_fileNameInArchive = $url['fragment']; |
$this->_position = 0; |
$this->_data = $this->_archive->getFromName( $this->_fileNameInArchive ); |
return true; |
} |
/** |
* Implements support for fstat(). |
* |
* @return boolean |
*/ |
public function statName() { |
return $this->_fileNameInArchive; |
} |
/** |
* Implements support for fstat(). |
* |
* @return boolean |
*/ |
public function url_stat() { |
return $this->statName( $this->_fileNameInArchive ); |
} |
/** |
* Implements support for fstat(). |
* |
* @return boolean |
*/ |
public function stream_stat() { |
return $this->_archive->statName( $this->_fileNameInArchive ); |
} |
/** |
* Implements support for fread(), fgets() etc. |
* |
* @param int $count maximum number of bytes to read |
* @return string |
*/ |
function stream_read($count) { |
$ret = substr($this->_data, $this->_position, $count); |
$this->_position += strlen($ret); |
return $ret; |
} |
/** |
* Returns the position of the file pointer, i.e. its offset into the file |
* stream. Implements support for ftell(). |
* |
* @return int |
*/ |
public function stream_tell() { |
return $this->_position; |
} |
/** |
* EOF stream |
* |
* @return bool |
*/ |
public function stream_eof() { |
return $this->_position >= strlen($this->_data); |
} |
/** |
* Seek stream |
* |
* @param int $offset byte offset |
* @param int $whence SEEK_SET, SEEK_CUR or SEEK_END |
* @return bool |
*/ |
public function stream_seek($offset, $whence) { |
switch ($whence) { |
case SEEK_SET: |
if ($offset < strlen($this->_data) && $offset >= 0) { |
$this->_position = $offset; |
return true; |
} else { |
return false; |
} |
break; |
case SEEK_CUR: |
if ($offset >= 0) { |
$this->_position += $offset; |
return true; |
} else { |
return false; |
} |
break; |
case SEEK_END: |
if (strlen($this->_data) + $offset >= 0) { |
$this->_position = strlen($this->_data) + $offset; |
return true; |
} else { |
return false; |
} |
break; |
default: |
return false; |
} |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/File.php |
---|
New file |
0,0 → 1,178 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_File |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_File |
{ |
/* |
* Use Temp or File Upload Temp for temporary files |
* |
* @protected |
* @var boolean |
*/ |
protected static $_useUploadTempDirectory = FALSE; |
/** |
* Set the flag indicating whether the File Upload Temp directory should be used for temporary files |
* |
* @param boolean $useUploadTempDir Use File Upload Temporary directory (true or false) |
*/ |
public static function setUseUploadTempDirectory($useUploadTempDir = FALSE) { |
self::$_useUploadTempDirectory = (boolean) $useUploadTempDir; |
} // function setUseUploadTempDirectory() |
/** |
* Get the flag indicating whether the File Upload Temp directory should be used for temporary files |
* |
* @return boolean Use File Upload Temporary directory (true or false) |
*/ |
public static function getUseUploadTempDirectory() { |
return self::$_useUploadTempDirectory; |
} // function getUseUploadTempDirectory() |
/** |
* Verify if a file exists |
* |
* @param string $pFilename Filename |
* @return bool |
*/ |
public static function file_exists($pFilename) { |
// Sick construction, but it seems that |
// file_exists returns strange values when |
// doing the original file_exists on ZIP archives... |
if ( strtolower(substr($pFilename, 0, 3)) == 'zip' ) { |
// Open ZIP file and verify if the file exists |
$zipFile = substr($pFilename, 6, strpos($pFilename, '#') - 6); |
$archiveFile = substr($pFilename, strpos($pFilename, '#') + 1); |
$zip = new ZipArchive(); |
if ($zip->open($zipFile) === true) { |
$returnValue = ($zip->getFromName($archiveFile) !== false); |
$zip->close(); |
return $returnValue; |
} else { |
return false; |
} |
} else { |
// Regular file_exists |
return file_exists($pFilename); |
} |
} |
/** |
* Returns canonicalized absolute pathname, also for ZIP archives |
* |
* @param string $pFilename |
* @return string |
*/ |
public static function realpath($pFilename) { |
// Returnvalue |
$returnValue = ''; |
// Try using realpath() |
if (file_exists($pFilename)) { |
$returnValue = realpath($pFilename); |
} |
// Found something? |
if ($returnValue == '' || ($returnValue === NULL)) { |
$pathArray = explode('/' , $pFilename); |
while(in_array('..', $pathArray) && $pathArray[0] != '..') { |
for ($i = 0; $i < count($pathArray); ++$i) { |
if ($pathArray[$i] == '..' && $i > 0) { |
unset($pathArray[$i]); |
unset($pathArray[$i - 1]); |
break; |
} |
} |
} |
$returnValue = implode('/', $pathArray); |
} |
// Return |
return $returnValue; |
} |
/** |
* Get the systems temporary directory. |
* |
* @return string |
*/ |
public static function sys_get_temp_dir() |
{ |
if (self::$_useUploadTempDirectory) { |
// use upload-directory when defined to allow running on environments having very restricted |
// open_basedir configs |
if (ini_get('upload_tmp_dir') !== FALSE) { |
if ($temp = ini_get('upload_tmp_dir')) { |
if (file_exists($temp)) |
return realpath($temp); |
} |
} |
} |
// sys_get_temp_dir is only available since PHP 5.2.1 |
// http://php.net/manual/en/function.sys-get-temp-dir.php#94119 |
if ( !function_exists('sys_get_temp_dir')) { |
if ($temp = getenv('TMP') ) { |
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); } |
} |
if ($temp = getenv('TEMP') ) { |
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); } |
} |
if ($temp = getenv('TMPDIR') ) { |
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); } |
} |
// trick for creating a file in system's temporary dir |
// without knowing the path of the system's temporary dir |
$temp = tempnam(__FILE__, ''); |
if (file_exists($temp)) { |
unlink($temp); |
return realpath(dirname($temp)); |
} |
return null; |
} |
// use ordinary built-in PHP function |
// There should be no problem with the 5.2.4 Suhosin realpath() bug, because this line should only |
// be called if we're running 5.2.1 or earlier |
return realpath(sys_get_temp_dir()); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/OLE.php |
---|
New file |
0,0 → 1,531 |
<?php |
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
// +----------------------------------------------------------------------+ |
// | PHP Version 4 | |
// +----------------------------------------------------------------------+ |
// | Copyright (c) 1997-2002 The PHP Group | |
// +----------------------------------------------------------------------+ |
// | This source file is subject to version 2.02 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. | |
// +----------------------------------------------------------------------+ |
// | Author: Xavier Noguer <xnoguer@php.net> | |
// | Based on OLE::Storage_Lite by Kawai, Takanori | |
// +----------------------------------------------------------------------+ |
// |
// $Id: OLE.php,v 1.13 2007/03/07 14:38:25 schmidt Exp $ |
/** |
* Array for storing OLE instances that are accessed from |
* OLE_ChainedBlockStream::stream_open(). |
* @var array |
*/ |
$GLOBALS['_OLE_INSTANCES'] = array(); |
/** |
* OLE package base class. |
* |
* @author Xavier Noguer <xnoguer@php.net> |
* @author Christian Schmidt <schmidt@php.net> |
* @category PHPExcel |
* @package PHPExcel_Shared_OLE |
*/ |
class PHPExcel_Shared_OLE |
{ |
const OLE_PPS_TYPE_ROOT = 5; |
const OLE_PPS_TYPE_DIR = 1; |
const OLE_PPS_TYPE_FILE = 2; |
const OLE_DATA_SIZE_SMALL = 0x1000; |
const OLE_LONG_INT_SIZE = 4; |
const OLE_PPS_SIZE = 0x80; |
/** |
* The file handle for reading an OLE container |
* @var resource |
*/ |
public $_file_handle; |
/** |
* Array of PPS's found on the OLE container |
* @var array |
*/ |
public $_list = array(); |
/** |
* Root directory of OLE container |
* @var OLE_PPS_Root |
*/ |
public $root; |
/** |
* Big Block Allocation Table |
* @var array (blockId => nextBlockId) |
*/ |
public $bbat; |
/** |
* Short Block Allocation Table |
* @var array (blockId => nextBlockId) |
*/ |
public $sbat; |
/** |
* Size of big blocks. This is usually 512. |
* @var int number of octets per block. |
*/ |
public $bigBlockSize; |
/** |
* Size of small blocks. This is usually 64. |
* @var int number of octets per block |
*/ |
public $smallBlockSize; |
/** |
* Reads an OLE container from the contents of the file given. |
* |
* @acces public |
* @param string $file |
* @return mixed true on success, PEAR_Error on failure |
*/ |
public function read($file) |
{ |
$fh = fopen($file, "r"); |
if (!$fh) { |
throw new PHPExcel_Reader_Exception("Can't open file $file"); |
} |
$this->_file_handle = $fh; |
$signature = fread($fh, 8); |
if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) { |
throw new PHPExcel_Reader_Exception("File doesn't seem to be an OLE container."); |
} |
fseek($fh, 28); |
if (fread($fh, 2) != "\xFE\xFF") { |
// This shouldn't be a problem in practice |
throw new PHPExcel_Reader_Exception("Only Little-Endian encoding is supported."); |
} |
// Size of blocks and short blocks in bytes |
$this->bigBlockSize = pow(2, self::_readInt2($fh)); |
$this->smallBlockSize = pow(2, self::_readInt2($fh)); |
// Skip UID, revision number and version number |
fseek($fh, 44); |
// Number of blocks in Big Block Allocation Table |
$bbatBlockCount = self::_readInt4($fh); |
// Root chain 1st block |
$directoryFirstBlockId = self::_readInt4($fh); |
// Skip unused bytes |
fseek($fh, 56); |
// Streams shorter than this are stored using small blocks |
$this->bigBlockThreshold = self::_readInt4($fh); |
// Block id of first sector in Short Block Allocation Table |
$sbatFirstBlockId = self::_readInt4($fh); |
// Number of blocks in Short Block Allocation Table |
$sbbatBlockCount = self::_readInt4($fh); |
// Block id of first sector in Master Block Allocation Table |
$mbatFirstBlockId = self::_readInt4($fh); |
// Number of blocks in Master Block Allocation Table |
$mbbatBlockCount = self::_readInt4($fh); |
$this->bbat = array(); |
// Remaining 4 * 109 bytes of current block is beginning of Master |
// Block Allocation Table |
$mbatBlocks = array(); |
for ($i = 0; $i < 109; ++$i) { |
$mbatBlocks[] = self::_readInt4($fh); |
} |
// Read rest of Master Block Allocation Table (if any is left) |
$pos = $this->_getBlockOffset($mbatFirstBlockId); |
for ($i = 0; $i < $mbbatBlockCount; ++$i) { |
fseek($fh, $pos); |
for ($j = 0; $j < $this->bigBlockSize / 4 - 1; ++$j) { |
$mbatBlocks[] = self::_readInt4($fh); |
} |
// Last block id in each block points to next block |
$pos = $this->_getBlockOffset(self::_readInt4($fh)); |
} |
// Read Big Block Allocation Table according to chain specified by |
// $mbatBlocks |
for ($i = 0; $i < $bbatBlockCount; ++$i) { |
$pos = $this->_getBlockOffset($mbatBlocks[$i]); |
fseek($fh, $pos); |
for ($j = 0 ; $j < $this->bigBlockSize / 4; ++$j) { |
$this->bbat[] = self::_readInt4($fh); |
} |
} |
// Read short block allocation table (SBAT) |
$this->sbat = array(); |
$shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4; |
$sbatFh = $this->getStream($sbatFirstBlockId); |
for ($blockId = 0; $blockId < $shortBlockCount; ++$blockId) { |
$this->sbat[$blockId] = self::_readInt4($sbatFh); |
} |
fclose($sbatFh); |
$this->_readPpsWks($directoryFirstBlockId); |
return true; |
} |
/** |
* @param int block id |
* @param int byte offset from beginning of file |
* @access public |
*/ |
public function _getBlockOffset($blockId) |
{ |
return 512 + $blockId * $this->bigBlockSize; |
} |
/** |
* Returns a stream for use with fread() etc. External callers should |
* use PHPExcel_Shared_OLE_PPS_File::getStream(). |
* @param int|PPS block id or PPS |
* @return resource read-only stream |
*/ |
public function getStream($blockIdOrPps) |
{ |
static $isRegistered = false; |
if (!$isRegistered) { |
stream_wrapper_register('ole-chainedblockstream', |
'PHPExcel_Shared_OLE_ChainedBlockStream'); |
$isRegistered = true; |
} |
// Store current instance in global array, so that it can be accessed |
// in OLE_ChainedBlockStream::stream_open(). |
// Object is removed from self::$instances in OLE_Stream::close(). |
$GLOBALS['_OLE_INSTANCES'][] = $this; |
$instanceId = end(array_keys($GLOBALS['_OLE_INSTANCES'])); |
$path = 'ole-chainedblockstream://oleInstanceId=' . $instanceId; |
if ($blockIdOrPps instanceof PHPExcel_Shared_OLE_PPS) { |
$path .= '&blockId=' . $blockIdOrPps->_StartBlock; |
$path .= '&size=' . $blockIdOrPps->Size; |
} else { |
$path .= '&blockId=' . $blockIdOrPps; |
} |
return fopen($path, 'r'); |
} |
/** |
* Reads a signed char. |
* @param resource file handle |
* @return int |
* @access public |
*/ |
private static function _readInt1($fh) |
{ |
list(, $tmp) = unpack("c", fread($fh, 1)); |
return $tmp; |
} |
/** |
* Reads an unsigned short (2 octets). |
* @param resource file handle |
* @return int |
* @access public |
*/ |
private static function _readInt2($fh) |
{ |
list(, $tmp) = unpack("v", fread($fh, 2)); |
return $tmp; |
} |
/** |
* Reads an unsigned long (4 octets). |
* @param resource file handle |
* @return int |
* @access public |
*/ |
private static function _readInt4($fh) |
{ |
list(, $tmp) = unpack("V", fread($fh, 4)); |
return $tmp; |
} |
/** |
* Gets information about all PPS's on the OLE container from the PPS WK's |
* creates an OLE_PPS object for each one. |
* |
* @access public |
* @param integer the block id of the first block |
* @return mixed true on success, PEAR_Error on failure |
*/ |
public function _readPpsWks($blockId) |
{ |
$fh = $this->getStream($blockId); |
for ($pos = 0; ; $pos += 128) { |
fseek($fh, $pos, SEEK_SET); |
$nameUtf16 = fread($fh, 64); |
$nameLength = self::_readInt2($fh); |
$nameUtf16 = substr($nameUtf16, 0, $nameLength - 2); |
// Simple conversion from UTF-16LE to ISO-8859-1 |
$name = str_replace("\x00", "", $nameUtf16); |
$type = self::_readInt1($fh); |
switch ($type) { |
case self::OLE_PPS_TYPE_ROOT: |
$pps = new PHPExcel_Shared_OLE_PPS_Root(null, null, array()); |
$this->root = $pps; |
break; |
case self::OLE_PPS_TYPE_DIR: |
$pps = new PHPExcel_Shared_OLE_PPS(null, null, null, null, null, |
null, null, null, null, array()); |
break; |
case self::OLE_PPS_TYPE_FILE: |
$pps = new PHPExcel_Shared_OLE_PPS_File($name); |
break; |
default: |
continue; |
} |
fseek($fh, 1, SEEK_CUR); |
$pps->Type = $type; |
$pps->Name = $name; |
$pps->PrevPps = self::_readInt4($fh); |
$pps->NextPps = self::_readInt4($fh); |
$pps->DirPps = self::_readInt4($fh); |
fseek($fh, 20, SEEK_CUR); |
$pps->Time1st = self::OLE2LocalDate(fread($fh, 8)); |
$pps->Time2nd = self::OLE2LocalDate(fread($fh, 8)); |
$pps->_StartBlock = self::_readInt4($fh); |
$pps->Size = self::_readInt4($fh); |
$pps->No = count($this->_list); |
$this->_list[] = $pps; |
// check if the PPS tree (starting from root) is complete |
if (isset($this->root) && |
$this->_ppsTreeComplete($this->root->No)) { |
break; |
} |
} |
fclose($fh); |
// Initialize $pps->children on directories |
foreach ($this->_list as $pps) { |
if ($pps->Type == self::OLE_PPS_TYPE_DIR || $pps->Type == self::OLE_PPS_TYPE_ROOT) { |
$nos = array($pps->DirPps); |
$pps->children = array(); |
while ($nos) { |
$no = array_pop($nos); |
if ($no != -1) { |
$childPps = $this->_list[$no]; |
$nos[] = $childPps->PrevPps; |
$nos[] = $childPps->NextPps; |
$pps->children[] = $childPps; |
} |
} |
} |
} |
return true; |
} |
/** |
* It checks whether the PPS tree is complete (all PPS's read) |
* starting with the given PPS (not necessarily root) |
* |
* @access public |
* @param integer $index The index of the PPS from which we are checking |
* @return boolean Whether the PPS tree for the given PPS is complete |
*/ |
public function _ppsTreeComplete($index) |
{ |
return isset($this->_list[$index]) && |
($pps = $this->_list[$index]) && |
($pps->PrevPps == -1 || |
$this->_ppsTreeComplete($pps->PrevPps)) && |
($pps->NextPps == -1 || |
$this->_ppsTreeComplete($pps->NextPps)) && |
($pps->DirPps == -1 || |
$this->_ppsTreeComplete($pps->DirPps)); |
} |
/** |
* Checks whether a PPS is a File PPS or not. |
* If there is no PPS for the index given, it will return false. |
* |
* @access public |
* @param integer $index The index for the PPS |
* @return bool true if it's a File PPS, false otherwise |
*/ |
public function isFile($index) |
{ |
if (isset($this->_list[$index])) { |
return ($this->_list[$index]->Type == self::OLE_PPS_TYPE_FILE); |
} |
return false; |
} |
/** |
* Checks whether a PPS is a Root PPS or not. |
* If there is no PPS for the index given, it will return false. |
* |
* @access public |
* @param integer $index The index for the PPS. |
* @return bool true if it's a Root PPS, false otherwise |
*/ |
public function isRoot($index) |
{ |
if (isset($this->_list[$index])) { |
return ($this->_list[$index]->Type == self::OLE_PPS_TYPE_ROOT); |
} |
return false; |
} |
/** |
* Gives the total number of PPS's found in the OLE container. |
* |
* @access public |
* @return integer The total number of PPS's found in the OLE container |
*/ |
public function ppsTotal() |
{ |
return count($this->_list); |
} |
/** |
* Gets data from a PPS |
* If there is no PPS for the index given, it will return an empty string. |
* |
* @access public |
* @param integer $index The index for the PPS |
* @param integer $position The position from which to start reading |
* (relative to the PPS) |
* @param integer $length The amount of bytes to read (at most) |
* @return string The binary string containing the data requested |
* @see OLE_PPS_File::getStream() |
*/ |
public function getData($index, $position, $length) |
{ |
// if position is not valid return empty string |
if (!isset($this->_list[$index]) || ($position >= $this->_list[$index]->Size) || ($position < 0)) { |
return ''; |
} |
$fh = $this->getStream($this->_list[$index]); |
$data = stream_get_contents($fh, $length, $position); |
fclose($fh); |
return $data; |
} |
/** |
* Gets the data length from a PPS |
* If there is no PPS for the index given, it will return 0. |
* |
* @access public |
* @param integer $index The index for the PPS |
* @return integer The amount of bytes in data the PPS has |
*/ |
public function getDataLength($index) |
{ |
if (isset($this->_list[$index])) { |
return $this->_list[$index]->Size; |
} |
return 0; |
} |
/** |
* Utility function to transform ASCII text to Unicode |
* |
* @access public |
* @static |
* @param string $ascii The ASCII string to transform |
* @return string The string in Unicode |
*/ |
public static function Asc2Ucs($ascii) |
{ |
$rawname = ''; |
for ($i = 0; $i < strlen($ascii); ++$i) { |
$rawname .= $ascii{$i} . "\x00"; |
} |
return $rawname; |
} |
/** |
* Utility function |
* Returns a string for the OLE container with the date given |
* |
* @access public |
* @static |
* @param integer $date A timestamp |
* @return string The string for the OLE container |
*/ |
public static function LocalDate2OLE($date = null) |
{ |
if (!isset($date)) { |
return "\x00\x00\x00\x00\x00\x00\x00\x00"; |
} |
// factor used for separating numbers into 4 bytes parts |
$factor = pow(2, 32); |
// days from 1-1-1601 until the beggining of UNIX era |
$days = 134774; |
// calculate seconds |
$big_date = $days*24*3600 + gmmktime(date("H",$date),date("i",$date),date("s",$date), |
date("m",$date),date("d",$date),date("Y",$date)); |
// multiply just to make MS happy |
$big_date *= 10000000; |
$high_part = floor($big_date / $factor); |
// lower 4 bytes |
$low_part = floor((($big_date / $factor) - $high_part) * $factor); |
// Make HEX string |
$res = ''; |
for ($i = 0; $i < 4; ++$i) { |
$hex = $low_part % 0x100; |
$res .= pack('c', $hex); |
$low_part /= 0x100; |
} |
for ($i = 0; $i < 4; ++$i) { |
$hex = $high_part % 0x100; |
$res .= pack('c', $hex); |
$high_part /= 0x100; |
} |
return $res; |
} |
/** |
* Returns a timestamp from an OLE container's date |
* |
* @access public |
* @static |
* @param integer $string A binary string with the encoded date |
* @return string The timestamp corresponding to the string |
*/ |
public static function OLE2LocalDate($string) |
{ |
if (strlen($string) != 8) { |
return new PEAR_Error("Expecting 8 byte string"); |
} |
// factor used for separating numbers into 4 bytes parts |
$factor = pow(2,32); |
list(, $high_part) = unpack('V', substr($string, 4, 4)); |
list(, $low_part) = unpack('V', substr($string, 0, 4)); |
$big_date = ($high_part * $factor) + $low_part; |
// translate to seconds |
$big_date /= 10000000; |
// days from 1-1-1601 until the beggining of UNIX era |
$days = 134774; |
// translate to seconds from beggining of UNIX era |
$big_date -= $days * 24 * 3600; |
return floor($big_date); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/CholeskyDecomposition.php |
---|
New file |
0,0 → 1,149 |
<?php |
/** |
* @package JAMA |
* |
* Cholesky decomposition class |
* |
* For a symmetric, positive definite matrix A, the Cholesky decomposition |
* is an lower triangular matrix L so that A = L*L'. |
* |
* If the matrix is not symmetric or positive definite, the constructor |
* returns a partial decomposition and sets an internal flag that may |
* be queried by the isSPD() method. |
* |
* @author Paul Meagher |
* @author Michael Bommarito |
* @version 1.2 |
*/ |
class CholeskyDecomposition { |
/** |
* Decomposition storage |
* @var array |
* @access private |
*/ |
private $L = array(); |
/** |
* Matrix row and column dimension |
* @var int |
* @access private |
*/ |
private $m; |
/** |
* Symmetric positive definite flag |
* @var boolean |
* @access private |
*/ |
private $isspd = true; |
/** |
* CholeskyDecomposition |
* |
* Class constructor - decomposes symmetric positive definite matrix |
* @param mixed Matrix square symmetric positive definite matrix |
*/ |
public function __construct($A = null) { |
if ($A instanceof Matrix) { |
$this->L = $A->getArray(); |
$this->m = $A->getRowDimension(); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = $i; $j < $this->m; ++$j) { |
for($sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; --$k) { |
$sum -= $this->L[$i][$k] * $this->L[$j][$k]; |
} |
if ($i == $j) { |
if ($sum >= 0) { |
$this->L[$i][$i] = sqrt($sum); |
} else { |
$this->isspd = false; |
} |
} else { |
if ($this->L[$i][$i] != 0) { |
$this->L[$j][$i] = $sum / $this->L[$i][$i]; |
} |
} |
} |
for ($k = $i+1; $k < $this->m; ++$k) { |
$this->L[$i][$k] = 0.0; |
} |
} |
} else { |
throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); |
} |
} // function __construct() |
/** |
* Is the matrix symmetric and positive definite? |
* |
* @return boolean |
*/ |
public function isSPD() { |
return $this->isspd; |
} // function isSPD() |
/** |
* getL |
* |
* Return triangular factor. |
* @return Matrix Lower triangular matrix |
*/ |
public function getL() { |
return new Matrix($this->L); |
} // function getL() |
/** |
* Solve A*X = B |
* |
* @param $B Row-equal matrix |
* @return Matrix L * L' * X = B |
*/ |
public function solve($B = null) { |
if ($B instanceof Matrix) { |
if ($B->getRowDimension() == $this->m) { |
if ($this->isspd) { |
$X = $B->getArrayCopy(); |
$nx = $B->getColumnDimension(); |
for ($k = 0; $k < $this->m; ++$k) { |
for ($i = $k + 1; $i < $this->m; ++$i) { |
for ($j = 0; $j < $nx; ++$j) { |
$X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k]; |
} |
} |
for ($j = 0; $j < $nx; ++$j) { |
$X[$k][$j] /= $this->L[$k][$k]; |
} |
} |
for ($k = $this->m - 1; $k >= 0; --$k) { |
for ($j = 0; $j < $nx; ++$j) { |
$X[$k][$j] /= $this->L[$k][$k]; |
} |
for ($i = 0; $i < $k; ++$i) { |
for ($j = 0; $j < $nx; ++$j) { |
$X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i]; |
} |
} |
} |
return new Matrix($X, $this->m, $nx); |
} else { |
throw new PHPExcel_Calculation_Exception(JAMAError(MatrixSPDException)); |
} |
} else { |
throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionException)); |
} |
} else { |
throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); |
} |
} // function solve() |
} // class CholeskyDecomposition |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/SingularValueDecomposition.php |
---|
New file |
0,0 → 1,526 |
<?php |
/** |
* @package JAMA |
* |
* For an m-by-n matrix A with m >= n, the singular value decomposition is |
* an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and |
* an n-by-n orthogonal matrix V so that A = U*S*V'. |
* |
* The singular values, sigma[$k] = S[$k][$k], are ordered so that |
* sigma[0] >= sigma[1] >= ... >= sigma[n-1]. |
* |
* The singular value decompostion always exists, so the constructor will |
* never fail. The matrix condition number and the effective numerical |
* rank can be computed from this decomposition. |
* |
* @author Paul Meagher |
* @license PHP v3.0 |
* @version 1.1 |
*/ |
class SingularValueDecomposition { |
/** |
* Internal storage of U. |
* @var array |
*/ |
private $U = array(); |
/** |
* Internal storage of V. |
* @var array |
*/ |
private $V = array(); |
/** |
* Internal storage of singular values. |
* @var array |
*/ |
private $s = array(); |
/** |
* Row dimension. |
* @var int |
*/ |
private $m; |
/** |
* Column dimension. |
* @var int |
*/ |
private $n; |
/** |
* Construct the singular value decomposition |
* |
* Derived from LINPACK code. |
* |
* @param $A Rectangular matrix |
* @return Structure to access U, S and V. |
*/ |
public function __construct($Arg) { |
// Initialize. |
$A = $Arg->getArrayCopy(); |
$this->m = $Arg->getRowDimension(); |
$this->n = $Arg->getColumnDimension(); |
$nu = min($this->m, $this->n); |
$e = array(); |
$work = array(); |
$wantu = true; |
$wantv = true; |
$nct = min($this->m - 1, $this->n); |
$nrt = max(0, min($this->n - 2, $this->m)); |
// Reduce A to bidiagonal form, storing the diagonal elements |
// in s and the super-diagonal elements in e. |
for ($k = 0; $k < max($nct,$nrt); ++$k) { |
if ($k < $nct) { |
// Compute the transformation for the k-th column and |
// place the k-th diagonal in s[$k]. |
// Compute 2-norm of k-th column without under/overflow. |
$this->s[$k] = 0; |
for ($i = $k; $i < $this->m; ++$i) { |
$this->s[$k] = hypo($this->s[$k], $A[$i][$k]); |
} |
if ($this->s[$k] != 0.0) { |
if ($A[$k][$k] < 0.0) { |
$this->s[$k] = -$this->s[$k]; |
} |
for ($i = $k; $i < $this->m; ++$i) { |
$A[$i][$k] /= $this->s[$k]; |
} |
$A[$k][$k] += 1.0; |
} |
$this->s[$k] = -$this->s[$k]; |
} |
for ($j = $k + 1; $j < $this->n; ++$j) { |
if (($k < $nct) & ($this->s[$k] != 0.0)) { |
// Apply the transformation. |
$t = 0; |
for ($i = $k; $i < $this->m; ++$i) { |
$t += $A[$i][$k] * $A[$i][$j]; |
} |
$t = -$t / $A[$k][$k]; |
for ($i = $k; $i < $this->m; ++$i) { |
$A[$i][$j] += $t * $A[$i][$k]; |
} |
// Place the k-th row of A into e for the |
// subsequent calculation of the row transformation. |
$e[$j] = $A[$k][$j]; |
} |
} |
if ($wantu AND ($k < $nct)) { |
// Place the transformation in U for subsequent back |
// multiplication. |
for ($i = $k; $i < $this->m; ++$i) { |
$this->U[$i][$k] = $A[$i][$k]; |
} |
} |
if ($k < $nrt) { |
// Compute the k-th row transformation and place the |
// k-th super-diagonal in e[$k]. |
// Compute 2-norm without under/overflow. |
$e[$k] = 0; |
for ($i = $k + 1; $i < $this->n; ++$i) { |
$e[$k] = hypo($e[$k], $e[$i]); |
} |
if ($e[$k] != 0.0) { |
if ($e[$k+1] < 0.0) { |
$e[$k] = -$e[$k]; |
} |
for ($i = $k + 1; $i < $this->n; ++$i) { |
$e[$i] /= $e[$k]; |
} |
$e[$k+1] += 1.0; |
} |
$e[$k] = -$e[$k]; |
if (($k+1 < $this->m) AND ($e[$k] != 0.0)) { |
// Apply the transformation. |
for ($i = $k+1; $i < $this->m; ++$i) { |
$work[$i] = 0.0; |
} |
for ($j = $k+1; $j < $this->n; ++$j) { |
for ($i = $k+1; $i < $this->m; ++$i) { |
$work[$i] += $e[$j] * $A[$i][$j]; |
} |
} |
for ($j = $k + 1; $j < $this->n; ++$j) { |
$t = -$e[$j] / $e[$k+1]; |
for ($i = $k + 1; $i < $this->m; ++$i) { |
$A[$i][$j] += $t * $work[$i]; |
} |
} |
} |
if ($wantv) { |
// Place the transformation in V for subsequent |
// back multiplication. |
for ($i = $k + 1; $i < $this->n; ++$i) { |
$this->V[$i][$k] = $e[$i]; |
} |
} |
} |
} |
// Set up the final bidiagonal matrix or order p. |
$p = min($this->n, $this->m + 1); |
if ($nct < $this->n) { |
$this->s[$nct] = $A[$nct][$nct]; |
} |
if ($this->m < $p) { |
$this->s[$p-1] = 0.0; |
} |
if ($nrt + 1 < $p) { |
$e[$nrt] = $A[$nrt][$p-1]; |
} |
$e[$p-1] = 0.0; |
// If required, generate U. |
if ($wantu) { |
for ($j = $nct; $j < $nu; ++$j) { |
for ($i = 0; $i < $this->m; ++$i) { |
$this->U[$i][$j] = 0.0; |
} |
$this->U[$j][$j] = 1.0; |
} |
for ($k = $nct - 1; $k >= 0; --$k) { |
if ($this->s[$k] != 0.0) { |
for ($j = $k + 1; $j < $nu; ++$j) { |
$t = 0; |
for ($i = $k; $i < $this->m; ++$i) { |
$t += $this->U[$i][$k] * $this->U[$i][$j]; |
} |
$t = -$t / $this->U[$k][$k]; |
for ($i = $k; $i < $this->m; ++$i) { |
$this->U[$i][$j] += $t * $this->U[$i][$k]; |
} |
} |
for ($i = $k; $i < $this->m; ++$i ) { |
$this->U[$i][$k] = -$this->U[$i][$k]; |
} |
$this->U[$k][$k] = 1.0 + $this->U[$k][$k]; |
for ($i = 0; $i < $k - 1; ++$i) { |
$this->U[$i][$k] = 0.0; |
} |
} else { |
for ($i = 0; $i < $this->m; ++$i) { |
$this->U[$i][$k] = 0.0; |
} |
$this->U[$k][$k] = 1.0; |
} |
} |
} |
// If required, generate V. |
if ($wantv) { |
for ($k = $this->n - 1; $k >= 0; --$k) { |
if (($k < $nrt) AND ($e[$k] != 0.0)) { |
for ($j = $k + 1; $j < $nu; ++$j) { |
$t = 0; |
for ($i = $k + 1; $i < $this->n; ++$i) { |
$t += $this->V[$i][$k]* $this->V[$i][$j]; |
} |
$t = -$t / $this->V[$k+1][$k]; |
for ($i = $k + 1; $i < $this->n; ++$i) { |
$this->V[$i][$j] += $t * $this->V[$i][$k]; |
} |
} |
} |
for ($i = 0; $i < $this->n; ++$i) { |
$this->V[$i][$k] = 0.0; |
} |
$this->V[$k][$k] = 1.0; |
} |
} |
// Main iteration loop for the singular values. |
$pp = $p - 1; |
$iter = 0; |
$eps = pow(2.0, -52.0); |
while ($p > 0) { |
// Here is where a test for too many iterations would go. |
// This section of the program inspects for negligible |
// elements in the s and e arrays. On completion the |
// variables kase and k are set as follows: |
// kase = 1 if s(p) and e[k-1] are negligible and k<p |
// kase = 2 if s(k) is negligible and k<p |
// kase = 3 if e[k-1] is negligible, k<p, and |
// s(k), ..., s(p) are not negligible (qr step). |
// kase = 4 if e(p-1) is negligible (convergence). |
for ($k = $p - 2; $k >= -1; --$k) { |
if ($k == -1) { |
break; |
} |
if (abs($e[$k]) <= $eps * (abs($this->s[$k]) + abs($this->s[$k+1]))) { |
$e[$k] = 0.0; |
break; |
} |
} |
if ($k == $p - 2) { |
$kase = 4; |
} else { |
for ($ks = $p - 1; $ks >= $k; --$ks) { |
if ($ks == $k) { |
break; |
} |
$t = ($ks != $p ? abs($e[$ks]) : 0.) + ($ks != $k + 1 ? abs($e[$ks-1]) : 0.); |
if (abs($this->s[$ks]) <= $eps * $t) { |
$this->s[$ks] = 0.0; |
break; |
} |
} |
if ($ks == $k) { |
$kase = 3; |
} else if ($ks == $p-1) { |
$kase = 1; |
} else { |
$kase = 2; |
$k = $ks; |
} |
} |
++$k; |
// Perform the task indicated by kase. |
switch ($kase) { |
// Deflate negligible s(p). |
case 1: |
$f = $e[$p-2]; |
$e[$p-2] = 0.0; |
for ($j = $p - 2; $j >= $k; --$j) { |
$t = hypo($this->s[$j],$f); |
$cs = $this->s[$j] / $t; |
$sn = $f / $t; |
$this->s[$j] = $t; |
if ($j != $k) { |
$f = -$sn * $e[$j-1]; |
$e[$j-1] = $cs * $e[$j-1]; |
} |
if ($wantv) { |
for ($i = 0; $i < $this->n; ++$i) { |
$t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$p-1]; |
$this->V[$i][$p-1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$p-1]; |
$this->V[$i][$j] = $t; |
} |
} |
} |
break; |
// Split at negligible s(k). |
case 2: |
$f = $e[$k-1]; |
$e[$k-1] = 0.0; |
for ($j = $k; $j < $p; ++$j) { |
$t = hypo($this->s[$j], $f); |
$cs = $this->s[$j] / $t; |
$sn = $f / $t; |
$this->s[$j] = $t; |
$f = -$sn * $e[$j]; |
$e[$j] = $cs * $e[$j]; |
if ($wantu) { |
for ($i = 0; $i < $this->m; ++$i) { |
$t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$k-1]; |
$this->U[$i][$k-1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$k-1]; |
$this->U[$i][$j] = $t; |
} |
} |
} |
break; |
// Perform one qr step. |
case 3: |
// Calculate the shift. |
$scale = max(max(max(max( |
abs($this->s[$p-1]),abs($this->s[$p-2])),abs($e[$p-2])), |
abs($this->s[$k])), abs($e[$k])); |
$sp = $this->s[$p-1] / $scale; |
$spm1 = $this->s[$p-2] / $scale; |
$epm1 = $e[$p-2] / $scale; |
$sk = $this->s[$k] / $scale; |
$ek = $e[$k] / $scale; |
$b = (($spm1 + $sp) * ($spm1 - $sp) + $epm1 * $epm1) / 2.0; |
$c = ($sp * $epm1) * ($sp * $epm1); |
$shift = 0.0; |
if (($b != 0.0) || ($c != 0.0)) { |
$shift = sqrt($b * $b + $c); |
if ($b < 0.0) { |
$shift = -$shift; |
} |
$shift = $c / ($b + $shift); |
} |
$f = ($sk + $sp) * ($sk - $sp) + $shift; |
$g = $sk * $ek; |
// Chase zeros. |
for ($j = $k; $j < $p-1; ++$j) { |
$t = hypo($f,$g); |
$cs = $f/$t; |
$sn = $g/$t; |
if ($j != $k) { |
$e[$j-1] = $t; |
} |
$f = $cs * $this->s[$j] + $sn * $e[$j]; |
$e[$j] = $cs * $e[$j] - $sn * $this->s[$j]; |
$g = $sn * $this->s[$j+1]; |
$this->s[$j+1] = $cs * $this->s[$j+1]; |
if ($wantv) { |
for ($i = 0; $i < $this->n; ++$i) { |
$t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$j+1]; |
$this->V[$i][$j+1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$j+1]; |
$this->V[$i][$j] = $t; |
} |
} |
$t = hypo($f,$g); |
$cs = $f/$t; |
$sn = $g/$t; |
$this->s[$j] = $t; |
$f = $cs * $e[$j] + $sn * $this->s[$j+1]; |
$this->s[$j+1] = -$sn * $e[$j] + $cs * $this->s[$j+1]; |
$g = $sn * $e[$j+1]; |
$e[$j+1] = $cs * $e[$j+1]; |
if ($wantu && ($j < $this->m - 1)) { |
for ($i = 0; $i < $this->m; ++$i) { |
$t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$j+1]; |
$this->U[$i][$j+1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$j+1]; |
$this->U[$i][$j] = $t; |
} |
} |
} |
$e[$p-2] = $f; |
$iter = $iter + 1; |
break; |
// Convergence. |
case 4: |
// Make the singular values positive. |
if ($this->s[$k] <= 0.0) { |
$this->s[$k] = ($this->s[$k] < 0.0 ? -$this->s[$k] : 0.0); |
if ($wantv) { |
for ($i = 0; $i <= $pp; ++$i) { |
$this->V[$i][$k] = -$this->V[$i][$k]; |
} |
} |
} |
// Order the singular values. |
while ($k < $pp) { |
if ($this->s[$k] >= $this->s[$k+1]) { |
break; |
} |
$t = $this->s[$k]; |
$this->s[$k] = $this->s[$k+1]; |
$this->s[$k+1] = $t; |
if ($wantv AND ($k < $this->n - 1)) { |
for ($i = 0; $i < $this->n; ++$i) { |
$t = $this->V[$i][$k+1]; |
$this->V[$i][$k+1] = $this->V[$i][$k]; |
$this->V[$i][$k] = $t; |
} |
} |
if ($wantu AND ($k < $this->m-1)) { |
for ($i = 0; $i < $this->m; ++$i) { |
$t = $this->U[$i][$k+1]; |
$this->U[$i][$k+1] = $this->U[$i][$k]; |
$this->U[$i][$k] = $t; |
} |
} |
++$k; |
} |
$iter = 0; |
--$p; |
break; |
} // end switch |
} // end while |
} // end constructor |
/** |
* Return the left singular vectors |
* |
* @access public |
* @return U |
*/ |
public function getU() { |
return new Matrix($this->U, $this->m, min($this->m + 1, $this->n)); |
} |
/** |
* Return the right singular vectors |
* |
* @access public |
* @return V |
*/ |
public function getV() { |
return new Matrix($this->V); |
} |
/** |
* Return the one-dimensional array of singular values |
* |
* @access public |
* @return diagonal of S. |
*/ |
public function getSingularValues() { |
return $this->s; |
} |
/** |
* Return the diagonal matrix of singular values |
* |
* @access public |
* @return S |
*/ |
public function getS() { |
for ($i = 0; $i < $this->n; ++$i) { |
for ($j = 0; $j < $this->n; ++$j) { |
$S[$i][$j] = 0.0; |
} |
$S[$i][$i] = $this->s[$i]; |
} |
return new Matrix($S); |
} |
/** |
* Two norm |
* |
* @access public |
* @return max(S) |
*/ |
public function norm2() { |
return $this->s[0]; |
} |
/** |
* Two norm condition number |
* |
* @access public |
* @return max(S)/min(S) |
*/ |
public function cond() { |
return $this->s[0] / $this->s[min($this->m, $this->n) - 1]; |
} |
/** |
* Effective numerical matrix rank |
* |
* @access public |
* @return Number of nonnegligible singular values. |
*/ |
public function rank() { |
$eps = pow(2.0, -52.0); |
$tol = max($this->m, $this->n) * $this->s[0] * $eps; |
$r = 0; |
for ($i = 0; $i < count($this->s); ++$i) { |
if ($this->s[$i] > $tol) { |
++$r; |
} |
} |
return $r; |
} |
} // class SingularValueDecomposition |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/CHANGELOG.TXT |
---|
New file |
0,0 → 1,16 |
Mar 1, 2005 11:15 AST by PM |
+ For consistency, renamed Math.php to Maths.java, utils to util, |
tests to test, docs to doc - |
+ Removed conditional logic from top of Matrix class. |
+ Switched to using hypo function in Maths.php for all php-hypot calls. |
NOTE TO SELF: Need to make sure that all decompositions have been |
switched over to using the bundled hypo. |
Feb 25, 2005 at 10:00 AST by PM |
+ Recommend using simpler Error.php instead of JAMA_Error.php but |
can be persuaded otherwise. |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php |
---|
New file |
0,0 → 1,234 |
<?php |
/** |
* @package JAMA |
* |
* For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n |
* orthogonal matrix Q and an n-by-n upper triangular matrix R so that |
* A = Q*R. |
* |
* The QR decompostion always exists, even if the matrix does not have |
* full rank, so the constructor will never fail. The primary use of the |
* QR decomposition is in the least squares solution of nonsquare systems |
* of simultaneous linear equations. This will fail if isFullRank() |
* returns false. |
* |
* @author Paul Meagher |
* @license PHP v3.0 |
* @version 1.1 |
*/ |
class PHPExcel_Shared_JAMA_QRDecomposition { |
const MatrixRankException = "Can only perform operation on full-rank matrix."; |
/** |
* Array for internal storage of decomposition. |
* @var array |
*/ |
private $QR = array(); |
/** |
* Row dimension. |
* @var integer |
*/ |
private $m; |
/** |
* Column dimension. |
* @var integer |
*/ |
private $n; |
/** |
* Array for internal storage of diagonal of R. |
* @var array |
*/ |
private $Rdiag = array(); |
/** |
* QR Decomposition computed by Householder reflections. |
* |
* @param matrix $A Rectangular matrix |
* @return Structure to access R and the Householder vectors and compute Q. |
*/ |
public function __construct($A) { |
if($A instanceof PHPExcel_Shared_JAMA_Matrix) { |
// Initialize. |
$this->QR = $A->getArrayCopy(); |
$this->m = $A->getRowDimension(); |
$this->n = $A->getColumnDimension(); |
// Main loop. |
for ($k = 0; $k < $this->n; ++$k) { |
// Compute 2-norm of k-th column without under/overflow. |
$nrm = 0.0; |
for ($i = $k; $i < $this->m; ++$i) { |
$nrm = hypo($nrm, $this->QR[$i][$k]); |
} |
if ($nrm != 0.0) { |
// Form k-th Householder vector. |
if ($this->QR[$k][$k] < 0) { |
$nrm = -$nrm; |
} |
for ($i = $k; $i < $this->m; ++$i) { |
$this->QR[$i][$k] /= $nrm; |
} |
$this->QR[$k][$k] += 1.0; |
// Apply transformation to remaining columns. |
for ($j = $k+1; $j < $this->n; ++$j) { |
$s = 0.0; |
for ($i = $k; $i < $this->m; ++$i) { |
$s += $this->QR[$i][$k] * $this->QR[$i][$j]; |
} |
$s = -$s/$this->QR[$k][$k]; |
for ($i = $k; $i < $this->m; ++$i) { |
$this->QR[$i][$j] += $s * $this->QR[$i][$k]; |
} |
} |
} |
$this->Rdiag[$k] = -$nrm; |
} |
} else { |
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); |
} |
} // function __construct() |
/** |
* Is the matrix full rank? |
* |
* @return boolean true if R, and hence A, has full rank, else false. |
*/ |
public function isFullRank() { |
for ($j = 0; $j < $this->n; ++$j) { |
if ($this->Rdiag[$j] == 0) { |
return false; |
} |
} |
return true; |
} // function isFullRank() |
/** |
* Return the Householder vectors |
* |
* @return Matrix Lower trapezoidal matrix whose columns define the reflections |
*/ |
public function getH() { |
for ($i = 0; $i < $this->m; ++$i) { |
for ($j = 0; $j < $this->n; ++$j) { |
if ($i >= $j) { |
$H[$i][$j] = $this->QR[$i][$j]; |
} else { |
$H[$i][$j] = 0.0; |
} |
} |
} |
return new PHPExcel_Shared_JAMA_Matrix($H); |
} // function getH() |
/** |
* Return the upper triangular factor |
* |
* @return Matrix upper triangular factor |
*/ |
public function getR() { |
for ($i = 0; $i < $this->n; ++$i) { |
for ($j = 0; $j < $this->n; ++$j) { |
if ($i < $j) { |
$R[$i][$j] = $this->QR[$i][$j]; |
} elseif ($i == $j) { |
$R[$i][$j] = $this->Rdiag[$i]; |
} else { |
$R[$i][$j] = 0.0; |
} |
} |
} |
return new PHPExcel_Shared_JAMA_Matrix($R); |
} // function getR() |
/** |
* Generate and return the (economy-sized) orthogonal factor |
* |
* @return Matrix orthogonal factor |
*/ |
public function getQ() { |
for ($k = $this->n-1; $k >= 0; --$k) { |
for ($i = 0; $i < $this->m; ++$i) { |
$Q[$i][$k] = 0.0; |
} |
$Q[$k][$k] = 1.0; |
for ($j = $k; $j < $this->n; ++$j) { |
if ($this->QR[$k][$k] != 0) { |
$s = 0.0; |
for ($i = $k; $i < $this->m; ++$i) { |
$s += $this->QR[$i][$k] * $Q[$i][$j]; |
} |
$s = -$s/$this->QR[$k][$k]; |
for ($i = $k; $i < $this->m; ++$i) { |
$Q[$i][$j] += $s * $this->QR[$i][$k]; |
} |
} |
} |
} |
/* |
for($i = 0; $i < count($Q); ++$i) { |
for($j = 0; $j < count($Q); ++$j) { |
if(! isset($Q[$i][$j]) ) { |
$Q[$i][$j] = 0; |
} |
} |
} |
*/ |
return new PHPExcel_Shared_JAMA_Matrix($Q); |
} // function getQ() |
/** |
* Least squares solution of A*X = B |
* |
* @param Matrix $B A Matrix with as many rows as A and any number of columns. |
* @return Matrix Matrix that minimizes the two norm of Q*R*X-B. |
*/ |
public function solve($B) { |
if ($B->getRowDimension() == $this->m) { |
if ($this->isFullRank()) { |
// Copy right hand side |
$nx = $B->getColumnDimension(); |
$X = $B->getArrayCopy(); |
// Compute Y = transpose(Q)*B |
for ($k = 0; $k < $this->n; ++$k) { |
for ($j = 0; $j < $nx; ++$j) { |
$s = 0.0; |
for ($i = $k; $i < $this->m; ++$i) { |
$s += $this->QR[$i][$k] * $X[$i][$j]; |
} |
$s = -$s/$this->QR[$k][$k]; |
for ($i = $k; $i < $this->m; ++$i) { |
$X[$i][$j] += $s * $this->QR[$i][$k]; |
} |
} |
} |
// Solve R*X = Y; |
for ($k = $this->n-1; $k >= 0; --$k) { |
for ($j = 0; $j < $nx; ++$j) { |
$X[$k][$j] /= $this->Rdiag[$k]; |
} |
for ($i = 0; $i < $k; ++$i) { |
for ($j = 0; $j < $nx; ++$j) { |
$X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k]; |
} |
} |
} |
$X = new PHPExcel_Shared_JAMA_Matrix($X); |
return ($X->getMatrix(0, $this->n-1, 0, $nx)); |
} else { |
throw new PHPExcel_Calculation_Exception(self::MatrixRankException); |
} |
} else { |
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); |
} |
} // function solve() |
} // PHPExcel_Shared_JAMA_class QRDecomposition |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php |
---|
New file |
0,0 → 1,862 |
<?php |
/** |
* @package JAMA |
* |
* Class to obtain eigenvalues and eigenvectors of a real matrix. |
* |
* If A is symmetric, then A = V*D*V' where the eigenvalue matrix D |
* is diagonal and the eigenvector matrix V is orthogonal (i.e. |
* A = V.times(D.times(V.transpose())) and V.times(V.transpose()) |
* equals the identity matrix). |
* |
* If A is not symmetric, then the eigenvalue matrix D is block diagonal |
* with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues, |
* lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda]. The |
* columns of V represent the eigenvectors in the sense that A*V = V*D, |
* i.e. A.times(V) equals V.times(D). The matrix V may be badly |
* conditioned, or even singular, so the validity of the equation |
* A = V*D*inverse(V) depends upon V.cond(). |
* |
* @author Paul Meagher |
* @license PHP v3.0 |
* @version 1.1 |
*/ |
class EigenvalueDecomposition { |
/** |
* Row and column dimension (square matrix). |
* @var int |
*/ |
private $n; |
/** |
* Internal symmetry flag. |
* @var int |
*/ |
private $issymmetric; |
/** |
* Arrays for internal storage of eigenvalues. |
* @var array |
*/ |
private $d = array(); |
private $e = array(); |
/** |
* Array for internal storage of eigenvectors. |
* @var array |
*/ |
private $V = array(); |
/** |
* Array for internal storage of nonsymmetric Hessenberg form. |
* @var array |
*/ |
private $H = array(); |
/** |
* Working storage for nonsymmetric algorithm. |
* @var array |
*/ |
private $ort; |
/** |
* Used for complex scalar division. |
* @var float |
*/ |
private $cdivr; |
private $cdivi; |
/** |
* Symmetric Householder reduction to tridiagonal form. |
* |
* @access private |
*/ |
private function tred2 () { |
// This is derived from the Algol procedures tred2 by |
// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for |
// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding |
// Fortran subroutine in EISPACK. |
$this->d = $this->V[$this->n-1]; |
// Householder reduction to tridiagonal form. |
for ($i = $this->n-1; $i > 0; --$i) { |
$i_ = $i -1; |
// Scale to avoid under/overflow. |
$h = $scale = 0.0; |
$scale += array_sum(array_map(abs, $this->d)); |
if ($scale == 0.0) { |
$this->e[$i] = $this->d[$i_]; |
$this->d = array_slice($this->V[$i_], 0, $i_); |
for ($j = 0; $j < $i; ++$j) { |
$this->V[$j][$i] = $this->V[$i][$j] = 0.0; |
} |
} else { |
// Generate Householder vector. |
for ($k = 0; $k < $i; ++$k) { |
$this->d[$k] /= $scale; |
$h += pow($this->d[$k], 2); |
} |
$f = $this->d[$i_]; |
$g = sqrt($h); |
if ($f > 0) { |
$g = -$g; |
} |
$this->e[$i] = $scale * $g; |
$h = $h - $f * $g; |
$this->d[$i_] = $f - $g; |
for ($j = 0; $j < $i; ++$j) { |
$this->e[$j] = 0.0; |
} |
// Apply similarity transformation to remaining columns. |
for ($j = 0; $j < $i; ++$j) { |
$f = $this->d[$j]; |
$this->V[$j][$i] = $f; |
$g = $this->e[$j] + $this->V[$j][$j] * $f; |
for ($k = $j+1; $k <= $i_; ++$k) { |
$g += $this->V[$k][$j] * $this->d[$k]; |
$this->e[$k] += $this->V[$k][$j] * $f; |
} |
$this->e[$j] = $g; |
} |
$f = 0.0; |
for ($j = 0; $j < $i; ++$j) { |
$this->e[$j] /= $h; |
$f += $this->e[$j] * $this->d[$j]; |
} |
$hh = $f / (2 * $h); |
for ($j=0; $j < $i; ++$j) { |
$this->e[$j] -= $hh * $this->d[$j]; |
} |
for ($j = 0; $j < $i; ++$j) { |
$f = $this->d[$j]; |
$g = $this->e[$j]; |
for ($k = $j; $k <= $i_; ++$k) { |
$this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]); |
} |
$this->d[$j] = $this->V[$i-1][$j]; |
$this->V[$i][$j] = 0.0; |
} |
} |
$this->d[$i] = $h; |
} |
// Accumulate transformations. |
for ($i = 0; $i < $this->n-1; ++$i) { |
$this->V[$this->n-1][$i] = $this->V[$i][$i]; |
$this->V[$i][$i] = 1.0; |
$h = $this->d[$i+1]; |
if ($h != 0.0) { |
for ($k = 0; $k <= $i; ++$k) { |
$this->d[$k] = $this->V[$k][$i+1] / $h; |
} |
for ($j = 0; $j <= $i; ++$j) { |
$g = 0.0; |
for ($k = 0; $k <= $i; ++$k) { |
$g += $this->V[$k][$i+1] * $this->V[$k][$j]; |
} |
for ($k = 0; $k <= $i; ++$k) { |
$this->V[$k][$j] -= $g * $this->d[$k]; |
} |
} |
} |
for ($k = 0; $k <= $i; ++$k) { |
$this->V[$k][$i+1] = 0.0; |
} |
} |
$this->d = $this->V[$this->n-1]; |
$this->V[$this->n-1] = array_fill(0, $j, 0.0); |
$this->V[$this->n-1][$this->n-1] = 1.0; |
$this->e[0] = 0.0; |
} |
/** |
* Symmetric tridiagonal QL algorithm. |
* |
* This is derived from the Algol procedures tql2, by |
* Bowdler, Martin, Reinsch, and Wilkinson, Handbook for |
* Auto. Comp., Vol.ii-Linear Algebra, and the corresponding |
* Fortran subroutine in EISPACK. |
* |
* @access private |
*/ |
private function tql2() { |
for ($i = 1; $i < $this->n; ++$i) { |
$this->e[$i-1] = $this->e[$i]; |
} |
$this->e[$this->n-1] = 0.0; |
$f = 0.0; |
$tst1 = 0.0; |
$eps = pow(2.0,-52.0); |
for ($l = 0; $l < $this->n; ++$l) { |
// Find small subdiagonal element |
$tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l])); |
$m = $l; |
while ($m < $this->n) { |
if (abs($this->e[$m]) <= $eps * $tst1) |
break; |
++$m; |
} |
// If m == l, $this->d[l] is an eigenvalue, |
// otherwise, iterate. |
if ($m > $l) { |
$iter = 0; |
do { |
// Could check iteration count here. |
$iter += 1; |
// Compute implicit shift |
$g = $this->d[$l]; |
$p = ($this->d[$l+1] - $g) / (2.0 * $this->e[$l]); |
$r = hypo($p, 1.0); |
if ($p < 0) |
$r *= -1; |
$this->d[$l] = $this->e[$l] / ($p + $r); |
$this->d[$l+1] = $this->e[$l] * ($p + $r); |
$dl1 = $this->d[$l+1]; |
$h = $g - $this->d[$l]; |
for ($i = $l + 2; $i < $this->n; ++$i) |
$this->d[$i] -= $h; |
$f += $h; |
// Implicit QL transformation. |
$p = $this->d[$m]; |
$c = 1.0; |
$c2 = $c3 = $c; |
$el1 = $this->e[$l + 1]; |
$s = $s2 = 0.0; |
for ($i = $m-1; $i >= $l; --$i) { |
$c3 = $c2; |
$c2 = $c; |
$s2 = $s; |
$g = $c * $this->e[$i]; |
$h = $c * $p; |
$r = hypo($p, $this->e[$i]); |
$this->e[$i+1] = $s * $r; |
$s = $this->e[$i] / $r; |
$c = $p / $r; |
$p = $c * $this->d[$i] - $s * $g; |
$this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]); |
// Accumulate transformation. |
for ($k = 0; $k < $this->n; ++$k) { |
$h = $this->V[$k][$i+1]; |
$this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h; |
$this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h; |
} |
} |
$p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1; |
$this->e[$l] = $s * $p; |
$this->d[$l] = $c * $p; |
// Check for convergence. |
} while (abs($this->e[$l]) > $eps * $tst1); |
} |
$this->d[$l] = $this->d[$l] + $f; |
$this->e[$l] = 0.0; |
} |
// Sort eigenvalues and corresponding vectors. |
for ($i = 0; $i < $this->n - 1; ++$i) { |
$k = $i; |
$p = $this->d[$i]; |
for ($j = $i+1; $j < $this->n; ++$j) { |
if ($this->d[$j] < $p) { |
$k = $j; |
$p = $this->d[$j]; |
} |
} |
if ($k != $i) { |
$this->d[$k] = $this->d[$i]; |
$this->d[$i] = $p; |
for ($j = 0; $j < $this->n; ++$j) { |
$p = $this->V[$j][$i]; |
$this->V[$j][$i] = $this->V[$j][$k]; |
$this->V[$j][$k] = $p; |
} |
} |
} |
} |
/** |
* Nonsymmetric reduction to Hessenberg form. |
* |
* This is derived from the Algol procedures orthes and ortran, |
* by Martin and Wilkinson, Handbook for Auto. Comp., |
* Vol.ii-Linear Algebra, and the corresponding |
* Fortran subroutines in EISPACK. |
* |
* @access private |
*/ |
private function orthes () { |
$low = 0; |
$high = $this->n-1; |
for ($m = $low+1; $m <= $high-1; ++$m) { |
// Scale column. |
$scale = 0.0; |
for ($i = $m; $i <= $high; ++$i) { |
$scale = $scale + abs($this->H[$i][$m-1]); |
} |
if ($scale != 0.0) { |
// Compute Householder transformation. |
$h = 0.0; |
for ($i = $high; $i >= $m; --$i) { |
$this->ort[$i] = $this->H[$i][$m-1] / $scale; |
$h += $this->ort[$i] * $this->ort[$i]; |
} |
$g = sqrt($h); |
if ($this->ort[$m] > 0) { |
$g *= -1; |
} |
$h -= $this->ort[$m] * $g; |
$this->ort[$m] -= $g; |
// Apply Householder similarity transformation |
// H = (I -u * u' / h) * H * (I -u * u') / h) |
for ($j = $m; $j < $this->n; ++$j) { |
$f = 0.0; |
for ($i = $high; $i >= $m; --$i) { |
$f += $this->ort[$i] * $this->H[$i][$j]; |
} |
$f /= $h; |
for ($i = $m; $i <= $high; ++$i) { |
$this->H[$i][$j] -= $f * $this->ort[$i]; |
} |
} |
for ($i = 0; $i <= $high; ++$i) { |
$f = 0.0; |
for ($j = $high; $j >= $m; --$j) { |
$f += $this->ort[$j] * $this->H[$i][$j]; |
} |
$f = $f / $h; |
for ($j = $m; $j <= $high; ++$j) { |
$this->H[$i][$j] -= $f * $this->ort[$j]; |
} |
} |
$this->ort[$m] = $scale * $this->ort[$m]; |
$this->H[$m][$m-1] = $scale * $g; |
} |
} |
// Accumulate transformations (Algol's ortran). |
for ($i = 0; $i < $this->n; ++$i) { |
for ($j = 0; $j < $this->n; ++$j) { |
$this->V[$i][$j] = ($i == $j ? 1.0 : 0.0); |
} |
} |
for ($m = $high-1; $m >= $low+1; --$m) { |
if ($this->H[$m][$m-1] != 0.0) { |
for ($i = $m+1; $i <= $high; ++$i) { |
$this->ort[$i] = $this->H[$i][$m-1]; |
} |
for ($j = $m; $j <= $high; ++$j) { |
$g = 0.0; |
for ($i = $m; $i <= $high; ++$i) { |
$g += $this->ort[$i] * $this->V[$i][$j]; |
} |
// Double division avoids possible underflow |
$g = ($g / $this->ort[$m]) / $this->H[$m][$m-1]; |
for ($i = $m; $i <= $high; ++$i) { |
$this->V[$i][$j] += $g * $this->ort[$i]; |
} |
} |
} |
} |
} |
/** |
* Performs complex division. |
* |
* @access private |
*/ |
private function cdiv($xr, $xi, $yr, $yi) { |
if (abs($yr) > abs($yi)) { |
$r = $yi / $yr; |
$d = $yr + $r * $yi; |
$this->cdivr = ($xr + $r * $xi) / $d; |
$this->cdivi = ($xi - $r * $xr) / $d; |
} else { |
$r = $yr / $yi; |
$d = $yi + $r * $yr; |
$this->cdivr = ($r * $xr + $xi) / $d; |
$this->cdivi = ($r * $xi - $xr) / $d; |
} |
} |
/** |
* Nonsymmetric reduction from Hessenberg to real Schur form. |
* |
* Code is derived from the Algol procedure hqr2, |
* by Martin and Wilkinson, Handbook for Auto. Comp., |
* Vol.ii-Linear Algebra, and the corresponding |
* Fortran subroutine in EISPACK. |
* |
* @access private |
*/ |
private function hqr2 () { |
// Initialize |
$nn = $this->n; |
$n = $nn - 1; |
$low = 0; |
$high = $nn - 1; |
$eps = pow(2.0, -52.0); |
$exshift = 0.0; |
$p = $q = $r = $s = $z = 0; |
// Store roots isolated by balanc and compute matrix norm |
$norm = 0.0; |
for ($i = 0; $i < $nn; ++$i) { |
if (($i < $low) OR ($i > $high)) { |
$this->d[$i] = $this->H[$i][$i]; |
$this->e[$i] = 0.0; |
} |
for ($j = max($i-1, 0); $j < $nn; ++$j) { |
$norm = $norm + abs($this->H[$i][$j]); |
} |
} |
// Outer loop over eigenvalue index |
$iter = 0; |
while ($n >= $low) { |
// Look for single small sub-diagonal element |
$l = $n; |
while ($l > $low) { |
$s = abs($this->H[$l-1][$l-1]) + abs($this->H[$l][$l]); |
if ($s == 0.0) { |
$s = $norm; |
} |
if (abs($this->H[$l][$l-1]) < $eps * $s) { |
break; |
} |
--$l; |
} |
// Check for convergence |
// One root found |
if ($l == $n) { |
$this->H[$n][$n] = $this->H[$n][$n] + $exshift; |
$this->d[$n] = $this->H[$n][$n]; |
$this->e[$n] = 0.0; |
--$n; |
$iter = 0; |
// Two roots found |
} else if ($l == $n-1) { |
$w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; |
$p = ($this->H[$n-1][$n-1] - $this->H[$n][$n]) / 2.0; |
$q = $p * $p + $w; |
$z = sqrt(abs($q)); |
$this->H[$n][$n] = $this->H[$n][$n] + $exshift; |
$this->H[$n-1][$n-1] = $this->H[$n-1][$n-1] + $exshift; |
$x = $this->H[$n][$n]; |
// Real pair |
if ($q >= 0) { |
if ($p >= 0) { |
$z = $p + $z; |
} else { |
$z = $p - $z; |
} |
$this->d[$n-1] = $x + $z; |
$this->d[$n] = $this->d[$n-1]; |
if ($z != 0.0) { |
$this->d[$n] = $x - $w / $z; |
} |
$this->e[$n-1] = 0.0; |
$this->e[$n] = 0.0; |
$x = $this->H[$n][$n-1]; |
$s = abs($x) + abs($z); |
$p = $x / $s; |
$q = $z / $s; |
$r = sqrt($p * $p + $q * $q); |
$p = $p / $r; |
$q = $q / $r; |
// Row modification |
for ($j = $n-1; $j < $nn; ++$j) { |
$z = $this->H[$n-1][$j]; |
$this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j]; |
$this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z; |
} |
// Column modification |
for ($i = 0; $i <= n; ++$i) { |
$z = $this->H[$i][$n-1]; |
$this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n]; |
$this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z; |
} |
// Accumulate transformations |
for ($i = $low; $i <= $high; ++$i) { |
$z = $this->V[$i][$n-1]; |
$this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n]; |
$this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z; |
} |
// Complex pair |
} else { |
$this->d[$n-1] = $x + $p; |
$this->d[$n] = $x + $p; |
$this->e[$n-1] = $z; |
$this->e[$n] = -$z; |
} |
$n = $n - 2; |
$iter = 0; |
// No convergence yet |
} else { |
// Form shift |
$x = $this->H[$n][$n]; |
$y = 0.0; |
$w = 0.0; |
if ($l < $n) { |
$y = $this->H[$n-1][$n-1]; |
$w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; |
} |
// Wilkinson's original ad hoc shift |
if ($iter == 10) { |
$exshift += $x; |
for ($i = $low; $i <= $n; ++$i) { |
$this->H[$i][$i] -= $x; |
} |
$s = abs($this->H[$n][$n-1]) + abs($this->H[$n-1][$n-2]); |
$x = $y = 0.75 * $s; |
$w = -0.4375 * $s * $s; |
} |
// MATLAB's new ad hoc shift |
if ($iter == 30) { |
$s = ($y - $x) / 2.0; |
$s = $s * $s + $w; |
if ($s > 0) { |
$s = sqrt($s); |
if ($y < $x) { |
$s = -$s; |
} |
$s = $x - $w / (($y - $x) / 2.0 + $s); |
for ($i = $low; $i <= $n; ++$i) { |
$this->H[$i][$i] -= $s; |
} |
$exshift += $s; |
$x = $y = $w = 0.964; |
} |
} |
// Could check iteration count here. |
$iter = $iter + 1; |
// Look for two consecutive small sub-diagonal elements |
$m = $n - 2; |
while ($m >= $l) { |
$z = $this->H[$m][$m]; |
$r = $x - $z; |
$s = $y - $z; |
$p = ($r * $s - $w) / $this->H[$m+1][$m] + $this->H[$m][$m+1]; |
$q = $this->H[$m+1][$m+1] - $z - $r - $s; |
$r = $this->H[$m+2][$m+1]; |
$s = abs($p) + abs($q) + abs($r); |
$p = $p / $s; |
$q = $q / $s; |
$r = $r / $s; |
if ($m == $l) { |
break; |
} |
if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) < |
$eps * (abs($p) * (abs($this->H[$m-1][$m-1]) + abs($z) + abs($this->H[$m+1][$m+1])))) { |
break; |
} |
--$m; |
} |
for ($i = $m + 2; $i <= $n; ++$i) { |
$this->H[$i][$i-2] = 0.0; |
if ($i > $m+2) { |
$this->H[$i][$i-3] = 0.0; |
} |
} |
// Double QR step involving rows l:n and columns m:n |
for ($k = $m; $k <= $n-1; ++$k) { |
$notlast = ($k != $n-1); |
if ($k != $m) { |
$p = $this->H[$k][$k-1]; |
$q = $this->H[$k+1][$k-1]; |
$r = ($notlast ? $this->H[$k+2][$k-1] : 0.0); |
$x = abs($p) + abs($q) + abs($r); |
if ($x != 0.0) { |
$p = $p / $x; |
$q = $q / $x; |
$r = $r / $x; |
} |
} |
if ($x == 0.0) { |
break; |
} |
$s = sqrt($p * $p + $q * $q + $r * $r); |
if ($p < 0) { |
$s = -$s; |
} |
if ($s != 0) { |
if ($k != $m) { |
$this->H[$k][$k-1] = -$s * $x; |
} elseif ($l != $m) { |
$this->H[$k][$k-1] = -$this->H[$k][$k-1]; |
} |
$p = $p + $s; |
$x = $p / $s; |
$y = $q / $s; |
$z = $r / $s; |
$q = $q / $p; |
$r = $r / $p; |
// Row modification |
for ($j = $k; $j < $nn; ++$j) { |
$p = $this->H[$k][$j] + $q * $this->H[$k+1][$j]; |
if ($notlast) { |
$p = $p + $r * $this->H[$k+2][$j]; |
$this->H[$k+2][$j] = $this->H[$k+2][$j] - $p * $z; |
} |
$this->H[$k][$j] = $this->H[$k][$j] - $p * $x; |
$this->H[$k+1][$j] = $this->H[$k+1][$j] - $p * $y; |
} |
// Column modification |
for ($i = 0; $i <= min($n, $k+3); ++$i) { |
$p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k+1]; |
if ($notlast) { |
$p = $p + $z * $this->H[$i][$k+2]; |
$this->H[$i][$k+2] = $this->H[$i][$k+2] - $p * $r; |
} |
$this->H[$i][$k] = $this->H[$i][$k] - $p; |
$this->H[$i][$k+1] = $this->H[$i][$k+1] - $p * $q; |
} |
// Accumulate transformations |
for ($i = $low; $i <= $high; ++$i) { |
$p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k+1]; |
if ($notlast) { |
$p = $p + $z * $this->V[$i][$k+2]; |
$this->V[$i][$k+2] = $this->V[$i][$k+2] - $p * $r; |
} |
$this->V[$i][$k] = $this->V[$i][$k] - $p; |
$this->V[$i][$k+1] = $this->V[$i][$k+1] - $p * $q; |
} |
} // ($s != 0) |
} // k loop |
} // check convergence |
} // while ($n >= $low) |
// Backsubstitute to find vectors of upper triangular form |
if ($norm == 0.0) { |
return; |
} |
for ($n = $nn-1; $n >= 0; --$n) { |
$p = $this->d[$n]; |
$q = $this->e[$n]; |
// Real vector |
if ($q == 0) { |
$l = $n; |
$this->H[$n][$n] = 1.0; |
for ($i = $n-1; $i >= 0; --$i) { |
$w = $this->H[$i][$i] - $p; |
$r = 0.0; |
for ($j = $l; $j <= $n; ++$j) { |
$r = $r + $this->H[$i][$j] * $this->H[$j][$n]; |
} |
if ($this->e[$i] < 0.0) { |
$z = $w; |
$s = $r; |
} else { |
$l = $i; |
if ($this->e[$i] == 0.0) { |
if ($w != 0.0) { |
$this->H[$i][$n] = -$r / $w; |
} else { |
$this->H[$i][$n] = -$r / ($eps * $norm); |
} |
// Solve real equations |
} else { |
$x = $this->H[$i][$i+1]; |
$y = $this->H[$i+1][$i]; |
$q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i]; |
$t = ($x * $s - $z * $r) / $q; |
$this->H[$i][$n] = $t; |
if (abs($x) > abs($z)) { |
$this->H[$i+1][$n] = (-$r - $w * $t) / $x; |
} else { |
$this->H[$i+1][$n] = (-$s - $y * $t) / $z; |
} |
} |
// Overflow control |
$t = abs($this->H[$i][$n]); |
if (($eps * $t) * $t > 1) { |
for ($j = $i; $j <= $n; ++$j) { |
$this->H[$j][$n] = $this->H[$j][$n] / $t; |
} |
} |
} |
} |
// Complex vector |
} else if ($q < 0) { |
$l = $n-1; |
// Last vector component imaginary so matrix is triangular |
if (abs($this->H[$n][$n-1]) > abs($this->H[$n-1][$n])) { |
$this->H[$n-1][$n-1] = $q / $this->H[$n][$n-1]; |
$this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n-1]; |
} else { |
$this->cdiv(0.0, -$this->H[$n-1][$n], $this->H[$n-1][$n-1] - $p, $q); |
$this->H[$n-1][$n-1] = $this->cdivr; |
$this->H[$n-1][$n] = $this->cdivi; |
} |
$this->H[$n][$n-1] = 0.0; |
$this->H[$n][$n] = 1.0; |
for ($i = $n-2; $i >= 0; --$i) { |
// double ra,sa,vr,vi; |
$ra = 0.0; |
$sa = 0.0; |
for ($j = $l; $j <= $n; ++$j) { |
$ra = $ra + $this->H[$i][$j] * $this->H[$j][$n-1]; |
$sa = $sa + $this->H[$i][$j] * $this->H[$j][$n]; |
} |
$w = $this->H[$i][$i] - $p; |
if ($this->e[$i] < 0.0) { |
$z = $w; |
$r = $ra; |
$s = $sa; |
} else { |
$l = $i; |
if ($this->e[$i] == 0) { |
$this->cdiv(-$ra, -$sa, $w, $q); |
$this->H[$i][$n-1] = $this->cdivr; |
$this->H[$i][$n] = $this->cdivi; |
} else { |
// Solve complex equations |
$x = $this->H[$i][$i+1]; |
$y = $this->H[$i+1][$i]; |
$vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q; |
$vi = ($this->d[$i] - $p) * 2.0 * $q; |
if ($vr == 0.0 & $vi == 0.0) { |
$vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z)); |
} |
$this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi); |
$this->H[$i][$n-1] = $this->cdivr; |
$this->H[$i][$n] = $this->cdivi; |
if (abs($x) > (abs($z) + abs($q))) { |
$this->H[$i+1][$n-1] = (-$ra - $w * $this->H[$i][$n-1] + $q * $this->H[$i][$n]) / $x; |
$this->H[$i+1][$n] = (-$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n-1]) / $x; |
} else { |
$this->cdiv(-$r - $y * $this->H[$i][$n-1], -$s - $y * $this->H[$i][$n], $z, $q); |
$this->H[$i+1][$n-1] = $this->cdivr; |
$this->H[$i+1][$n] = $this->cdivi; |
} |
} |
// Overflow control |
$t = max(abs($this->H[$i][$n-1]),abs($this->H[$i][$n])); |
if (($eps * $t) * $t > 1) { |
for ($j = $i; $j <= $n; ++$j) { |
$this->H[$j][$n-1] = $this->H[$j][$n-1] / $t; |
$this->H[$j][$n] = $this->H[$j][$n] / $t; |
} |
} |
} // end else |
} // end for |
} // end else for complex case |
} // end for |
// Vectors of isolated roots |
for ($i = 0; $i < $nn; ++$i) { |
if ($i < $low | $i > $high) { |
for ($j = $i; $j < $nn; ++$j) { |
$this->V[$i][$j] = $this->H[$i][$j]; |
} |
} |
} |
// Back transformation to get eigenvectors of original matrix |
for ($j = $nn-1; $j >= $low; --$j) { |
for ($i = $low; $i <= $high; ++$i) { |
$z = 0.0; |
for ($k = $low; $k <= min($j,$high); ++$k) { |
$z = $z + $this->V[$i][$k] * $this->H[$k][$j]; |
} |
$this->V[$i][$j] = $z; |
} |
} |
} // end hqr2 |
/** |
* Constructor: Check for symmetry, then construct the eigenvalue decomposition |
* |
* @access public |
* @param A Square matrix |
* @return Structure to access D and V. |
*/ |
public function __construct($Arg) { |
$this->A = $Arg->getArray(); |
$this->n = $Arg->getColumnDimension(); |
$issymmetric = true; |
for ($j = 0; ($j < $this->n) & $issymmetric; ++$j) { |
for ($i = 0; ($i < $this->n) & $issymmetric; ++$i) { |
$issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]); |
} |
} |
if ($issymmetric) { |
$this->V = $this->A; |
// Tridiagonalize. |
$this->tred2(); |
// Diagonalize. |
$this->tql2(); |
} else { |
$this->H = $this->A; |
$this->ort = array(); |
// Reduce to Hessenberg form. |
$this->orthes(); |
// Reduce Hessenberg to real Schur form. |
$this->hqr2(); |
} |
} |
/** |
* Return the eigenvector matrix |
* |
* @access public |
* @return V |
*/ |
public function getV() { |
return new Matrix($this->V, $this->n, $this->n); |
} |
/** |
* Return the real parts of the eigenvalues |
* |
* @access public |
* @return real(diag(D)) |
*/ |
public function getRealEigenvalues() { |
return $this->d; |
} |
/** |
* Return the imaginary parts of the eigenvalues |
* |
* @access public |
* @return imag(diag(D)) |
*/ |
public function getImagEigenvalues() { |
return $this->e; |
} |
/** |
* Return the block diagonal eigenvalue matrix |
* |
* @access public |
* @return D |
*/ |
public function getD() { |
for ($i = 0; $i < $this->n; ++$i) { |
$D[$i] = array_fill(0, $this->n, 0.0); |
$D[$i][$i] = $this->d[$i]; |
if ($this->e[$i] == 0) { |
continue; |
} |
$o = ($this->e[$i] > 0) ? $i + 1 : $i - 1; |
$D[$i][$o] = $this->e[$i]; |
} |
return new Matrix($D); |
} |
} // class EigenvalueDecomposition |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/Matrix.php |
---|
New file |
0,0 → 1,1059 |
<?php |
/** |
* @package JAMA |
*/ |
/** PHPExcel root directory */ |
if (!defined('PHPEXCEL_ROOT')) { |
/** |
* @ignore |
*/ |
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); |
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); |
} |
/* |
* Matrix class |
* |
* @author Paul Meagher |
* @author Michael Bommarito |
* @author Lukasz Karapuda |
* @author Bartek Matosiuk |
* @version 1.8 |
* @license PHP v3.0 |
* @see http://math.nist.gov/javanumerics/jama/ |
*/ |
class PHPExcel_Shared_JAMA_Matrix { |
const PolymorphicArgumentException = "Invalid argument pattern for polymorphic function."; |
const ArgumentTypeException = "Invalid argument type."; |
const ArgumentBoundsException = "Invalid argument range."; |
const MatrixDimensionException = "Matrix dimensions are not equal."; |
const ArrayLengthException = "Array length must be a multiple of m."; |
/** |
* Matrix storage |
* |
* @var array |
* @access public |
*/ |
public $A = array(); |
/** |
* Matrix row dimension |
* |
* @var int |
* @access private |
*/ |
private $m; |
/** |
* Matrix column dimension |
* |
* @var int |
* @access private |
*/ |
private $n; |
/** |
* Polymorphic constructor |
* |
* As PHP has no support for polymorphic constructors, we hack our own sort of polymorphism using func_num_args, func_get_arg, and gettype. In essence, we're just implementing a simple RTTI filter and calling the appropriate constructor. |
*/ |
public function __construct() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
//Rectangular matrix - m x n initialized from 2D array |
case 'array': |
$this->m = count($args[0]); |
$this->n = count($args[0][0]); |
$this->A = $args[0]; |
break; |
//Square matrix - n x n |
case 'integer': |
$this->m = $args[0]; |
$this->n = $args[0]; |
$this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); |
break; |
//Rectangular matrix - m x n |
case 'integer,integer': |
$this->m = $args[0]; |
$this->n = $args[1]; |
$this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); |
break; |
//Rectangular matrix - m x n initialized from packed array |
case 'array,integer': |
$this->m = $args[1]; |
if ($this->m != 0) { |
$this->n = count($args[0]) / $this->m; |
} else { |
$this->n = 0; |
} |
if (($this->m * $this->n) == count($args[0])) { |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$this->A[$i][$j] = $args[0][$i + $j * $this->m]; |
} |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::ArrayLengthException); |
} |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function __construct() |
/** |
* getArray |
* |
* @return array Matrix array |
*/ |
public function getArray() { |
return $this->A; |
} // function getArray() |
/** |
* getRowDimension |
* |
* @return int Row dimension |
*/ |
public function getRowDimension() { |
return $this->m; |
} // function getRowDimension() |
/** |
* getColumnDimension |
* |
* @return int Column dimension |
*/ |
public function getColumnDimension() { |
return $this->n; |
} // function getColumnDimension() |
/** |
* get |
* |
* Get the i,j-th element of the matrix. |
* @param int $i Row position |
* @param int $j Column position |
* @return mixed Element (int/float/double) |
*/ |
public function get($i = null, $j = null) { |
return $this->A[$i][$j]; |
} // function get() |
/** |
* getMatrix |
* |
* Get a submatrix |
* @param int $i0 Initial row index |
* @param int $iF Final row index |
* @param int $j0 Initial column index |
* @param int $jF Final column index |
* @return Matrix Submatrix |
*/ |
public function getMatrix() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
//A($i0...; $j0...) |
case 'integer,integer': |
list($i0, $j0) = $args; |
if ($i0 >= 0) { $m = $this->m - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
$R = new PHPExcel_Shared_JAMA_Matrix($m, $n); |
for($i = $i0; $i < $this->m; ++$i) { |
for($j = $j0; $j < $this->n; ++$j) { |
$R->set($i, $j, $this->A[$i][$j]); |
} |
} |
return $R; |
break; |
//A($i0...$iF; $j0...$jF) |
case 'integer,integer,integer,integer': |
list($i0, $iF, $j0, $jF) = $args; |
if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
$R = new PHPExcel_Shared_JAMA_Matrix($m+1, $n+1); |
for($i = $i0; $i <= $iF; ++$i) { |
for($j = $j0; $j <= $jF; ++$j) { |
$R->set($i - $i0, $j - $j0, $this->A[$i][$j]); |
} |
} |
return $R; |
break; |
//$R = array of row indices; $C = array of column indices |
case 'array,array': |
list($RL, $CL) = $args; |
if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
$R = new PHPExcel_Shared_JAMA_Matrix($m, $n); |
for($i = 0; $i < $m; ++$i) { |
for($j = 0; $j < $n; ++$j) { |
$R->set($i - $i0, $j - $j0, $this->A[$RL[$i]][$CL[$j]]); |
} |
} |
return $R; |
break; |
//$RL = array of row indices; $CL = array of column indices |
case 'array,array': |
list($RL, $CL) = $args; |
if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
$R = new PHPExcel_Shared_JAMA_Matrix($m, $n); |
for($i = 0; $i < $m; ++$i) { |
for($j = 0; $j < $n; ++$j) { |
$R->set($i, $j, $this->A[$RL[$i]][$CL[$j]]); |
} |
} |
return $R; |
break; |
//A($i0...$iF); $CL = array of column indices |
case 'integer,integer,array': |
list($i0, $iF, $CL) = $args; |
if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
$R = new PHPExcel_Shared_JAMA_Matrix($m, $n); |
for($i = $i0; $i < $iF; ++$i) { |
for($j = 0; $j < $n; ++$j) { |
$R->set($i - $i0, $j, $this->A[$RL[$i]][$j]); |
} |
} |
return $R; |
break; |
//$RL = array of row indices |
case 'array,integer,integer': |
list($RL, $j0, $jF) = $args; |
if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } |
$R = new PHPExcel_Shared_JAMA_Matrix($m, $n+1); |
for($i = 0; $i < $m; ++$i) { |
for($j = $j0; $j <= $jF; ++$j) { |
$R->set($i, $j - $j0, $this->A[$RL[$i]][$j]); |
} |
} |
return $R; |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function getMatrix() |
/** |
* checkMatrixDimensions |
* |
* Is matrix B the same size? |
* @param Matrix $B Matrix B |
* @return boolean |
*/ |
public function checkMatrixDimensions($B = null) { |
if ($B instanceof PHPExcel_Shared_JAMA_Matrix) { |
if (($this->m == $B->getRowDimension()) && ($this->n == $B->getColumnDimension())) { |
return true; |
} else { |
throw new PHPExcel_Calculation_Exception(self::MatrixDimensionException); |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); |
} |
} // function checkMatrixDimensions() |
/** |
* set |
* |
* Set the i,j-th element of the matrix. |
* @param int $i Row position |
* @param int $j Column position |
* @param mixed $c Int/float/double value |
* @return mixed Element (int/float/double) |
*/ |
public function set($i = null, $j = null, $c = null) { |
// Optimized set version just has this |
$this->A[$i][$j] = $c; |
} // function set() |
/** |
* identity |
* |
* Generate an identity matrix. |
* @param int $m Row dimension |
* @param int $n Column dimension |
* @return Matrix Identity matrix |
*/ |
public function identity($m = null, $n = null) { |
return $this->diagonal($m, $n, 1); |
} // function identity() |
/** |
* diagonal |
* |
* Generate a diagonal matrix |
* @param int $m Row dimension |
* @param int $n Column dimension |
* @param mixed $c Diagonal value |
* @return Matrix Diagonal matrix |
*/ |
public function diagonal($m = null, $n = null, $c = 1) { |
$R = new PHPExcel_Shared_JAMA_Matrix($m, $n); |
for($i = 0; $i < $m; ++$i) { |
$R->set($i, $i, $c); |
} |
return $R; |
} // function diagonal() |
/** |
* getMatrixByRow |
* |
* Get a submatrix by row index/range |
* @param int $i0 Initial row index |
* @param int $iF Final row index |
* @return Matrix Submatrix |
*/ |
public function getMatrixByRow($i0 = null, $iF = null) { |
if (is_int($i0)) { |
if (is_int($iF)) { |
return $this->getMatrix($i0, 0, $iF + 1, $this->n); |
} else { |
return $this->getMatrix($i0, 0, $i0 + 1, $this->n); |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); |
} |
} // function getMatrixByRow() |
/** |
* getMatrixByCol |
* |
* Get a submatrix by column index/range |
* @param int $i0 Initial column index |
* @param int $iF Final column index |
* @return Matrix Submatrix |
*/ |
public function getMatrixByCol($j0 = null, $jF = null) { |
if (is_int($j0)) { |
if (is_int($jF)) { |
return $this->getMatrix(0, $j0, $this->m, $jF + 1); |
} else { |
return $this->getMatrix(0, $j0, $this->m, $j0 + 1); |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); |
} |
} // function getMatrixByCol() |
/** |
* transpose |
* |
* Tranpose matrix |
* @return Matrix Transposed matrix |
*/ |
public function transpose() { |
$R = new PHPExcel_Shared_JAMA_Matrix($this->n, $this->m); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$R->set($j, $i, $this->A[$i][$j]); |
} |
} |
return $R; |
} // function transpose() |
/** |
* trace |
* |
* Sum of diagonal elements |
* @return float Sum of diagonal elements |
*/ |
public function trace() { |
$s = 0; |
$n = min($this->m, $this->n); |
for($i = 0; $i < $n; ++$i) { |
$s += $this->A[$i][$i]; |
} |
return $s; |
} // function trace() |
/** |
* uminus |
* |
* Unary minus matrix -A |
* @return Matrix Unary minus matrix |
*/ |
public function uminus() { |
} // function uminus() |
/** |
* plus |
* |
* A + B |
* @param mixed $B Matrix/Array |
* @return Matrix Sum |
*/ |
public function plus() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]); |
} |
} |
return $M; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function plus() |
/** |
* plusEquals |
* |
* A = A + B |
* @param mixed $B Matrix/Array |
* @return Matrix Sum |
*/ |
public function plusEquals() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$validValues = True; |
$value = $M->get($i, $j); |
if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { |
$this->A[$i][$j] = trim($this->A[$i][$j],'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); |
} |
if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { |
$value = trim($value,'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); |
} |
if ($validValues) { |
$this->A[$i][$j] += $value; |
} else { |
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); |
} |
} |
} |
return $this; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function plusEquals() |
/** |
* minus |
* |
* A - B |
* @param mixed $B Matrix/Array |
* @return Matrix Sum |
*/ |
public function minus() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]); |
} |
} |
return $M; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function minus() |
/** |
* minusEquals |
* |
* A = A - B |
* @param mixed $B Matrix/Array |
* @return Matrix Sum |
*/ |
public function minusEquals() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$validValues = True; |
$value = $M->get($i, $j); |
if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { |
$this->A[$i][$j] = trim($this->A[$i][$j],'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); |
} |
if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { |
$value = trim($value,'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); |
} |
if ($validValues) { |
$this->A[$i][$j] -= $value; |
} else { |
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); |
} |
} |
} |
return $this; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function minusEquals() |
/** |
* arrayTimes |
* |
* Element-by-element multiplication |
* Cij = Aij * Bij |
* @param mixed $B Matrix/Array |
* @return Matrix Matrix Cij |
*/ |
public function arrayTimes() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]); |
} |
} |
return $M; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function arrayTimes() |
/** |
* arrayTimesEquals |
* |
* Element-by-element multiplication |
* Aij = Aij * Bij |
* @param mixed $B Matrix/Array |
* @return Matrix Matrix Aij |
*/ |
public function arrayTimesEquals() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$validValues = True; |
$value = $M->get($i, $j); |
if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { |
$this->A[$i][$j] = trim($this->A[$i][$j],'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); |
} |
if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { |
$value = trim($value,'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); |
} |
if ($validValues) { |
$this->A[$i][$j] *= $value; |
} else { |
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); |
} |
} |
} |
return $this; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function arrayTimesEquals() |
/** |
* arrayRightDivide |
* |
* Element-by-element right division |
* A / B |
* @param Matrix $B Matrix B |
* @return Matrix Division result |
*/ |
public function arrayRightDivide() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$validValues = True; |
$value = $M->get($i, $j); |
if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { |
$this->A[$i][$j] = trim($this->A[$i][$j],'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); |
} |
if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { |
$value = trim($value,'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); |
} |
if ($validValues) { |
if ($value == 0) { |
// Trap for Divide by Zero error |
$M->set($i, $j, '#DIV/0!'); |
} else { |
$M->set($i, $j, $this->A[$i][$j] / $value); |
} |
} else { |
$M->set($i, $j, PHPExcel_Calculation_Functions::NaN()); |
} |
} |
} |
return $M; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function arrayRightDivide() |
/** |
* arrayRightDivideEquals |
* |
* Element-by-element right division |
* Aij = Aij / Bij |
* @param mixed $B Matrix/Array |
* @return Matrix Matrix Aij |
*/ |
public function arrayRightDivideEquals() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j); |
} |
} |
return $M; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function arrayRightDivideEquals() |
/** |
* arrayLeftDivide |
* |
* Element-by-element Left division |
* A / B |
* @param Matrix $B Matrix B |
* @return Matrix Division result |
*/ |
public function arrayLeftDivide() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j]); |
} |
} |
return $M; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function arrayLeftDivide() |
/** |
* arrayLeftDivideEquals |
* |
* Element-by-element Left division |
* Aij = Aij / Bij |
* @param mixed $B Matrix/Array |
* @return Matrix Matrix Aij |
*/ |
public function arrayLeftDivideEquals() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j]; |
} |
} |
return $M; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function arrayLeftDivideEquals() |
/** |
* times |
* |
* Matrix multiplication |
* @param mixed $n Matrix/Array/Scalar |
* @return Matrix Product |
*/ |
public function times() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $B = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
if ($this->n == $B->m) { |
$C = new PHPExcel_Shared_JAMA_Matrix($this->m, $B->n); |
for($j = 0; $j < $B->n; ++$j) { |
for ($k = 0; $k < $this->n; ++$k) { |
$Bcolj[$k] = $B->A[$k][$j]; |
} |
for($i = 0; $i < $this->m; ++$i) { |
$Arowi = $this->A[$i]; |
$s = 0; |
for($k = 0; $k < $this->n; ++$k) { |
$s += $Arowi[$k] * $Bcolj[$k]; |
} |
$C->A[$i][$j] = $s; |
} |
} |
return $C; |
} else { |
throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionMismatch)); |
} |
break; |
case 'array': |
$B = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
if ($this->n == $B->m) { |
$C = new PHPExcel_Shared_JAMA_Matrix($this->m, $B->n); |
for($i = 0; $i < $C->m; ++$i) { |
for($j = 0; $j < $C->n; ++$j) { |
$s = "0"; |
for($k = 0; $k < $C->n; ++$k) { |
$s += $this->A[$i][$k] * $B->A[$k][$j]; |
} |
$C->A[$i][$j] = $s; |
} |
} |
return $C; |
} else { |
throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionMismatch)); |
} |
return $M; |
break; |
case 'integer': |
$C = new PHPExcel_Shared_JAMA_Matrix($this->A); |
for($i = 0; $i < $C->m; ++$i) { |
for($j = 0; $j < $C->n; ++$j) { |
$C->A[$i][$j] *= $args[0]; |
} |
} |
return $C; |
break; |
case 'double': |
$C = new PHPExcel_Shared_JAMA_Matrix($this->m, $this->n); |
for($i = 0; $i < $C->m; ++$i) { |
for($j = 0; $j < $C->n; ++$j) { |
$C->A[$i][$j] = $args[0] * $this->A[$i][$j]; |
} |
} |
return $C; |
break; |
case 'float': |
$C = new PHPExcel_Shared_JAMA_Matrix($this->A); |
for($i = 0; $i < $C->m; ++$i) { |
for($j = 0; $j < $C->n; ++$j) { |
$C->A[$i][$j] *= $args[0]; |
} |
} |
return $C; |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function times() |
/** |
* power |
* |
* A = A ^ B |
* @param mixed $B Matrix/Array |
* @return Matrix Sum |
*/ |
public function power() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
break; |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$validValues = True; |
$value = $M->get($i, $j); |
if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { |
$this->A[$i][$j] = trim($this->A[$i][$j],'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); |
} |
if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { |
$value = trim($value,'"'); |
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); |
} |
if ($validValues) { |
$this->A[$i][$j] = pow($this->A[$i][$j],$value); |
} else { |
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); |
} |
} |
} |
return $this; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function power() |
/** |
* concat |
* |
* A = A & B |
* @param mixed $B Matrix/Array |
* @return Matrix Sum |
*/ |
public function concat() { |
if (func_num_args() > 0) { |
$args = func_get_args(); |
$match = implode(",", array_map('gettype', $args)); |
switch($match) { |
case 'object': |
if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } |
case 'array': |
$M = new PHPExcel_Shared_JAMA_Matrix($args[0]); |
break; |
default: |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
break; |
} |
$this->checkMatrixDimensions($M); |
for($i = 0; $i < $this->m; ++$i) { |
for($j = 0; $j < $this->n; ++$j) { |
$this->A[$i][$j] = trim($this->A[$i][$j],'"').trim($M->get($i, $j),'"'); |
} |
} |
return $this; |
} else { |
throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); |
} |
} // function concat() |
/** |
* Solve A*X = B. |
* |
* @param Matrix $B Right hand side |
* @return Matrix ... Solution if A is square, least squares solution otherwise |
*/ |
public function solve($B) { |
if ($this->m == $this->n) { |
$LU = new PHPExcel_Shared_JAMA_LUDecomposition($this); |
return $LU->solve($B); |
} else { |
$QR = new QRDecomposition($this); |
return $QR->solve($B); |
} |
} // function solve() |
/** |
* Matrix inverse or pseudoinverse. |
* |
* @return Matrix ... Inverse(A) if A is square, pseudoinverse otherwise. |
*/ |
public function inverse() { |
return $this->solve($this->identity($this->m, $this->m)); |
} // function inverse() |
/** |
* det |
* |
* Calculate determinant |
* @return float Determinant |
*/ |
public function det() { |
$L = new PHPExcel_Shared_JAMA_LUDecomposition($this); |
return $L->det(); |
} // function det() |
} // class PHPExcel_Shared_JAMA_Matrix |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Maths.php |
---|
New file |
0,0 → 1,43 |
<?php |
/** |
* @package JAMA |
* |
* Pythagorean Theorem: |
* |
* a = 3 |
* b = 4 |
* r = sqrt(square(a) + square(b)) |
* r = 5 |
* |
* r = sqrt(a^2 + b^2) without under/overflow. |
*/ |
function hypo($a, $b) { |
if (abs($a) > abs($b)) { |
$r = $b / $a; |
$r = abs($a) * sqrt(1 + $r * $r); |
} elseif ($b != 0) { |
$r = $a / $b; |
$r = abs($b) * sqrt(1 + $r * $r); |
} else { |
$r = 0.0; |
} |
return $r; |
} // function hypo() |
/** |
* Mike Bommarito's version. |
* Compute n-dimensional hyotheneuse. |
* |
function hypot() { |
$s = 0; |
foreach (func_get_args() as $d) { |
if (is_numeric($d)) { |
$s += pow($d, 2); |
} else { |
throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); |
} |
} |
return sqrt($s); |
} |
*/ |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Error.php |
---|
New file |
0,0 → 1,82 |
<?php |
/** |
* @package JAMA |
* |
* Error handling |
* @author Michael Bommarito |
* @version 01292005 |
*/ |
//Language constant |
define('JAMALANG', 'EN'); |
//All errors may be defined by the following format: |
//define('ExceptionName', N); |
//$error['lang'][ExceptionName] = 'Error message'; |
$error = array(); |
/* |
I've used Babelfish and a little poor knowledge of Romance/Germanic languages for the translations here. |
Feel free to correct anything that looks amiss to you. |
*/ |
define('PolymorphicArgumentException', -1); |
$error['EN'][PolymorphicArgumentException] = "Invalid argument pattern for polymorphic function."; |
$error['FR'][PolymorphicArgumentException] = "Modèle inadmissible d'argument pour la fonction polymorphe.". |
$error['DE'][PolymorphicArgumentException] = "Unzulässiges Argumentmuster für polymorphe Funktion."; |
define('ArgumentTypeException', -2); |
$error['EN'][ArgumentTypeException] = "Invalid argument type."; |
$error['FR'][ArgumentTypeException] = "Type inadmissible d'argument."; |
$error['DE'][ArgumentTypeException] = "Unzulässige Argumentart."; |
define('ArgumentBoundsException', -3); |
$error['EN'][ArgumentBoundsException] = "Invalid argument range."; |
$error['FR'][ArgumentBoundsException] = "Gamme inadmissible d'argument."; |
$error['DE'][ArgumentBoundsException] = "Unzulässige Argumentstrecke."; |
define('MatrixDimensionException', -4); |
$error['EN'][MatrixDimensionException] = "Matrix dimensions are not equal."; |
$error['FR'][MatrixDimensionException] = "Les dimensions de Matrix ne sont pas égales."; |
$error['DE'][MatrixDimensionException] = "Matrixmaße sind nicht gleich."; |
define('PrecisionLossException', -5); |
$error['EN'][PrecisionLossException] = "Significant precision loss detected."; |
$error['FR'][PrecisionLossException] = "Perte significative de précision détectée."; |
$error['DE'][PrecisionLossException] = "Bedeutender Präzision Verlust ermittelte."; |
define('MatrixSPDException', -6); |
$error['EN'][MatrixSPDException] = "Can only perform operation on symmetric positive definite matrix."; |
$error['FR'][MatrixSPDException] = "Perte significative de précision détectée."; |
$error['DE'][MatrixSPDException] = "Bedeutender Präzision Verlust ermittelte."; |
define('MatrixSingularException', -7); |
$error['EN'][MatrixSingularException] = "Can only perform operation on singular matrix."; |
define('MatrixRankException', -8); |
$error['EN'][MatrixRankException] = "Can only perform operation on full-rank matrix."; |
define('ArrayLengthException', -9); |
$error['EN'][ArrayLengthException] = "Array length must be a multiple of m."; |
define('RowLengthException', -10); |
$error['EN'][RowLengthException] = "All rows must have the same length."; |
/** |
* Custom error handler |
* @param int $num Error number |
*/ |
function JAMAError($errorNumber = null) { |
global $error; |
if (isset($errorNumber)) { |
if (isset($error[JAMALANG][$errorNumber])) { |
return $error[JAMALANG][$errorNumber]; |
} else { |
return $error['EN'][$errorNumber]; |
} |
} else { |
return ("Invalid argument to JAMAError()"); |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php |
---|
New file |
0,0 → 1,258 |
<?php |
/** |
* @package JAMA |
* |
* For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n |
* unit lower triangular matrix L, an n-by-n upper triangular matrix U, |
* and a permutation vector piv of length m so that A(piv,:) = L*U. |
* If m < n, then L is m-by-m and U is m-by-n. |
* |
* The LU decompostion with pivoting always exists, even if the matrix is |
* singular, so the constructor will never fail. The primary use of the |
* LU decomposition is in the solution of square systems of simultaneous |
* linear equations. This will fail if isNonsingular() returns false. |
* |
* @author Paul Meagher |
* @author Bartosz Matosiuk |
* @author Michael Bommarito |
* @version 1.1 |
* @license PHP v3.0 |
*/ |
class PHPExcel_Shared_JAMA_LUDecomposition { |
const MatrixSingularException = "Can only perform operation on singular matrix."; |
const MatrixSquareException = "Mismatched Row dimension"; |
/** |
* Decomposition storage |
* @var array |
*/ |
private $LU = array(); |
/** |
* Row dimension. |
* @var int |
*/ |
private $m; |
/** |
* Column dimension. |
* @var int |
*/ |
private $n; |
/** |
* Pivot sign. |
* @var int |
*/ |
private $pivsign; |
/** |
* Internal storage of pivot vector. |
* @var array |
*/ |
private $piv = array(); |
/** |
* LU Decomposition constructor. |
* |
* @param $A Rectangular matrix |
* @return Structure to access L, U and piv. |
*/ |
public function __construct($A) { |
if ($A instanceof PHPExcel_Shared_JAMA_Matrix) { |
// Use a "left-looking", dot-product, Crout/Doolittle algorithm. |
$this->LU = $A->getArray(); |
$this->m = $A->getRowDimension(); |
$this->n = $A->getColumnDimension(); |
for ($i = 0; $i < $this->m; ++$i) { |
$this->piv[$i] = $i; |
} |
$this->pivsign = 1; |
$LUrowi = $LUcolj = array(); |
// Outer loop. |
for ($j = 0; $j < $this->n; ++$j) { |
// Make a copy of the j-th column to localize references. |
for ($i = 0; $i < $this->m; ++$i) { |
$LUcolj[$i] = &$this->LU[$i][$j]; |
} |
// Apply previous transformations. |
for ($i = 0; $i < $this->m; ++$i) { |
$LUrowi = $this->LU[$i]; |
// Most of the time is spent in the following dot product. |
$kmax = min($i,$j); |
$s = 0.0; |
for ($k = 0; $k < $kmax; ++$k) { |
$s += $LUrowi[$k] * $LUcolj[$k]; |
} |
$LUrowi[$j] = $LUcolj[$i] -= $s; |
} |
// Find pivot and exchange if necessary. |
$p = $j; |
for ($i = $j+1; $i < $this->m; ++$i) { |
if (abs($LUcolj[$i]) > abs($LUcolj[$p])) { |
$p = $i; |
} |
} |
if ($p != $j) { |
for ($k = 0; $k < $this->n; ++$k) { |
$t = $this->LU[$p][$k]; |
$this->LU[$p][$k] = $this->LU[$j][$k]; |
$this->LU[$j][$k] = $t; |
} |
$k = $this->piv[$p]; |
$this->piv[$p] = $this->piv[$j]; |
$this->piv[$j] = $k; |
$this->pivsign = $this->pivsign * -1; |
} |
// Compute multipliers. |
if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) { |
for ($i = $j+1; $i < $this->m; ++$i) { |
$this->LU[$i][$j] /= $this->LU[$j][$j]; |
} |
} |
} |
} else { |
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); |
} |
} // function __construct() |
/** |
* Get lower triangular factor. |
* |
* @return array Lower triangular factor |
*/ |
public function getL() { |
for ($i = 0; $i < $this->m; ++$i) { |
for ($j = 0; $j < $this->n; ++$j) { |
if ($i > $j) { |
$L[$i][$j] = $this->LU[$i][$j]; |
} elseif ($i == $j) { |
$L[$i][$j] = 1.0; |
} else { |
$L[$i][$j] = 0.0; |
} |
} |
} |
return new PHPExcel_Shared_JAMA_Matrix($L); |
} // function getL() |
/** |
* Get upper triangular factor. |
* |
* @return array Upper triangular factor |
*/ |
public function getU() { |
for ($i = 0; $i < $this->n; ++$i) { |
for ($j = 0; $j < $this->n; ++$j) { |
if ($i <= $j) { |
$U[$i][$j] = $this->LU[$i][$j]; |
} else { |
$U[$i][$j] = 0.0; |
} |
} |
} |
return new PHPExcel_Shared_JAMA_Matrix($U); |
} // function getU() |
/** |
* Return pivot permutation vector. |
* |
* @return array Pivot vector |
*/ |
public function getPivot() { |
return $this->piv; |
} // function getPivot() |
/** |
* Alias for getPivot |
* |
* @see getPivot |
*/ |
public function getDoublePivot() { |
return $this->getPivot(); |
} // function getDoublePivot() |
/** |
* Is the matrix nonsingular? |
* |
* @return true if U, and hence A, is nonsingular. |
*/ |
public function isNonsingular() { |
for ($j = 0; $j < $this->n; ++$j) { |
if ($this->LU[$j][$j] == 0) { |
return false; |
} |
} |
return true; |
} // function isNonsingular() |
/** |
* Count determinants |
* |
* @return array d matrix deterninat |
*/ |
public function det() { |
if ($this->m == $this->n) { |
$d = $this->pivsign; |
for ($j = 0; $j < $this->n; ++$j) { |
$d *= $this->LU[$j][$j]; |
} |
return $d; |
} else { |
throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); |
} |
} // function det() |
/** |
* Solve A*X = B |
* |
* @param $B A Matrix with as many rows as A and any number of columns. |
* @return X so that L*U*X = B(piv,:) |
* @PHPExcel_Calculation_Exception IllegalArgumentException Matrix row dimensions must agree. |
* @PHPExcel_Calculation_Exception RuntimeException Matrix is singular. |
*/ |
public function solve($B) { |
if ($B->getRowDimension() == $this->m) { |
if ($this->isNonsingular()) { |
// Copy right hand side with pivoting |
$nx = $B->getColumnDimension(); |
$X = $B->getMatrix($this->piv, 0, $nx-1); |
// Solve L*Y = B(piv,:) |
for ($k = 0; $k < $this->n; ++$k) { |
for ($i = $k+1; $i < $this->n; ++$i) { |
for ($j = 0; $j < $nx; ++$j) { |
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; |
} |
} |
} |
// Solve U*X = Y; |
for ($k = $this->n-1; $k >= 0; --$k) { |
for ($j = 0; $j < $nx; ++$j) { |
$X->A[$k][$j] /= $this->LU[$k][$k]; |
} |
for ($i = 0; $i < $k; ++$i) { |
for ($j = 0; $j < $nx; ++$j) { |
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; |
} |
} |
} |
return $X; |
} else { |
throw new PHPExcel_Calculation_Exception(self::MatrixSingularException); |
} |
} else { |
throw new PHPExcel_Calculation_Exception(self::MatrixSquareException); |
} |
} // function solve() |
} // class PHPExcel_Shared_JAMA_LUDecomposition |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer.php |
---|
New file |
0,0 → 1,83 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher_DgContainer |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher_DgContainer |
{ |
/** |
* Drawing index, 1-based. |
* |
* @var int |
*/ |
private $_dgId; |
/** |
* Last shape index in this drawing |
* |
* @var int |
*/ |
private $_lastSpId; |
private $_spgrContainer = null; |
public function getDgId() |
{ |
return $this->_dgId; |
} |
public function setDgId($value) |
{ |
$this->_dgId = $value; |
} |
public function getLastSpId() |
{ |
return $this->_lastSpId; |
} |
public function setLastSpId($value) |
{ |
$this->_lastSpId = $value; |
} |
public function getSpgrContainer() |
{ |
return $this->_spgrContainer; |
} |
public function setSpgrContainer($spgrContainer) |
{ |
return $this->_spgrContainer = $spgrContainer; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php |
---|
New file |
0,0 → 1,65 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher_DggContainer_BstoreContainer |
{ |
/** |
* BLIP Store Entries. Each of them holds one BLIP (Big Large Image or Picture) |
* |
* @var array |
*/ |
private $_BSECollection = array(); |
/** |
* Add a BLIP Store Entry |
* |
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $BSE |
*/ |
public function addBSE($BSE) |
{ |
$this->_BSECollection[] = $BSE; |
$BSE->setParent($this); |
} |
/** |
* Get the collection of BLIP Store Entries |
* |
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE[] |
*/ |
public function getBSECollection() |
{ |
return $this->_BSECollection; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php |
---|
New file |
0,0 → 1,91 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip |
{ |
/** |
* The parent BSE |
* |
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE |
*/ |
private $_parent; |
/** |
* Raw image data |
* |
* @var string |
*/ |
private $_data; |
/** |
* Get the raw image data |
* |
* @return string |
*/ |
public function getData() |
{ |
return $this->_data; |
} |
/** |
* Set the raw image data |
* |
* @param string |
*/ |
public function setData($data) |
{ |
$this->_data = $data; |
} |
/** |
* Set parent BSE |
* |
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $parent |
*/ |
public function setParent($parent) |
{ |
$this->_parent = $parent; |
} |
/** |
* Get parent BSE |
* |
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $parent |
*/ |
public function getParent() |
{ |
return $this->_parent; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php |
---|
New file |
0,0 → 1,120 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE |
{ |
const BLIPTYPE_ERROR = 0x00; |
const BLIPTYPE_UNKNOWN = 0x01; |
const BLIPTYPE_EMF = 0x02; |
const BLIPTYPE_WMF = 0x03; |
const BLIPTYPE_PICT = 0x04; |
const BLIPTYPE_JPEG = 0x05; |
const BLIPTYPE_PNG = 0x06; |
const BLIPTYPE_DIB = 0x07; |
const BLIPTYPE_TIFF = 0x11; |
const BLIPTYPE_CMYKJPEG = 0x12; |
/** |
* The parent BLIP Store Entry Container |
* |
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer |
*/ |
private $_parent; |
/** |
* The BLIP (Big Large Image or Picture) |
* |
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip |
*/ |
private $_blip; |
/** |
* The BLIP type |
* |
* @var int |
*/ |
private $_blipType; |
/** |
* Set parent BLIP Store Entry Container |
* |
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer $parent |
*/ |
public function setParent($parent) |
{ |
$this->_parent = $parent; |
} |
/** |
* Get the BLIP |
* |
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip |
*/ |
public function getBlip() |
{ |
return $this->_blip; |
} |
/** |
* Set the BLIP |
* |
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip $blip |
*/ |
public function setBlip($blip) |
{ |
$this->_blip = $blip; |
$blip->setParent($this); |
} |
/** |
* Get the BLIP type |
* |
* @return int |
*/ |
public function getBlipType() |
{ |
return $this->_blipType; |
} |
/** |
* Set the BLIP type |
* |
* @param int |
*/ |
public function setBlipType($blipType) |
{ |
$this->_blipType = $blipType; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer.php |
---|
New file |
0,0 → 1,203 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher_DggContainer |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher_DggContainer |
{ |
/** |
* Maximum shape index of all shapes in all drawings increased by one |
* |
* @var int |
*/ |
private $_spIdMax; |
/** |
* Total number of drawings saved |
* |
* @var int |
*/ |
private $_cDgSaved; |
/** |
* Total number of shapes saved (including group shapes) |
* |
* @var int |
*/ |
private $_cSpSaved; |
/** |
* BLIP Store Container |
* |
* @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer |
*/ |
private $_bstoreContainer; |
/** |
* Array of options for the drawing group |
* |
* @var array |
*/ |
private $_OPT = array(); |
/** |
* Array of identifier clusters containg information about the maximum shape identifiers |
* |
* @var array |
*/ |
private $_IDCLs = array(); |
/** |
* Get maximum shape index of all shapes in all drawings (plus one) |
* |
* @return int |
*/ |
public function getSpIdMax() |
{ |
return $this->_spIdMax; |
} |
/** |
* Set maximum shape index of all shapes in all drawings (plus one) |
* |
* @param int |
*/ |
public function setSpIdMax($value) |
{ |
$this->_spIdMax = $value; |
} |
/** |
* Get total number of drawings saved |
* |
* @return int |
*/ |
public function getCDgSaved() |
{ |
return $this->_cDgSaved; |
} |
/** |
* Set total number of drawings saved |
* |
* @param int |
*/ |
public function setCDgSaved($value) |
{ |
$this->_cDgSaved = $value; |
} |
/** |
* Get total number of shapes saved (including group shapes) |
* |
* @return int |
*/ |
public function getCSpSaved() |
{ |
return $this->_cSpSaved; |
} |
/** |
* Set total number of shapes saved (including group shapes) |
* |
* @param int |
*/ |
public function setCSpSaved($value) |
{ |
$this->_cSpSaved = $value; |
} |
/** |
* Get BLIP Store Container |
* |
* @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer |
*/ |
public function getBstoreContainer() |
{ |
return $this->_bstoreContainer; |
} |
/** |
* Set BLIP Store Container |
* |
* @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer $bstoreContainer |
*/ |
public function setBstoreContainer($bstoreContainer) |
{ |
$this->_bstoreContainer = $bstoreContainer; |
} |
/** |
* Set an option for the drawing group |
* |
* @param int $property The number specifies the option |
* @param mixed $value |
*/ |
public function setOPT($property, $value) |
{ |
$this->_OPT[$property] = $value; |
} |
/** |
* Get an option for the drawing group |
* |
* @param int $property The number specifies the option |
* @return mixed |
*/ |
public function getOPT($property) |
{ |
if (isset($this->_OPT[$property])) { |
return $this->_OPT[$property]; |
} |
return null; |
} |
/** |
* Get identifier clusters |
* |
* @return array |
*/ |
public function getIDCLs() |
{ |
return $this->_IDCLs; |
} |
/** |
* Set identifier clusters. array(<drawingId> => <max shape id>, ...) |
* |
* @param array $pValue |
*/ |
public function setIDCLs($pValue) |
{ |
$this->_IDCLs = $pValue; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php |
---|
New file |
0,0 → 1,395 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer |
{ |
/** |
* Parent Shape Group Container |
* |
* @var PHPExcel_Shared_Escher_DgContainer_SpgrContainer |
*/ |
private $_parent; |
/** |
* Is this a group shape? |
* |
* @var boolean |
*/ |
private $_spgr = false; |
/** |
* Shape type |
* |
* @var int |
*/ |
private $_spType; |
/** |
* Shape flag |
* |
* @var int |
*/ |
private $_spFlag; |
/** |
* Shape index (usually group shape has index 0, and the rest: 1,2,3...) |
* |
* @var boolean |
*/ |
private $_spId; |
/** |
* Array of options |
* |
* @var array |
*/ |
private $_OPT; |
/** |
* Cell coordinates of upper-left corner of shape, e.g. 'A1' |
* |
* @var string |
*/ |
private $_startCoordinates; |
/** |
* Horizontal offset of upper-left corner of shape measured in 1/1024 of column width |
* |
* @var int |
*/ |
private $_startOffsetX; |
/** |
* Vertical offset of upper-left corner of shape measured in 1/256 of row height |
* |
* @var int |
*/ |
private $_startOffsetY; |
/** |
* Cell coordinates of bottom-right corner of shape, e.g. 'B2' |
* |
* @var string |
*/ |
private $_endCoordinates; |
/** |
* Horizontal offset of bottom-right corner of shape measured in 1/1024 of column width |
* |
* @var int |
*/ |
private $_endOffsetX; |
/** |
* Vertical offset of bottom-right corner of shape measured in 1/256 of row height |
* |
* @var int |
*/ |
private $_endOffsetY; |
/** |
* Set parent Shape Group Container |
* |
* @param PHPExcel_Shared_Escher_DgContainer_SpgrContainer $parent |
*/ |
public function setParent($parent) |
{ |
$this->_parent = $parent; |
} |
/** |
* Get the parent Shape Group Container |
* |
* @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer |
*/ |
public function getParent() |
{ |
return $this->_parent; |
} |
/** |
* Set whether this is a group shape |
* |
* @param boolean $value |
*/ |
public function setSpgr($value = false) |
{ |
$this->_spgr = $value; |
} |
/** |
* Get whether this is a group shape |
* |
* @return boolean |
*/ |
public function getSpgr() |
{ |
return $this->_spgr; |
} |
/** |
* Set the shape type |
* |
* @param int $value |
*/ |
public function setSpType($value) |
{ |
$this->_spType = $value; |
} |
/** |
* Get the shape type |
* |
* @return int |
*/ |
public function getSpType() |
{ |
return $this->_spType; |
} |
/** |
* Set the shape flag |
* |
* @param int $value |
*/ |
public function setSpFlag($value) |
{ |
$this->_spFlag = $value; |
} |
/** |
* Get the shape flag |
* |
* @return int |
*/ |
public function getSpFlag() |
{ |
return $this->_spFlag; |
} |
/** |
* Set the shape index |
* |
* @param int $value |
*/ |
public function setSpId($value) |
{ |
$this->_spId = $value; |
} |
/** |
* Get the shape index |
* |
* @return int |
*/ |
public function getSpId() |
{ |
return $this->_spId; |
} |
/** |
* Set an option for the Shape Group Container |
* |
* @param int $property The number specifies the option |
* @param mixed $value |
*/ |
public function setOPT($property, $value) |
{ |
$this->_OPT[$property] = $value; |
} |
/** |
* Get an option for the Shape Group Container |
* |
* @param int $property The number specifies the option |
* @return mixed |
*/ |
public function getOPT($property) |
{ |
if (isset($this->_OPT[$property])) { |
return $this->_OPT[$property]; |
} |
return null; |
} |
/** |
* Get the collection of options |
* |
* @return array |
*/ |
public function getOPTCollection() |
{ |
return $this->_OPT; |
} |
/** |
* Set cell coordinates of upper-left corner of shape |
* |
* @param string $value |
*/ |
public function setStartCoordinates($value = 'A1') |
{ |
$this->_startCoordinates = $value; |
} |
/** |
* Get cell coordinates of upper-left corner of shape |
* |
* @return string |
*/ |
public function getStartCoordinates() |
{ |
return $this->_startCoordinates; |
} |
/** |
* Set offset in x-direction of upper-left corner of shape measured in 1/1024 of column width |
* |
* @param int $startOffsetX |
*/ |
public function setStartOffsetX($startOffsetX = 0) |
{ |
$this->_startOffsetX = $startOffsetX; |
} |
/** |
* Get offset in x-direction of upper-left corner of shape measured in 1/1024 of column width |
* |
* @return int |
*/ |
public function getStartOffsetX() |
{ |
return $this->_startOffsetX; |
} |
/** |
* Set offset in y-direction of upper-left corner of shape measured in 1/256 of row height |
* |
* @param int $startOffsetY |
*/ |
public function setStartOffsetY($startOffsetY = 0) |
{ |
$this->_startOffsetY = $startOffsetY; |
} |
/** |
* Get offset in y-direction of upper-left corner of shape measured in 1/256 of row height |
* |
* @return int |
*/ |
public function getStartOffsetY() |
{ |
return $this->_startOffsetY; |
} |
/** |
* Set cell coordinates of bottom-right corner of shape |
* |
* @param string $value |
*/ |
public function setEndCoordinates($value = 'A1') |
{ |
$this->_endCoordinates = $value; |
} |
/** |
* Get cell coordinates of bottom-right corner of shape |
* |
* @return string |
*/ |
public function getEndCoordinates() |
{ |
return $this->_endCoordinates; |
} |
/** |
* Set offset in x-direction of bottom-right corner of shape measured in 1/1024 of column width |
* |
* @param int $startOffsetX |
*/ |
public function setEndOffsetX($endOffsetX = 0) |
{ |
$this->_endOffsetX = $endOffsetX; |
} |
/** |
* Get offset in x-direction of bottom-right corner of shape measured in 1/1024 of column width |
* |
* @return int |
*/ |
public function getEndOffsetX() |
{ |
return $this->_endOffsetX; |
} |
/** |
* Set offset in y-direction of bottom-right corner of shape measured in 1/256 of row height |
* |
* @param int $endOffsetY |
*/ |
public function setEndOffsetY($endOffsetY = 0) |
{ |
$this->_endOffsetY = $endOffsetY; |
} |
/** |
* Get offset in y-direction of bottom-right corner of shape measured in 1/256 of row height |
* |
* @return int |
*/ |
public function getEndOffsetY() |
{ |
return $this->_endOffsetY; |
} |
/** |
* Get the nesting level of this spContainer. This is the number of spgrContainers between this spContainer and |
* the dgContainer. A value of 1 = immediately within first spgrContainer |
* Higher nesting level occurs if and only if spContainer is part of a shape group |
* |
* @return int Nesting level |
*/ |
public function getNestingLevel() |
{ |
$nestingLevel = 0; |
$parent = $this->getParent(); |
while ($parent instanceof PHPExcel_Shared_Escher_DgContainer_SpgrContainer) { |
++$nestingLevel; |
$parent = $parent->getParent(); |
} |
return $nestingLevel; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php |
---|
New file |
0,0 → 1,109 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Escher_DgContainer_SpgrContainer |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Escher |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Escher_DgContainer_SpgrContainer |
{ |
/** |
* Parent Shape Group Container |
* |
* @var PHPExcel_Shared_Escher_DgContainer_SpgrContainer |
*/ |
private $_parent; |
/** |
* Shape Container collection |
* |
* @var array |
*/ |
private $_children = array(); |
/** |
* Set parent Shape Group Container |
* |
* @param PHPExcel_Shared_Escher_DgContainer_SpgrContainer $parent |
*/ |
public function setParent($parent) |
{ |
$this->_parent = $parent; |
} |
/** |
* Get the parent Shape Group Container if any |
* |
* @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer|null |
*/ |
public function getParent() |
{ |
return $this->_parent; |
} |
/** |
* Add a child. This will be either spgrContainer or spContainer |
* |
* @param mixed $child |
*/ |
public function addChild($child) |
{ |
$this->_children[] = $child; |
$child->setParent($this); |
} |
/** |
* Get collection of Shape Containers |
*/ |
public function getChildren() |
{ |
return $this->_children; |
} |
/** |
* Recursively get all spContainers within this spgrContainer |
* |
* @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer[] |
*/ |
public function getAllSpContainers() |
{ |
$allSpContainers = array(); |
foreach ($this->_children as $child) { |
if ($child instanceof PHPExcel_Shared_Escher_DgContainer_SpgrContainer) { |
$allSpContainers = array_merge($allSpContainers, $child->getAllSpContainers()); |
} else { |
$allSpContainers[] = $child; |
} |
} |
return $allSpContainers; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/Excel5.php |
---|
New file |
0,0 → 1,317 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Shared_Excel5 |
* |
* @category PHPExcel |
* @package PHPExcel_Shared |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Shared_Excel5 |
{ |
/** |
* Get the width of a column in pixels. We use the relationship y = ceil(7x) where |
* x is the width in intrinsic Excel units (measuring width in number of normal characters) |
* This holds for Arial 10 |
* |
* @param PHPExcel_Worksheet $sheet The sheet |
* @param string $col The column |
* @return integer The width in pixels |
*/ |
public static function sizeCol($sheet, $col = 'A') |
{ |
// default font of the workbook |
$font = $sheet->getParent()->getDefaultStyle()->getFont(); |
$columnDimensions = $sheet->getColumnDimensions(); |
// first find the true column width in pixels (uncollapsed and unhidden) |
if ( isset($columnDimensions[$col]) and $columnDimensions[$col]->getWidth() != -1 ) { |
// then we have column dimension with explicit width |
$columnDimension = $columnDimensions[$col]; |
$width = $columnDimension->getWidth(); |
$pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); |
} else if ($sheet->getDefaultColumnDimension()->getWidth() != -1) { |
// then we have default column dimension with explicit width |
$defaultColumnDimension = $sheet->getDefaultColumnDimension(); |
$width = $defaultColumnDimension->getWidth(); |
$pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); |
} else { |
// we don't even have any default column dimension. Width depends on default font |
$pixelWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($font, true); |
} |
// now find the effective column width in pixels |
if (isset($columnDimensions[$col]) and !$columnDimensions[$col]->getVisible()) { |
$effectivePixelWidth = 0; |
} else { |
$effectivePixelWidth = $pixelWidth; |
} |
return $effectivePixelWidth; |
} |
/** |
* Convert the height of a cell from user's units to pixels. By interpolation |
* the relationship is: y = 4/3x. If the height hasn't been set by the user we |
* use the default value. If the row is hidden we use a value of zero. |
* |
* @param PHPExcel_Worksheet $sheet The sheet |
* @param integer $row The row index (1-based) |
* @return integer The width in pixels |
*/ |
public static function sizeRow($sheet, $row = 1) |
{ |
// default font of the workbook |
$font = $sheet->getParent()->getDefaultStyle()->getFont(); |
$rowDimensions = $sheet->getRowDimensions(); |
// first find the true row height in pixels (uncollapsed and unhidden) |
if ( isset($rowDimensions[$row]) and $rowDimensions[$row]->getRowHeight() != -1) { |
// then we have a row dimension |
$rowDimension = $rowDimensions[$row]; |
$rowHeight = $rowDimension->getRowHeight(); |
$pixelRowHeight = (int) ceil(4 * $rowHeight / 3); // here we assume Arial 10 |
} else if ($sheet->getDefaultRowDimension()->getRowHeight() != -1) { |
// then we have a default row dimension with explicit height |
$defaultRowDimension = $sheet->getDefaultRowDimension(); |
$rowHeight = $defaultRowDimension->getRowHeight(); |
$pixelRowHeight = PHPExcel_Shared_Drawing::pointsToPixels($rowHeight); |
} else { |
// we don't even have any default row dimension. Height depends on default font |
$pointRowHeight = PHPExcel_Shared_Font::getDefaultRowHeightByFont($font); |
$pixelRowHeight = PHPExcel_Shared_Font::fontSizeToPixels($pointRowHeight); |
} |
// now find the effective row height in pixels |
if ( isset($rowDimensions[$row]) and !$rowDimensions[$row]->getVisible() ) { |
$effectivePixelRowHeight = 0; |
} else { |
$effectivePixelRowHeight = $pixelRowHeight; |
} |
return $effectivePixelRowHeight; |
} |
/** |
* Get the horizontal distance in pixels between two anchors |
* The distanceX is found as sum of all the spanning columns widths minus correction for the two offsets |
* |
* @param PHPExcel_Worksheet $sheet |
* @param string $startColumn |
* @param integer $startOffsetX Offset within start cell measured in 1/1024 of the cell width |
* @param string $endColumn |
* @param integer $endOffsetX Offset within end cell measured in 1/1024 of the cell width |
* @return integer Horizontal measured in pixels |
*/ |
public static function getDistanceX(PHPExcel_Worksheet $sheet, $startColumn = 'A', $startOffsetX = 0, $endColumn = 'A', $endOffsetX = 0) |
{ |
$distanceX = 0; |
// add the widths of the spanning columns |
$startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumn) - 1; // 1-based |
$endColumnIndex = PHPExcel_Cell::columnIndexFromString($endColumn) - 1; // 1-based |
for ($i = $startColumnIndex; $i <= $endColumnIndex; ++$i) { |
$distanceX += self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($i)); |
} |
// correct for offsetX in startcell |
$distanceX -= (int) floor(self::sizeCol($sheet, $startColumn) * $startOffsetX / 1024); |
// correct for offsetX in endcell |
$distanceX -= (int) floor(self::sizeCol($sheet, $endColumn) * (1 - $endOffsetX / 1024)); |
return $distanceX; |
} |
/** |
* Get the vertical distance in pixels between two anchors |
* The distanceY is found as sum of all the spanning rows minus two offsets |
* |
* @param PHPExcel_Worksheet $sheet |
* @param integer $startRow (1-based) |
* @param integer $startOffsetY Offset within start cell measured in 1/256 of the cell height |
* @param integer $endRow (1-based) |
* @param integer $endOffsetY Offset within end cell measured in 1/256 of the cell height |
* @return integer Vertical distance measured in pixels |
*/ |
public static function getDistanceY(PHPExcel_Worksheet $sheet, $startRow = 1, $startOffsetY = 0, $endRow = 1, $endOffsetY = 0) |
{ |
$distanceY = 0; |
// add the widths of the spanning rows |
for ($row = $startRow; $row <= $endRow; ++$row) { |
$distanceY += self::sizeRow($sheet, $row); |
} |
// correct for offsetX in startcell |
$distanceY -= (int) floor(self::sizeRow($sheet, $startRow) * $startOffsetY / 256); |
// correct for offsetX in endcell |
$distanceY -= (int) floor(self::sizeRow($sheet, $endRow) * (1 - $endOffsetY / 256)); |
return $distanceY; |
} |
/** |
* Convert 1-cell anchor coordinates to 2-cell anchor coordinates |
* This function is ported from PEAR Spreadsheet_Writer_Excel with small modifications |
* |
* Calculate the vertices that define the position of the image as required by |
* the OBJ record. |
* |
* +------------+------------+ |
* | A | B | |
* +-----+------------+------------+ |
* | |(x1,y1) | | |
* | 1 |(A1)._______|______ | |
* | | | | | |
* | | | | | |
* +-----+----| BITMAP |-----+ |
* | | | | | |
* | 2 | |______________. | |
* | | | (B2)| |
* | | | (x2,y2)| |
* +---- +------------+------------+ |
* |
* Example of a bitmap that covers some of the area from cell A1 to cell B2. |
* |
* Based on the width and height of the bitmap we need to calculate 8 vars: |
* $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2. |
* The width and height of the cells are also variable and have to be taken into |
* account. |
* The values of $col_start and $row_start are passed in from the calling |
* function. The values of $col_end and $row_end are calculated by subtracting |
* the width and height of the bitmap from the width and height of the |
* underlying cells. |
* The vertices are expressed as a percentage of the underlying cell width as |
* follows (rhs values are in pixels): |
* |
* x1 = X / W *1024 |
* y1 = Y / H *256 |
* x2 = (X-1) / W *1024 |
* y2 = (Y-1) / H *256 |
* |
* Where: X is distance from the left side of the underlying cell |
* Y is distance from the top of the underlying cell |
* W is the width of the cell |
* H is the height of the cell |
* |
* @param PHPExcel_Worksheet $sheet |
* @param string $coordinates E.g. 'A1' |
* @param integer $offsetX Horizontal offset in pixels |
* @param integer $offsetY Vertical offset in pixels |
* @param integer $width Width in pixels |
* @param integer $height Height in pixels |
* @return array |
*/ |
public static function oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height) |
{ |
list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinates); |
$col_start = PHPExcel_Cell::columnIndexFromString($column) - 1; |
$row_start = $row - 1; |
$x1 = $offsetX; |
$y1 = $offsetY; |
// Initialise end cell to the same as the start cell |
$col_end = $col_start; // Col containing lower right corner of object |
$row_end = $row_start; // Row containing bottom right corner of object |
// Zero the specified offset if greater than the cell dimensions |
if ($x1 >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start))) { |
$x1 = 0; |
} |
if ($y1 >= self::sizeRow($sheet, $row_start + 1)) { |
$y1 = 0; |
} |
$width = $width + $x1 -1; |
$height = $height + $y1 -1; |
// Subtract the underlying cell widths to find the end cell of the image |
while ($width >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end))) { |
$width -= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)); |
++$col_end; |
} |
// Subtract the underlying cell heights to find the end cell of the image |
while ($height >= self::sizeRow($sheet, $row_end + 1)) { |
$height -= self::sizeRow($sheet, $row_end + 1); |
++$row_end; |
} |
// Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell |
// with zero height or width. |
if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) { |
return; |
} |
if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) == 0) { |
return; |
} |
if (self::sizeRow($sheet, $row_start + 1) == 0) { |
return; |
} |
if (self::sizeRow($sheet, $row_end + 1) == 0) { |
return; |
} |
// Convert the pixel values to the percentage value expected by Excel |
$x1 = $x1 / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024; |
$y1 = $y1 / self::sizeRow($sheet, $row_start + 1) * 256; |
$x2 = ($width + 1) / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object |
$y2 = ($height + 1) / self::sizeRow($sheet, $row_end + 1) * 256; // Distance to bottom of object |
$startCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_start) . ($row_start + 1); |
$endCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_end) . ($row_end + 1); |
$twoAnchor = array( |
'startCoordinates' => $startCoordinates, |
'startOffsetX' => $x1, |
'startOffsetY' => $y1, |
'endCoordinates' => $endCoordinates, |
'endOffsetX' => $x2, |
'endOffsetY' => $y2, |
); |
return $twoAnchor; |
} |
} |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/trend/exponentialBestFitClass.php |
---|
New file |
0,0 → 1,148 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); |
/** |
* PHPExcel_Exponential_Best_Fit |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit |
{ |
/** |
* Algorithm type to use for best-fit |
* (Name of this trend class) |
* |
* @var string |
**/ |
protected $_bestFitType = 'exponential'; |
/** |
* Return the Y-Value for a specified value of X |
* |
* @param float $xValue X-Value |
* @return float Y-Value |
**/ |
public function getValueOfYForX($xValue) { |
return $this->getIntersect() * pow($this->getSlope(),($xValue - $this->_Xoffset)); |
} // function getValueOfYForX() |
/** |
* Return the X-Value for a specified value of Y |
* |
* @param float $yValue Y-Value |
* @return float X-Value |
**/ |
public function getValueOfXForY($yValue) { |
return log(($yValue + $this->_Yoffset) / $this->getIntersect()) / log($this->getSlope()); |
} // function getValueOfXForY() |
/** |
* Return the Equation of the best-fit line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getEquation($dp=0) { |
$slope = $this->getSlope($dp); |
$intersect = $this->getIntersect($dp); |
return 'Y = '.$intersect.' * '.$slope.'^X'; |
} // function getEquation() |
/** |
* Return the Slope of the line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getSlope($dp=0) { |
if ($dp != 0) { |
return round(exp($this->_slope),$dp); |
} |
return exp($this->_slope); |
} // function getSlope() |
/** |
* Return the Value of X where it intersects Y = 0 |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getIntersect($dp=0) { |
if ($dp != 0) { |
return round(exp($this->_intersect),$dp); |
} |
return exp($this->_intersect); |
} // function getIntersect() |
/** |
* Execute the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
private function _exponential_regression($yValues, $xValues, $const) { |
foreach($yValues as &$value) { |
if ($value < 0.0) { |
$value = 0 - log(abs($value)); |
} elseif ($value > 0.0) { |
$value = log($value); |
} |
} |
unset($value); |
$this->_leastSquareFit($yValues, $xValues, $const); |
} // function _exponential_regression() |
/** |
* Define the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
function __construct($yValues, $xValues=array(), $const=True) { |
if (parent::__construct($yValues, $xValues) !== False) { |
$this->_exponential_regression($yValues, $xValues, $const); |
} |
} // function __construct() |
} // class exponentialBestFit |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/trend/linearBestFitClass.php |
---|
New file |
0,0 → 1,111 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); |
/** |
* PHPExcel_Linear_Best_Fit |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Linear_Best_Fit extends PHPExcel_Best_Fit |
{ |
/** |
* Algorithm type to use for best-fit |
* (Name of this trend class) |
* |
* @var string |
**/ |
protected $_bestFitType = 'linear'; |
/** |
* Return the Y-Value for a specified value of X |
* |
* @param float $xValue X-Value |
* @return float Y-Value |
**/ |
public function getValueOfYForX($xValue) { |
return $this->getIntersect() + $this->getSlope() * $xValue; |
} // function getValueOfYForX() |
/** |
* Return the X-Value for a specified value of Y |
* |
* @param float $yValue Y-Value |
* @return float X-Value |
**/ |
public function getValueOfXForY($yValue) { |
return ($yValue - $this->getIntersect()) / $this->getSlope(); |
} // function getValueOfXForY() |
/** |
* Return the Equation of the best-fit line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getEquation($dp=0) { |
$slope = $this->getSlope($dp); |
$intersect = $this->getIntersect($dp); |
return 'Y = '.$intersect.' + '.$slope.' * X'; |
} // function getEquation() |
/** |
* Execute the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
private function _linear_regression($yValues, $xValues, $const) { |
$this->_leastSquareFit($yValues, $xValues,$const); |
} // function _linear_regression() |
/** |
* Define the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
function __construct($yValues, $xValues=array(), $const=True) { |
if (parent::__construct($yValues, $xValues) !== False) { |
$this->_linear_regression($yValues, $xValues, $const); |
} |
} // function __construct() |
} // class linearBestFit |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/trend/trendClass.php |
---|
New file |
0,0 → 1,156 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/linearBestFitClass.php'; |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/logarithmicBestFitClass.php'; |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/exponentialBestFitClass.php'; |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/powerBestFitClass.php'; |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/polynomialBestFitClass.php'; |
/** |
* PHPExcel_trendClass |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class trendClass |
{ |
const TREND_LINEAR = 'Linear'; |
const TREND_LOGARITHMIC = 'Logarithmic'; |
const TREND_EXPONENTIAL = 'Exponential'; |
const TREND_POWER = 'Power'; |
const TREND_POLYNOMIAL_2 = 'Polynomial_2'; |
const TREND_POLYNOMIAL_3 = 'Polynomial_3'; |
const TREND_POLYNOMIAL_4 = 'Polynomial_4'; |
const TREND_POLYNOMIAL_5 = 'Polynomial_5'; |
const TREND_POLYNOMIAL_6 = 'Polynomial_6'; |
const TREND_BEST_FIT = 'Bestfit'; |
const TREND_BEST_FIT_NO_POLY = 'Bestfit_no_Polynomials'; |
/** |
* Names of the best-fit trend analysis methods |
* |
* @var string[] |
**/ |
private static $_trendTypes = array( self::TREND_LINEAR, |
self::TREND_LOGARITHMIC, |
self::TREND_EXPONENTIAL, |
self::TREND_POWER |
); |
/** |
* Names of the best-fit trend polynomial orders |
* |
* @var string[] |
**/ |
private static $_trendTypePolyOrders = array( self::TREND_POLYNOMIAL_2, |
self::TREND_POLYNOMIAL_3, |
self::TREND_POLYNOMIAL_4, |
self::TREND_POLYNOMIAL_5, |
self::TREND_POLYNOMIAL_6 |
); |
/** |
* Cached results for each method when trying to identify which provides the best fit |
* |
* @var PHPExcel_Best_Fit[] |
**/ |
private static $_trendCache = array(); |
public static function calculate($trendType=self::TREND_BEST_FIT, $yValues, $xValues=array(), $const=True) { |
// Calculate number of points in each dataset |
$nY = count($yValues); |
$nX = count($xValues); |
// Define X Values if necessary |
if ($nX == 0) { |
$xValues = range(1,$nY); |
$nX = $nY; |
} elseif ($nY != $nX) { |
// Ensure both arrays of points are the same size |
trigger_error("trend(): Number of elements in coordinate arrays do not match.", E_USER_ERROR); |
} |
$key = md5($trendType.$const.serialize($yValues).serialize($xValues)); |
// Determine which trend method has been requested |
switch ($trendType) { |
// Instantiate and return the class for the requested trend method |
case self::TREND_LINEAR : |
case self::TREND_LOGARITHMIC : |
case self::TREND_EXPONENTIAL : |
case self::TREND_POWER : |
if (!isset(self::$_trendCache[$key])) { |
$className = 'PHPExcel_'.$trendType.'_Best_Fit'; |
self::$_trendCache[$key] = new $className($yValues,$xValues,$const); |
} |
return self::$_trendCache[$key]; |
break; |
case self::TREND_POLYNOMIAL_2 : |
case self::TREND_POLYNOMIAL_3 : |
case self::TREND_POLYNOMIAL_4 : |
case self::TREND_POLYNOMIAL_5 : |
case self::TREND_POLYNOMIAL_6 : |
if (!isset(self::$_trendCache[$key])) { |
$order = substr($trendType,-1); |
self::$_trendCache[$key] = new PHPExcel_Polynomial_Best_Fit($order,$yValues,$xValues,$const); |
} |
return self::$_trendCache[$key]; |
break; |
case self::TREND_BEST_FIT : |
case self::TREND_BEST_FIT_NO_POLY : |
// If the request is to determine the best fit regression, then we test each trend line in turn |
// Start by generating an instance of each available trend method |
foreach(self::$_trendTypes as $trendMethod) { |
$className = 'PHPExcel_'.$trendMethod.'BestFit'; |
$bestFit[$trendMethod] = new $className($yValues,$xValues,$const); |
$bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit(); |
} |
if ($trendType != self::TREND_BEST_FIT_NO_POLY) { |
foreach(self::$_trendTypePolyOrders as $trendMethod) { |
$order = substr($trendMethod,-1); |
$bestFit[$trendMethod] = new PHPExcel_Polynomial_Best_Fit($order,$yValues,$xValues,$const); |
if ($bestFit[$trendMethod]->getError()) { |
unset($bestFit[$trendMethod]); |
} else { |
$bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit(); |
} |
} |
} |
// Determine which of our trend lines is the best fit, and then we return the instance of that trend class |
arsort($bestFitValue); |
$bestFitType = key($bestFitValue); |
return $bestFit[$bestFitType]; |
break; |
default : |
return false; |
} |
} // function calculate() |
} // class trendClass |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/trend/powerBestFitClass.php |
---|
New file |
0,0 → 1,142 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; |
/** |
* PHPExcel_Power_Best_Fit |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit |
{ |
/** |
* Algorithm type to use for best-fit |
* (Name of this trend class) |
* |
* @var string |
**/ |
protected $_bestFitType = 'power'; |
/** |
* Return the Y-Value for a specified value of X |
* |
* @param float $xValue X-Value |
* @return float Y-Value |
**/ |
public function getValueOfYForX($xValue) { |
return $this->getIntersect() * pow(($xValue - $this->_Xoffset),$this->getSlope()); |
} // function getValueOfYForX() |
/** |
* Return the X-Value for a specified value of Y |
* |
* @param float $yValue Y-Value |
* @return float X-Value |
**/ |
public function getValueOfXForY($yValue) { |
return pow((($yValue + $this->_Yoffset) / $this->getIntersect()),(1 / $this->getSlope())); |
} // function getValueOfXForY() |
/** |
* Return the Equation of the best-fit line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getEquation($dp=0) { |
$slope = $this->getSlope($dp); |
$intersect = $this->getIntersect($dp); |
return 'Y = '.$intersect.' * X^'.$slope; |
} // function getEquation() |
/** |
* Return the Value of X where it intersects Y = 0 |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getIntersect($dp=0) { |
if ($dp != 0) { |
return round(exp($this->_intersect),$dp); |
} |
return exp($this->_intersect); |
} // function getIntersect() |
/** |
* Execute the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
private function _power_regression($yValues, $xValues, $const) { |
foreach($xValues as &$value) { |
if ($value < 0.0) { |
$value = 0 - log(abs($value)); |
} elseif ($value > 0.0) { |
$value = log($value); |
} |
} |
unset($value); |
foreach($yValues as &$value) { |
if ($value < 0.0) { |
$value = 0 - log(abs($value)); |
} elseif ($value > 0.0) { |
$value = log($value); |
} |
} |
unset($value); |
$this->_leastSquareFit($yValues, $xValues, $const); |
} // function _power_regression() |
/** |
* Define the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
function __construct($yValues, $xValues=array(), $const=True) { |
if (parent::__construct($yValues, $xValues) !== False) { |
$this->_power_regression($yValues, $xValues, $const); |
} |
} // function __construct() |
} // class powerBestFit |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/trend/bestFitClass.php |
---|
New file |
0,0 → 1,432 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
/** |
* PHPExcel_Best_Fit |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Best_Fit |
{ |
/** |
* Indicator flag for a calculation error |
* |
* @var boolean |
**/ |
protected $_error = False; |
/** |
* Algorithm type to use for best-fit |
* |
* @var string |
**/ |
protected $_bestFitType = 'undetermined'; |
/** |
* Number of entries in the sets of x- and y-value arrays |
* |
* @var int |
**/ |
protected $_valueCount = 0; |
/** |
* X-value dataseries of values |
* |
* @var float[] |
**/ |
protected $_xValues = array(); |
/** |
* Y-value dataseries of values |
* |
* @var float[] |
**/ |
protected $_yValues = array(); |
/** |
* Flag indicating whether values should be adjusted to Y=0 |
* |
* @var boolean |
**/ |
protected $_adjustToZero = False; |
/** |
* Y-value series of best-fit values |
* |
* @var float[] |
**/ |
protected $_yBestFitValues = array(); |
protected $_goodnessOfFit = 1; |
protected $_stdevOfResiduals = 0; |
protected $_covariance = 0; |
protected $_correlation = 0; |
protected $_SSRegression = 0; |
protected $_SSResiduals = 0; |
protected $_DFResiduals = 0; |
protected $_F = 0; |
protected $_slope = 0; |
protected $_slopeSE = 0; |
protected $_intersect = 0; |
protected $_intersectSE = 0; |
protected $_Xoffset = 0; |
protected $_Yoffset = 0; |
public function getError() { |
return $this->_error; |
} // function getBestFitType() |
public function getBestFitType() { |
return $this->_bestFitType; |
} // function getBestFitType() |
/** |
* Return the Y-Value for a specified value of X |
* |
* @param float $xValue X-Value |
* @return float Y-Value |
*/ |
public function getValueOfYForX($xValue) { |
return False; |
} // function getValueOfYForX() |
/** |
* Return the X-Value for a specified value of Y |
* |
* @param float $yValue Y-Value |
* @return float X-Value |
*/ |
public function getValueOfXForY($yValue) { |
return False; |
} // function getValueOfXForY() |
/** |
* Return the original set of X-Values |
* |
* @return float[] X-Values |
*/ |
public function getXValues() { |
return $this->_xValues; |
} // function getValueOfXForY() |
/** |
* Return the Equation of the best-fit line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
*/ |
public function getEquation($dp=0) { |
return False; |
} // function getEquation() |
/** |
* Return the Slope of the line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
*/ |
public function getSlope($dp=0) { |
if ($dp != 0) { |
return round($this->_slope,$dp); |
} |
return $this->_slope; |
} // function getSlope() |
/** |
* Return the standard error of the Slope |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
*/ |
public function getSlopeSE($dp=0) { |
if ($dp != 0) { |
return round($this->_slopeSE,$dp); |
} |
return $this->_slopeSE; |
} // function getSlopeSE() |
/** |
* Return the Value of X where it intersects Y = 0 |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
*/ |
public function getIntersect($dp=0) { |
if ($dp != 0) { |
return round($this->_intersect,$dp); |
} |
return $this->_intersect; |
} // function getIntersect() |
/** |
* Return the standard error of the Intersect |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
*/ |
public function getIntersectSE($dp=0) { |
if ($dp != 0) { |
return round($this->_intersectSE,$dp); |
} |
return $this->_intersectSE; |
} // function getIntersectSE() |
/** |
* Return the goodness of fit for this regression |
* |
* @param int $dp Number of places of decimal precision to return |
* @return float |
*/ |
public function getGoodnessOfFit($dp=0) { |
if ($dp != 0) { |
return round($this->_goodnessOfFit,$dp); |
} |
return $this->_goodnessOfFit; |
} // function getGoodnessOfFit() |
public function getGoodnessOfFitPercent($dp=0) { |
if ($dp != 0) { |
return round($this->_goodnessOfFit * 100,$dp); |
} |
return $this->_goodnessOfFit * 100; |
} // function getGoodnessOfFitPercent() |
/** |
* Return the standard deviation of the residuals for this regression |
* |
* @param int $dp Number of places of decimal precision to return |
* @return float |
*/ |
public function getStdevOfResiduals($dp=0) { |
if ($dp != 0) { |
return round($this->_stdevOfResiduals,$dp); |
} |
return $this->_stdevOfResiduals; |
} // function getStdevOfResiduals() |
public function getSSRegression($dp=0) { |
if ($dp != 0) { |
return round($this->_SSRegression,$dp); |
} |
return $this->_SSRegression; |
} // function getSSRegression() |
public function getSSResiduals($dp=0) { |
if ($dp != 0) { |
return round($this->_SSResiduals,$dp); |
} |
return $this->_SSResiduals; |
} // function getSSResiduals() |
public function getDFResiduals($dp=0) { |
if ($dp != 0) { |
return round($this->_DFResiduals,$dp); |
} |
return $this->_DFResiduals; |
} // function getDFResiduals() |
public function getF($dp=0) { |
if ($dp != 0) { |
return round($this->_F,$dp); |
} |
return $this->_F; |
} // function getF() |
public function getCovariance($dp=0) { |
if ($dp != 0) { |
return round($this->_covariance,$dp); |
} |
return $this->_covariance; |
} // function getCovariance() |
public function getCorrelation($dp=0) { |
if ($dp != 0) { |
return round($this->_correlation,$dp); |
} |
return $this->_correlation; |
} // function getCorrelation() |
public function getYBestFitValues() { |
return $this->_yBestFitValues; |
} // function getYBestFitValues() |
protected function _calculateGoodnessOfFit($sumX,$sumY,$sumX2,$sumY2,$sumXY,$meanX,$meanY, $const) { |
$SSres = $SScov = $SScor = $SStot = $SSsex = 0.0; |
foreach($this->_xValues as $xKey => $xValue) { |
$bestFitY = $this->_yBestFitValues[$xKey] = $this->getValueOfYForX($xValue); |
$SSres += ($this->_yValues[$xKey] - $bestFitY) * ($this->_yValues[$xKey] - $bestFitY); |
if ($const) { |
$SStot += ($this->_yValues[$xKey] - $meanY) * ($this->_yValues[$xKey] - $meanY); |
} else { |
$SStot += $this->_yValues[$xKey] * $this->_yValues[$xKey]; |
} |
$SScov += ($this->_xValues[$xKey] - $meanX) * ($this->_yValues[$xKey] - $meanY); |
if ($const) { |
$SSsex += ($this->_xValues[$xKey] - $meanX) * ($this->_xValues[$xKey] - $meanX); |
} else { |
$SSsex += $this->_xValues[$xKey] * $this->_xValues[$xKey]; |
} |
} |
$this->_SSResiduals = $SSres; |
$this->_DFResiduals = $this->_valueCount - 1 - $const; |
if ($this->_DFResiduals == 0.0) { |
$this->_stdevOfResiduals = 0.0; |
} else { |
$this->_stdevOfResiduals = sqrt($SSres / $this->_DFResiduals); |
} |
if (($SStot == 0.0) || ($SSres == $SStot)) { |
$this->_goodnessOfFit = 1; |
} else { |
$this->_goodnessOfFit = 1 - ($SSres / $SStot); |
} |
$this->_SSRegression = $this->_goodnessOfFit * $SStot; |
$this->_covariance = $SScov / $this->_valueCount; |
$this->_correlation = ($this->_valueCount * $sumXY - $sumX * $sumY) / sqrt(($this->_valueCount * $sumX2 - pow($sumX,2)) * ($this->_valueCount * $sumY2 - pow($sumY,2))); |
$this->_slopeSE = $this->_stdevOfResiduals / sqrt($SSsex); |
$this->_intersectSE = $this->_stdevOfResiduals * sqrt(1 / ($this->_valueCount - ($sumX * $sumX) / $sumX2)); |
if ($this->_SSResiduals != 0.0) { |
if ($this->_DFResiduals == 0.0) { |
$this->_F = 0.0; |
} else { |
$this->_F = $this->_SSRegression / ($this->_SSResiduals / $this->_DFResiduals); |
} |
} else { |
if ($this->_DFResiduals == 0.0) { |
$this->_F = 0.0; |
} else { |
$this->_F = $this->_SSRegression / $this->_DFResiduals; |
} |
} |
} // function _calculateGoodnessOfFit() |
protected function _leastSquareFit($yValues, $xValues, $const) { |
// calculate sums |
$x_sum = array_sum($xValues); |
$y_sum = array_sum($yValues); |
$meanX = $x_sum / $this->_valueCount; |
$meanY = $y_sum / $this->_valueCount; |
$mBase = $mDivisor = $xx_sum = $xy_sum = $yy_sum = 0.0; |
for($i = 0; $i < $this->_valueCount; ++$i) { |
$xy_sum += $xValues[$i] * $yValues[$i]; |
$xx_sum += $xValues[$i] * $xValues[$i]; |
$yy_sum += $yValues[$i] * $yValues[$i]; |
if ($const) { |
$mBase += ($xValues[$i] - $meanX) * ($yValues[$i] - $meanY); |
$mDivisor += ($xValues[$i] - $meanX) * ($xValues[$i] - $meanX); |
} else { |
$mBase += $xValues[$i] * $yValues[$i]; |
$mDivisor += $xValues[$i] * $xValues[$i]; |
} |
} |
// calculate slope |
// $this->_slope = (($this->_valueCount * $xy_sum) - ($x_sum * $y_sum)) / (($this->_valueCount * $xx_sum) - ($x_sum * $x_sum)); |
$this->_slope = $mBase / $mDivisor; |
// calculate intersect |
// $this->_intersect = ($y_sum - ($this->_slope * $x_sum)) / $this->_valueCount; |
if ($const) { |
$this->_intersect = $meanY - ($this->_slope * $meanX); |
} else { |
$this->_intersect = 0; |
} |
$this->_calculateGoodnessOfFit($x_sum,$y_sum,$xx_sum,$yy_sum,$xy_sum,$meanX,$meanY,$const); |
} // function _leastSquareFit() |
/** |
* Define the regression |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
function __construct($yValues, $xValues=array(), $const=True) { |
// Calculate number of points |
$nY = count($yValues); |
$nX = count($xValues); |
// Define X Values if necessary |
if ($nX == 0) { |
$xValues = range(1,$nY); |
$nX = $nY; |
} elseif ($nY != $nX) { |
// Ensure both arrays of points are the same size |
$this->_error = True; |
return False; |
} |
$this->_valueCount = $nY; |
$this->_xValues = $xValues; |
$this->_yValues = $yValues; |
} // function __construct() |
} // class bestFit |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/trend/logarithmicBestFitClass.php |
---|
New file |
0,0 → 1,120 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); |
/** |
* PHPExcel_Logarithmic_Best_Fit |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit |
{ |
/** |
* Algorithm type to use for best-fit |
* (Name of this trend class) |
* |
* @var string |
**/ |
protected $_bestFitType = 'logarithmic'; |
/** |
* Return the Y-Value for a specified value of X |
* |
* @param float $xValue X-Value |
* @return float Y-Value |
**/ |
public function getValueOfYForX($xValue) { |
return $this->getIntersect() + $this->getSlope() * log($xValue - $this->_Xoffset); |
} // function getValueOfYForX() |
/** |
* Return the X-Value for a specified value of Y |
* |
* @param float $yValue Y-Value |
* @return float X-Value |
**/ |
public function getValueOfXForY($yValue) { |
return exp(($yValue - $this->getIntersect()) / $this->getSlope()); |
} // function getValueOfXForY() |
/** |
* Return the Equation of the best-fit line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getEquation($dp=0) { |
$slope = $this->getSlope($dp); |
$intersect = $this->getIntersect($dp); |
return 'Y = '.$intersect.' + '.$slope.' * log(X)'; |
} // function getEquation() |
/** |
* Execute the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
private function _logarithmic_regression($yValues, $xValues, $const) { |
foreach($xValues as &$value) { |
if ($value < 0.0) { |
$value = 0 - log(abs($value)); |
} elseif ($value > 0.0) { |
$value = log($value); |
} |
} |
unset($value); |
$this->_leastSquareFit($yValues, $xValues, $const); |
} // function _logarithmic_regression() |
/** |
* Define the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
function __construct($yValues, $xValues=array(), $const=True) { |
if (parent::__construct($yValues, $xValues) !== False) { |
$this->_logarithmic_regression($yValues, $xValues, $const); |
} |
} // function __construct() |
} // class logarithmicBestFit |
/trunk/jrest/lib/PHPExcel/Classes/PHPExcel/Shared/trend/polynomialBestFitClass.php |
---|
New file |
0,0 → 1,224 |
<?php |
/** |
* PHPExcel |
* |
* Copyright (c) 2006 - 2013 PHPExcel |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
* License as published by the Free Software Foundation; either |
* version 2.1 of the License, or (at your option) any later version. |
* |
* This library is distributed in the hope that it will be useful, |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 library; if not, write to the Free Software |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL |
* @version ##VERSION##, ##DATE## |
*/ |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; |
require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; |
/** |
* PHPExcel_Polynomial_Best_Fit |
* |
* @category PHPExcel |
* @package PHPExcel_Shared_Trend |
* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) |
*/ |
class PHPExcel_Polynomial_Best_Fit extends PHPExcel_Best_Fit |
{ |
/** |
* Algorithm type to use for best-fit |
* (Name of this trend class) |
* |
* @var string |
**/ |
protected $_bestFitType = 'polynomial'; |
/** |
* Polynomial order |
* |
* @protected |
* @var int |
**/ |
protected $_order = 0; |
/** |
* Return the order of this polynomial |
* |
* @return int |
**/ |
public function getOrder() { |
return $this->_order; |
} // function getOrder() |
/** |
* Return the Y-Value for a specified value of X |
* |
* @param float $xValue X-Value |
* @return float Y-Value |
**/ |
public function getValueOfYForX($xValue) { |
$retVal = $this->getIntersect(); |
$slope = $this->getSlope(); |
foreach($slope as $key => $value) { |
if ($value != 0.0) { |
$retVal += $value * pow($xValue, $key + 1); |
} |
} |
return $retVal; |
} // function getValueOfYForX() |
/** |
* Return the X-Value for a specified value of Y |
* |
* @param float $yValue Y-Value |
* @return float X-Value |
**/ |
public function getValueOfXForY($yValue) { |
return ($yValue - $this->getIntersect()) / $this->getSlope(); |
} // function getValueOfXForY() |
/** |
* Return the Equation of the best-fit line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getEquation($dp=0) { |
$slope = $this->getSlope($dp); |
$intersect = $this->getIntersect($dp); |
$equation = 'Y = '.$intersect; |
foreach($slope as $key => $value) { |
if ($value != 0.0) { |
$equation .= ' + '.$value.' * X'; |
if ($key > 0) { |
$equation .= '^'.($key + 1); |
} |
} |
} |
return $equation; |
} // function getEquation() |
/** |
* Return the Slope of the line |
* |
* @param int $dp Number of places of decimal precision to display |
* @return string |
**/ |
public function getSlope($dp=0) { |
if ($dp != 0) { |
$coefficients = array(); |
foreach($this->_slope as $coefficient) { |
$coefficients[] = round($coefficient,$dp); |
} |
return $coefficients; |
} |
return $this->_slope; |
} // function getSlope() |
public function getCoefficients($dp=0) { |
return array_merge(array($this->getIntersect($dp)),$this->getSlope($dp)); |
} // function getCoefficients() |
/** |
* Execute the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param int $order Order of Polynomial for this regression |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
private function _polynomial_regression($order, $yValues, $xValues, $const) { |
// calculate sums |
$x_sum = array_sum($xValues); |
$y_sum = array_sum($yValues); |
$xx_sum = $xy_sum = 0; |
for($i = 0; $i < $this->_valueCount; ++$i) { |
$xy_sum += $xValues[$i] * $yValues[$i]; |
$xx_sum += $xValues[$i] * $xValues[$i]; |
$yy_sum += $yValues[$i] * $yValues[$i]; |
} |
/* |
* This routine uses logic from the PHP port of polyfit version 0.1 |
* written by Michael Bommarito and Paul Meagher |
* |
* The function fits a polynomial function of order $order through |
* a series of x-y data points using least squares. |
* |
*/ |
for ($i = 0; $i < $this->_valueCount; ++$i) { |
for ($j = 0; $j <= $order; ++$j) { |
$A[$i][$j] = pow($xValues[$i], $j); |
} |
} |
for ($i=0; $i < $this->_valueCount; ++$i) { |
$B[$i] = array($yValues[$i]); |
} |
$matrixA = new Matrix($A); |
$matrixB = new Matrix($B); |
$C = $matrixA->solve($matrixB); |
$coefficients = array(); |
for($i = 0; $i < $C->m; ++$i) { |
$r = $C->get($i, 0); |
if (abs($r) <= pow(10, -9)) { |
$r = 0; |
} |
$coefficients[] = $r; |
} |
$this->_intersect = array_shift($coefficients); |
$this->_slope = $coefficients; |
$this->_calculateGoodnessOfFit($x_sum,$y_sum,$xx_sum,$yy_sum,$xy_sum); |
foreach($this->_xValues as $xKey => $xValue) { |
$this->_yBestFitValues[$xKey] = $this->getValueOfYForX($xValue); |
} |
} // function _polynomial_regression() |
/** |
* Define the regression and calculate the goodness of fit for a set of X and Y data values |
* |
* @param int $order Order of Polynomial for this regression |
* @param float[] $yValues The set of Y-values for this regression |
* @param float[] $xValues The set of X-values for this regression |
* @param boolean $const |
*/ |
function __construct($order, $yValues, $xValues=array(), $const=True) { |
if (parent::__construct($yValues, $xValues) !== False) { |
if ($order < $this->_valueCount) { |
$this->_bestFitType .= '_'.$order; |
$this->_order = $order; |
$this->_polynomial_regression($order, $yValues, $xValues, $const); |
if (($this->getGoodnessOfFit() < 0.0) || ($this->getGoodnessOfFit() > 1.0)) { |
$this->_error = True; |
} |
} else { |
$this->_error = True; |
} |
} |
} // function __construct() |
} // class polynomialBestFit |