"downloadInfo.json", "holdTime" => 43200, "versionFile" => "installedVersion.json", "zipFile" => "tmpZipFile.zip", "updateignore" => ".updateignore", "name" => "", "branch" => "master", "cache" => "cache/", "save" => "", "prerelease" => false, "exceptions" => false, ); protected $allRelease = array(); protected $streamContext = null; public function __construct($option) { //options if (is_array($option)) { if (! isset($option['name'])) { throw new \Exception('No Name in Option Set'); } $this->options = $option + $this->options; } elseif (is_string($option)) { $this->options['name'] = $option; } else { throw new \Exception('No Option Set'); } $this->options['save'] = rtrim($this->options['save'], '/'); if ($this->options['save'] !== '') { $this->options['save'] .= '/'; if (!HelperClass::fileExists($this->options['save'])) { mkdir($this->options['save']); } } $this->options['cache'] = $this->options['save'] . rtrim($this->options['cache'], '/'); if ($this->options['cache'] !== '') { $this->options['cache'] .= '/'; if (!HelperClass::fileExists($this->options['cache'])) { mkdir($this->options['cache']); } } $caBundleDir = dirname(__FILE__); if (HelperClass::isInPhar()) { $caBundleDir = dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache']; if (! HelperClass::fileExists($this->options['cache'] . "ca_bundle.crt")) { copy(dirname(__FILE__) . "/ca_bundle.crt",$caBundleDir . "ca_bundle.crt"); } } $this->cachedInfo = new CacheOneFile(dirname($_SERVER["SCRIPT_FILENAME"]) . "/" . $this->options['cache'] . $this->options['cacheFile'],$this->options['holdTime']); $this->streamContext = stream_context_create( array( 'http' => array( 'header' => "User-Agent: Awesome-Update-My-Self-" . $this->options['name'] . "\r\nAccept: application/vnd.github.v3+json\r\n", ), 'ssl' => array( 'cafile' => $caBundleDir . '/ca_bundle.crt', 'verify_peer' => true, ), ) ); $this->streamContext2 = stream_context_create( array( 'http' => array( 'header' => "User-Agent: Awesome-Update-My-Self-" . $this->options['name'] . "\r\n", ), 'ssl' => array( 'cafile' => $caBundleDir . '/ca_bundle.crt', 'verify_peer' => true, ), ) ); $this->allRelease = $this->getRemoteInfos(); } protected function getRemoteInfos() { $path = "https://api.github.com/repos/" . $this->options['name'] ."/releases"; if ($this->cachedInfo->is()) { $fileContent = $this->cachedInfo->get(); } else { if (!in_array('https', stream_get_wrappers())) { if($this->options["exceptions"]){ throw new \Exception("No HTTPS Wrapper Exception"); } else { return array(); } } $fileContent = @file_get_contents($path, false, $this->streamContext); if ($fileContent === false) { if($this->options["exceptions"]){ throw new \Exception("No Internet Exception"); } else { return array(); } } $json = json_decode($fileContent, true); if (isset($json['message'])) { if($this->options["exceptions"]){ throw new \Exception("API Exception[" . $json['message'] . "]"); } else { $json = array(); } } $fileContent = json_encode($json, JSON_PRETTY_PRINT); $this->cachedInfo->set($fileContent); return $json; } return json_decode($fileContent, true); } public function able() { if (!in_array('https', stream_get_wrappers())) { return false; } if (empty($this->allRelease)) { return false; } $this->getNewestInfo(); if (HelperClass::fileExists($this->options['cache'] . $this->options['versionFile'])) { $fileContent = file_get_contents($this->options['cache'] . $this->options['versionFile']); $current = json_decode($fileContent, true); if (isset($current['id']) && $current['id'] == $this->newestInfo['id']) { return false; } if (isset($current['tag_name']) && $current['tag_name'] == $this->newestInfo['tag_name']) { return false; } } return true; } public function update() { $newestRelease = $this->getNewestInfo(); if ($this->able()) { if ($this->download($newestRelease['zipball_url'])) { if ($this->unZip()) { unlink($this->options['cache'] . $this->options['zipFile']); file_put_contents($this->options['cache'] . $this->options['versionFile'], json_encode(array( "id" => $newestRelease['id'], "tag_name" => $newestRelease['tag_name'] ), JSON_PRETTY_PRINT)); return true; } } } return false; } protected function download($url) { $file = @fopen($url, 'r', false, $this->streamContext2); if ($file == false) { if($this->options["exceptions"]){ throw new \Exception("Download faild Exception"); } else { return false; } } file_put_contents( dirname($_SERVER['SCRIPT_FILENAME']) . "/" . $this->options['cache'] . $this->options['zipFile'], $file ); fclose($file); return true; } protected function unZip() { $path = dirname($_SERVER['SCRIPT_FILENAME']) . "/" . $this->options['cache'] . $this->options['zipFile']; $updateIgnore = array(); if (HelperClass::fileExists($this->options['updateignore'])) { $updateIgnore = file($this->options['updateignore']); foreach($updateIgnore as &$ignore) { $ignore = $this->options['save'] . trim($ignore); } } $zip = new \ZipArchive(); if ($zip->open($path) === true) { $cutLength = strlen($zip->getNameIndex(0)); for ($i = 1; $i < $zip->numFiles; $i++) {//iterate throw the Zip $name = $this->options['save'] . substr($zip->getNameIndex($i), $cutLength); $do = true; foreach($updateIgnore as $ignore) { if (substr($name, 0, strlen($ignore)) == $ignore) { $do = false; break; } } if ($do) { $stat = $zip->statIndex($i); if ($stat["crc"] == 0) { if (!HelperClass::fileExists($name)) { mkdir($name); } } else { copy("zip://" . $path . "#" . $zip->getNameIndex($i), $name); } } } $zip->close(); return true; } else { return false; } } public function getCurrentInfo() { if(isset($this->currentInfo)) { return $this->currentInfo; } $this->currentInfo = null; if (HelperClass::fileExists($this->options['cache'] . $this->options['versionFile'])) { $fileContent = file_get_contents($this->options['cache'] . $this->options['versionFile']); $current = json_decode($fileContent, true); foreach ($this->allRelease as $release) { if (isset($current['id']) && $current['id'] == $release['id']) { $this->currentInfo = $release; break; } if (isset($current['tag_name']) && $current['tag_name'] == $release['tag_name']) { $this->currentInfo = $release; break; } } } return $this->currentInfo; } public function getNewestInfo() { if(isset($this->newestInfo)) { return $this->newestInfo; } foreach ($this->allRelease as $release) { if (!$this->options['prerelease'] && $release['prerelease']) { continue; } if ($this->options['branch'] !== $release['target_commitish']) { continue; } $this->newestInfo = $release; break; } return $this->newestInfo; } }