diff options
Diffstat (limited to 'admin/survey/excel/PHPExcel/Shared')
54 files changed, 20412 insertions, 0 deletions
diff --git a/admin/survey/excel/PHPExcel/Shared/CodePage.php b/admin/survey/excel/PHPExcel/Shared/CodePage.php new file mode 100644 index 0000000..1b99347 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/CodePage.php @@ -0,0 +1,101 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_CodePage
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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 int $number Microsoft Code Page Indentifier
+ * @return string Code Page Name
+ * @throws 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 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 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 Exception('Unknown codepage: ' . $codePage);
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Date.php b/admin/survey/excel/PHPExcel/Shared/Date.php new file mode 100644 index 0000000..600d54c --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Date.php @@ -0,0 +1,356 @@ +<?php
+
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_Date
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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'
+ );
+
+ /*
+ * Base calendar year to use for calculations
+ *
+ * @private
+ * @var int
+ */
+ private static $ExcelBaseDate = self::CALENDAR_WINDOWS_1900;
+
+ /*
+ * Object type for PHP Date/Time values
+ *
+ * @private
+ * @var string
+ */
+ public static $dateTimeObjectType = 'DateTime';
+
+
+ /**
+ * Set the Excel calendar (Windows 1900 or Mac 1904)
+ *
+ * @param integer $baseDate Excel base date
+ * @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 $baseDate Excel base date
+ */
+ public static function getExcelCalendar() {
+ return self::$ExcelBaseDate;
+ } // function getExcelCalendar()
+
+
+ /**
+ * Convert a date from Excel to PHP
+ *
+ * @param long $dateValue Excel date/time value
+ * @return long PHP serialized date/time
+ */
+ public static function ExcelToPHP($dateValue = 0) {
+ if (self::$ExcelBaseDate == self::CALENDAR_WINDOWS_1900) {
+ $myExcelBaseDate = 25569;
+ // Adjust for the spurious 29-Feb-1900 (Day 60)
+ if ($dateValue < 60) {
+ --$myExcelBaseDate;
+ }
+ } else {
+ $myExcelBaseDate = 24107;
+ }
+
+ // Perform conversion
+ if ($dateValue >= 1) {
+ $utcDays = $dateValue - $myExcelBaseDate;
+ $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);
+ }
+
+ // Return
+ return $returnValue;
+ } // function ExcelToPHP()
+
+
+ /**
+ * Convert a date from Excel to a PHP Date/Time object
+ *
+ * @param long $dateValue Excel date/time value
+ * @return long 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
+ * @return mixed Excel date/time value
+ * or boolean FALSE on failure
+ */
+ public static function PHPToExcel($dateValue = 0) {
+ $saveTimeZone = date_default_timezone_get();
+ date_default_timezone_set('UTC');
+ $retValue = FALSE;
+ if ((is_object($dateValue)) && ($dateValue instanceof self::$dateTimeObjectType)) {
+ $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; }
+ $myExcelBaseDate = 2415020;
+ } else {
+ $myExcelBaseDate = 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 - $myExcelBaseDate + $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->getParent()->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) {
+ $i = FALSE;
+ foreach(explode('"',$pFormatCode) as $subVal) {
+ // Only test in alternate array entries (the non-quoted blocks)
+ if (($i = !$i) && (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;
+ }
+
+
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Drawing.php b/admin/survey/excel/PHPExcel/Shared/Drawing.php new file mode 100644 index 0000000..e8bf4a1 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Drawing.php @@ -0,0 +1,272 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_Drawing
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher.php b/admin/survey/excel/PHPExcel/Shared/Escher.php new file mode 100644 index 0000000..64c11c2 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher.php @@ -0,0 +1,91 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer.php b/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer.php new file mode 100644 index 0000000..c2e9e42 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer.php @@ -0,0 +1,83 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher_DgContainer
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php b/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php new file mode 100644 index 0000000..a33e4e4 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php @@ -0,0 +1,109 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher_DgContainer_SpgrContainer
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php new file mode 100644 index 0000000..b8ee537 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php @@ -0,0 +1,395 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer.php b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer.php new file mode 100644 index 0000000..b84da41 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer.php @@ -0,0 +1,203 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher_DggContainer
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php new file mode 100644 index 0000000..24d7ba3 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php @@ -0,0 +1,65 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher_DggContainer_BstoreContainer
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php new file mode 100644 index 0000000..80a9ef0 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -0,0 +1,120 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php new file mode 100644 index 0000000..46bfb16 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php @@ -0,0 +1,91 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Escher
+ * @copyright Copyright (c) 2006 - 2012 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Excel5.php b/admin/survey/excel/PHPExcel/Shared/Excel5.php new file mode 100644 index 0000000..55e9f72 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Excel5.php @@ -0,0 +1,317 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+/**
+ * PHPExcel_Shared_Excel5
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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 integer $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 $startOffset Offset within start cell measured in 1/1024 of the cell width
+ * @param string $endColumn
+ * @param integer $endOffset 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 string $startRow (1-based)
+ * @param integer $startOffset Offset within start cell measured in 1/256 of the cell height
+ * @param string $endRow (1-based)
+ * @param integer $endOffset 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/File.php b/admin/survey/excel/PHPExcel/Shared/File.php new file mode 100644 index 0000000..f6314ef --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/File.php @@ -0,0 +1,139 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_File
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ */
+class PHPExcel_Shared_File
+{
+ /**
+ * 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()
+ {
+ // 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());
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/Font.php b/admin/survey/excel/PHPExcel/Shared/Font.php new file mode 100644 index 0000000..9414463 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/Font.php @@ -0,0 +1,775 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_Font
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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 int $fontSize Font size (in pixels or points)
+ * @param bool $fontSizeInPixels Is the font size specified in pixels (true) or in points (false) ?
+ * @param string $cellText Text to calculate width
+ * @param int $rotation Rotation angle
+ * @return int 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 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 (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 Exception
+ */
+ public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) {
+ if (!function_exists('imagettfbbox')) {
+ throw new 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 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 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 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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/CHANGELOG.TXT b/admin/survey/excel/PHPExcel/Shared/JAMA/CHANGELOG.TXT new file mode 100644 index 0000000..2fc9cd4 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/CHANGELOG.TXT @@ -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.
+
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php b/admin/survey/excel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php new file mode 100644 index 0000000..2d1fdfb --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php @@ -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 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 Exception(JAMAError(MatrixSPDException));
+ }
+ } else {
+ throw new Exception(JAMAError(MatrixDimensionException));
+ }
+ } else {
+ throw new Exception(JAMAError(ArgumentTypeException));
+ }
+ } // function solve()
+
+} // class CholeskyDecomposition
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php b/admin/survey/excel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php new file mode 100644 index 0000000..716af82 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php @@ -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
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/LUDecomposition.php b/admin/survey/excel/PHPExcel/Shared/JAMA/LUDecomposition.php new file mode 100644 index 0000000..98e918c --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/LUDecomposition.php @@ -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 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 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,:)
+ * @exception IllegalArgumentException Matrix row dimensions must agree.
+ * @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 Exception(self::MatrixSingularException);
+ }
+ } else {
+ throw new Exception(self::MatrixSquareException);
+ }
+ } // function solve()
+
+} // class PHPExcel_Shared_JAMA_LUDecomposition
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/Matrix.php b/admin/survey/excel/PHPExcel/Shared/JAMA/Matrix.php new file mode 100644 index 0000000..e66e8e0 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/Matrix.php @@ -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 Exception(self::ArrayLengthException);
+ }
+ break;
+ default:
+ throw new Exception(self::PolymorphicArgumentException);
+ break;
+ }
+ } else {
+ throw new 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 Exception(self::ArgumentBoundsException); }
+ if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new 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 Exception(self::ArgumentBoundsException); }
+ if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new 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 Exception(self::ArgumentBoundsException); }
+ if (count($CL) > 0) { $n = count($CL); } else { throw new 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 Exception(self::ArgumentBoundsException); }
+ if (count($CL) > 0) { $n = count($CL); } else { throw new 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 Exception(self::ArgumentBoundsException); }
+ if (count($CL) > 0) { $n = count($CL); } else { throw new 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 Exception(self::ArgumentBoundsException); }
+ if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new 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 Exception(self::PolymorphicArgumentException);
+ break;
+ }
+ } else {
+ throw new 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 Exception(self::MatrixDimensionException);
+ }
+ } else {
+ throw new 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 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 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 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 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 Exception(self::PolymorphicArgumentException);
+ break;
+ }
+ } else {
+ throw new 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 Exception(self::ArgumentTypeException); }
+ break;
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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 Exception(self::ArgumentTypeException); }
+ case 'array':
+ $M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
+ break;
+ default:
+ throw new 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 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
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/QRDecomposition.php b/admin/survey/excel/PHPExcel/Shared/JAMA/QRDecomposition.php new file mode 100644 index 0000000..4492fa5 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/QRDecomposition.php @@ -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 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 Exception(self::MatrixRankException);
+ }
+ } else {
+ throw new Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException);
+ }
+ } // function solve()
+
+} // PHPExcel_Shared_JAMA_class QRDecomposition
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php b/admin/survey/excel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php new file mode 100644 index 0000000..ecfb0cd --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/SingularValueDecomposition.php @@ -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
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LMQuadTest.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LMQuadTest.php new file mode 100644 index 0000000..706d9e9 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LMQuadTest.php @@ -0,0 +1,116 @@ +<?php
+/**
+ * quadratic (p-o)'S'S(p-o)
+ * solve for o, S
+ * S is a single scale factor
+ */
+class LMQuadTest {
+
+ /**
+ * @param array[] $x
+ * @param array[] $a
+ */
+ function val($x, $a) {
+ if (count($a) != 3) die ("Wrong number of elements in array a");
+ if (count($x) != 2) die ("Wrong number of elements in array x");
+
+ $ox = $a[0];
+ $oy = $a[1];
+ $s = $a[2];
+
+ $sdx = $s * ($x[0] - $ox);
+ $sdy = $s * ($x[1] - $oy);
+
+ return ($sdx * $sdx) + ($sdy * $sdy);
+ } // function val()
+
+
+ /**
+ * z = (p-o)'S'S(p-o)
+ * dz/dp = 2S'S(p-o)
+ *
+ * z = (s*(px-ox))^2 + (s*(py-oy))^2
+ * dz/dox = -2(s*(px-ox))*s
+ * dz/ds = 2*s*[(px-ox)^2 + (py-oy)^2]
+ *
+ * z = (s*dx)^2 + (s*dy)^2
+ * dz/ds = 2(s*dx)*dx + 2(s*dy)*dy
+ *
+ * @param array[] $x
+ * @param array[] $a
+ * @param int $a_k
+ * @param array[] $a
+ */
+ function grad($x, $a, $a_k) {
+ if (count($a) != 3) die ("Wrong number of elements in array a");
+ if (count($x) != 2) die ("Wrong number of elements in array x");
+ if ($a_k < 3) die ("a_k=".$a_k);
+
+ $ox = $a[0];
+ $oy = $a[1];
+ $s = $a[2];
+
+ $dx = ($x[0] - $ox);
+ $dy = ($x[1] - $oy);
+
+ if ($a_k == 0)
+ return -2.*$s*$s*$dx;
+ elseif ($a_k == 1)
+ return -2.*$s*$s*$dy;
+ else
+ return 2.*$s*($dx*$dx + $dy*$dy);
+ } // function grad()
+
+
+ /**
+ * @return array[] $a
+ */
+ function initial() {
+ $a[0] = 0.05;
+ $a[1] = 0.1;
+ $a[2] = 1.0;
+
+ return $a;
+ } // function initial()
+
+
+ /**
+ * @return Object[] $a
+ */
+ function testdata() {
+ $npts = 25;
+
+ $a[0] = 0.;
+ $a[1] = 0.;
+ $a[2] = 0.9;
+
+ $i = 0;
+
+ for ($r = -2; $r <= 2; ++$r) {
+ for ($c = -2; $c <= 2; ++$c) {
+ $x[$i][0] = $c;
+ $x[$i][1] = $r;
+ $y[$i] = $this->val($x[$i], $a);
+ print("Quad ".$c.",".$r." -> ".$y[$i]."<br />");
+ $s[$i] = 1.;
+ ++$i;
+ }
+ }
+ print("quad x= ");
+
+ $qx = new Matrix($x);
+ $qx->print(10, 2);
+
+ print("quad y= ");
+ $qy = new Matrix($y, $npts);
+ $qy->print(10, 2);
+
+ $o[0] = $x;
+ $o[1] = $a;
+ $o[2] = $y;
+ $o[3] = $s;
+
+ return $o;
+ } // function testdata()
+
+} // class LMQuadTest
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php new file mode 100644 index 0000000..27c8937 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php @@ -0,0 +1,59 @@ +<?php
+
+require_once "../Matrix.php";
+
+/**
+ * Given n points (x0,y0)...(xn-1,yn-1), the following methid computes
+ * the polynomial factors of the n-1't degree polynomial passing through
+ * the n points.
+ *
+ * Example: Passing in three points (2,3) (1,4) and (3,7) will produce
+ * the results [2.5, -8.5, 10] which means that the points are on the
+ * curve y = 2.5x² - 8.5x + 10.
+ *
+ * @see http://geosoft.no/software/lagrange/LagrangeInterpolation.java.html
+ * @author Jacob Dreyer
+ * @author Paul Meagher (port to PHP and minor changes)
+ *
+ * @param x[] float
+ * @param y[] float
+ */
+class LagrangeInterpolation {
+
+ public function findPolynomialFactors($x, $y) {
+ $n = count($x);
+
+ $data = array(); // double[n][n];
+ $rhs = array(); // double[n];
+
+ for ($i = 0; $i < $n; ++$i) {
+ $v = 1;
+ for ($j = 0; $j < $n; ++$j) {
+ $data[$i][$n-$j-1] = $v;
+ $v *= $x[$i];
+ }
+ $rhs[$i] = $y[$i];
+ }
+
+ // Solve m * s = b
+ $m = new Matrix($data);
+ $b = new Matrix($rhs, $n);
+
+ $s = $m->solve($b);
+
+ return $s->getRowPackedCopy();
+ } // function findPolynomialFactors()
+
+} // class LagrangeInterpolation
+
+
+$x = array(2.0, 1.0, 3.0);
+$y = array(3.0, 4.0, 7.0);
+
+$li = new LagrangeInterpolation;
+$f = $li->findPolynomialFactors($x, $y);
+
+
+for ($i = 0; $i < 3; ++$i) {
+ echo $f[$i]."<br />";
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php new file mode 100644 index 0000000..cd9cb9a --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php @@ -0,0 +1,59 @@ +<?php
+
+require_once "../Matrix.php";
+
+/**
+ * Given n points (x0,y0)...(xn-1,yn-1), the following method computes
+ * the polynomial factors of the n-1't degree polynomial passing through
+ * the n points.
+ *
+ * Example: Passing in three points (2,3) (1,4) and (3,7) will produce
+ * the results [2.5, -8.5, 10] which means that the points are on the
+ * curve y = 2.5x² - 8.5x + 10.
+ *
+ * @see http://geosoft.no/software/lagrange/LagrangeInterpolation.java.html
+ * @see http://source.freehep.org/jcvsweb/ilc/LCSIM/wdview/lcsim/src/org/lcsim/fit/polynomial/PolynomialFitter.java
+ * @author Jacob Dreyer
+ * @author Paul Meagher (port to PHP and minor changes)
+ *
+ * @param x[] float
+ * @param y[] float
+ */
+class LagrangeInterpolation {
+
+ public function findPolynomialFactors($x, $y) {
+ $n = count($x);
+
+ $data = array(); // double[n][n];
+ $rhs = array(); // double[n];
+
+ for ($i = 0; $i < $n; ++$i) {
+ $v = 1;
+ for ($j = 0; $j < $n; ++$j) {
+ $data[$i][$n-$j-1] = $v;
+ $v *= $x[$i];
+ }
+ $rhs[$i] = $y[$i];
+ }
+
+ // Solve m * s = b
+ $m = new Matrix($data);
+ $b = new Matrix($rhs, $n);
+
+ $s = $m->solve($b);
+
+ return $s->getRowPackedCopy();
+ } // function findPolynomialFactors()
+
+} // class LagrangeInterpolation
+
+
+$x = array(2.0, 1.0, 3.0);
+$y = array(3.0, 4.0, 7.0);
+
+$li = new LagrangeInterpolation;
+$f = $li->findPolynomialFactors($x, $y);
+
+for ($i = 0; $i < 3; ++$i) {
+ echo $f[$i]."<br />";
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php new file mode 100644 index 0000000..01c4acc --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php @@ -0,0 +1,185 @@ +<?php
+
+// Levenberg-Marquardt in PHP
+
+// http://www.idiom.com/~zilla/Computer/Javanumeric/LM.java
+
+class LevenbergMarquardt {
+
+ /**
+ * Calculate the current sum-squared-error
+ *
+ * Chi-squared is the distribution of squared Gaussian errors,
+ * thus the name.
+ *
+ * @param double[][] $x
+ * @param double[] $a
+ * @param double[] $y,
+ * @param double[] $s,
+ * @param object $f
+ */
+ function chiSquared($x, $a, $y, $s, $f) {
+ $npts = count($y);
+ $sum = 0.0;
+
+ for ($i = 0; $i < $npts; ++$i) {
+ $d = $y[$i] - $f->val($x[$i], $a);
+ $d = $d / $s[$i];
+ $sum = $sum + ($d*$d);
+ }
+
+ return $sum;
+ } // function chiSquared()
+
+
+ /**
+ * Minimize E = sum {(y[k] - f(x[k],a)) / s[k]}^2
+ * The individual errors are optionally scaled by s[k].
+ * Note that LMfunc implements the value and gradient of f(x,a),
+ * NOT the value and gradient of E with respect to a!
+ *
+ * @param x array of domain points, each may be multidimensional
+ * @param y corresponding array of values
+ * @param a the parameters/state of the model
+ * @param vary false to indicate the corresponding a[k] is to be held fixed
+ * @param s2 sigma^2 for point i
+ * @param lambda blend between steepest descent (lambda high) and
+ * jump to bottom of quadratic (lambda zero).
+ * Start with 0.001.
+ * @param termepsilon termination accuracy (0.01)
+ * @param maxiter stop and return after this many iterations if not done
+ * @param verbose set to zero (no prints), 1, 2
+ *
+ * @return the new lambda for future iterations.
+ * Can use this and maxiter to interleave the LM descent with some other
+ * task, setting maxiter to something small.
+ */
+ function solve($x, $a, $y, $s, $vary, $f, $lambda, $termepsilon, $maxiter, $verbose) {
+ $npts = count($y);
+ $nparm = count($a);
+
+ if ($verbose > 0) {
+ print("solve x[".count($x)."][".count($x[0])."]");
+ print(" a[".count($a)."]");
+ println(" y[".count(length)."]");
+ }
+
+ $e0 = $this->chiSquared($x, $a, $y, $s, $f);
+
+ //double lambda = 0.001;
+ $done = false;
+
+ // g = gradient, H = hessian, d = step to minimum
+ // H d = -g, solve for d
+ $H = array();
+ $g = array();
+
+ //double[] d = new double[nparm];
+
+ $oos2 = array();
+
+ for($i = 0; $i < $npts; ++$i) {
+ $oos2[$i] = 1./($s[$i]*$s[$i]);
+ }
+ $iter = 0;
+ $term = 0; // termination count test
+
+ do {
+ ++$iter;
+
+ // hessian approximation
+ for( $r = 0; $r < $nparm; ++$r) {
+ for( $c = 0; $c < $nparm; ++$c) {
+ for( $i = 0; $i < $npts; ++$i) {
+ if ($i == 0) $H[$r][$c] = 0.;
+ $xi = $x[$i];
+ $H[$r][$c] += ($oos2[$i] * $f->grad($xi, $a, $r) * $f->grad($xi, $a, $c));
+ } //npts
+ } //c
+ } //r
+
+ // boost diagonal towards gradient descent
+ for( $r = 0; $r < $nparm; ++$r)
+ $H[$r][$r] *= (1. + $lambda);
+
+ // gradient
+ for( $r = 0; $r < $nparm; ++$r) {
+ for( $i = 0; $i < $npts; ++$i) {
+ if ($i == 0) $g[$r] = 0.;
+ $xi = $x[$i];
+ $g[$r] += ($oos2[$i] * ($y[$i]-$f->val($xi,$a)) * $f->grad($xi, $a, $r));
+ }
+ } //npts
+
+ // scale (for consistency with NR, not necessary)
+ if ($false) {
+ for( $r = 0; $r < $nparm; ++$r) {
+ $g[$r] = -0.5 * $g[$r];
+ for( $c = 0; $c < $nparm; ++$c) {
+ $H[$r][$c] *= 0.5;
+ }
+ }
+ }
+
+ // solve H d = -g, evaluate error at new location
+ //double[] d = DoubleMatrix.solve(H, g);
+// double[] d = (new Matrix(H)).lu().solve(new Matrix(g, nparm)).getRowPackedCopy();
+ //double[] na = DoubleVector.add(a, d);
+// double[] na = (new Matrix(a, nparm)).plus(new Matrix(d, nparm)).getRowPackedCopy();
+// double e1 = chiSquared(x, na, y, s, f);
+
+// if (verbose > 0) {
+// System.out.println("\n\niteration "+iter+" lambda = "+lambda);
+// System.out.print("a = ");
+// (new Matrix(a, nparm)).print(10, 2);
+// if (verbose > 1) {
+// System.out.print("H = ");
+// (new Matrix(H)).print(10, 2);
+// System.out.print("g = ");
+// (new Matrix(g, nparm)).print(10, 2);
+// System.out.print("d = ");
+// (new Matrix(d, nparm)).print(10, 2);
+// }
+// System.out.print("e0 = " + e0 + ": ");
+// System.out.print("moved from ");
+// (new Matrix(a, nparm)).print(10, 2);
+// System.out.print("e1 = " + e1 + ": ");
+// if (e1 < e0) {
+// System.out.print("to ");
+// (new Matrix(na, nparm)).print(10, 2);
+// } else {
+// System.out.println("move rejected");
+// }
+// }
+
+ // termination test (slightly different than NR)
+// if (Math.abs(e1-e0) > termepsilon) {
+// term = 0;
+// } else {
+// term++;
+// if (term == 4) {
+// System.out.println("terminating after " + iter + " iterations");
+// done = true;
+// }
+// }
+// if (iter >= maxiter) done = true;
+
+ // in the C++ version, found that changing this to e1 >= e0
+ // was not a good idea. See comment there.
+ //
+// if (e1 > e0 || Double.isNaN(e1)) { // new location worse than before
+// lambda *= 10.;
+// } else { // new location better, accept new parameters
+// lambda *= 0.1;
+// e0 = e1;
+// // simply assigning a = na will not get results copied back to caller
+// for( int i = 0; i < nparm; i++ ) {
+// if (vary[i]) a[i] = na[i];
+// }
+// }
+ } while(!$done);
+
+ return $lambda;
+ } // function solve()
+
+} // class LevenbergMarquardt
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/MagicSquareExample.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/MagicSquareExample.php new file mode 100644 index 0000000..8a66903 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/MagicSquareExample.php @@ -0,0 +1,182 @@ +<?php
+/**
+* @package JAMA
+*/
+
+require_once "../Matrix.php";
+
+/**
+* Example of use of Matrix Class, featuring magic squares.
+*/
+class MagicSquareExample {
+
+ /**
+ * Generate magic square test matrix.
+ * @param int n dimension of matrix
+ */
+ function magic($n) {
+
+ // Odd order
+
+ if (($n % 2) == 1) {
+ $a = ($n+1)/2;
+ $b = ($n+1);
+ for ($j = 0; $j < $n; ++$j)
+ for ($i = 0; $i < $n; ++$i)
+ $M[$i][$j] = $n*(($i+$j+$a) % $n) + (($i+2*$j+$b) % $n) + 1;
+
+ // Doubly Even Order
+
+ } else if (($n % 4) == 0) {
+ for ($j = 0; $j < $n; ++$j) {
+ for ($i = 0; $i < $n; ++$i) {
+ if ((($i+1)/2)%2 == (($j+1)/2)%2)
+ $M[$i][$j] = $n*$n-$n*$i-$j;
+ else
+ $M[$i][$j] = $n*$i+$j+1;
+ }
+ }
+
+ // Singly Even Order
+
+ } else {
+
+ $p = $n/2;
+ $k = ($n-2)/4;
+ $A = $this->magic($p);
+ $M = array();
+ for ($j = 0; $j < $p; ++$j) {
+ for ($i = 0; $i < $p; ++$i) {
+ $aij = $A->get($i,$j);
+ $M[$i][$j] = $aij;
+ $M[$i][$j+$p] = $aij + 2*$p*$p;
+ $M[$i+$p][$j] = $aij + 3*$p*$p;
+ $M[$i+$p][$j+$p] = $aij + $p*$p;
+ }
+ }
+
+ for ($i = 0; $i < $p; ++$i) {
+ for ($j = 0; $j < $k; ++$j) {
+ $t = $M[$i][$j];
+ $M[$i][$j] = $M[$i+$p][$j];
+ $M[$i+$p][$j] = $t;
+ }
+ for ($j = $n-$k+1; $j < $n; ++$j) {
+ $t = $M[$i][$j];
+ $M[$i][$j] = $M[$i+$p][$j];
+ $M[$i+$p][$j] = $t;
+ }
+ }
+
+ $t = $M[$k][0]; $M[$k][0] = $M[$k+$p][0]; $M[$k+$p][0] = $t;
+ $t = $M[$k][$k]; $M[$k][$k] = $M[$k+$p][$k]; $M[$k+$p][$k] = $t;
+
+ }
+
+ return new Matrix($M);
+
+ }
+
+ /**
+ * Simple function to replicate PHP 5 behaviour
+ */
+ function microtime_float() {
+ list($usec, $sec) = explode(" ", microtime());
+ return ((float)$usec + (float)$sec);
+ }
+
+ /**
+ * Tests LU, QR, SVD and symmetric Eig decompositions.
+ *
+ * n = order of magic square.
+ * trace = diagonal sum, should be the magic sum, (n^3 + n)/2.
+ * max_eig = maximum eigenvalue of (A + A')/2, should equal trace.
+ * rank = linear algebraic rank, should equal n if n is odd,
+ * be less than n if n is even.
+ * cond = L_2 condition number, ratio of singular values.
+ * lu_res = test of LU factorization, norm1(L*U-A(p,:))/(n*eps).
+ * qr_res = test of QR factorization, norm1(Q*R-A)/(n*eps).
+ */
+ function main() {
+ ?>
+ <p>Test of Matrix Class, using magic squares.</p>
+ <p>See MagicSquareExample.main() for an explanation.</p>
+ <table border='1' cellspacing='0' cellpadding='4'>
+ <tr>
+ <th>n</th>
+ <th>trace</th>
+ <th>max_eig</th>
+ <th>rank</th>
+ <th>cond</th>
+ <th>lu_res</th>
+ <th>qr_res</th>
+ </tr>
+ <?php
+ $start_time = $this->microtime_float();
+ $eps = pow(2.0,-52.0);
+ for ($n = 3; $n <= 6; ++$n) {
+ echo "<tr>";
+
+ echo "<td align='right'>$n</td>";
+
+ $M = $this->magic($n);
+ $t = (int) $M->trace();
+
+ echo "<td align='right'>$t</td>";
+
+ $O = $M->plus($M->transpose());
+ $E = new EigenvalueDecomposition($O->times(0.5));
+ $d = $E->getRealEigenvalues();
+
+ echo "<td align='right'>".$d[$n-1]."</td>";
+
+ $r = $M->rank();
+
+ echo "<td align='right'>".$r."</td>";
+
+ $c = $M->cond();
+
+ if ($c < 1/$eps)
+ echo "<td align='right'>".sprintf("%.3f",$c)."</td>";
+ else
+ echo "<td align='right'>Inf</td>";
+
+ $LU = new LUDecomposition($M);
+ $L = $LU->getL();
+ $U = $LU->getU();
+ $p = $LU->getPivot();
+ // Java version: R = L.times(U).minus(M.getMatrix(p,0,n-1));
+ $S = $L->times($U);
+ $R = $S->minus($M->getMatrix($p,0,$n-1));
+ $res = $R->norm1()/($n*$eps);
+
+ echo "<td align='right'>".sprintf("%.3f",$res)."</td>";
+
+ $QR = new QRDecomposition($M);
+ $Q = $QR->getQ();
+ $R = $QR->getR();
+ $S = $Q->times($R);
+ $R = $S->minus($M);
+ $res = $R->norm1()/($n*$eps);
+
+ echo "<td align='right'>".sprintf("%.3f",$res)."</td>";
+
+ echo "</tr>";
+
+ }
+ echo "<table>";
+ echo "<br />";
+
+ $stop_time = $this->microtime_float();
+ $etime = $stop_time - $start_time;
+
+ echo "<p>Elapsed time is ". sprintf("%.4f",$etime) ." seconds.</p>";
+
+ }
+
+}
+
+$magic = new MagicSquareExample();
+$magic->main();
+
+?>
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/Stats.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/Stats.php new file mode 100644 index 0000000..7d1359b --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/Stats.php @@ -0,0 +1,1605 @@ +<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Jesus M. Castagnetto <jmcastagnetto@php.net> |
+// +----------------------------------------------------------------------+
+//
+// $Id: Stats.php,v 1.15 2003/06/01 11:40:30 jmcastagnetto Exp $
+//
+
+include_once 'PEAR.php';
+
+/**
+* @package Math_Stats
+*/
+
+// Constants for defining the statistics to calculate /*{{{*/
+/**
+* STATS_BASIC to generate the basic descriptive statistics
+*/
+define('STATS_BASIC', 1);
+/**
+* STATS_FULL to generate also higher moments, mode, median, etc.
+*/
+define('STATS_FULL', 2);
+/*}}}*/
+
+// Constants describing the data set format /*{{{*/
+/**
+* STATS_DATA_SIMPLE for an array of numeric values. This is the default.
+* e.g. $data = array(2,3,4,5,1,1,6);
+*/
+define('STATS_DATA_SIMPLE', 0);
+/**
+* STATS_DATA_CUMMULATIVE for an associative array of frequency values,
+* where in each array entry, the index is the data point and the
+* value the count (frequency):
+* e.g. $data = array(3=>4, 2.3=>5, 1.25=>6, 0.5=>3)
+*/
+define('STATS_DATA_CUMMULATIVE', 1);
+/*}}}*/
+
+// Constants defining how to handle nulls /*{{{*/
+/**
+* STATS_REJECT_NULL, reject data sets with null values. This is the default.
+* Any non-numeric value is considered a null in this context.
+*/
+define('STATS_REJECT_NULL', -1);
+/**
+* STATS_IGNORE_NULL, ignore null values and prune them from the data.
+* Any non-numeric value is considered a null in this context.
+*/
+define('STATS_IGNORE_NULL', -2);
+/**
+* STATS_USE_NULL_AS_ZERO, assign the value of 0 (zero) to null values.
+* Any non-numeric value is considered a null in this context.
+*/
+define('STATS_USE_NULL_AS_ZERO', -3);
+/*}}}*/
+
+/**
+* A class to calculate descriptive statistics from a data set.
+* Data sets can be simple arrays of data, or a cummulative hash.
+* The second form is useful when passing large data set,
+* for example the data set:
+*
+* <pre>
+* $data1 = array (1,2,1,1,1,1,3,3,4.1,3,2,2,4.1,1,1,2,3,3,2,2,1,1,2,2);
+* </pre>
+*
+* can be epxressed more compactly as:
+*
+* <pre>
+* $data2 = array('1'=>9, '2'=>8, '3'=>5, '4.1'=>2);
+* </pre>
+*
+* Example of use:
+*
+* <pre>
+* include_once 'Math/Stats.php';
+* $s = new Math_Stats();
+* $s->setData($data1);
+* // or
+* // $s->setData($data2, STATS_DATA_CUMMULATIVE);
+* $stats = $s->calcBasic();
+* echo 'Mean: '.$stats['mean'].' StDev: '.$stats['stdev'].' <br />\n';
+*
+* // using data with nulls
+* // first ignoring them:
+* $data3 = array(1.2, 'foo', 2.4, 3.1, 4.2, 3.2, null, 5.1, 6.2);
+* $s->setNullOption(STATS_IGNORE_NULL);
+* $s->setData($data3);
+* $stats3 = $s->calcFull();
+*
+* // and then assuming nulls == 0
+* $s->setNullOption(STATS_USE_NULL_AS_ZERO);
+* $s->setData($data3);
+* $stats3 = $s->calcFull();
+* </pre>
+*
+* Originally this class was part of NumPHP (Numeric PHP package)
+*
+* @author Jesus M. Castagnetto <jmcastagnetto@php.net>
+* @version 0.8
+* @access public
+* @package Math_Stats
+*/
+class Base {/*{{{*/
+ // properties /*{{{*/
+
+ /**
+ * The simple or cummulative data set.
+ * Null by default.
+ *
+ * @access private
+ * @var array
+ */
+ public $_data = null;
+
+ /**
+ * Expanded data set. Only set when cummulative data
+ * is being used. Null by default.
+ *
+ * @access private
+ * @var array
+ */
+ public $_dataExpanded = null;
+
+ /**
+ * Flag for data type, one of STATS_DATA_SIMPLE or
+ * STATS_DATA_CUMMULATIVE. Null by default.
+ *
+ * @access private
+ * @var int
+ */
+ public $_dataOption = null;
+
+ /**
+ * Flag for null handling options. One of STATS_REJECT_NULL,
+ * STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO
+ *
+ * @access private
+ * @var int
+ */
+ public $_nullOption;
+
+ /**
+ * Array for caching result values, should be reset
+ * when using setData()
+ *
+ * @access private
+ * @var array
+ */
+ public $_calculatedValues = array();
+
+ /*}}}*/
+
+ /**
+ * Constructor for the class
+ *
+ * @access public
+ * @param optional int $nullOption how to handle null values
+ * @return object Math_Stats
+ */
+ function Math_Stats($nullOption=STATS_REJECT_NULL) {/*{{{*/
+ $this->_nullOption = $nullOption;
+ }/*}}}*/
+
+ /**
+ * Sets and verifies the data, checking for nulls and using
+ * the current null handling option
+ *
+ * @access public
+ * @param array $arr the data set
+ * @param optional int $opt data format: STATS_DATA_CUMMULATIVE or STATS_DATA_SIMPLE (default)
+ * @return mixed true on success, a PEAR_Error object otherwise
+ */
+ function setData($arr, $opt=STATS_DATA_SIMPLE) {/*{{{*/
+ if (!is_array($arr)) {
+ return PEAR::raiseError('invalid data, an array of numeric data was expected');
+ }
+ $this->_data = null;
+ $this->_dataExpanded = null;
+ $this->_dataOption = null;
+ $this->_calculatedValues = array();
+ if ($opt == STATS_DATA_SIMPLE) {
+ $this->_dataOption = $opt;
+ $this->_data = array_values($arr);
+ } else if ($opt == STATS_DATA_CUMMULATIVE) {
+ $this->_dataOption = $opt;
+ $this->_data = $arr;
+ $this->_dataExpanded = array();
+ }
+ return $this->_validate();
+ }/*}}}*/
+
+ /**
+ * Returns the data which might have been modified
+ * according to the current null handling options.
+ *
+ * @access public
+ * @param boolean $expanded whether to return a expanded list, default is false
+ * @return mixed array of data on success, a PEAR_Error object otherwise
+ * @see _validate()
+ */
+ function getData($expanded=false) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE && $expanded) {
+ return $this->_dataExpanded;
+ } else {
+ return $this->_data;
+ }
+ }/*}}}*/
+
+ /**
+ * Sets the null handling option.
+ * Must be called before assigning a new data set containing null values
+ *
+ * @access public
+ * @return mixed true on success, a PEAR_Error object otherwise
+ * @see _validate()
+ */
+ function setNullOption($nullOption) {/*{{{*/
+ if ($nullOption == STATS_REJECT_NULL
+ || $nullOption == STATS_IGNORE_NULL
+ || $nullOption == STATS_USE_NULL_AS_ZERO) {
+ $this->_nullOption = $nullOption;
+ return true;
+ } else {
+ return PEAR::raiseError('invalid null handling option expecting: '.
+ 'STATS_REJECT_NULL, STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO');
+ }
+ }/*}}}*/
+
+ /**
+ * Transforms the data by substracting each entry from the mean and
+ * dividing by its standard deviation. This will reset all pre-calculated
+ * values to their original (unset) defaults.
+ *
+ * @access public
+ * @return mixed true on success, a PEAR_Error object otherwise
+ * @see mean()
+ * @see stDev()
+ * @see setData()
+ */
+ function studentize() {/*{{{*/
+ $mean = $this->mean();
+ if (PEAR::isError($mean)) {
+ return $mean;
+ }
+ $std = $this->stDev();
+ if (PEAR::isError($std)) {
+ return $std;
+ }
+ if ($std == 0) {
+ return PEAR::raiseError('cannot studentize data, standard deviation is zero.');
+ }
+ $arr = array();
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ foreach ($this->_data as $val=>$freq) {
+ $newval = ($val - $mean) / $std;
+ $arr["$newval"] = $freq;
+ }
+ } else {
+ foreach ($this->_data as $val) {
+ $newval = ($val - $mean) / $std;
+ $arr[] = $newval;
+ }
+ }
+ return $this->setData($arr, $this->_dataOption);
+ }/*}}}*/
+
+ /**
+ * Transforms the data by substracting each entry from the mean.
+ * This will reset all pre-calculated values to their original (unset) defaults.
+ *
+ * @access public
+ * @return mixed true on success, a PEAR_Error object otherwise
+ * @see mean()
+ * @see setData()
+ */
+ function center() {/*{{{*/
+ $mean = $this->mean();
+ if (PEAR::isError($mean)) {
+ return $mean;
+ }
+ $arr = array();
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ foreach ($this->_data as $val=>$freq) {
+ $newval = $val - $mean;
+ $arr["$newval"] = $freq;
+ }
+ } else {
+ foreach ($this->_data as $val) {
+ $newval = $val - $mean;
+ $arr[] = $newval;
+ }
+ }
+ return $this->setData($arr, $this->_dataOption);
+ }/*}}}*/
+
+ /**
+ * Calculates the basic or full statistics for the data set
+ *
+ * @access public
+ * @param int $mode one of STATS_BASIC or STATS_FULL
+ * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
+ * or only the error message will be returned (when false), if an error happens.
+ * @return mixed an associative array of statistics on success, a PEAR_Error object otherwise
+ * @see calcBasic()
+ * @see calcFull()
+ */
+ function calc($mode, $returnErrorObject=true) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if ($mode == STATS_BASIC) {
+ return $this->calcBasic($returnErrorObject);
+ } elseif ($mode == STATS_FULL) {
+ return $this->calcFull($returnErrorObject);
+ } else {
+ return PEAR::raiseError('incorrect mode, expected STATS_BASIC or STATS_FULL');
+ }
+ }/*}}}*/
+
+ /**
+ * Calculates a basic set of statistics
+ *
+ * @access public
+ * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
+ * or only the error message will be returned (when false), if an error happens.
+ * @return mixed an associative array of statistics on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see calcFull()
+ */
+ function calcBasic($returnErrorObject=true) {/*{{{*/
+ return array (
+ 'min' => $this->__format($this->min(), $returnErrorObject),
+ 'max' => $this->__format($this->max(), $returnErrorObject),
+ 'sum' => $this->__format($this->sum(), $returnErrorObject),
+ 'sum2' => $this->__format($this->sum2(), $returnErrorObject),
+ 'count' => $this->__format($this->count(), $returnErrorObject),
+ 'mean' => $this->__format($this->mean(), $returnErrorObject),
+ 'stdev' => $this->__format($this->stDev(), $returnErrorObject),
+ 'variance' => $this->__format($this->variance(), $returnErrorObject),
+ 'range' => $this->__format($this->range(), $returnErrorObject)
+ );
+ }/*}}}*/
+
+ /**
+ * Calculates a full set of statistics
+ *
+ * @access public
+ * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
+ * or only the error message will be returned (when false), if an error happens.
+ * @return mixed an associative array of statistics on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see calcBasic()
+ */
+ function calcFull($returnErrorObject=true) {/*{{{*/
+ return array (
+ 'min' => $this->__format($this->min(), $returnErrorObject),
+ 'max' => $this->__format($this->max(), $returnErrorObject),
+ 'sum' => $this->__format($this->sum(), $returnErrorObject),
+ 'sum2' => $this->__format($this->sum2(), $returnErrorObject),
+ 'count' => $this->__format($this->count(), $returnErrorObject),
+ 'mean' => $this->__format($this->mean(), $returnErrorObject),
+ 'median' => $this->__format($this->median(), $returnErrorObject),
+ 'mode' => $this->__format($this->mode(), $returnErrorObject),
+ 'midrange' => $this->__format($this->midrange(), $returnErrorObject),
+ 'geometric_mean' => $this->__format($this->geometricMean(), $returnErrorObject),
+ 'harmonic_mean' => $this->__format($this->harmonicMean(), $returnErrorObject),
+ 'stdev' => $this->__format($this->stDev(), $returnErrorObject),
+ 'absdev' => $this->__format($this->absDev(), $returnErrorObject),
+ 'variance' => $this->__format($this->variance(), $returnErrorObject),
+ 'range' => $this->__format($this->range(), $returnErrorObject),
+ 'std_error_of_mean' => $this->__format($this->stdErrorOfMean(), $returnErrorObject),
+ 'skewness' => $this->__format($this->skewness(), $returnErrorObject),
+ 'kurtosis' => $this->__format($this->kurtosis(), $returnErrorObject),
+ 'coeff_of_variation' => $this->__format($this->coeffOfVariation(), $returnErrorObject),
+ 'sample_central_moments' => array (
+ 1 => $this->__format($this->sampleCentralMoment(1), $returnErrorObject),
+ 2 => $this->__format($this->sampleCentralMoment(2), $returnErrorObject),
+ 3 => $this->__format($this->sampleCentralMoment(3), $returnErrorObject),
+ 4 => $this->__format($this->sampleCentralMoment(4), $returnErrorObject),
+ 5 => $this->__format($this->sampleCentralMoment(5), $returnErrorObject)
+ ),
+ 'sample_raw_moments' => array (
+ 1 => $this->__format($this->sampleRawMoment(1), $returnErrorObject),
+ 2 => $this->__format($this->sampleRawMoment(2), $returnErrorObject),
+ 3 => $this->__format($this->sampleRawMoment(3), $returnErrorObject),
+ 4 => $this->__format($this->sampleRawMoment(4), $returnErrorObject),
+ 5 => $this->__format($this->sampleRawMoment(5), $returnErrorObject)
+ ),
+ 'frequency' => $this->__format($this->frequency(), $returnErrorObject),
+ 'quartiles' => $this->__format($this->quartiles(), $returnErrorObject),
+ 'interquartile_range' => $this->__format($this->interquartileRange(), $returnErrorObject),
+ 'interquartile_mean' => $this->__format($this->interquartileMean(), $returnErrorObject),
+ 'quartile_deviation' => $this->__format($this->quartileDeviation(), $returnErrorObject),
+ 'quartile_variation_coefficient' => $this->__format($this->quartileVariationCoefficient(), $returnErrorObject),
+ 'quartile_skewness_coefficient' => $this->__format($this->quartileSkewnessCoefficient(), $returnErrorObject)
+ );
+ }/*}}}*/
+
+ /**
+ * Calculates the minimum of a data set.
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the minimum value on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see max()
+ */
+ function min() {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (!array_key_exists('min', $this->_calculatedValues)) {
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ $min = min(array_keys($this->_data));
+ } else {
+ $min = min($this->_data);
+ }
+ $this->_calculatedValues['min'] = $min;
+ }
+ return $this->_calculatedValues['min'];
+ }/*}}}*/
+
+ /**
+ * Calculates the maximum of a data set.
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the maximum value on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see min()
+ */
+ function max() {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (!array_key_exists('max', $this->_calculatedValues)) {
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ $max = max(array_keys($this->_data));
+ } else {
+ $max = max($this->_data);
+ }
+ $this->_calculatedValues['max'] = $max;
+ }
+ return $this->_calculatedValues['max'];
+ }/*}}}*/
+
+ /**
+ * Calculates SUM { xi }
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the sum on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see sum2()
+ * @see sumN()
+ */
+ function sum() {/*{{{*/
+ if (!array_key_exists('sum', $this->_calculatedValues)) {
+ $sum = $this->sumN(1);
+ if (PEAR::isError($sum)) {
+ return $sum;
+ } else {
+ $this->_calculatedValues['sum'] = $sum;
+ }
+ }
+ return $this->_calculatedValues['sum'];
+ }/*}}}*/
+
+ /**
+ * Calculates SUM { (xi)^2 }
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the sum on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see sum()
+ * @see sumN()
+ */
+ function sum2() {/*{{{*/
+ if (!array_key_exists('sum2', $this->_calculatedValues)) {
+ $sum2 = $this->sumN(2);
+ if (PEAR::isError($sum2)) {
+ return $sum2;
+ } else {
+ $this->_calculatedValues['sum2'] = $sum2;
+ }
+ }
+ return $this->_calculatedValues['sum2'];
+ }/*}}}*/
+
+ /**
+ * Calculates SUM { (xi)^n }
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @param numeric $n the exponent
+ * @return mixed the sum on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see sum()
+ * @see sum2()
+ */
+ function sumN($n) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ $sumN = 0;
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ foreach($this->_data as $val=>$freq) {
+ $sumN += $freq * pow((double)$val, (double)$n);
+ }
+ } else {
+ foreach($this->_data as $val) {
+ $sumN += pow((double)$val, (double)$n);
+ }
+ }
+ return $sumN;
+ }/*}}}*/
+
+ /**
+ * Calculates PROD { (xi) }, (the product of all observations)
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the product on success, a PEAR_Error object otherwise
+ * @see productN()
+ */
+ function product() {/*{{{*/
+ if (!array_key_exists('product', $this->_calculatedValues)) {
+ $product = $this->productN(1);
+ if (PEAR::isError($product)) {
+ return $product;
+ } else {
+ $this->_calculatedValues['product'] = $product;
+ }
+ }
+ return $this->_calculatedValues['product'];
+ }/*}}}*/
+
+ /**
+ * Calculates PROD { (xi)^n }, which is the product of all observations
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @param numeric $n the exponent
+ * @return mixed the product on success, a PEAR_Error object otherwise
+ * @see product()
+ */
+ function productN($n) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ $prodN = 1.0;
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ foreach($this->_data as $val=>$freq) {
+ if ($val == 0) {
+ return 0.0;
+ }
+ $prodN *= $freq * pow((double)$val, (double)$n);
+ }
+ } else {
+ foreach($this->_data as $val) {
+ if ($val == 0) {
+ return 0.0;
+ }
+ $prodN *= pow((double)$val, (double)$n);
+ }
+ }
+ return $prodN;
+
+ }/*}}}*/
+
+ /**
+ * Calculates the number of data points in the set
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the count on success, a PEAR_Error object otherwise
+ * @see calc()
+ */
+ function count() {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (!array_key_exists('count', $this->_calculatedValues)) {
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ $count = count($this->_dataExpanded);
+ } else {
+ $count = count($this->_data);
+ }
+ $this->_calculatedValues['count'] = $count;
+ }
+ return $this->_calculatedValues['count'];
+ }/*}}}*/
+
+ /**
+ * Calculates the mean (average) of the data points in the set
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the mean value on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see sum()
+ * @see count()
+ */
+ function mean() {/*{{{*/
+ if (!array_key_exists('mean', $this->_calculatedValues)) {
+ $sum = $this->sum();
+ if (PEAR::isError($sum)) {
+ return $sum;
+ }
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ $this->_calculatedValues['mean'] = $sum / $count;
+ }
+ return $this->_calculatedValues['mean'];
+ }/*}}}*/
+
+ /**
+ * Calculates the range of the data set = max - min
+ *
+ * @access public
+ * @return mixed the value of the range on success, a PEAR_Error object otherwise.
+ */
+ function range() {/*{{{*/
+ if (!array_key_exists('range', $this->_calculatedValues)) {
+ $min = $this->min();
+ if (PEAR::isError($min)) {
+ return $min;
+ }
+ $max = $this->max();
+ if (PEAR::isError($max)) {
+ return $max;
+ }
+ $this->_calculatedValues['range'] = $max - $min;
+ }
+ return $this->_calculatedValues['range'];
+
+ }/*}}}*/
+
+ /**
+ * Calculates the variance (unbiased) of the data points in the set
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the variance value on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see __sumdiff()
+ * @see count()
+ */
+ function variance() {/*{{{*/
+ if (!array_key_exists('variance', $this->_calculatedValues)) {
+ $variance = $this->__calcVariance();
+ if (PEAR::isError($variance)) {
+ return $variance;
+ }
+ $this->_calculatedValues['variance'] = $variance;
+ }
+ return $this->_calculatedValues['variance'];
+ }/*}}}*/
+
+ /**
+ * Calculates the standard deviation (unbiased) of the data points in the set
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the standard deviation on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see variance()
+ */
+ function stDev() {/*{{{*/
+ if (!array_key_exists('stDev', $this->_calculatedValues)) {
+ $variance = $this->variance();
+ if (PEAR::isError($variance)) {
+ return $variance;
+ }
+ $this->_calculatedValues['stDev'] = sqrt($variance);
+ }
+ return $this->_calculatedValues['stDev'];
+ }/*}}}*/
+
+ /**
+ * Calculates the variance (unbiased) of the data points in the set
+ * given a fixed mean (average) value. Not used in calcBasic(), calcFull()
+ * or calc().
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @param numeric $mean the fixed mean value
+ * @return mixed the variance on success, a PEAR_Error object otherwise
+ * @see __sumdiff()
+ * @see count()
+ * @see variance()
+ */
+ function varianceWithMean($mean) {/*{{{*/
+ return $this->__calcVariance($mean);
+ }/*}}}*/
+
+ /**
+ * Calculates the standard deviation (unbiased) of the data points in the set
+ * given a fixed mean (average) value. Not used in calcBasic(), calcFull()
+ * or calc().
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @param numeric $mean the fixed mean value
+ * @return mixed the standard deviation on success, a PEAR_Error object otherwise
+ * @see varianceWithMean()
+ * @see stDev()
+ */
+ function stDevWithMean($mean) {/*{{{*/
+ $varianceWM = $this->varianceWithMean($mean);
+ if (PEAR::isError($varianceWM)) {
+ return $varianceWM;
+ }
+ return sqrt($varianceWM);
+ }/*}}}*/
+
+ /**
+ * Calculates the absolute deviation of the data points in the set
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the absolute deviation on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see __sumabsdev()
+ * @see count()
+ * @see absDevWithMean()
+ */
+ function absDev() {/*{{{*/
+ if (!array_key_exists('absDev', $this->_calculatedValues)) {
+ $absDev = $this->__calcAbsoluteDeviation();
+ if (PEAR::isError($absdev)) {
+ return $absdev;
+ }
+ $this->_calculatedValues['absDev'] = $absDev;
+ }
+ return $this->_calculatedValues['absDev'];
+ }/*}}}*/
+
+ /**
+ * Calculates the absolute deviation of the data points in the set
+ * given a fixed mean (average) value. Not used in calcBasic(), calcFull()
+ * or calc().
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @param numeric $mean the fixed mean value
+ * @return mixed the absolute deviation on success, a PEAR_Error object otherwise
+ * @see __sumabsdev()
+ * @see absDev()
+ */
+ function absDevWithMean($mean) {/*{{{*/
+ return $this->__calcAbsoluteDeviation($mean);
+ }/*}}}*/
+
+ /**
+ * Calculates the skewness of the data distribution in the set
+ * The skewness measures the degree of asymmetry of a distribution,
+ * and is related to the third central moment of a distribution.
+ * A normal distribution has a skewness = 0
+ * A distribution with a tail off towards the high end of the scale
+ * (positive skew) has a skewness > 0
+ * A distribution with a tail off towards the low end of the scale
+ * (negative skew) has a skewness < 0
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the skewness value on success, a PEAR_Error object otherwise
+ * @see __sumdiff()
+ * @see count()
+ * @see stDev()
+ * @see calc()
+ */
+ function skewness() {/*{{{*/
+ if (!array_key_exists('skewness', $this->_calculatedValues)) {
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ $stDev = $this->stDev();
+ if (PEAR::isError($stDev)) {
+ return $stDev;
+ }
+ $sumdiff3 = $this->__sumdiff(3);
+ if (PEAR::isError($sumdiff3)) {
+ return $sumdiff3;
+ }
+ $this->_calculatedValues['skewness'] = ($sumdiff3 / ($count * pow($stDev, 3)));
+ }
+ return $this->_calculatedValues['skewness'];
+ }/*}}}*/
+
+ /**
+ * Calculates the kurtosis of the data distribution in the set
+ * The kurtosis measures the degrees of peakedness of a distribution.
+ * It is also called the "excess" or "excess coefficient", and is
+ * a normalized form of the fourth central moment of a distribution.
+ * A normal distributions has kurtosis = 0
+ * A narrow and peaked (leptokurtic) distribution has a
+ * kurtosis > 0
+ * A flat and wide (platykurtic) distribution has a kurtosis < 0
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the kurtosis value on success, a PEAR_Error object otherwise
+ * @see __sumdiff()
+ * @see count()
+ * @see stDev()
+ * @see calc()
+ */
+ function kurtosis() {/*{{{*/
+ if (!array_key_exists('kurtosis', $this->_calculatedValues)) {
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ $stDev = $this->stDev();
+ if (PEAR::isError($stDev)) {
+ return $stDev;
+ }
+ $sumdiff4 = $this->__sumdiff(4);
+ if (PEAR::isError($sumdiff4)) {
+ return $sumdiff4;
+ }
+ $this->_calculatedValues['kurtosis'] = ($sumdiff4 / ($count * pow($stDev, 4))) - 3;
+ }
+ return $this->_calculatedValues['kurtosis'];
+ }/*}}}*/
+
+ /**
+ * Calculates the median of a data set.
+ * The median is the value such that half of the points are below it
+ * in a sorted data set.
+ * If the number of values is odd, it is the middle item.
+ * If the number of values is even, is the average of the two middle items.
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the median value on success, a PEAR_Error object otherwise
+ * @see count()
+ * @see calc()
+ */
+ function median() {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (!array_key_exists('median', $this->_calculatedValues)) {
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ $arr =& $this->_dataExpanded;
+ } else {
+ $arr =& $this->_data;
+ }
+ $n = $this->count();
+ if (PEAR::isError($n)) {
+ return $n;
+ }
+ $h = intval($n / 2);
+ if ($n % 2 == 0) {
+ $median = ($arr[$h] + $arr[$h - 1]) / 2;
+ } else {
+ $median = $arr[$h + 1];
+ }
+ $this->_calculatedValues['median'] = $median;
+ }
+ return $this->_calculatedValues['median'];
+ }/*}}}*/
+
+ /**
+ * Calculates the mode of a data set.
+ * The mode is the value with the highest frequency in the data set.
+ * There can be more than one mode.
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed an array of mode value on success, a PEAR_Error object otherwise
+ * @see frequency()
+ * @see calc()
+ */
+ function mode() {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (!array_key_exists('mode', $this->_calculatedValues)) {
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ $arr = $this->_data;
+ } else {
+ $arr = $this->frequency();
+ }
+ arsort($arr);
+ $mcount = 1;
+ foreach ($arr as $val=>$freq) {
+ if ($mcount == 1) {
+ $mode = array($val);
+ $mfreq = $freq;
+ ++$mcount;
+ continue;
+ }
+ if ($mfreq == $freq)
+ $mode[] = $val;
+ if ($mfreq > $freq)
+ break;
+ }
+ $this->_calculatedValues['mode'] = $mode;
+ }
+ return $this->_calculatedValues['mode'];
+ }/*}}}*/
+
+ /**
+ * Calculates the midrange of a data set.
+ * The midrange is the average of the minimum and maximum of the data set.
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the midrange value on success, a PEAR_Error object otherwise
+ * @see min()
+ * @see max()
+ * @see calc()
+ */
+ function midrange() {/*{{{*/
+ if (!array_key_exists('midrange', $this->_calculatedValues)) {
+ $min = $this->min();
+ if (PEAR::isError($min)) {
+ return $min;
+ }
+ $max = $this->max();
+ if (PEAR::isError($max)) {
+ return $max;
+ }
+ $this->_calculatedValues['midrange'] = (($max + $min) / 2);
+ }
+ return $this->_calculatedValues['midrange'];
+ }/*}}}*/
+
+ /**
+ * Calculates the geometrical mean of the data points in the set
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the geometrical mean value on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see product()
+ * @see count()
+ */
+ function geometricMean() {/*{{{*/
+ if (!array_key_exists('geometricMean', $this->_calculatedValues)) {
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ $prod = $this->product();
+ if (PEAR::isError($prod)) {
+ return $prod;
+ }
+ if ($prod == 0.0) {
+ return 0.0;
+ }
+ if ($prod < 0) {
+ return PEAR::raiseError('The product of the data set is negative, geometric mean undefined.');
+ }
+ $this->_calculatedValues['geometricMean'] = pow($prod , 1 / $count);
+ }
+ return $this->_calculatedValues['geometricMean'];
+ }/*}}}*/
+
+ /**
+ * Calculates the harmonic mean of the data points in the set
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the harmonic mean value on success, a PEAR_Error object otherwise
+ * @see calc()
+ * @see count()
+ */
+ function harmonicMean() {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (!array_key_exists('harmonicMean', $this->_calculatedValues)) {
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ $invsum = 0.0;
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ foreach($this->_data as $val=>$freq) {
+ if ($val == 0) {
+ return PEAR::raiseError('cannot calculate a '.
+ 'harmonic mean with data values of zero.');
+ }
+ $invsum += $freq / $val;
+ }
+ } else {
+ foreach($this->_data as $val) {
+ if ($val == 0) {
+ return PEAR::raiseError('cannot calculate a '.
+ 'harmonic mean with data values of zero.');
+ }
+ $invsum += 1 / $val;
+ }
+ }
+ $this->_calculatedValues['harmonicMean'] = $count / $invsum;
+ }
+ return $this->_calculatedValues['harmonicMean'];
+ }/*}}}*/
+
+ /**
+ * Calculates the nth central moment (m{n}) of a data set.
+ *
+ * The definition of a sample central moment is:
+ *
+ * m{n} = 1/N * SUM { (xi - avg)^n }
+ *
+ * where: N = sample size, avg = sample mean.
+ *
+ * @access public
+ * @param integer $n moment to calculate
+ * @return mixed the numeric value of the moment on success, PEAR_Error otherwise
+ */
+ function sampleCentralMoment($n) {/*{{{*/
+ if (!is_int($n) || $n < 1) {
+ return PEAR::isError('moment must be a positive integer >= 1.');
+ }
+
+ if ($n == 1) {
+ return 0;
+ }
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ if ($count == 0) {
+ return PEAR::raiseError("Cannot calculate {$n}th sample moment, ".
+ 'there are zero data entries');
+ }
+ $sum = $this->__sumdiff($n);
+ if (PEAR::isError($sum)) {
+ return $sum;
+ }
+ return ($sum / $count);
+ }/*}}}*/
+
+ /**
+ * Calculates the nth raw moment (m{n}) of a data set.
+ *
+ * The definition of a sample central moment is:
+ *
+ * m{n} = 1/N * SUM { xi^n }
+ *
+ * where: N = sample size, avg = sample mean.
+ *
+ * @access public
+ * @param integer $n moment to calculate
+ * @return mixed the numeric value of the moment on success, PEAR_Error otherwise
+ */
+ function sampleRawMoment($n) {/*{{{*/
+ if (!is_int($n) || $n < 1) {
+ return PEAR::isError('moment must be a positive integer >= 1.');
+ }
+
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ if ($count == 0) {
+ return PEAR::raiseError("Cannot calculate {$n}th raw moment, ".
+ 'there are zero data entries.');
+ }
+ $sum = $this->sumN($n);
+ if (PEAR::isError($sum)) {
+ return $sum;
+ }
+ return ($sum / $count);
+ }/*}}}*/
+
+
+ /**
+ * Calculates the coefficient of variation of a data set.
+ * The coefficient of variation measures the spread of a set of data
+ * as a proportion of its mean. It is often expressed as a percentage.
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed the coefficient of variation on success, a PEAR_Error object otherwise
+ * @see stDev()
+ * @see mean()
+ * @see calc()
+ */
+ function coeffOfVariation() {/*{{{*/
+ if (!array_key_exists('coeffOfVariation', $this->_calculatedValues)) {
+ $mean = $this->mean();
+ if (PEAR::isError($mean)) {
+ return $mean;
+ }
+ if ($mean == 0.0) {
+ return PEAR::raiseError('cannot calculate the coefficient '.
+ 'of variation, mean of sample is zero');
+ }
+ $stDev = $this->stDev();
+ if (PEAR::isError($stDev)) {
+ return $stDev;
+ }
+
+ $this->_calculatedValues['coeffOfVariation'] = $stDev / $mean;
+ }
+ return $this->_calculatedValues['coeffOfVariation'];
+ }/*}}}*/
+
+ /**
+ * Calculates the standard error of the mean.
+ * It is the standard deviation of the sampling distribution of
+ * the mean. The formula is:
+ *
+ * S.E. Mean = SD / (N)^(1/2)
+ *
+ * This formula does not assume a normal distribution, and shows
+ * that the size of the standard error of the mean is inversely
+ * proportional to the square root of the sample size.
+ *
+ * @access public
+ * @return mixed the standard error of the mean on success, a PEAR_Error object otherwise
+ * @see stDev()
+ * @see count()
+ * @see calc()
+ */
+ function stdErrorOfMean() {/*{{{*/
+ if (!array_key_exists('stdErrorOfMean', $this->_calculatedValues)) {
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ $stDev = $this->stDev();
+ if (PEAR::isError($stDev)) {
+ return $stDev;
+ }
+ $this->_calculatedValues['stdErrorOfMean'] = $stDev / sqrt($count);
+ }
+ return $this->_calculatedValues['stdErrorOfMean'];
+ }/*}}}*/
+
+ /**
+ * Calculates the value frequency table of a data set.
+ * Handles cummulative data sets correctly
+ *
+ * @access public
+ * @return mixed an associative array of value=>frequency items on success, a PEAR_Error object otherwise
+ * @see min()
+ * @see max()
+ * @see calc()
+ */
+ function frequency() {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (!array_key_exists('frequency', $this->_calculatedValues)) {
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ $freq = $this->_data;
+ } else {
+ $freq = array();
+ foreach ($this->_data as $val) {
+ $freq["$val"]++;
+ }
+ ksort($freq);
+ }
+ $this->_calculatedValues['frequency'] = $freq;
+ }
+ return $this->_calculatedValues['frequency'];
+ }/*}}}*/
+
+ /**
+ * The quartiles are defined as the values that divide a sorted
+ * data set into four equal-sized subsets, and correspond to the
+ * 25th, 50th, and 75th percentiles.
+ *
+ * @access public
+ * @return mixed an associative array of quartiles on success, a PEAR_Error otherwise
+ * @see percentile()
+ */
+ function quartiles() {/*{{{*/
+ if (!array_key_exists('quartiles', $this->_calculatedValues)) {
+ $q1 = $this->percentile(25);
+ if (PEAR::isError($q1)) {
+ return $q1;
+ }
+ $q2 = $this->percentile(50);
+ if (PEAR::isError($q2)) {
+ return $q2;
+ }
+ $q3 = $this->percentile(75);
+ if (PEAR::isError($q3)) {
+ return $q3;
+ }
+ $this->_calculatedValues['quartiles'] = array (
+ '25' => $q1,
+ '50' => $q2,
+ '75' => $q3
+ );
+ }
+ return $this->_calculatedValues['quartiles'];
+ }/*}}}*/
+
+ /**
+ * The interquartile mean is defined as the mean of the values left
+ * after discarding the lower 25% and top 25% ranked values, i.e.:
+ *
+ * interquart mean = mean(<P(25),P(75)>)
+ *
+ * where: P = percentile
+ *
+ * @todo need to double check the equation
+ * @access public
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see quartiles()
+ */
+ function interquartileMean() {/*{{{*/
+ if (!array_key_exists('interquartileMean', $this->_calculatedValues)) {
+ $quart = $this->quartiles();
+ if (PEAR::isError($quart)) {
+ return $quart;
+ }
+ $q3 = $quart['75'];
+ $q1 = $quart['25'];
+ $sum = 0;
+ $n = 0;
+ foreach ($this->getData(true) as $val) {
+ if ($val >= $q1 && $val <= $q3) {
+ $sum += $val;
+ ++$n;
+ }
+ }
+ if ($n == 0) {
+ return PEAR::raiseError('error calculating interquartile mean, '.
+ 'empty interquartile range of values.');
+ }
+ $this->_calculatedValues['interquartileMean'] = $sum / $n;
+ }
+ return $this->_calculatedValues['interquartileMean'];
+ }/*}}}*/
+
+ /**
+ * The interquartile range is the distance between the 75th and 25th
+ * percentiles. Basically the range of the middle 50% of the data set,
+ * and thus is not affected by outliers or extreme values.
+ *
+ * interquart range = P(75) - P(25)
+ *
+ * where: P = percentile
+ *
+ * @access public
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see quartiles()
+ */
+ function interquartileRange() {/*{{{*/
+ if (!array_key_exists('interquartileRange', $this->_calculatedValues)) {
+ $quart = $this->quartiles();
+ if (PEAR::isError($quart)) {
+ return $quart;
+ }
+ $q3 = $quart['75'];
+ $q1 = $quart['25'];
+ $this->_calculatedValues['interquartileRange'] = $q3 - $q1;
+ }
+ return $this->_calculatedValues['interquartileRange'];
+ }/*}}}*/
+
+ /**
+ * The quartile deviation is half of the interquartile range value
+ *
+ * quart dev = (P(75) - P(25)) / 2
+ *
+ * where: P = percentile
+ *
+ * @access public
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see quartiles()
+ * @see interquartileRange()
+ */
+ function quartileDeviation() {/*{{{*/
+ if (!array_key_exists('quartileDeviation', $this->_calculatedValues)) {
+ $iqr = $this->interquartileRange();
+ if (PEAR::isError($iqr)) {
+ return $iqr;
+ }
+ $this->_calculatedValues['quartileDeviation'] = $iqr / 2;
+ }
+ return $this->_calculatedValues['quartileDeviation'];
+ }/*}}}*/
+
+ /**
+ * The quartile variation coefficient is defines as follows:
+ *
+ * quart var coeff = 100 * (P(75) - P(25)) / (P(75) + P(25))
+ *
+ * where: P = percentile
+ *
+ * @todo need to double check the equation
+ * @access public
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see quartiles()
+ */
+ function quartileVariationCoefficient() {/*{{{*/
+ if (!array_key_exists('quartileVariationCoefficient', $this->_calculatedValues)) {
+ $quart = $this->quartiles();
+ if (PEAR::isError($quart)) {
+ return $quart;
+ }
+ $q3 = $quart['75'];
+ $q1 = $quart['25'];
+ $d = $q3 - $q1;
+ $s = $q3 + $q1;
+ $this->_calculatedValues['quartileVariationCoefficient'] = 100 * $d / $s;
+ }
+ return $this->_calculatedValues['quartileVariationCoefficient'];
+ }/*}}}*/
+
+ /**
+ * The quartile skewness coefficient (also known as Bowley Skewness),
+ * is defined as follows:
+ *
+ * quart skewness coeff = (P(25) - 2*P(50) + P(75)) / (P(75) - P(25))
+ *
+ * where: P = percentile
+ *
+ * @todo need to double check the equation
+ * @access public
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see quartiles()
+ */
+ function quartileSkewnessCoefficient() {/*{{{*/
+ if (!array_key_exists('quartileSkewnessCoefficient', $this->_calculatedValues)) {
+ $quart = $this->quartiles();
+ if (PEAR::isError($quart)) {
+ return $quart;
+ }
+ $q3 = $quart['75'];
+ $q2 = $quart['50'];
+ $q1 = $quart['25'];
+ $d = $q3 - 2*$q2 + $q1;
+ $s = $q3 - $q1;
+ $this->_calculatedValues['quartileSkewnessCoefficient'] = $d / $s;
+ }
+ return $this->_calculatedValues['quartileSkewnessCoefficient'];
+ }/*}}}*/
+
+ /**
+ * The pth percentile is the value such that p% of the a sorted data set
+ * is smaller than it, and (100 - p)% of the data is larger.
+ *
+ * A quick algorithm to pick the appropriate value from a sorted data
+ * set is as follows:
+ *
+ * - Count the number of values: n
+ * - Calculate the position of the value in the data list: i = p * (n + 1)
+ * - if i is an integer, return the data at that position
+ * - if i < 1, return the minimum of the data set
+ * - if i > n, return the maximum of the data set
+ * - otherwise, average the entries at adjacent positions to i
+ *
+ * The median is the 50th percentile value.
+ *
+ * @todo need to double check generality of the algorithm
+ *
+ * @access public
+ * @param numeric $p the percentile to estimate, e.g. 25 for 25th percentile
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see quartiles()
+ * @see median()
+ */
+ function percentile($p) {/*{{{*/
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ $data =& $this->_dataExpanded;
+ } else {
+ $data =& $this->_data;
+ }
+ $obsidx = $p * ($count + 1) / 100;
+ if (intval($obsidx) == $obsidx) {
+ return $data[($obsidx - 1)];
+ } elseif ($obsidx < 1) {
+ return $data[0];
+ } elseif ($obsidx > $count) {
+ return $data[($count - 1)];
+ } else {
+ $left = floor($obsidx - 1);
+ $right = ceil($obsidx - 1);
+ return ($data[$left] + $data[$right]) / 2;
+ }
+ }/*}}}*/
+
+ // private methods
+
+ /**
+ * Utility function to calculate: SUM { (xi - mean)^n }
+ *
+ * @access private
+ * @param numeric $power the exponent
+ * @param optional double $mean the data set mean value
+ * @return mixed the sum on success, a PEAR_Error object otherwise
+ *
+ * @see stDev()
+ * @see variaceWithMean();
+ * @see skewness();
+ * @see kurtosis();
+ */
+ function __sumdiff($power, $mean=null) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (is_null($mean)) {
+ $mean = $this->mean();
+ if (PEAR::isError($mean)) {
+ return $mean;
+ }
+ }
+ $sdiff = 0;
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ foreach ($this->_data as $val=>$freq) {
+ $sdiff += $freq * pow((double)($val - $mean), (double)$power);
+ }
+ } else {
+ foreach ($this->_data as $val)
+ $sdiff += pow((double)($val - $mean), (double)$power);
+ }
+ return $sdiff;
+ }/*}}}*/
+
+ /**
+ * Utility function to calculate the variance with or without
+ * a fixed mean
+ *
+ * @access private
+ * @param $mean the fixed mean to use, null as default
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see variance()
+ * @see varianceWithMean()
+ */
+ function __calcVariance($mean = null) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ $sumdiff2 = $this->__sumdiff(2, $mean);
+ if (PEAR::isError($sumdiff2)) {
+ return $sumdiff2;
+ }
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ if ($count == 1) {
+ return PEAR::raiseError('cannot calculate variance of a singe data point');
+ }
+ return ($sumdiff2 / ($count - 1));
+ }/*}}}*/
+
+ /**
+ * Utility function to calculate the absolute deviation with or without
+ * a fixed mean
+ *
+ * @access private
+ * @param $mean the fixed mean to use, null as default
+ * @return mixed a numeric value on success, a PEAR_Error otherwise
+ * @see absDev()
+ * @see absDevWithMean()
+ */
+ function __calcAbsoluteDeviation($mean = null) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ $count = $this->count();
+ if (PEAR::isError($count)) {
+ return $count;
+ }
+ $sumabsdev = $this->__sumabsdev($mean);
+ if (PEAR::isError($sumabsdev)) {
+ return $sumabsdev;
+ }
+ return $sumabsdev / $count;
+ }/*}}}*/
+
+ /**
+ * Utility function to calculate: SUM { | xi - mean | }
+ *
+ * @access private
+ * @param optional double $mean the mean value for the set or population
+ * @return mixed the sum on success, a PEAR_Error object otherwise
+ *
+ * @see absDev()
+ * @see absDevWithMean()
+ */
+ function __sumabsdev($mean=null) {/*{{{*/
+ if ($this->_data == null) {
+ return PEAR::raiseError('data has not been set');
+ }
+ if (is_null($mean)) {
+ $mean = $this->mean();
+ }
+ $sdev = 0;
+ if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
+ foreach ($this->_data as $val=>$freq) {
+ $sdev += $freq * abs($val - $mean);
+ }
+ } else {
+ foreach ($this->_data as $val) {
+ $sdev += abs($val - $mean);
+ }
+ }
+ return $sdev;
+ }/*}}}*/
+
+ /**
+ * Utility function to format a PEAR_Error to be used by calc(),
+ * calcBasic() and calcFull()
+ *
+ * @access private
+ * @param mixed $v value to be formatted
+ * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
+ * or only the error message will be returned (when false)
+ * @return mixed if the value is a PEAR_Error object, and $useErrorObject
+ * is false, then a string with the error message will be returned,
+ * otherwise the value will not be modified and returned as passed.
+ */
+ function __format($v, $useErrorObject=true) {/*{{{*/
+ if (PEAR::isError($v) && $useErrorObject == false) {
+ return $v->getMessage();
+ } else {
+ return $v;
+ }
+ }/*}}}*/
+
+ /**
+ * Utility function to validate the data and modify it
+ * according to the current null handling option
+ *
+ * @access private
+ * @return mixed true on success, a PEAR_Error object otherwise
+ *
+ * @see setData()
+ */
+ function _validate() {/*{{{*/
+ $flag = ($this->_dataOption == STATS_DATA_CUMMULATIVE);
+ foreach ($this->_data as $key=>$value) {
+ $d = ($flag) ? $key : $value;
+ $v = ($flag) ? $value : $key;
+ if (!is_numeric($d)) {
+ switch ($this->_nullOption) {
+ case STATS_IGNORE_NULL :
+ unset($this->_data["$key"]);
+ break;
+ case STATS_USE_NULL_AS_ZERO:
+ if ($flag) {
+ unset($this->_data["$key"]);
+ $this->_data[0] += $v;
+ } else {
+ $this->_data[$key] = 0;
+ }
+ break;
+ case STATS_REJECT_NULL :
+ default:
+ return PEAR::raiseError('data rejected, contains NULL values');
+ break;
+ }
+ }
+ }
+ if ($flag) {
+ ksort($this->_data);
+ $this->_dataExpanded = array();
+ foreach ($this->_data as $val=>$freq) {
+ $this->_dataExpanded = array_pad($this->_dataExpanded, count($this->_dataExpanded) + $freq, $val);
+ }
+ sort($this->_dataExpanded);
+ } else {
+ sort($this->_data);
+ }
+ return true;
+ }/*}}}*/
+
+}/*}}}*/
+
+// vim: ts=4:sw=4:et:
+// vim6: fdl=1: fdm=marker:
+
+?>
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/benchmark.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/benchmark.php new file mode 100644 index 0000000..42a4884 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/benchmark.php @@ -0,0 +1,263 @@ +<?php
+
+error_reporting(E_ALL);
+
+/**
+ * @package JAMA
+ */
+
+require_once '../Matrix.php';
+require_once 'Stats.php';
+
+
+/**
+ * Example of use of Matrix Class, featuring magic squares.
+ */
+class Benchmark {
+ public $stat;
+
+
+ /**
+ * Simple function to replicate PHP 5 behaviour
+ */
+ function microtime_float() {
+ list($usec, $sec) = explode(" ", microtime());
+
+ return ((float)$usec + (float)$sec);
+ } // function microtime_float()
+
+
+ function displayStats($times = null) {
+ $this->stat->setData($times);
+ $stats = $this->stat->calcFull();
+
+ echo '<table style="margin-left:32px;">';
+ echo '<tr><td style="text-align:right;"><b>n:</b><td style="text-align:right;">' . $stats['count'] . ' </td></tr>';
+ echo '<tr><td style="text-align:right;"><b>Mean:</b><td style="text-align:right;">' . $stats['mean'] . ' </td></tr>';
+ echo '<tr><td style="text-align:right;"><b>Min.:</b><td style="text-align:right;">' . $stats['min'] . ' </td></tr>';
+ echo '<tr><td style="text-align:right;"><b>Max.:</b><td style="text-align:right;">' . $stats['max'] . ' </td></tr>';
+ echo '<tr><td style="text-align:right;"><b>σ:</b><td style="text-align:right;">' . $stats['stdev'] . ' </td></tr>';
+ echo '<tr><td style="text-align:right;"><b>Variance:</b><td style="text-align:right;">' . $stats['variance'] . ' </td></tr>';
+ echo '<tr><td style="text-align:right;"><b>Range:</b><td style="text-align:right;">' . $stats['range'] . ' </td></tr>';
+ echo '</table>';
+
+ return $stats;
+ } // function displayStats()
+
+
+ function runEig($n = 4, $t = 100) {
+ $times = array();
+
+ for ($i = 0; $i < $t; ++$i) {
+ $M = Matrix::random($n, $n);
+ $start_time = $this->microtime_float();
+ $E = new EigenvalueDecomposition($M);
+ $stop_time = $this->microtime_float();
+ $times[] = $stop_time - $start_time;
+ }
+
+ return $times;
+ } // function runEig()
+
+
+ function runLU($n = 4, $t = 100) {
+ $times = array();
+
+ for ($i = 0; $i < $t; ++$i) {
+ $M = Matrix::random($n, $n);
+ $start_time = $this->microtime_float();
+ $E = new LUDecomposition($M);
+ $stop_time = $this->microtime_float();
+ $times[] = $stop_time - $start_time;
+ }
+
+ return $times;
+ } // function runLU()
+
+
+ function runQR($n = 4, $t = 100) {
+ $times = array();
+
+ for ($i = 0; $i < $t; ++$i) {
+ $M = Matrix::random($n, $n);
+ $start_time = $this->microtime_float();
+ $E = new QRDecomposition($M);
+ $stop_time = $this->microtime_float();
+ $times[] = $stop_time - $start_time;
+ }
+
+ return $times;
+ } // function runQR()
+
+
+ function runCholesky($n = 4, $t = 100) {
+ $times = array();
+
+ for ($i = 0; $i < $t; ++$i) {
+ $M = Matrix::random($n, $n);
+ $start_time = $this->microtime_float();
+ $E = new CholeskyDecomposition($M);
+ $stop_time = $this->microtime_float();
+ $times[] = $stop_time - $start_time;
+ }
+
+ return $times;
+ } // function runCholesky()
+
+
+ function runSVD($n = 4, $t = 100) {
+ $times = array();
+
+ for ($i = 0; $i < $t; ++$i) {
+ $M = Matrix::random($n, $n);
+ $start_time = $this->microtime_float();
+ $E = new SingularValueDecomposition($M);
+ $stop_time = $this->microtime_float();
+ $times[] = $stop_time - $start_time;
+ }
+
+ return $times;
+ } // function runSVD()
+
+
+ function run() {
+ $n = 8;
+ $t = 16;
+ $sum = 0;
+ echo "<b>Cholesky decomposition: $t random {$n}x{$n} matrices</b><br />";
+ $r = $this->displayStats($this->runCholesky($n, $t));
+ $sum += $r['mean'] * $n;
+
+ echo '<hr />';
+
+ echo "<b>Eigenvalue decomposition: $t random {$n}x{$n} matrices</b><br />";
+ $r = $this->displayStats($this->runEig($n, $t));
+ $sum += $r['mean'] * $n;
+
+ echo '<hr />';
+
+ echo "<b>LU decomposition: $t random {$n}x{$n} matrices</b><br />";
+ $r = $this->displayStats($this->runLU($n, $t));
+ $sum += $r['mean'] * $n;
+
+ echo '<hr />';
+
+ echo "<b>QR decomposition: $t random {$n}x{$n} matrices</b><br />";
+ $r = $this->displayStats($this->runQR($n, $t));
+ $sum += $r['mean'] * $n;
+
+ echo '<hr />';
+
+ echo "<b>Singular Value decomposition: $t random {$n}x{$n} matrices</b><br />";
+ $r = $this->displayStats($this->runSVD($n, $t));
+ $sum += $r['mean'] * $n;
+
+ return $sum;
+ } // function run()
+
+
+ public function __construct() {
+ $this->stat = new Base();
+ } // function Benchmark()
+
+} // class Benchmark (end MagicSquareExample)
+
+
+$benchmark = new Benchmark();
+
+switch($_REQUEST['decomposition']) {
+ case 'cholesky':
+ $m = array();
+ for ($i = 2; $i <= 8; $i *= 2) {
+ $t = 32 / $i;
+ echo "<b>Cholesky decomposition: $t random {$i}x{$i} matrices</b><br />";
+ $s = $benchmark->displayStats($benchmark->runCholesky($i, $t));
+ $m[$i] = $s['mean'];
+ echo "<br />";
+ }
+ echo '<pre>';
+ foreach($m as $x => $y) {
+ echo "$x\t" . 1000*$y . "\n";
+ }
+ echo '</pre>';
+ break;
+ case 'eigenvalue':
+ $m = array();
+ for ($i = 2; $i <= 8; $i *= 2) {
+ $t = 32 / $i;
+ echo "<b>Eigenvalue decomposition: $t random {$i}x{$i} matrices</b><br />";
+ $s = $benchmark->displayStats($benchmark->runEig($i, $t));
+ $m[$i] = $s['mean'];
+ echo "<br />";
+ }
+ echo '<pre>';
+ foreach($m as $x => $y) {
+ echo "$x\t" . 1000*$y . "\n";
+ }
+ echo '</pre>';
+ break;
+ case 'lu':
+ $m = array();
+ for ($i = 2; $i <= 8; $i *= 2) {
+ $t = 32 / $i;
+ echo "<b>LU decomposition: $t random {$i}x{$i} matrices</b><br />";
+ $s = $benchmark->displayStats($benchmark->runLU($i, $t));
+ $m[$i] = $s['mean'];
+ echo "<br />";
+ }
+ echo '<pre>';
+ foreach($m as $x => $y) {
+ echo "$x\t" . 1000*$y . "\n";
+ }
+ echo '</pre>';
+ break;
+ case 'qr':
+ $m = array();
+ for ($i = 2; $i <= 8; $i *= 2) {
+ $t = 32 / $i;
+ echo "<b>QR decomposition: $t random {$i}x{$i} matrices</b><br />";
+ $s = $benchmark->displayStats($benchmark->runQR($i, $t));
+ $m[$i] = $s['mean'];
+ echo "<br />";
+ }
+ echo '<pre>';
+ foreach($m as $x => $y) {
+ echo "$x\t" . 1000*$y . "\n";
+ }
+ echo '</pre>';
+ break;
+ case 'svd':
+ $m = array();
+ for($i = 2; $i <= 8; $i *= 2) {
+ $t = 32 / $i;
+ echo "<b>Singular value decomposition: $t random {$i}x{$i} matrices</b><br />";
+ $s = $benchmark->displayStats($benchmark->runSVD($i, $t));
+ $m[$i] = $s['mean'];
+ echo "<br />";
+ }
+ echo '<pre>';
+ foreach($m as $x => $y) {
+ echo "$x\t" . 1000*$y . "\n";
+ }
+ echo '</pre>';
+ break;
+ case 'all':
+ $s = $benchmark->run();
+ print("<br /><b>Total<b>: {$s}s<br />");
+ break;
+ default:
+ ?>
+ <ul>
+ <li><a href="benchmark.php?decomposition=all">Complete Benchmark</a>
+ <ul>
+ <li><a href="benchmark.php?decomposition=cholesky">Cholesky</a></li>
+ <li><a href="benchmark.php?decomposition=eigenvalue">Eigenvalue</a></li>
+ <li><a href="benchmark.php?decomposition=lu">LU</a></li>
+ <li><a href="benchmark.php?decomposition=qr">QR</a></li>
+ <li><a href="benchmark.php?decomposition=svd">Singular Value</a></li>
+ </ul>
+ </li>
+ </ul>
+ <?php
+ break;
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/polyfit.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/polyfit.php new file mode 100644 index 0000000..fffc864 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/polyfit.php @@ -0,0 +1,73 @@ +<?php
+require_once "../Matrix.php";
+/*
+* @package JAMA
+* @author Michael Bommarito
+* @author Paul Meagher
+* @version 0.1
+*
+* Function to fit an order n polynomial function through
+* a series of x-y data points using least squares.
+*
+* @param $X array x values
+* @param $Y array y values
+* @param $n int order of polynomial to be used for fitting
+* @returns array $coeffs of polynomial coefficients
+* Pre-Conditions: the system is not underdetermined: sizeof($X) > $n+1
+*/
+function polyfit($X, $Y, $n) {
+ for ($i = 0; $i < sizeof($X); ++$i)
+ for ($j = 0; $j <= $n; ++$j)
+ $A[$i][$j] = pow($X[$i], $j);
+ for ($i=0; $i < sizeof($Y); ++$i)
+ $B[$i] = array($Y[$i]);
+ $matrixA = new Matrix($A);
+ $matrixB = new Matrix($B);
+ $C = $matrixA->solve($matrixB);
+ return $C->getMatrix(0, $n, 0, 1);
+}
+
+function printpoly( $C = null ) {
+ for($i = $C->m - 1; $i >= 0; --$i) {
+ $r = $C->get($i, 0);
+ if ( abs($r) <= pow(10, -9) )
+ $r = 0;
+ if ($i == $C->m - 1)
+ echo $r . "x<sup>$i</sup>";
+ else if ($i < $C->m - 1)
+ echo " + " . $r . "x<sup>$i</sup>";
+ else if ($i == 0)
+ echo " + " . $r;
+ }
+}
+
+$X = array(0,1,2,3,4,5);
+$Y = array(4,3,12,67,228, 579);
+$points = new Matrix(array($X, $Y));
+$points->toHTML();
+printpoly(polyfit($X, $Y, 4));
+
+echo '<hr />';
+
+$X = array(0,1,2,3,4,5);
+$Y = array(1,2,5,10,17, 26);
+$points = new Matrix(array($X, $Y));
+$points->toHTML();
+printpoly(polyfit($X, $Y, 2));
+
+echo '<hr />';
+
+$X = array(0,1,2,3,4,5,6);
+$Y = array(-90,-104,-178,-252,-26, 1160, 4446);
+$points = new Matrix(array($X, $Y));
+$points->toHTML();
+printpoly(polyfit($X, $Y, 5));
+
+echo '<hr />';
+
+$X = array(0,1,2,3,4);
+$Y = array(mt_rand(0, 10), mt_rand(40, 80), mt_rand(240, 400), mt_rand(1800, 2215), mt_rand(8000, 9000));
+$points = new Matrix(array($X, $Y));
+$points->toHTML();
+printpoly(polyfit($X, $Y, 3));
+?>
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/examples/tile.php b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/tile.php new file mode 100644 index 0000000..b5c48e1 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/examples/tile.php @@ -0,0 +1,78 @@ +<?php
+
+include "../Matrix.php";
+
+/**
+* Tiling of matrix X in [rowWise by colWise] dimension. Tiling
+* creates a larger matrix than the original data X. Example, if
+* X is to be tiled in a [3 x 4] manner, then:
+*
+* / \
+* | X X X X |
+* C = | X X X X |
+* | X X X X |
+* \ /
+*
+* @param X Matrix
+* @param rowWise int
+* @param colWise int
+* @return Matrix
+*/
+
+function tile(&$X, $rowWise, $colWise){
+
+ $xArray = $X->getArray();
+ print_r($xArray);
+
+ $countRow = 0;
+ $countColumn = 0;
+
+ $m = $X->getRowDimension();
+ $n = $X->getColumnDimension();
+
+ if( $rowWise<1 || $colWise<1 ){
+ die("tile : Array index is out-of-bound.");
+ }
+
+ $newRowDim = $m*$rowWise;
+ $newColDim = $n*$colWise;
+
+ $result = array();
+
+ for($i=0 ; $i<$newRowDim; ++$i) {
+
+ $holder = array();
+
+ for($j=0 ; $j<$newColDim ; ++$j) {
+
+ $holder[$j] = $xArray[$countRow][$countColumn++];
+
+ // reset the column-index to zero to avoid reference to out-of-bound index in xArray[][]
+
+ if($countColumn == $n) { $countColumn = 0; }
+
+ } // end for
+
+ ++$countRow;
+
+ // reset the row-index to zero to avoid reference to out-of-bound index in xArray[][]
+
+ if($countRow == $m) { $countRow = 0; }
+
+ $result[$i] = $holder;
+
+ } // end for
+
+ return new Matrix($result);
+
+}
+
+
+$X =array(1,2,3,4,5,6,7,8,9);
+$nRow = 3;
+$nCol = 3;
+$tiled_matrix = tile(new Matrix($X), $nRow, $nCol);
+echo "<pre>";
+print_r($tiled_matrix);
+echo "</pre>";
+?>
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/tests/TestMatrix.php b/admin/survey/excel/PHPExcel/Shared/JAMA/tests/TestMatrix.php new file mode 100644 index 0000000..cf8128b --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/tests/TestMatrix.php @@ -0,0 +1,415 @@ +<?php
+
+require_once "../Matrix.php";
+
+class TestMatrix {
+
+ function TestMatrix() {
+
+ // define test variables
+
+ $errorCount = 0;
+ $warningCount = 0;
+ $columnwise = array(1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.);
+ $rowwise = array(1.,4.,7.,10.,2.,5.,8.,11.,3.,6.,9.,12.);
+ $avals = array(array(1.,4.,7.,10.),array(2.,5.,8.,11.),array(3.,6.,9.,12.));
+ $rankdef = $avals;
+ $tvals = array(array(1.,2.,3.),array(4.,5.,6.),array(7.,8.,9.),array(10.,11.,12.));
+ $subavals = array(array(5.,8.,11.),array(6.,9.,12.));
+ $rvals = array(array(1.,4.,7.),array(2.,5.,8.,11.),array(3.,6.,9.,12.));
+ $pvals = array(array(1.,1.,1.),array(1.,2.,3.),array(1.,3.,6.));
+ $ivals = array(array(1.,0.,0.,0.),array(0.,1.,0.,0.),array(0.,0.,1.,0.));
+ $evals = array(array(0.,1.,0.,0.),array(1.,0.,2.e-7,0.),array(0.,-2.e-7,0.,1.),array(0.,0.,1.,0.));
+ $square = array(array(166.,188.,210.),array(188.,214.,240.),array(210.,240.,270.));
+ $sqSolution = array(array(13.),array(15.));
+ $condmat = array(array(1.,3.),array(7.,9.));
+ $rows = 3;
+ $cols = 4;
+ $invalidID = 5; /* should trigger bad shape for construction with val */
+ $raggedr = 0; /* (raggedr,raggedc) should be out of bounds in ragged array */
+ $raggedc = 4;
+ $validID = 3; /* leading dimension of intended test Matrices */
+ $nonconformld = 4; /* leading dimension which is valid, but nonconforming */
+ $ib = 1; /* index ranges for sub Matrix */
+ $ie = 2;
+ $jb = 1;
+ $je = 3;
+ $rowindexset = array(1,2);
+ $badrowindexset = array(1,3);
+ $columnindexset = array(1,2,3);
+ $badcolumnindexset = array(1,2,4);
+ $columnsummax = 33.;
+ $rowsummax = 30.;
+ $sumofdiagonals = 15;
+ $sumofsquares = 650;
+
+ /**
+ * Test matrix methods
+ */
+
+ /**
+ * Constructors and constructor-like methods:
+ *
+ * Matrix(double[], int)
+ * Matrix(double[][])
+ * Matrix(int, int)
+ * Matrix(int, int, double)
+ * Matrix(int, int, double[][])
+ * constructWithCopy(double[][])
+ * random(int,int)
+ * identity(int)
+ */
+ echo "<p>Testing constructors and constructor-like methods...</p>";
+
+ $A = new Matrix($columnwise, 3);
+ if($A instanceof Matrix) {
+ $this->try_success("Column-packed constructor...");
+ } else
+ $errorCount = $this->try_failure($errorCount, "Column-packed constructor...", "Unable to construct Matrix");
+
+ $T = new Matrix($tvals);
+ if($T instanceof Matrix)
+ $this->try_success("2D array constructor...");
+ else
+ $errorCount = $this->try_failure($errorCount, "2D array constructor...", "Unable to construct Matrix");
+
+ $A = new Matrix($columnwise, $validID);
+ $B = new Matrix($avals);
+ $tmp = $B->get(0,0);
+ $avals[0][0] = 0.0;
+ $C = $B->minus($A);
+ $avals[0][0] = $tmp;
+ $B = Matrix::constructWithCopy($avals);
+ $tmp = $B->get(0,0);
+ $avals[0][0] = 0.0;
+ /** check that constructWithCopy behaves properly **/
+ if ( ( $tmp - $B->get(0,0) ) != 0.0 )
+ $errorCount = $this->try_failure($errorCount,"constructWithCopy... ","copy not effected... data visible outside");
+ else
+ $this->try_success("constructWithCopy... ","");
+
+ $I = new Matrix($ivals);
+ if ( $this->checkMatrices($I,Matrix::identity(3,4)) )
+ $this->try_success("identity... ","");
+ else
+ $errorCount = $this->try_failure($errorCount,"identity... ","identity Matrix not successfully created");
+
+ /**
+ * Access Methods:
+ *
+ * getColumnDimension()
+ * getRowDimension()
+ * getArray()
+ * getArrayCopy()
+ * getColumnPackedCopy()
+ * getRowPackedCopy()
+ * get(int,int)
+ * getMatrix(int,int,int,int)
+ * getMatrix(int,int,int[])
+ * getMatrix(int[],int,int)
+ * getMatrix(int[],int[])
+ * set(int,int,double)
+ * setMatrix(int,int,int,int,Matrix)
+ * setMatrix(int,int,int[],Matrix)
+ * setMatrix(int[],int,int,Matrix)
+ * setMatrix(int[],int[],Matrix)
+ */
+ print "<p>Testing access methods...</p>";
+
+ $B = new Matrix($avals);
+ if($B->getRowDimension() == $rows)
+ $this->try_success("getRowDimension...");
+ else
+ $errorCount = $this->try_failure($errorCount, "getRowDimension...");
+
+ if($B->getColumnDimension() == $cols)
+ $this->try_success("getColumnDimension...");
+ else
+ $errorCount = $this->try_failure($errorCount, "getColumnDimension...");
+
+ $barray = $B->getArray();
+ if($this->checkArrays($barray, $avals))
+ $this->try_success("getArray...");
+ else
+ $errorCount = $this->try_failure($errorCount, "getArray...");
+
+ $bpacked = $B->getColumnPackedCopy();
+ if($this->checkArrays($bpacked, $columnwise))
+ $this->try_success("getColumnPackedCopy...");
+ else
+ $errorCount = $this->try_failure($errorCount, "getColumnPackedCopy...");
+
+ $bpacked = $B->getRowPackedCopy();
+ if($this->checkArrays($bpacked, $rowwise))
+ $this->try_success("getRowPackedCopy...");
+ else
+ $errorCount = $this->try_failure($errorCount, "getRowPackedCopy...");
+
+ /**
+ * Array-like methods:
+ * minus
+ * minusEquals
+ * plus
+ * plusEquals
+ * arrayLeftDivide
+ * arrayLeftDivideEquals
+ * arrayRightDivide
+ * arrayRightDivideEquals
+ * arrayTimes
+ * arrayTimesEquals
+ * uminus
+ */
+ print "<p>Testing array-like methods...</p>";
+
+ /**
+ * I/O methods:
+ * read
+ * print
+ * serializable:
+ * writeObject
+ * readObject
+ */
+ print "<p>Testing I/O methods...</p>";
+
+ /**
+ * Test linear algebra methods
+ */
+ echo "<p>Testing linear algebra methods...<p>";
+
+ $A = new Matrix($columnwise, 3);
+ if( $this->checkMatrices($A->transpose(), $T) )
+ $this->try_success("Transpose check...");
+ else
+ $errorCount = $this->try_failure($errorCount, "Transpose check...", "Matrices are not equal");
+
+ if($this->checkScalars($A->norm1(), $columnsummax))
+ $this->try_success("Maximum column sum...");
+ else
+ $errorCount = $this->try_failure($errorCount, "Maximum column sum...", "Incorrect: " . $A->norm1() . " != " . $columnsummax);
+
+ if($this->checkScalars($A->normInf(), $rowsummax))
+ $this->try_success("Maximum row sum...");
+ else
+ $errorCount = $this->try_failure($errorCount, "Maximum row sum...", "Incorrect: " . $A->normInf() . " != " . $rowsummax );
+
+ if($this->checkScalars($A->normF(), sqrt($sumofsquares)))
+ $this->try_success("Frobenius norm...");
+ else
+ $errorCount = $this->try_failure($errorCount, "Frobenius norm...", "Incorrect:" . $A->normF() . " != " . sqrt($sumofsquares));
+
+ if($this->checkScalars($A->trace(), $sumofdiagonals))
+ $this->try_success("Matrix trace...");
+ else
+ $errorCount = $this->try_failure($errorCount, "Matrix trace...", "Incorrect: " . $A->trace() . " != " . $sumofdiagonals);
+
+ $B = $A->getMatrix(0, $A->getRowDimension(), 0, $A->getRowDimension());
+ if( $B->det() == 0 )
+ $this->try_success("Matrix determinant...");
+ else
+ $errorCount = $this->try_failure($errorCount, "Matrix determinant...", "Incorrect: " . $B->det() . " != " . 0);
+
+ $A = new Matrix($columnwise,3);
+ $SQ = new Matrix($square);
+ if ($this->checkMatrices($SQ, $A->times($A->transpose())))
+ $this->try_success("times(Matrix)...");
+ else {
+ $errorCount = $this->try_failure($errorCount, "times(Matrix)...", "Unable to multiply matrices");
+ $SQ->toHTML();
+ $AT->toHTML();
+ }
+
+ $A = new Matrix($columnwise, 4);
+
+ $QR = $A->qr();
+ $R = $QR->getR();
+ $Q = $QR->getQ();
+ if($this->checkMatrices($A, $Q->times($R)))
+ $this->try_success("QRDecomposition...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"QRDecomposition...","incorrect qr decomposition calculation");
+
+ $A = new Matrix($columnwise, 4);
+ $SVD = $A->svd();
+ $U = $SVD->getU();
+ $S = $SVD->getS();
+ $V = $SVD->getV();
+ if ($this->checkMatrices($A, $U->times($S->times($V->transpose()))))
+ $this->try_success("SingularValueDecomposition...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"SingularValueDecomposition...","incorrect singular value decomposition calculation");
+
+ $n = $A->getColumnDimension();
+ $A = $A->getMatrix(0,$n-1,0,$n-1);
+ $A->set(0,0,0.);
+
+ $LU = $A->lu();
+ $L = $LU->getL();
+ if ( $this->checkMatrices($A->getMatrix($LU->getPivot(),0,$n-1), $L->times($LU->getU())) )
+ $this->try_success("LUDecomposition...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"LUDecomposition...","incorrect LU decomposition calculation");
+
+ $X = $A->inverse();
+ if ( $this->checkMatrices($A->times($X),Matrix::identity(3,3)) )
+ $this->try_success("inverse()...","");
+ else
+ $errorCount = $this->try_failure($errorCount, "inverse()...","incorrect inverse calculation");
+
+ $DEF = new Matrix($rankdef);
+ if($this->checkScalars($DEF->rank(), min($DEF->getRowDimension(), $DEF->getColumnDimension())-1))
+ $this->try_success("Rank...");
+ else
+ $this->try_failure("Rank...", "incorrect rank calculation");
+
+ $B = new Matrix($condmat);
+ $SVD = $B->svd();
+ $singularvalues = $SVD->getSingularValues();
+ if($this->checkScalars($B->cond(), $singularvalues[0]/$singularvalues[min($B->getRowDimension(), $B->getColumnDimension())-1]))
+ $this->try_success("Condition number...");
+ else
+ $this->try_failure("Condition number...", "incorrect condition number calculation");
+
+ $SUB = new Matrix($subavals);
+ $O = new Matrix($SUB->getRowDimension(),1,1.0);
+ $SOL = new Matrix($sqSolution);
+ $SQ = $SUB->getMatrix(0,$SUB->getRowDimension()-1,0,$SUB->getRowDimension()-1);
+ if ( $this->checkMatrices($SQ->solve($SOL),$O) )
+ $this->try_success("solve()...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"solve()...","incorrect lu solve calculation");
+
+ $A = new Matrix($pvals);
+ $Chol = $A->chol();
+ $L = $Chol->getL();
+ if ( $this->checkMatrices($A, $L->times($L->transpose())) )
+ $this->try_success("CholeskyDecomposition...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"CholeskyDecomposition...","incorrect Cholesky decomposition calculation");
+
+ $X = $Chol->solve(Matrix::identity(3,3));
+ if ( $this->checkMatrices($A->times($X), Matrix::identity(3,3)) )
+ $this->try_success("CholeskyDecomposition solve()...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"CholeskyDecomposition solve()...","incorrect Choleskydecomposition solve calculation");
+
+ $Eig = $A->eig();
+ $D = $Eig->getD();
+ $V = $Eig->getV();
+ if( $this->checkMatrices($A->times($V),$V->times($D)) )
+ $this->try_success("EigenvalueDecomposition (symmetric)...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (symmetric)...","incorrect symmetric Eigenvalue decomposition calculation");
+
+ $A = new Matrix($evals);
+ $Eig = $A->eig();
+ $D = $Eig->getD();
+ $V = $Eig->getV();
+ if ( $this->checkMatrices($A->times($V),$V->times($D)) )
+ $this->try_success("EigenvalueDecomposition (nonsymmetric)...","");
+ else
+ $errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (nonsymmetric)...","incorrect nonsymmetric Eigenvalue decomposition calculation");
+
+ print("<b>{$errorCount} total errors</b>.");
+ }
+
+ /**
+ * Print appropriate messages for successful outcome try
+ * @param string $s
+ * @param string $e
+ */
+ function try_success($s, $e = "") {
+ print "> ". $s ."success<br />";
+ if ($e != "")
+ print "> Message: ". $e ."<br />";
+ }
+
+ /**
+ * Print appropriate messages for unsuccessful outcome try
+ * @param int $count
+ * @param string $s
+ * @param string $e
+ * @return int incremented counter
+ */
+ function try_failure($count, $s, $e="") {
+ print "> ". $s ."*** failure ***<br />> Message: ". $e ."<br />";
+ return ++$count;
+ }
+
+ /**
+ * Print appropriate messages for unsuccessful outcome try
+ * @param int $count
+ * @param string $s
+ * @param string $e
+ * @return int incremented counter
+ */
+ function try_warning($count, $s, $e="") {
+ print "> ". $s ."*** warning ***<br />> Message: ". $e ."<br />";
+ return ++$count;
+ }
+
+ /**
+ * Check magnitude of difference of "scalars".
+ * @param float $x
+ * @param float $y
+ */
+ function checkScalars($x, $y) {
+ $eps = pow(2.0,-52.0);
+ if ($x == 0 & abs($y) < 10*$eps) return;
+ if ($y == 0 & abs($x) < 10*$eps) return;
+ if (abs($x-$y) > 10 * $eps * max(abs($x),abs($y)))
+ return false;
+ else
+ return true;
+ }
+
+ /**
+ * Check norm of difference of "vectors".
+ * @param float $x[]
+ * @param float $y[]
+ */
+ function checkVectors($x, $y) {
+ $nx = count($x);
+ $ny = count($y);
+ if ($nx == $ny)
+ for($i=0; $i < $nx; ++$i)
+ $this->checkScalars($x[$i],$y[$i]);
+ else
+ die("Attempt to compare vectors of different lengths");
+ }
+
+ /**
+ * Check norm of difference of "arrays".
+ * @param float $x[][]
+ * @param float $y[][]
+ */
+ function checkArrays($x, $y) {
+ $A = new Matrix($x);
+ $B = new Matrix($y);
+ return $this->checkMatrices($A,$B);
+ }
+
+ /**
+ * Check norm of difference of "matrices".
+ * @param matrix $X
+ * @param matrix $Y
+ */
+ function checkMatrices($X = null, $Y = null) {
+ if( $X == null || $Y == null )
+ return false;
+
+ $eps = pow(2.0,-52.0);
+ if ($X->norm1() == 0. & $Y->norm1() < 10*$eps) return true;
+ if ($Y->norm1() == 0. & $X->norm1() < 10*$eps) return true;
+
+ $A = $X->minus($Y);
+
+ if ($A->norm1() > 1000 * $eps * max($X->norm1(),$Y->norm1()))
+ die("The norm of (X-Y) is too large: ".$A->norm1());
+ else
+ return true;
+ }
+
+}
+
+$test = new TestMatrix;
+?>
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/utils/Error.php b/admin/survey/excel/PHPExcel/Shared/JAMA/utils/Error.php new file mode 100644 index 0000000..c895aa9 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/utils/Error.php @@ -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()");
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/JAMA/utils/Maths.php b/admin/survey/excel/PHPExcel/Shared/JAMA/utils/Maths.php new file mode 100644 index 0000000..5488e00 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/JAMA/utils/Maths.php @@ -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 Exception(JAMAError(ArgumentTypeException));
+ }
+ }
+ return sqrt($s);
+}
+*/
diff --git a/admin/survey/excel/PHPExcel/Shared/OLE.php b/admin/survey/excel/PHPExcel/Shared/OLE.php new file mode 100644 index 0000000..0f6222b --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/OLE.php @@ -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 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 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 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);
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/OLE/ChainedBlockStream.php b/admin/survey/excel/PHPExcel/Shared/OLE/ChainedBlockStream.php new file mode 100644 index 0000000..286e834 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/OLE/ChainedBlockStream.php @@ -0,0 +1,229 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (C) 2006 - 2012 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 1.7.8, 2012-10-12
+ */
+
+/**
+ * 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 )
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/OLE/PPS.php b/admin/survey/excel/PHPExcel/Shared/OLE/PPS.php new file mode 100644 index 0000000..6e3a689 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/OLE/PPS.php @@ -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;
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/OLE/PPS/File.php b/admin/survey/excel/PHPExcel/Shared/OLE/PPS/File.php new file mode 100644 index 0000000..3d651af --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/OLE/PPS/File.php @@ -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);
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/OLE/PPS/Root.php b/admin/survey/excel/PHPExcel/Shared/OLE/PPS/Root.php new file mode 100644 index 0000000..82cf9d1 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/OLE/PPS/Root.php @@ -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 Exception("Can't create temporary file.");
+ }
+ } else {
+ $this->_FILEH_ = fopen($filename, "wb");
+ }
+ if ($this->_FILEH_ == false) {
+ throw new 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));
+ }
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/OLERead.php b/admin/survey/excel/PHPExcel/Shared/OLERead.php new file mode 100644 index 0000000..1c2c0ac --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/OLERead.php @@ -0,0 +1,317 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+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 Exception
+ */
+ public function read($sFileName)
+ {
+ // Check if file exists and is readable
+ if(!is_readable($sFileName)) {
+ throw new Exception("Could not open " . $sFileName . " for reading! File does not exist, or it is not readable.");
+ }
+
+ // Get the file data
+ $this->data = file_get_contents($sFileName);
+
+ // Check OLE identifier
+ if (substr($this->data, 0, 8) != self::IDENTIFIER_OLE) {
+ throw new Exception('The filename ' . $sFileName . ' is not recognised as an OLE file');
+ }
+
+ // 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 = $index = 0;
+ $this->bigBlockChain = array();
+
+ $bbs = self::BIG_BLOCK_SIZE / 4;
+ for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
+ $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
+
+ for ($j = 0 ; $j < $bbs; ++$j) {
+ $this->bigBlockChain[$index] = self::_GetInt4d($this->data, $pos);
+ $pos += 4 ;
+ ++$index;
+ }
+ }
+
+ $pos = $index = 0;
+ $sbdBlock = $this->sbdStartBlock;
+ $this->smallBlockChain = array();
+
+ while ($sbdBlock != -2) {
+ $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
+
+ for ($j = 0; $j < $bbs; ++$j) {
+ $this->smallBlockChain[$index] = self::_GetInt4d($this->data, $pos);
+ $pos += 4;
+ ++$index;
+ }
+
+ $sbdBlock = $this->bigBlockChain[$sbdBlock];
+ }
+
+ // 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 = $this->smallBlockChain[$block];
+ }
+
+ 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 = $this->bigBlockChain[$block];
+ }
+
+ 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 = $this->bigBlockChain[$block];
+ }
+ 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);
+
+ // Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook)
+ if (($name == 'Workbook') || ($name == 'Book') || ($name == 'WORKBOOK') || ($name == 'BOOK')) {
+ $this->wrkbook = count($this->props) - 1;
+ }
+
+ // Root entry
+ if ($name == 'Root Entry' || $name == 'ROOT ENTRY' || $name == 'R') {
+ $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;
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/PCLZip/gnu-lgpl.txt b/admin/survey/excel/PHPExcel/Shared/PCLZip/gnu-lgpl.txt new file mode 100644 index 0000000..cbee875 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/PCLZip/gnu-lgpl.txt @@ -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!
+
+
diff --git a/admin/survey/excel/PHPExcel/Shared/PCLZip/pclzip.lib.php b/admin/survey/excel/PHPExcel/Shared/PCLZip/pclzip.lib.php new file mode 100644 index 0000000..4bf05a5 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/PCLZip/pclzip.lib.php @@ -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;
+ }
+ // --------------------------------------------------------------------------------
+
+
+?>
diff --git a/admin/survey/excel/PHPExcel/Shared/PCLZip/readme.txt b/admin/survey/excel/PHPExcel/Shared/PCLZip/readme.txt new file mode 100644 index 0000000..6ed8839 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/PCLZip/readme.txt @@ -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
diff --git a/admin/survey/excel/PHPExcel/Shared/PasswordHasher.php b/admin/survey/excel/PHPExcel/Shared/PasswordHasher.php new file mode 100644 index 0000000..9c8a3b4 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/PasswordHasher.php @@ -0,0 +1,67 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_PasswordHasher
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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;
+ $i = 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) << $i; // shifted ASCII value
+ $rotated_bits = $value >> 15; // rotated bits beyond bit 15
+ $value &= 0x7fff; // first 15 bits
+ $password ^= ($value | $rotated_bits);
+ ++$i;
+ }
+
+ $password ^= strlen($pPassword);
+ $password ^= 0xCE4B;
+
+ return(strtoupper(dechex($password)));
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/String.php b/admin/survey/excel/PHPExcel/Shared/String.php new file mode 100644 index 0000000..3dac3e5 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/String.php @@ -0,0 +1,730 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_String
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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
+ * @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, 0x08);
+ $data .= pack('v', count($arrcRuns));
+ // characters
+ $data .= $value;
+ 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 iconv, then mbstring, or no convertion
+ *
+ * @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()) {
+ $value = iconv($from, $to, $value);
+ return $value;
+ }
+
+ if (self::getIsMbstringEnabled()) {
+ $value = mb_convert_encoding($value, $to, $from);
+ return $value;
+ }
+ 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::getIsIconvEnabled()) {
+ return iconv_strlen($value, $enc);
+ }
+
+ if (self::getIsMbstringEnabled()) {
+ return mb_strlen($value, $enc);
+ }
+
+ // else strlen
+ return strlen($value);
+ }
+
+ /**
+ * Get a substring of a UTF-8 encoded string
+ *
+ * @param string $pValue UTF-8 encoded string
+ * @param int $start Start offset
+ * @param int $length Maximum number of characters in substring
+ * @return string
+ */
+ public static function Substring($pValue = '', $pStart = 0, $pLength = 0)
+ {
+ if (self::getIsIconvEnabled()) {
+ return iconv_substr($pValue, $pStart, $pLength, 'UTF-8');
+ }
+
+ if (self::getIsMbstringEnabled()) {
+ return mb_substr($pValue, $pStart, $pLength, 'UTF-8');
+ }
+
+ // else substr
+ return substr($pValue, $pStart, $pLength);
+ }
+
+
+ /**
+ * 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'];
+ }
+ 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;
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/XMLWriter.php b/admin/survey/excel/PHPExcel/Shared/XMLWriter.php new file mode 100644 index 0000000..c601019 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/XMLWriter.php @@ -0,0 +1,127 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+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 - 2012 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);
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/ZipArchive.php b/admin/survey/excel/PHPExcel/Shared/ZipArchive.php new file mode 100644 index 0000000..b9eae98 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/ZipArchive.php @@ -0,0 +1,114 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+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 - 2012 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 Exception("Error zipping files : " . $this->_zip->errorInfo(true));
+ }
+
+ unlink($this->_tempDir.'/'.$filenameParts["basename"]);
+ }
+
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/ZipStreamWrapper.php b/admin/survey/excel/PHPExcel/Shared/ZipStreamWrapper.php new file mode 100644 index 0000000..8c55884 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/ZipStreamWrapper.php @@ -0,0 +1,183 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Shared_ZipStreamWrapper
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared
+ * @copyright Copyright (c) 2006 - 2012 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 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 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;
+ }
+ }
+}
diff --git a/admin/survey/excel/PHPExcel/Shared/trend/bestFitClass.php b/admin/survey/excel/PHPExcel/Shared/trend/bestFitClass.php new file mode 100644 index 0000000..dd2c094 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/trend/bestFitClass.php @@ -0,0 +1,432 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+/**
+ * PHPExcel_Best_Fit
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Trend
+ * @copyright Copyright (c) 2006 - 2012 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
diff --git a/admin/survey/excel/PHPExcel/Shared/trend/exponentialBestFitClass.php b/admin/survey/excel/PHPExcel/Shared/trend/exponentialBestFitClass.php new file mode 100644 index 0000000..6cc8201 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/trend/exponentialBestFitClass.php @@ -0,0 +1,148 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php');
+
+
+/**
+ * PHPExcel_Exponential_Best_Fit
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Trend
+ * @copyright Copyright (c) 2006 - 2012 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
\ No newline at end of file diff --git a/admin/survey/excel/PHPExcel/Shared/trend/linearBestFitClass.php b/admin/survey/excel/PHPExcel/Shared/trend/linearBestFitClass.php new file mode 100644 index 0000000..0fe62b1 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/trend/linearBestFitClass.php @@ -0,0 +1,111 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php');
+
+
+/**
+ * PHPExcel_Linear_Best_Fit
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Trend
+ * @copyright Copyright (c) 2006 - 2012 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
\ No newline at end of file diff --git a/admin/survey/excel/PHPExcel/Shared/trend/logarithmicBestFitClass.php b/admin/survey/excel/PHPExcel/Shared/trend/logarithmicBestFitClass.php new file mode 100644 index 0000000..acccc53 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/trend/logarithmicBestFitClass.php @@ -0,0 +1,120 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php');
+
+
+/**
+ * PHPExcel_Logarithmic_Best_Fit
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Trend
+ * @copyright Copyright (c) 2006 - 2012 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
\ No newline at end of file diff --git a/admin/survey/excel/PHPExcel/Shared/trend/polynomialBestFitClass.php b/admin/survey/excel/PHPExcel/Shared/trend/polynomialBestFitClass.php new file mode 100644 index 0000000..eef0060 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/trend/polynomialBestFitClass.php @@ -0,0 +1,224 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+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 - 2012 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
\ No newline at end of file diff --git a/admin/survey/excel/PHPExcel/Shared/trend/powerBestFitClass.php b/admin/survey/excel/PHPExcel/Shared/trend/powerBestFitClass.php new file mode 100644 index 0000000..22c23d7 --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/trend/powerBestFitClass.php @@ -0,0 +1,142 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php';
+
+
+/**
+ * PHPExcel_Power_Best_Fit
+ *
+ * @category PHPExcel
+ * @package PHPExcel_Shared_Trend
+ * @copyright Copyright (c) 2006 - 2012 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
\ No newline at end of file diff --git a/admin/survey/excel/PHPExcel/Shared/trend/trendClass.php b/admin/survey/excel/PHPExcel/Shared/trend/trendClass.php new file mode 100644 index 0000000..59d1b1f --- /dev/null +++ b/admin/survey/excel/PHPExcel/Shared/trend/trendClass.php @@ -0,0 +1,156 @@ +<?php
+/**
+ * PHPExcel
+ *
+ * Copyright (c) 2006 - 2012 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 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
+ * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
+ * @version 1.7.8, 2012-10-12
+ */
+
+
+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 - 2012 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
\ No newline at end of file |