Add PCLZIP alternative to ZipArchive

Resolves #106
This commit is contained in:
Brandon Skrtich 2014-03-16 11:57:48 -06:00
parent f4d7fa427d
commit b9244d6318
6 changed files with 6110 additions and 11 deletions

View File

@ -30,6 +30,12 @@
*/
class PHPWord_Settings
{
/** constants */
/** Available Zip library classes */
const PCLZIP = 'PHPWord_Shared_ZipArchive';
const ZIPARCHIVE = 'ZipArchive';
/**
* Compatibility option for XMLWriter
*
@ -37,6 +43,15 @@ class PHPWord_Settings
*/
private static $_xmlWriterCompatibility = true;
/**
* Name of the class used for Zip file management
* e.g.
* ZipArchive
*
* @var string
*/
private static $_zipClass = self::ZIPARCHIVE;
/**
* Set the compatibility option used by the XMLWriter
*
@ -50,7 +65,7 @@ class PHPWord_Settings
return true;
}
return false;
}
} // function setCompatibility()
/**
* Return the compatibility option used by the XMLWriter
@ -60,5 +75,36 @@ class PHPWord_Settings
public static function getCompatibility()
{
return self::$_xmlWriterCompatibility;
} // function getCompatibility()
/**
* Set the Zip handler Class that PHPWord should use for Zip file management (PCLZip or ZipArchive)
*
* @param string $zipClass The Zip handler class that PHPWord should use for Zip file management
* e.g. PHPWord_Settings::PCLZip or PHPWord_Settings::ZipArchive
* @return boolean Success or failure
*/
public static function setZipClass($zipClass)
{
if (($zipClass === self::PCLZIP) ||
($zipClass === self::ZIPARCHIVE)) {
self::$_zipClass = $zipClass;
return TRUE;
}
return FALSE;
} // function setZipClass()
/**
* Return the name of the Zip handler Class that PHPWord is configured to use (PCLZip or ZipArchive)
* or Zip file management
*
* @return string Name of the Zip handler Class that PHPWord is configured to use
* for Zip file management
* e.g. PHPWord_Settings::PCLZip or PHPWord_Settings::ZipArchive
*/
public static function getZipClass()
{
return self::$_zipClass;
} // function getZipClass()
}

View File

