1<?php
2require_once 'pclzip/pclzip.lib.php';
3require_once 'ZipInterface.php';
4class PclZipProxyException extends \Exception
5{ }
6/**
7 * Proxy class for the PclZip library
8 * You need PHP 5.2 at least
9 * You need Zip Extension or PclZip library
10 * Encoding : ISO-8859-1
11 * Last commit by $Author: neveldo $
12 * Date - $Date: 2009-05-29 10:05:11 +0200 (ven., 29 mai 2009) $
13 * SVN Revision - $Rev: 28 $
14 * Id : $Id: odf.php 28 2009-05-29 08:05:11Z neveldo $
15 *
16 * @copyright  GPL License 2008 - Julien Pauli - Cyril PIERRE de GEYER - Anaska (http://www.anaska.com)
17 * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
18 * @version 1.3
19 */
20class PclZipProxy implements ZipInterface
21{
22	const TMP_DIR = './tmp';
23	protected $openned = false;
24	protected $filename;
25	protected $pclzip;
26    /**
27     * Class constructor
28     *
29     * @throws PclZipProxyException
30     */
31	public function __construct()
32	{
33		if (! class_exists('PclZip')) {
34			throw new PclZipProxyException('PclZip class not loaded - PclZip library
35			 is required for using PclZipProxy'); ;
36		}
37	}
38	/**
39	 * Open a Zip archive
40	 *
41	 * @param StringHelper $filename the name of the archive to open
42	 * @return true if openning has succeeded
43	 */
44	public function open($filename)
45	{
46		if (true === $this->openned) {
47			$this->close();
48		}
49		if (!file_exists(self::TMP_DIR)) {
50			mkdir(self::TMP_DIR);
51		}
52		$this->filename = $filename;
53		$this->pclzip = new PclZip($this->filename);
54		$this->openned = true;
55		return true;
56	}
57	/**
58	 * Retrieve the content of a file within the archive from its name
59	 *
60	 * @param StringHelper $name the name of the file to extract
61	 * @return the content of the file in a string
62	 */
63	public function getFromName($name)
64	{
65		if (false === $this->openned) {
66			return false;
67		}
68		$name = preg_replace("/(?:\.|\/)*(.*)/", "\\1", $name);
69		$extraction = $this->pclzip->extract(PCLZIP_OPT_BY_NAME, $name,
70			PCLZIP_OPT_EXTRACT_AS_STRING);
71		if (!empty($extraction)) {
72			return $extraction[0]['content'];
73		}
74		return false;
75	}
76	/**
77	 * Add a file within the archive from a string
78	 *
79	 * @param StringHelper $localname the local path to the file in the archive
80	 * @param StringHelper $contents the content of the file
81	 * @return true if the file has been successful added
82	 */
83	public function addFromString($localname, $contents)
84	{
85		if (false === $this->openned) {
86			return false;
87		}
88		if (file_exists($this->filename) && !is_writable($this->filename)) {
89			return false;
90		}
91		$localname = preg_replace("/(?:\.|\/)*(.*)/", "\\1", $localname);
92		$localpath = dirname($localname);
93		$tmpfilename = self::TMP_DIR . '/' . basename($localname);
94		if (false !== file_put_contents($tmpfilename, $contents)) {
95			$this->pclzip->delete(PCLZIP_OPT_BY_NAME, $localname);
96			$add = $this->pclzip->add($tmpfilename,
97				PCLZIP_OPT_REMOVE_PATH, self::TMP_DIR,
98				PCLZIP_OPT_ADD_PATH, $localpath);
99			unlink($tmpfilename);
100			if (!empty($add)) {
101				return true;
102			}
103		}
104		return false;
105	}
106	/**
107	 * Add a file within the archive from a file
108	 *
109	 * @param StringHelper $filename the path to the file we want to add
110	 * @param StringHelper $localname the local path to the file in the archive
111	 * @return true if the file has been successful added
112	 */
113	public function addFile($filename, $localname = null)
114	{
115		if (false === $this->openned) {
116			return false;
117		}
118		if ((file_exists($this->filename) && !is_writable($this->filename))
119			|| !file_exists($filename)) {
120			return false;
121		}
122		if (isSet($localname)) {
123			$localname = preg_replace("/(?:\.|\/)*(.*)/", "\\1", $localname);
124			$localpath = dirname($localname);
125			$tmpfilename = self::TMP_DIR . '/' . basename($localname);
126		} else {
127			$localname = basename($filename);
128			$tmpfilename = self::TMP_DIR . '/' . $localname;
129			$localpath = '';
130		}
131		if (file_exists($filename)) {
132			copy($filename, $tmpfilename);
133			$this->pclzip->delete(PCLZIP_OPT_BY_NAME, $localname);
134			$this->pclzip->add($tmpfilename,
135				PCLZIP_OPT_REMOVE_PATH, self::TMP_DIR,
136				PCLZIP_OPT_ADD_PATH, $localpath);
137			unlink($tmpfilename);
138			return true;
139		}
140		return false;
141	}
142	/**
143	 * Close the Zip archive
144	 * @return true
145	 */
146	public function close()
147	{
148		if (false === $this->openned) {
149			return false;
150		}
151		$this->pclzip = $this->filename = null;
152		$this->openned = false;
153		if (file_exists(self::TMP_DIR)) {
154			$this->_rrmdir(self::TMP_DIR);
155			rmdir(self::TMP_DIR);
156		}
157		return true;
158	}
159	/**
160	 * Empty the temporary working directory recursively
161	 * @param $dir the temporary working directory
162	 * @return void
163	 */
164	private function _rrmdir($dir)
165	{
166		if ($handle = opendir($dir)) {
167			while (false !== ($file = readdir($handle))) {
168				if ($file != '.' && $file != '..') {
169					if (is_dir($dir . '/' . $file)) {
170						$this->_rrmdir($dir . '/' . $file);
171						rmdir($dir . '/' . $file);
172					} else {
173						unlink($dir . '/' . $file);
174					}
175				}
176			}
177			closedir($handle);
178		}
179	}
180}
181
182?>
183