11<?php
22/**
3- * The Unzipper extracts .zip or .rar archives and .gz files on webservers. It's handy if you
4- * do not have shell access. E.g. if you want to upload a lot of files
5- * (php framework or image collection) as archive to save time.
6- *
3+ * The Unzipper extracts .zip or .rar archives and .gz files on webservers.
4+ * It's handy if you do not have shell access. E.g. if you want to upload a lot
5+ * of files (php framework or image collection) as an archive to save time.
6+ * As of version 0.1.0 it also supports creating archives.
77 *
88 * @author Andreas Tasch, at[tec], attec.at
99 * @license GNU GPL v3
1010 * @package attec.toolbox
11- * @version 0.0.4 Beta
11+ * @version 0.1.0
1212 */
13+ define ('VERSION ' , '0.1.0 ' );
1314
1415$ timestart = microtime (TRUE );
16+ $ GLOBALS ['status ' ] = array ();
1517
1618$ arc = new Unzipper ;
19+ if (isset ($ _POST ['dounzip ' ])) {
20+ //check if an archive was selected for unzipping
21+ $ archive = isset ($ _POST ['zipfile ' ]) ? strip_tags ($ _POST ['zipfile ' ]) : '' ;
22+ $ destination = isset ($ _POST ['extpath ' ]) ? strip_tags ($ _POST ['extpath ' ]) : '' ;
23+ $ arc ->prepareExtraction ($ archive , $ destination );
24+ }
25+
26+ if (isset ($ _POST ['dozip ' ])) {
27+ $ zippath = !empty ($ _POST ['zippath ' ]) ? strip_tags ($ _POST ['zippath ' ]) : '. ' ;
28+ // Resulting zipfile e.g. zipper--2016-07-23--11-55.zip
29+ $ zipfile = 'zipper- ' . date ("Y-m-d--H-i " ) . '.zip ' ;
30+ Zipper::zipDir ($ zippath , $ zipfile );
31+ }
1732
1833$ timeend = microtime (TRUE );
1934$ time = $ timeend - $ timestart ;
@@ -41,32 +56,30 @@ public function __construct() {
4156 closedir ($ dh );
4257
4358 if (!empty ($ this ->zipfiles )) {
44- self :: $ status = ' .zip or .gz or .rar files found, ready for extraction ' ;
59+ $ GLOBALS [ ' status ' ] = array ( ' info ' => ' .zip or .gz or .rar files found, ready for extraction ') ;
4560 }
4661 else {
47- self :: $ status = ' <span class="status--ERROR">Error: No .zip or .gz or rar files found.</span> ' ;
62+ $ GLOBALS [ ' status ' ] = array ( ' info ' => ' No .zip or .gz or rar files found. So only zipping functionality available. ' ) ;
4863 }
4964 }
65+ }
5066
51- //check if an archive was selected for unzipping
52- //check if archive has been selected
53- $ input = isset ($ _POST ['zipfile ' ]) ? strip_tags ($ _POST ['zipfile ' ]) : '' ;
54- $ destination = isset ($ _POST ['extpath ' ]) ? strip_tags ($ _POST ['extpath ' ]) : '' ;
55- //allow only local existing archives to extract
56- if ($ input !== '' ) {
57- if (empty ($ destination )) {
58- $ extpath = $ this ->localdir ;
59- }
60- else {
61- $ extpath = $ this ->localdir . '/ ' . $ destination ;
62- if (!is_dir ($ extpath )) {
63- mkdir ($ extpath );
64- }
65- }
66- if (in_array ($ input , $ this ->zipfiles )) {
67- self ::extract ($ input , $ extpath );
67+ public function prepareExtraction ($ archive , $ destination ) {
68+ // Determine paths.
69+ if (empty ($ destination )) {
70+ $ extpath = $ this ->localdir ;
71+ }
72+ else {
73+ $ extpath = $ this ->localdir . '/ ' . $ destination ;
74+ // todo move this to extraction function
75+ if (!is_dir ($ extpath )) {
76+ mkdir ($ extpath );
6877 }
6978 }
79+ //allow only local existing archives to extract
80+ if (in_array ($ archive , $ this ->zipfiles )) {
81+ self ::extract ($ archive , $ extpath );
82+ }
7083 }
7184
7285 /**
@@ -100,7 +113,7 @@ public static function extract($archive, $destination) {
100113 public static function extractZipArchive ($ archive , $ destination ) {
101114 // Check if webserver supports unzipping.
102115 if (!class_exists ('ZipArchive ' )) {
103- self :: $ status = ' <span class="status--ERROR"> Error: Your PHP version does not support unzip functionality.</span> ' ;
116+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error: Your PHP version does not support unzip functionality. ' ) ;
104117 return ;
105118 }
106119
@@ -112,14 +125,14 @@ public static function extractZipArchive($archive, $destination) {
112125 if (is_writeable ($ destination . '/ ' )) {
113126 $ zip ->extractTo ($ destination );
114127 $ zip ->close ();
115- self :: $ status = ' <span class="status--OK"> Files unzipped successfully</span> ' ;
128+ $ GLOBALS [ ' status ' ] = array ( ' success ' => ' Files unzipped successfully ' ) ;
116129 }
117130 else {
118- self :: $ status = ' <span class="status--ERROR"> Error: Directory not writeable by webserver.</span> ' ;
131+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error: Directory not writeable by webserver. ' ) ;
119132 }
120133 }
121134 else {
122- self :: $ status = ' <span class="status--ERROR"> Error: Cannot read .zip archive.</span> ' ;
135+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error: Cannot read .zip archive. ' ) ;
123136 }
124137 }
125138
@@ -132,7 +145,7 @@ public static function extractZipArchive($archive, $destination) {
132145 public static function extractGzipFile ($ archive , $ destination ) {
133146 // Check if zlib is enabled
134147 if (!function_exists ('gzopen ' )) {
135- self :: $ status = ' <span class="status--ERROR"> Error: Your PHP has no zlib support enabled.</span> ' ;
148+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error: Your PHP has no zlib support enabled. ' ) ;
136149 return ;
137150 }
138151
@@ -148,10 +161,10 @@ public static function extractGzipFile($archive, $destination) {
148161
149162 // Check if file was extracted.
150163 if (file_exists ($ destination . '/ ' . $ filename )) {
151- self :: $ status = ' <span class="status--OK"> File unzipped successfully.</span> ' ;
164+ $ GLOBALS [ ' status ' ] = array ( ' success ' => ' File unzipped successfully. ' ) ;
152165 }
153166 else {
154- self :: $ status = ' <span class="status--ERROR"> Error unzipping file.</span> ' ;
167+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error unzipping file. ' ) ;
155168 }
156169
157170 }
@@ -165,7 +178,7 @@ public static function extractGzipFile($archive, $destination) {
165178 public static function extractRarArchive ($ archive , $ destination ) {
166179 // Check if webserver supports unzipping.
167180 if (!class_exists ('RarArchive ' )) {
168- self :: $ status = ' <span class="status--ERROR"> Error: Your PHP version does not support .rar archive functionality. <a class="info" href="http://php.net/manual/en/rar.installation.php" target="_blank">How to install RarArchive</a></span> ' ;
181+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error: Your PHP version does not support .rar archive functionality. <a class="info" href="http://php.net/manual/en/rar.installation.php" target="_blank">How to install RarArchive</a> ' ) ;
169182 return ;
170183 }
171184 // Check if archive is readable.
@@ -177,25 +190,96 @@ public static function extractRarArchive($archive, $destination) {
177190 $ entry ->extract ($ destination );
178191 }
179192 $ rar ->close ();
180- self :: $ status = ' <span class="status--OK"> Files extracted successfully</span> ' ;
193+ $ GLOBALS [ ' status ' ] = array ( ' success ' => ' Files extracted successfully. ' ) ;
181194 }
182195 else {
183- self :: $ status = ' <span class="status--ERROR"> Error: Directory not writeable by webserver.</span> ' ;
196+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error: Directory not writeable by webserver. ' ) ;
184197 }
185198 }
186199 else {
187- self :: $ status = ' <span class="status--ERROR"> Error: Cannot read .rar archive.</span> ' ;
200+ $ GLOBALS [ ' status ' ] = array ( ' error ' => ' Error: Cannot read .rar archive. ' ) ;
188201 }
189202 }
190203
191204}
192205
206+ /**
207+ * Class Zipper
208+ *
209+ * Copied and slightly modified from http://at2.php.net/manual/en/class.ziparchive.php#110719
210+ * @author umbalaconmeogia
211+ */
212+ class Zipper
213+ {
214+ /**
215+ * Add files and sub-directories in a folder to zip file.
216+ * @param string $folder
217+ * @param ZipArchive $zipFile
218+ * @param int $exclusiveLength Number of text to be exclusived from the file path.
219+ */
220+ private static function folderToZip ($ folder , &$ zipFile , $ exclusiveLength ) {
221+ $ handle = opendir ($ folder );
222+
223+ while (false !== $ f = readdir ($ handle )) {
224+ // Check for local/parent path or zipping file itself and skip.
225+ if ($ f != '. ' && $ f != '.. ' && $ f != basename (__FILE__ )) {
226+ $ filePath = "$ folder/ $ f " ;
227+ // Remove prefix from file path before add to zip.
228+ $ localPath = substr ($ filePath , $ exclusiveLength );
229+
230+ if (is_file ($ filePath )) {
231+ $ zipFile ->addFile ($ filePath , $ localPath );
232+ } elseif (is_dir ($ filePath )) {
233+ // Add sub-directory.
234+ $ zipFile ->addEmptyDir ($ localPath );
235+ self ::folderToZip ($ filePath , $ zipFile , $ exclusiveLength );
236+ }
237+ }
238+ }
239+ closedir ($ handle );
240+ }
241+
242+ /**
243+ * Zip a folder (include itself).
244+ * Usage:
245+ * Zipper::zipDir('path/to/sourceDir', 'path/to/out.zip');
246+ *
247+ * @param string $sourcePath
248+ * Relative path of directory to be zipped.
249+ *
250+ * @param string $outZipPath
251+ * Relative path of the resulting output zip file.
252+ */
253+ public static function zipDir ($ sourcePath , $ outZipPath )
254+ {
255+ $ pathInfo = pathinfo ($ sourcePath );
256+ $ parentPath = $ pathInfo ['dirname ' ];
257+ $ dirName = $ pathInfo ['basename ' ];
258+
259+ $ z = new ZipArchive ();
260+ $ z ->open ($ outZipPath , ZipArchive::CREATE );
261+ $ z ->addEmptyDir ($ dirName );
262+ if ($ sourcePath == $ dirName ) {
263+ self ::folderToZip ($ sourcePath , $ z , 0 );
264+ } else {
265+ self ::folderToZip ($ sourcePath , $ z , strlen ("$ parentPath/ " ));
266+ }
267+ $ z ->close ();
268+
269+ $ GLOBALS ['status ' ] = array ('success ' => 'Successfully created archive ' . $ outZipPath );
270+ }
271+ }
272+
273+ class Status {
274+ public static $ messages = array ();
275+ }
276+
193277?>
194278
195279<!DOCTYPE html>
196280<html>
197281<head>
198- <title>File Unzipper</title>
282+ <title>File Unzipper + Zipper </title>
199283 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
200284 <style type="text/css">
201285 <!--
@@ -211,6 +295,8 @@ public static function extractRarArchive($archive, $destination) {
211295
212296 fieldset {
213297 border: 0;
298+ background-color: #EEE;
299+ margin: 10px 0 10px 0;
214300 }
215301
216302 .select {
@@ -219,25 +305,36 @@ public static function extractRarArchive($archive, $destination) {
219305 }
220306
221307 .status {
222- margin-top: 20px;
223- padding: 5px;
308+ margin: 0;
309+ margin-bottom: 20px;
310+ padding: 10px;
224311 font-size: 80%;
225312 background: #EEE;
226313 border: 1px dotted #DDD;
227314 }
228315
229316 .status--ERROR {
230- color: red;
231- font-weight: bold ;
317+ background- color: red;
318+ color: white ;
232319 font-size: 120%;
233320 }
234321
235- .status--OK {
236- color: green;
322+ .status--SUCCESS {
323+ background- color: green;
237324 font-weight: bold;
325+ color: white;
238326 font-size: 120%
239327 }
240328
329+ .small {
330+ font-size: 0.7rem;
331+ font-weight: normal;
332+ }
333+
334+ .version {
335+ font-size: 80%;
336+ }
337+
241338 .form-field {
242339 border: 1px solid #AAA;
243340 padding: 8px;
@@ -268,9 +365,13 @@ public static function extractRarArchive($archive, $destination) {
268365 </style>
269366</head>
270367<body>
271- <h1>Archive Unzipper</h1>
368+ <p class="status status--<?php echo strtoupper (key ($ GLOBALS ['status ' ])); ?> ">
369+ Status: <?php echo reset ($ GLOBALS ['status ' ]); ?> <br/>
370+ <span class="small">Processing Time: <?php echo $ time ; ?> seconds</span>
371+ </p>
272372<form action="" method="POST">
273373 <fieldset>
374+ <h1>Archive Unzipper</h1>
274375 <label for="zipfile">Select .zip or .rar archive or .gz file you want to extract:</label>
275376 <select name="zipfile" size="1" class="select">
276377 <?php foreach ($ arc ->zipfiles as $ zip ) {
@@ -281,13 +382,19 @@ public static function extractRarArchive($archive, $destination) {
281382 <label for="extpath">Extraction path (optional):</label>
282383 <input type="text" name="extpath" class="form-field"
283384 placeholder="mypath"/>
284- <p class="info">Enter extraction path without leading or trailing slashes (e.g. "mypath"). If left blank current directory will be used.</p>
285- <input type="submit" name="submit" class="submit" value="Unzip Archive"/>
385+ <p class="info">Enter extraction path without leading or trailing slashes (e.g. "mypath"). If left empty current directory will be used.</p>
386+ <input type="submit" name="dounzip" class="submit" value="Unzip Archive"/>
387+ </fieldset>
388+
389+ <fieldset>
390+ <h1>Archive Zipper</h1>
391+ <label for="zippath">Path that should be zipped (optional):</label>
392+ <input type="text" name="zippath" class="form-field"
393+ placeholder="zippath"/>
394+ <p class="info">Enter path to be zipped without leading or trailing slashes (e.g. "zippath"). If left empty current directory will be used.</p>
395+ <input type="submit" name="dozip" class="submit" value="Zip Archive"/>
286396 </fieldset>
287397</form>
288- <p class="status">
289- Status: <?php echo $ arc ::$ status ; ?> <br/>
290- Processing Time: <?php echo $ time ; ?> ms
291- </p>
398+ <p class="version">Unzipper version: <?php echo VERSION ; ?> </p>
292399</body>
293400</html>
0 commit comments