@ -30,11 +30,39 @@
*/
class PHPWord_Shared_File
{
/*
* Use Temp or File Upload Temp for temporary files
*
* @protected
* @var boolean
*/
protected static $_useUploadTempDirectory = FALSE;
/**
* Set the flag indicating whether the File Upload Temp directory should be used for temporary files
*
* @param boolean $useUploadTempDir Use File Upload Temporary directory (true or false)
*/
public static function setUseUploadTempDirectory($useUploadTempDir = FALSE) {
self::$_useUploadTempDirectory = (boolean) $useUploadTempDir;
} // function setUseUploadTempDirectory()
/**
* Get the flag indicating whether the File Upload Temp directory should be used for temporary files
*
* @return boolean Use File Upload Temporary directory (true or false)
*/
public static function getUseUploadTempDirectory() {
return self::$_useUploadTempDirectory;
} // function getUseUploadTempDirectory()
/**
* Verify if a file exists
*
* @param string $pFilename Filename
* @return bool
* @return boolean
*/
public static function file_exists($pFilename)
{
@ -74,4 +102,70 @@ class PHPWord_Shared_File
// Return
return $returnValue;
}
/**
* Return the Image Type from a file
*
* @param string $filename
* @return return
*/
public static function imagetype($filename) {
if (function_exists('exif_imagetype')) {
return exif_imagetype($filename);
} else {
if ((list($width, $height, $type, $attr) = getimagesize( $filename )) !== false) {
return $type;
}
}
return false;
}
/**
* Get the systems temporary directory.
*
* @return string
*/
public static function sys_get_temp_dir()
{
if (self::$_useUploadTempDirectory) {
// use upload-directory when defined to allow running on environments having very restricted
// open_basedir configs
if (ini_get('upload_tmp_dir') !== FALSE) {
if ($temp = ini_get('upload_tmp_dir')) {
if (file_exists($temp))
return realpath($temp);
}
}
}
// sys_get_temp_dir is only available since PHP 5.2.1
// http://php.net/manual/en/function.sys-get-temp-dir.php#94119
if ( !function_exists('sys_get_temp_dir')) {
if ($temp = getenv('TMP') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
if ($temp = getenv('TEMP') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
if ($temp = getenv('TMPDIR') ) {
if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); }
}
// trick for creating a file in system's temporary dir
// without knowing the path of the system's temporary dir
$temp = tempnam(__FILE__, '');
if (file_exists($temp)) {
unlink($temp);
return realpath(dirname($temp));
}
return null;
}
// use ordinary built-in PHP function
// There should be no problem with the 5.2.4 Suhosin realpath() bug, because this line should only
// be called if we're running 5.2.1 or earlier
return realpath(sys_get_temp_dir());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,204 @@
<?php
/**
* PHPWord
*
* Copyright (c) 2014 PHPWord
*
* 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 PHPWord
* @package PHPWord
* @copyright Copyright (c) 2014 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version 0.8.0
*/
if (!defined('PCLZIP_TEMPORARY_DIR')) {
// PCLZIP needs the temp path to end in a back slash
define('PCLZIP_TEMPORARY_DIR', PHPWord_Shared_File::sys_get_temp_dir().'/');
}
require_once(PHPWORD_BASE_PATH . 'PHPWord/Shared/PCLZip/pclzip.lib.php');
/**
* PHPWord_Shared_ZipArchive
*
* @category PHPWord
* @package PHPWord_Shared_ZipArchive
* @copyright Copyright (c) 2006 - 2014 PHPWord (http://www.codeplex.com/PHPWord)
*/
class PHPWord_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 = PHPWord_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.
*
* @param string $filename Directory/Name of the file to add to the zip archive
* @param string $localname Directory/Name of the file added to the zip
*/
public function addFile($filename, $localname = NULL) {
$filenameParts = pathinfo($filename);
$localnameParts = pathinfo($localname);
// To Rename the file while adding it to the zip we
// need to create a temp file with the correct name
if ($filenameParts['basename'] != $localnameParts['basename']) {
$temppath = $this->_tempDir.'/'.$localnameParts['basename'];
copy($filename, $temppath);
$filename = $temppath;
$filenameParts = pathinfo($temppath);
}
$res = $this->_zip->add($filename,
PCLZIP_OPT_REMOVE_PATH, $filenameParts['dirname'],
PCLZIP_OPT_ADD_PATH, $localnameParts["dirname"]
);
if ($res == 0) {
throw new PHPWord_Writer_Exception("Error zipping files : " . $this->_zip->errorInfo(true));
return false;
}
return true;
}
/**
* 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);
// Write $contents to a temp file
$handle = fopen($this->_tempDir.'/'.$filenameParts["basename"], "wb");
fwrite($handle, $contents);
fclose($handle);
// Add temp file to zip
$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 PHPWord_Writer_Exception("Error zipping files : " . $this->_zip->errorInfo(true));
return false;
}
// Remove temp file
unlink($this->_tempDir.'/'.$filenameParts["basename"]);
return true;
}
/**
* Find if given fileName exist in archive (Emulate ZipArchive locateName())
*
* @param string $fileName Filename for the file in zip archive
* @return boolean
*/
public function locateName($fileName) {
$list = $this->_zip->listContent();
$listCount = count($list);
$list_index = -1;
for ($i = 0; $i < $listCount; ++$i) {
if (strtolower($list[$i]["filename"]) == strtolower($fileName) ||
strtolower($list[$i]["stored_filename"]) == strtolower($fileName)) {
$list_index = $i;
break;
}
}
return ($list_index > -1);
}
/**
* Extract file from archive by given fileName (Emulate ZipArchive getFromName())
*
* @param string $fileName Filename for the file in zip archive
* @return string $contents File string contents
*/
public function getFromName($fileName) {
$list = $this->_zip->listContent();
$listCount = count($list);
$list_index = -1;
for ($i = 0; $i < $listCount; ++$i) {
if (strtolower($list[$i]["filename"]) == strtolower($fileName) ||
strtolower($list[$i]["stored_filename"]) == strtolower($fileName)) {
$list_index = $i;
break;
}
}
$extracted = "";
if ($list_index != -1) {
$extracted = $this->_zip->extractByIndex($list_index, PCLZIP_OPT_EXTRACT_AS_STRING);
} else {
$filename = substr($fileName, 1);
$list_index = -1;
for ($i = 0; $i < $listCount; ++$i) {
if (strtolower($list[$i]["filename"]) == strtolower($fileName) ||
strtolower($list[$i]["stored_filename"]) == strtolower($fileName)) {
$list_index = $i;
break;
}
}
$extracted = $this->_zip->extractByIndex($list_index, PCLZIP_OPT_EXTRACT_AS_STRING);
}
if ((is_array($extracted)) && ($extracted != 0)) {
$contents = $extracted[0]["content"];
}
return $contents;
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* PHPWord
*
* Copyright (c) 2014 PHPWord
*
* 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 PHPWord
* @package PHPWord
* @copyright Copyright (c) 2014 PHPWord
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* @version 0.8.0
*/
/**
* Class PHPWord_Exception
*/
class PHPWord_Writer_Exception extends PHPWord_Exception
{
/**
* Error handler callback
*
* @param mixed $code
* @param mixed $string
* @param mixed $file
* @param mixed $line
* @param mixed $context
*/
public static function errorHandlerCallback($code, $string, $file, $line, $context)
{
$e = new self($string, $code);
$e->line = $line;
$e->file = $file;
throw $e;
}
}

View File

@ -77,11 +77,23 @@ class PHPWord_Writer_Word2007 implements PHPWord_Writer_IWriter
}
// Create new ZIP file and open it for writing
$objZip = new ZipArchive();
$zipClass = PHPWord_Settings::getZipClass();
$objZip = new $zipClass();
// Retrieve OVERWRITE and CREATE constants from the instantiated zip class
// This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP
$ro = new ReflectionObject($objZip);
$zipOverWrite = $ro->getConstant('OVERWRITE');
$zipCreate = $ro->getConstant('CREATE');
// Remove any existing file
if (file_exists($pFilename)) {
unlink($pFilename);
}
// Try opening the ZIP file
if ($objZip->open($pFilename, ZIPARCHIVE::OVERWRITE) !== true) {
if ($objZip->open($pFilename, ZIPARCHIVE::CREATE) !== true) {
if ($objZip->open($pFilename, $zipOverWrite) !== true) {
if ($objZip->open($pFilename, $zipCreate) !== true) {
throw new Exception("Could not open " . $pFilename . " for writing.");
}
}