|
|
@@ -0,0 +1,168 @@
|
|
|
+<?php
|
|
|
+namespace application\controllers;
|
|
|
+
|
|
|
+class ZipController {
|
|
|
+
|
|
|
+ /** @var ZipFile */
|
|
|
+ private $zipFile = null;
|
|
|
+ private $zipBuffer = "";
|
|
|
+ private $destination = null;
|
|
|
+
|
|
|
+ public function extractZip($data) {
|
|
|
+ $this->destination = '/home/' . $data['username'] . '/' . $data['$domain'];
|
|
|
+ $url = $data['zip'];
|
|
|
+ @set_time_limit(3600);
|
|
|
+ $ch = curl_init();
|
|
|
+ curl_setopt($ch, CURLOPT_URL, $url);
|
|
|
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
|
|
|
+ curl_setopt($ch, CURLOPT_TIMEOUT, 3600);
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
|
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
+ //curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
|
|
|
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
+ //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
|
+ curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, 'readZip'));
|
|
|
+ $r = curl_exec($ch);
|
|
|
+ $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
+ $error = curl_error($ch);
|
|
|
+ if ($status != 200) {
|
|
|
+ throw new ErrorException("Zip download error (code: $status)".($error ? ": $error" : ''));
|
|
|
+ }
|
|
|
+ curl_close($ch);
|
|
|
+ if ($this->zipFile) { $this->zipFile->close(); }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function readZip($ch, $data) {
|
|
|
+ if (is_file($this->destination.'/index.html')) {
|
|
|
+ rename($this->destination.'/index.html', $this->destination.'/index_backup.html');
|
|
|
+ }
|
|
|
+ $size = function_exists('mb_strlen') ? mb_strlen($data, '8bit') : strlen($data);
|
|
|
+ $this->zipBuffer .= $data;
|
|
|
+ //self::debugLog("Receive: ".$data);
|
|
|
+ $continue = true;
|
|
|
+ while ($continue) {
|
|
|
+ $continue = false;
|
|
|
+ $size_0 = function_exists('mb_strlen') ? mb_strlen($this->zipBuffer, '8bit') : strlen($this->zipBuffer);
|
|
|
+ if ($this->zipFile && $size_0 >= $this->zipFile->compressedSize) {
|
|
|
+ $continue = true;
|
|
|
+ $this->zipFile->writeUncompressed(substr($this->zipBuffer, 0, $this->zipFile->compressedSize));
|
|
|
+ $this->zipBuffer = substr($this->zipBuffer, $this->zipFile->compressedSize);
|
|
|
+ $this->zipFile->close();
|
|
|
+ $this->zipFile = null;
|
|
|
+ } else if (!$this->zipFile && ($fp = strpos($this->zipBuffer, ZipFile::ZIP_FILE_HEAD)) !== false) {
|
|
|
+ $continue = true;
|
|
|
+ $this->zipBuffer = substr($this->zipBuffer, $fp);
|
|
|
+ $hsize = 26 + strlen(ZipFile::ZIP_FILE_HEAD);
|
|
|
+ if (strlen($this->zipBuffer) <= $hsize) { break; } // need more data
|
|
|
+ $name_size_raw = unpack('v', substr($this->zipBuffer, strlen(ZipFile::ZIP_FILE_HEAD) + 22, 2));
|
|
|
+ $name_size = intval(reset($name_size_raw));
|
|
|
+ $extra_size_raw = unpack('v', substr($this->zipBuffer, strlen(ZipFile::ZIP_FILE_HEAD) + 24, 2));
|
|
|
+ $extra_size = intval(reset($extra_size_raw));
|
|
|
+ $hsize += $name_size + $extra_size;
|
|
|
+ if (strlen($this->zipBuffer) < $hsize) { break; } // need more data
|
|
|
+ // parse file header
|
|
|
+ if ($this->zipFile) { $this->zipFile->close(); }
|
|
|
+ $this->zipFile = ZipFile::parse(substr($this->zipBuffer, 0, $hsize), $this->destination);
|
|
|
+ //self::debugLog('File: '.$this->zipFile->baseDir.'/'.$this->zipFile->name);
|
|
|
+ $this->zipFile->open();
|
|
|
+ $this->zipBuffer = substr($this->zipBuffer, $hsize);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $size;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+class ZipFile {
|
|
|
+
|
|
|
+ const ZIP_FILE_HEAD = "\x50\x4b\x03\x04";
|
|
|
+
|
|
|
+ public $version;
|
|
|
+ public $flags;
|
|
|
+ public $compression;
|
|
|
+ public $modDateTime;
|
|
|
+ public $crc32;
|
|
|
+ public $crc32Raw;
|
|
|
+ public $compressedSize;
|
|
|
+ public $size;
|
|
|
+ public $sizeRaw;
|
|
|
+ public $name;
|
|
|
+ public $extra;
|
|
|
+ public $baseDir;
|
|
|
+ private $handle;
|
|
|
+
|
|
|
+ public function __construct($baseDir = null) {
|
|
|
+ $this->baseDir = rtrim($baseDir, '/');
|
|
|
+ $this->modDateTime = date('Y-m-d H:i:s');
|
|
|
+ $this->compressedSize = 0;
|
|
|
+ $this->size = 0;
|
|
|
+ $this->name = 'new file';
|
|
|
+ }
|
|
|
+
|
|
|
+ public function open() {
|
|
|
+ $dir = dirname($this->baseDir.'/'.$this->name);
|
|
|
+ if (!is_dir($dir)) { mkdir($dir, 0755, true); }
|
|
|
+ if (!empty($this->name)) {
|
|
|
+ $this->handle = fopen($this->baseDir.'/'.$this->name, 'w');
|
|
|
+ } else {
|
|
|
+ throw new ErrorException("File name is empty");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function close() {
|
|
|
+ if ($this->handle !== false) {
|
|
|
+ fclose($this->handle);
|
|
|
+ chmod($this->baseDir.'/'.$this->name, 0644);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function write($data) {
|
|
|
+ if ($this->handle !== false) {
|
|
|
+ fwrite($this->handle, $data);
|
|
|
+ } else {
|
|
|
+ throw new ErrorException("File is not open");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function writeUncompressed($data) {
|
|
|
+ $data_u = gzinflate($data);
|
|
|
+ $this->write($data_u);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param string $data
|
|
|
+ * @return ZipFile
|
|
|
+ */
|
|
|
+ public static function parse($data, $baseDir = null) {
|
|
|
+ $data = substr($data, strlen(self::ZIP_FILE_HEAD));
|
|
|
+ $fh = new ZipFile($baseDir);
|
|
|
+ $fh->version = substr($data, 0, 2);
|
|
|
+ $fh->flags = substr($data, 2, 2);
|
|
|
+ $fh->compression = substr($data, 4, 2);
|
|
|
+ $hexdtime_raw = unpack('V', substr($data, 6, 4));
|
|
|
+ $hexdtime = reset($hexdtime_raw);
|
|
|
+ $fh->modDateTime = ''.((($hexdtime >> 25) & 0xff) + 1980).'-'.
|
|
|
+ sprintf('%02d', ($hexdtime >> 21) & 0x0f).'-'.
|
|
|
+ sprintf('%02d', ($hexdtime >> 16) & 0x1f).' '.
|
|
|
+ sprintf('%02d', ($hexdtime >> 11) & 0x1f).':'.
|
|
|
+ sprintf('%02d', ($hexdtime >> 5) & 0x3f).':'.
|
|
|
+ sprintf('%02d', ($hexdtime << 1) & 0x1f);
|
|
|
+ $fh->crc32Raw = substr($data, 10, 4);
|
|
|
+ $crc32 = unpack('V', $fh->crc32Raw);
|
|
|
+ $fh->crc32 = sprintf('%08x', reset($crc32));
|
|
|
+ $clen = unpack('V', substr($data, 14, 4));
|
|
|
+ $fh->compressedSize = reset($clen);
|
|
|
+ $fh->sizeRaw = substr($data, 18, 4);
|
|
|
+ $ulen = unpack('V', $fh->sizeRaw);
|
|
|
+ $fh->size = reset($ulen);
|
|
|
+ $nlen_raw = unpack('v', substr($data, 22, 2));
|
|
|
+ $nlen = reset($nlen_raw);
|
|
|
+ $elen_raw = unpack('v', substr($data, 24, 2));
|
|
|
+ $elen = reset($elen_raw);
|
|
|
+ $fh->name = substr($data, 26, $nlen);
|
|
|
+ $fh->extra = substr($data, 26 + $nlen, $elen);
|
|
|
+ return $fh;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|