2014-03-16 11:57:48 -06:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* PHPWord
|
|
|
|
|
*
|
2014-03-28 19:41:33 +07:00
|
|
|
* @link https://github.com/PHPOffice/PHPWord
|
2014-05-05 12:38:31 +04:00
|
|
|
* @copyright 2010-2014 PHPWord contributors
|
2014-05-04 21:03:28 +04:00
|
|
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
2014-03-16 11:57:48 -06:00
|
|
|
*/
|
|
|
|
|
|
2014-03-28 19:41:33 +07:00
|
|
|
namespace PhpOffice\PhpWord\Shared;
|
|
|
|
|
|
2014-04-18 01:58:03 +07:00
|
|
|
// PCLZIP needs the temp path to end in a back slash
|
2014-03-28 19:41:33 +07:00
|
|
|
// @codeCoverageIgnoreStart
|
2014-03-16 11:57:48 -06:00
|
|
|
if (!defined('PCLZIP_TEMPORARY_DIR')) {
|
2014-03-28 19:41:33 +07:00
|
|
|
define('PCLZIP_TEMPORARY_DIR', sys_get_temp_dir() . '/');
|
2014-03-16 11:57:48 -06:00
|
|
|
}
|
2014-03-28 19:41:33 +07:00
|
|
|
require_once 'PCLZip/pclzip.lib.php';
|
|
|
|
|
// @codeCoverageIgnoreEnd
|
2014-03-16 11:57:48 -06:00
|
|
|
|
|
|
|
|
/**
|
2014-03-28 19:41:33 +07:00
|
|
|
* PCLZip wrapper
|
2014-03-16 11:57:48 -06:00
|
|
|
*
|
2014-04-11 19:04:53 +07:00
|
|
|
* @since 0.10.0
|
2014-03-16 11:57:48 -06:00
|
|
|
*/
|
2014-03-28 19:41:33 +07:00
|
|
|
class ZipArchive
|
|
|
|
|
{
|
2014-03-16 11:57:48 -06:00
|
|
|
/** constants */
|
|
|
|
|
const OVERWRITE = 'OVERWRITE';
|
|
|
|
|
const CREATE = 'CREATE';
|
|
|
|
|
|
2014-04-08 16:09:31 +07:00
|
|
|
/**
|
|
|
|
|
* Number of files (emulate ZipArchive::$numFiles)
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
public $numFiles = 0;
|
|
|
|
|
|
2014-03-16 11:57:48 -06:00
|
|
|
/**
|
|
|
|
|
* Temporary storage directory
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2014-04-03 11:34:06 +07:00
|
|
|
private $tempDir;
|
2014-03-16 11:57:48 -06:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Zip Archive Stream Handle
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2014-04-03 11:34:06 +07:00
|
|
|
private $zip;
|
2014-03-16 11:57:48 -06:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Open a new zip archive
|
|
|
|
|
*
|
2014-04-08 16:09:31 +07:00
|
|
|
* @param string $filename Filename for the zip archive
|
2014-03-16 11:57:48 -06:00
|
|
|
* @return boolean
|
|
|
|
|
*/
|
2014-04-08 16:09:31 +07:00
|
|
|
public function open($filename)
|
2014-03-28 19:41:33 +07:00
|
|
|
{
|
2014-04-03 11:34:06 +07:00
|
|
|
$this->tempDir = sys_get_temp_dir();
|
2014-04-08 16:09:31 +07:00
|
|
|
$this->zip = new \PclZip($filename);
|
|
|
|
|
$this->numFiles = count($this->zip->listContent());
|
2014-03-16 11:57:48 -06:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-04-18 01:58:03 +07:00
|
|
|
* Close this zip archive (emulate \ZipArchive)
|
2014-03-16 11:57:48 -06:00
|
|
|
*
|
2014-03-28 19:41:33 +07:00
|
|
|
* @codeCoverageIgnore
|
2014-03-16 11:57:48 -06:00
|
|
|
*/
|
2014-03-28 19:41:33 +07:00
|
|
|
public function close()
|
|
|
|
|
{
|
2014-03-16 11:57:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-04-18 01:58:03 +07:00
|
|
|
* Add a new file to the zip archive (emulate \ZipArchive)
|
2014-03-16 11:57:48 -06:00
|
|
|
*
|
|
|
|
|
* @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
|
|
|
|
|
*/
|
2014-03-28 19:41:33 +07:00
|
|
|
public function addFile($filename, $localname = null)
|
|
|
|
|
{
|
|
|
|
|
$filename = realpath($filename);
|
2014-03-16 11:57:48 -06:00
|
|
|
$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']) {
|
2014-04-03 11:34:06 +07:00
|
|
|
$temppath = $this->tempDir . '/' . $localnameParts['basename'];
|
2014-03-16 11:57:48 -06:00
|
|
|
copy($filename, $temppath);
|
|
|
|
|
$filename = $temppath;
|
|
|
|
|
$filenameParts = pathinfo($temppath);
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-03 11:34:06 +07:00
|
|
|
$res = $this->zip->add(
|
2014-03-28 19:41:33 +07:00
|
|
|
$filename,
|
|
|
|
|
PCLZIP_OPT_REMOVE_PATH,
|
|
|
|
|
$filenameParts['dirname'],
|
|
|
|
|
PCLZIP_OPT_ADD_PATH,
|
|
|
|
|
$localnameParts["dirname"]
|
|
|
|
|
);
|
2014-03-16 11:57:48 -06:00
|
|
|
|
2014-04-18 01:58:03 +07:00
|
|
|
return ($res == 0) ? false : true;
|
2014-03-16 11:57:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-04-18 01:58:03 +07:00
|
|
|
* Add a new file to the zip archive from a string of raw data (emulate \ZipArchive)
|
2014-03-16 11:57:48 -06:00
|
|
|
*
|
|
|
|
|
* @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
|
|
|
|
|
*/
|
2014-03-28 19:41:33 +07:00
|
|
|
public function addFromString($localname, $contents)
|
|
|
|
|
{
|
2014-03-16 11:57:48 -06:00
|
|
|
$filenameParts = pathinfo($localname);
|
|
|
|
|
|
|
|
|
|
// Write $contents to a temp file
|
2014-04-03 11:34:06 +07:00
|
|
|
$handle = fopen($this->tempDir . '/' . $filenameParts["basename"], "wb");
|
2014-03-16 11:57:48 -06:00
|
|
|
fwrite($handle, $contents);
|
|
|
|
|
fclose($handle);
|
|
|
|
|
|
|
|
|
|
// Add temp file to zip
|
2014-04-03 11:34:06 +07:00
|
|
|
$res = $this->zip->add(
|
|
|
|
|
$this->tempDir . '/' . $filenameParts["basename"],
|
2014-03-28 19:41:33 +07:00
|
|
|
PCLZIP_OPT_REMOVE_PATH,
|
2014-04-03 11:34:06 +07:00
|
|
|
$this->tempDir,
|
2014-03-28 19:41:33 +07:00
|
|
|
PCLZIP_OPT_ADD_PATH,
|
|
|
|
|
$filenameParts["dirname"]
|
|
|
|
|
);
|
2014-03-16 11:57:48 -06:00
|
|
|
|
|
|
|
|
// Remove temp file
|
2014-04-18 01:58:03 +07:00
|
|
|
@unlink($this->tempDir . '/' . $filenameParts["basename"]);
|
2014-03-16 11:57:48 -06:00
|
|
|
|
2014-04-18 01:58:03 +07:00
|
|
|
return ($res == 0) ? false : true;
|
2014-03-16 11:57:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-04-18 01:58:03 +07:00
|
|
|
* Returns the index of the entry in the archive (emulate \ZipArchive)
|
2014-03-16 11:57:48 -06:00
|
|
|
*
|
2014-04-18 01:58:03 +07:00
|
|
|
* @param string $filename Filename for the file in zip archive
|
|
|
|
|
* @return integer|false
|
2014-03-16 11:57:48 -06:00
|
|
|
*/
|
2014-04-08 16:09:31 +07:00
|
|
|
public function locateName($filename)
|
2014-03-28 19:41:33 +07:00
|
|
|
{
|
2014-04-03 11:34:06 +07:00
|
|
|
$list = $this->zip->listContent();
|
2014-03-16 11:57:48 -06:00
|
|
|
$listCount = count($list);
|
2014-04-03 11:34:06 +07:00
|
|
|
$listIndex = -1;
|
2014-03-16 11:57:48 -06:00
|
|
|
for ($i = 0; $i < $listCount; ++$i) {
|
2014-04-08 16:09:31 +07:00
|
|
|
if (strtolower($list[$i]["filename"]) == strtolower($filename) ||
|
|
|
|
|
strtolower($list[$i]["stored_filename"]) == strtolower($filename)) {
|
2014-04-03 11:34:06 +07:00
|
|
|
$listIndex = $i;
|
2014-03-16 11:57:48 -06:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-03-28 19:41:33 +07:00
|
|
|
|
2014-04-18 01:58:03 +07:00
|
|
|
return ($listIndex > -1) ? $listIndex : false;
|
2014-03-16 11:57:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-04-18 01:58:03 +07:00
|
|
|
* Extract file from archive by given file name (emulate \ZipArchive)
|
2014-03-16 11:57:48 -06:00
|
|
|
*
|
2014-04-08 16:09:31 +07:00
|
|
|
* @param string $filename Filename for the file in zip archive
|
2014-04-18 01:58:03 +07:00
|
|
|
* @return string|false $contents File string contents
|
2014-03-16 11:57:48 -06:00
|
|
|
*/
|
2014-04-08 16:09:31 +07:00
|
|
|
public function getFromName($filename)
|
2014-03-28 19:41:33 +07:00
|
|
|
{
|
2014-04-18 01:58:03 +07:00
|
|
|
$listIndex = $this->locateName($filename);
|
|
|
|
|
$contents = false;
|
2014-04-05 01:41:48 +07:00
|
|
|
|
2014-04-18 01:58:03 +07:00
|
|
|
if ($listIndex !== false) {
|
2014-04-03 11:34:06 +07:00
|
|
|
$extracted = $this->zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING);
|
2014-03-16 11:57:48 -06:00
|
|
|
} else {
|
2014-04-08 16:09:31 +07:00
|
|
|
$filename = substr($filename, 1);
|
2014-04-18 01:58:03 +07:00
|
|
|
$listIndex = $this->locateName($filename);
|
2014-04-03 11:34:06 +07:00
|
|
|
$extracted = $this->zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING);
|
2014-03-16 11:57:48 -06:00
|
|
|
}
|
|
|
|
|
if ((is_array($extracted)) && ($extracted != 0)) {
|
|
|
|
|
$contents = $extracted[0]["content"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $contents;
|
|
|
|
|
}
|
2014-04-08 16:09:31 +07:00
|
|
|
|
|
|
|
|
/**
|
2014-04-18 01:58:03 +07:00
|
|
|
* Returns the name of an entry using its index (emulate \ZipArchive)
|
2014-04-08 16:09:31 +07:00
|
|
|
*
|
|
|
|
|
* @param integer $index
|
|
|
|
|
* @return string|false
|
2014-04-18 01:58:03 +07:00
|
|
|
* @since 0.10.0
|
2014-04-08 16:09:31 +07:00
|
|
|
*/
|
|
|
|
|
public function getNameIndex($index)
|
|
|
|
|
{
|
|
|
|
|
$list = $this->zip->listContent();
|
2014-04-12 00:59:29 +02:00
|
|
|
if (isset($list[$index])) {
|
2014-04-08 16:09:31 +07:00
|
|
|
return $list[$index]['filename'];
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-18 01:58:03 +07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Extract the archive contents (emulate \ZipArchive)
|
|
|
|
|
*
|
|
|
|
|
* @param string $destination
|
|
|
|
|
* @param string|array $entries
|
|
|
|
|
* @return boolean
|
|
|
|
|
* @since 0.10.0
|
|
|
|
|
*/
|
|
|
|
|
public function extractTo($destination, $entries = null)
|
|
|
|
|
{
|
|
|
|
|
if (!is_dir($destination)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Extract all files
|
|
|
|
|
if (is_null($entries)) {
|
|
|
|
|
$result = $this->zip->extract(PCLZIP_OPT_PATH, $destination);
|
|
|
|
|
return ($result > 0) ? true : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Extract by entries
|
|
|
|
|
if (!is_array($entries)) {
|
|
|
|
|
$entries = array($entries);
|
|
|
|
|
}
|
|
|
|
|
foreach ($entries as $entry) {
|
|
|
|
|
$entryIndex = $this->locateName($entry);
|
|
|
|
|
$result = $this->zip->extractByIndex($entryIndex, PCLZIP_OPT_PATH, $destination);
|
|
|
|
|
if ($result <= 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2014-03-16 11:57:48 -06:00
|
|
|
}
|