_log = app('log'); $this->setTempDir(($tempDir !== null) ? $tempDir : storage_path('app/auto-update/temp')); $this->setInstallDir(($installDir !== null) ? $installDir : base_path()); $this->_latestVersion = new version('0.0.0'); $this->_currentVersion = new version('0.0.0'); // Init cache $this->_cache = app('cache'); ini_set('max_execution_time', $maxExecutionTime); } /** * Set the temporary download directory. * * @param string $dir * @return $this|void */ public function setTempDir($dir) { $dir = $this->addTrailingSlash($dir); if (!is_dir($dir)) { $this->_log->debug(sprintf('Creating new temporary directory "%s"', $dir)); if (!mkdir($dir, 0755, true)) { $this->_log->critical(sprintf('Could not create temporary directory "%s"', $dir)); return; } } $this->_tempDir = $dir; return $this; } /** * Set the install directory. * * @param string $dir * @return $this|void */ public function setInstallDir($dir) { $dir = $this->addTrailingSlash($dir); if (!is_dir($dir)) { $this->_log->debug(sprintf('Creating new install directory "%s"', $dir)); if (!mkdir($dir, 0755, true)) { $this->_log->critical(sprintf('Could not create install directory "%s"', $dir)); return; } } $this->_installDir = $dir; return $this; } /** * Set the update filename. * * @param string $updateFile * @return $this */ public function setUpdateFile($updateFile) { $this->_updateFile = $updateFile; return $this; } /** * Set the update filename. * * @param string $updateUrl * @return $this */ public function setUpdateUrl($updateUrl) { $this->_updateUrl = $updateUrl; return $this; } /** * Set the update branch. * * @param string branch * @return $this */ public function setBranch($branch) { $this->_branch = $branch; return $this; } /** * Set the version of the current installed software. * * @param string $currentVersion * * @return bool */ public function setCurrentVersion($currentVersion) { $version = new version($currentVersion); if ($version->valid() === null) { $this->_log->error(sprintf('Invalid current version "%s"', $currentVersion)); return false; } $this->_currentVersion = $version; return $this; } /** * Set authentication * @param $username * @param $password */ public function setBasicAuth($username, $password) { $this->_username = $username; $this->_password = $password; } /** * Set authentication in update method of users and password exist * @return null|resource */ private function _useBasicAuth() { if ($this->_username && $this->_password) { return stream_context_create(array( 'http' => array( 'header' => "Authorization: Basic " . base64_encode("$this->_username:$this->_password") ) )); } return null; } /** * Get the name of the latest version. * * @return \vierbergenlars\SemVer\version */ public function getLatestVersion() { return $this->_latestVersion; } public function getUpdates() { return $this->_updates; } /** * Get an array of versions which will be installed. * * @return array */ public function getVersionsToUpdate() { return array_map(function ($update) { return $update['version']; }, $this->_updates); } /** * Get the results of the last simulation. * * @return array */ public function getSimulationResults() { return $this->_simulationResults; } /** * Remove directory recursively. * * @param string $dir * * @return void */ private function _removeDir($dir) { $this->_log->debug(sprintf('Remove directory "%s"', $dir)); if (!is_dir($dir)) { $this->_log->warning(sprintf('"%s" is not a directory!', $dir)); return false; } $objects = array_diff(scandir($dir), array('.', '..')); foreach ($objects as $object) { if (is_dir($dir . DIRECTORY_SEPARATOR . $object)) $this->_removeDir($dir . DIRECTORY_SEPARATOR . $object); else unlink($dir . DIRECTORY_SEPARATOR . $object); } return rmdir($dir); } /** * Check for a new version * * @return int|bool * true: New version is available * false: Error while checking for update * int: Status code (i.e. AutoUpdate::NO_UPDATE_AVAILABLE) */ public function checkUpdate() { $this->_log->notice('Checking for a new update...'); // Reset previous updates $this->_latestVersion = new version('0.0.0'); $this->_updates = []; $versions = null; // $this->_cache->get('update-versions'); // Create absolute url to update file $updateFile = $this->_updateUrl . '/' . $this->_updateFile; if (!empty($this->_branch)) $updateFile .= '.' . $this->_branch; // Check if cache is empty if ($versions === null || $versions === false) { $this->_log->debug(sprintf('Get new updates from %s', $updateFile)); // Read update file from update server //$update = @file_get_contents($updateFile, $this->_useBasicAuth()); $data = [ 'domain' => request()->getHost() ]; $update = Curl::to($updateFile) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->withData($data) ->get(); if ($update === false) { $this->_log->info(sprintf('Could not download update file "%s"!', $updateFile)); return false; } // Parse update file $updateFileExtension = substr(strrchr($this->_updateFile, '.'), 1); switch ($updateFileExtension) { case 'ini': $versions = @parse_ini_string($update, true); if (!is_array($versions)) { $this->_log->error('Unable to parse ini update file!'); return false; } $versions = array_map(function ($block) { return isset($block['url']) ? $block['url'] : false; }, $versions); break; case 'json': $versions = (array)@json_decode($update); if (!is_array($versions)) { $this->_log->error('Unable to parse json update file!'); return false; } if (isset($versions['result']) && 0 == $versions['result']) { return $versions; } break; default: $this->_log->error(sprintf('Unknown file extension "%s"', $updateFileExtension)); return false; } $this->_cache->put('update-versions', $versions); } else { $this->_log->debug('Got updates from cache'); } if (!is_array($versions)) { $this->_log->error(sprintf('Could not read versions from server %s', $updateFile)); return false; } // Check for latest version foreach ($versions as $versionRaw => $updateUrl) { // $this->checkDomain($updateUrl->domain); $version = new version($versionRaw); if ($version->valid() === null) { $this->_log->info(sprintf('Could not parse version "%s" from update server "%s"', $versionRaw, $updateFile)); continue; } if (version::gt($version, $this->_currentVersion)) { if (version::gt($version, $this->_latestVersion)) $this->_latestVersion = $version; $this->_updates[] = [ 'version' => $version->getVersion(), 'url' => $updateUrl->url, 'description' => $updateUrl->description, 'created_at' => strtotime($updateUrl->created_at->date), 'upgrade' => $updateUrl->upgrade, 'php_version' => $updateUrl->php_version ]; } } // Sort versions to install usort($this->_updates, function ($a, $b) { return version::compare($a['version'], $b['version']); }); if ($this->newVersionAvailable()) { $this->_log->debug(sprintf('New version "%s" available', $this->_latestVersion)); return true; } else { $this->_log->debug('No new version available'); return self::NO_UPDATE_AVAILABLE; } } /* * 检测指定的 key 和 密钥是否存在 * * * @params string $fileName 检查路径 * @params array $keyAndSecret ['key' => string, 'secret' => string] * @params array $postData post 传参 * * @return mixed */ public function isKeySecretExists($fileName, $keyAndSecret, $postData, $message='') { //dd($fileName . "
" . $keyAndSecret['key'] . '==> ' . $keyAndSecret['secret'] . '
' . $postData . "
" . $message); $content = Curl::to($fileName) ->withHeader( "Authorization: Basic " . base64_encode("{$keyAndSecret['key']}:{$keyAndSecret['secret']}") ) ->withData($postData) ->get(); //var_dump($content);exit(); $result = json_decode($content, true); if(!$result['isExists']) { $this->_log->error($message . $result['message']); } return $result; } /** * Check if a new version is available. * * @return bool */ public function newVersionAvailable() { if (!empty($this->_updates) && $this->_updates['upgrade'] != 'master') { return true; } return version::gt($this->_latestVersion, $this->_currentVersion); } /** * Download the update * * @param string $updateUrl Url where to download from * @param string $updateFile Path where to save the download * * @return bool */ protected function _downloadUpdate($updateUrl, $updateFile) { $this->_log->info(sprintf('Downloading update "%s" to "%s"', $updateUrl, $updateFile)); return Curl::to($updateUrl) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->withContentType('application/zip, application/octet-stream') ->withOption('FOLLOWLOCATION',true) ->withOption('TIMEOUT',100) ->download($updateFile); } protected function _downloadUpdate_v2($updateUrl, $updateFile, $client) { $this->_log->info(sprintf('Downloading update "%s" to "%s"', $updateUrl, $updateFile)); //获取文件夹数据 $checkUpdateFileUurl = $updateUrl . '/check/' . $client . '/0'; $files = Curl::to($checkUpdateFileUurl) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->asJsonResponse(true) ->get(); if (!is_null($files) && !empty($files['result'])) { $downloadUrl = $updateUrl . '/download/'; foreach ($files['result'] as $item) { $updateUrl = $downloadUrl . $client . '/' . $item; $updateFile = $this->_tempDir . $item; Curl::to($updateUrl) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->withContentType('application/zip, application/octet-stream') ->withOption('FOLLOWLOCATION',true) ->withOption('TIMEOUT',100) ->download($updateFile); } } return true; } /** * Simulate update process. * * @param string $updateFile * * @return bool */ protected function _simulateInstall($updateFile) { $this->_log->notice('[SIMULATE] Install new version'); clearstatcache(); // Check if zip file could be opened $zip = zip_open($updateFile); if (!is_resource($zip)) { $this->_log->error(sprintf('Could not open zip file "%s", error: %d', $updateFile, $zip)); return false; } $i = -1; $files = []; $simulateSuccess = true; while ($file = zip_read($zip)) { $i++; $filename = zip_entry_name($file); $foldername = $this->_installDir . dirname($filename); $absoluteFilename = $this->_installDir . $filename; $files[$i] = [ 'filename' => $filename, 'foldername' => $foldername, 'absolute_filename' => $absoluteFilename, ]; $this->_log->debug(sprintf('[SIMULATE] Updating file "%s"', $filename)); // Check if parent directory is writable if (!is_dir($foldername)) { $this->_log->debug(sprintf('[SIMULATE] Create directory "%s"', $foldername)); $files[$i]['parent_folder_exists'] = false; $parent = dirname($foldername); if(!is_dir($parent)){ if (!mkdir($parent, $this->dirPermissions, true)) { $files[$i]['parent_folder_writable'] = false; $simulateSuccess = false; $this->_log->error(sprintf('Directory "%s" has to be writeable!', $parent)); } } if (!is_writable($parent)) { $files[$i]['parent_folder_writable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] Directory "%s" has to be writeable!', $parent)); } else { $files[$i]['parent_folder_writable'] = true; } } // Skip if entry is a directory if (substr($filename, -1, 1) == DIRECTORY_SEPARATOR || substr($filename, -1, 1) == '.') continue; // Read file contents from archive $contents = zip_entry_read($file, zip_entry_filesize($file)); if ($contents === false) { $files[$i]['extractable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] Coud not read contents of file "%s" from zip file!', $filename)); } // Write to file if (file_exists($absoluteFilename)) { $files[$i]['file_exists'] = true; if (!is_writable($absoluteFilename)) { $files[$i]['file_writable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] Could not overwrite "%s"!', $absoluteFilename)); } } else { $files[$i]['file_exists'] = false; if (is_dir($foldername)) { if (!is_writable($foldername)) { $files[$i]['file_writable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] The file "%s" could not be created!', $absoluteFilename)); } else { $files[$i]['file_writable'] = true; } } else { $files[$i]['file_writable'] = true; $this->_log->debug(sprintf('[SIMULATE] The file "%s" could be created', $absoluteFilename)); } } if ($filename == $this->updateScriptName) { $this->_log->debug(sprintf('[SIMULATE] Update script "%s" found', $absoluteFilename)); $files[$i]['update_script'] = true; } else { $files[$i]['update_script'] = false; } } $this->_simulationResults = $files; return $simulateSuccess; } protected function _simulateInstall_v2($updateFile, $version, $client = 1) { $this->_log->notice('[SIMULATE] Install new version'); clearstatcache(); // Check if zip file could be opened $dir = $this->_tempDir . $version; if (!is_dir($dir)) { $this->_log->error(sprintf('Could not open dir "%s", error: %d', $version, $dir)); return false; } $files = []; $simulateSuccess = true; if (is_dir($dir)) { $allfiles = app(Filesystem::class)->allFiles($dir); foreach ($allfiles as $key => $rows) { $filename = $rows->getRelativePathname(); $foldername = $this->_installDir . dirname($filename); $absoluteFilename = $this->_installDir . $filename; if (2 == $client || (1 == $client && config('app.framework') == 'platform')) { $foldername = $this->_installDir . 'addons/yun_shop/' . dirname($filename); $absoluteFilename = $this->_installDir . 'addons/yun_shop/' . $filename; } $files[$key] = [ 'filename' => $filename, 'foldername' => $foldername, 'absolute_filename' => $absoluteFilename, ]; $this->_log->debug(sprintf('[SIMULATE] Updating file "%s"', $filename)); // Check if parent directory is writable if (!is_dir($foldername)) { $this->_log->debug(sprintf('[SIMULATE] Create directory "%s"', $foldername)); $files[$key]['parent_folder_exists'] = false; $parent = dirname($foldername); if(!is_dir($parent)){ if (!mkdir($parent, $this->dirPermissions, true)) { $files[$key]['parent_folder_writable'] = false; $simulateSuccess = false; $this->_log->error(sprintf('Directory "%s" has to be writeable!', $parent)); } } if (!is_writable($parent)) { $files[$key]['parent_folder_writable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] Directory "%s" has to be writeable!', $parent)); } else { $files[$key]['parent_folder_writable'] = true; } } // Skip if entry is a directory if (substr($filename, -1, 1) == DIRECTORY_SEPARATOR || substr($filename, -1, 1) == '.') continue; // Read file contents from archive $contents = file_get_contents($rows->getPathname()); if ($contents === false) { $files[$key]['extractable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] Coud not read contents of file "%s" from zip file!', $filename)); } // Write to file if (file_exists($absoluteFilename)) { $files[$key]['file_exists'] = true; if (!is_writable($absoluteFilename)) { $files[$key]['file_writable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] Could not overwrite "%s"!', $absoluteFilename)); } } else { $files[$key]['file_exists'] = false; if (is_dir($foldername)) { if (!is_writable($foldername)) { $files[$key]['file_writable'] = false; $simulateSuccess = false; $this->_log->warning(sprintf('[SIMULATE] The file "%s" could not be created!', $absoluteFilename)); } else { $files[$key]['file_writable'] = true; } } else { $files[$key]['file_writable'] = true; $this->_log->debug(sprintf('[SIMULATE] The file "%s" could be created', $absoluteFilename)); } } if ($filename == $this->updateScriptName) { $this->_log->debug(sprintf('[SIMULATE] Update script "%s" found', $absoluteFilename)); $files[$key]['update_script'] = true; } else { $files[$key]['update_script'] = false; } } } $this->_simulationResults = $files; return $simulateSuccess; } /** * Install update. * * @param string $updateFile Path to the update file * @param bool $simulateInstall Check for directory and file permissions before copying files * * @return bool */ protected function _install($updateFile, $simulateInstall, $version) { $this->_log->notice(sprintf('Trying to install update "%s"', $updateFile)); // Check if install should be simulated if ($simulateInstall && !$this->_simulateInstall($updateFile)) { $this->_log->critical('Simulation of update process failed!'); return self::ERROR_SIMULATE; } clearstatcache(); // Check if zip file could be opened $zip = zip_open($updateFile); if (!is_resource($zip)) { $this->_log->error(sprintf('Could not open zip file "%s", error: %d', $updateFile, $zip)); return false; } // Read every file from archive while ($file = zip_read($zip)) { $filename = zip_entry_name($file); $foldername = $this->_installDir . dirname($filename); $absoluteFilename = $this->_installDir . $filename; $this->_log->debug(sprintf('Updating file "%s"', $filename)); if (!is_dir($foldername)) { if (!mkdir($foldername, $this->dirPermissions, true)) { $this->_log->error(sprintf('Directory "%s" has to be writeable!', $foldername)); return false; } } // Skip if entry is a directory if (substr($filename, -1, 1) == '/' || substr($filename, -1, 1) == '\\' || substr($filename, -1, 1) == '.') continue; // Read file contents from archive $contents = zip_entry_read($file, zip_entry_filesize($file)); if ($contents === false) { $this->_log->error(sprintf('Coud not read zip entry "%s"', $file)); continue; } // Write to file if (file_exists($absoluteFilename)) { if (!is_writable($absoluteFilename)) { $this->_log->error('Could not overwrite "%s"!', $absoluteFilename); zip_close($zip); return false; } } else { if (!touch($absoluteFilename)) { $this->_log->error(sprintf('[SIMULATE] The file "%s" could not be created!', $absoluteFilename)); zip_close($zip); return false; } $this->_log->debug(sprintf('File "%s" created', $absoluteFilename)); } $updateHandle = @fopen($absoluteFilename, 'w'); if (!$updateHandle) { $this->_log->error(sprintf('Could not open file "%s"!', $absoluteFilename)); zip_close($zip); return false; } if (!empty($contents) && !fwrite($updateHandle, $contents)) { $this->_log->error(sprintf('Could not write to file "%s"!', $absoluteFilename)); zip_close($zip); return false; } fclose($updateHandle); //If file is a update script, include if ($filename == $this->updateScriptName) { $this->_log->debug(sprintf('Try to include update script "%s"', $absoluteFilename)); require($absoluteFilename); $this->_log->info(sprintf('Update script "%s" included!', $absoluteFilename)); if (!unlink($absoluteFilename)) { $this->_log->warning(sprintf('Could not delete update script "%s"!', $absoluteFilename)); } } } zip_close($zip); // TODO $this->_log->notice(sprintf('Update "%s" successfully installed', $version)); return true; } protected function _install_v2($updateFile, $simulateInstall, $version, $client = 1) { $this->_log->notice(sprintf('Trying to install update "%s"', $updateFile)); // Check if install should be simulated if ($simulateInstall && !$this->_simulateInstall_v2($updateFile, $version, $client)) { $this->_log->critical('Simulation of update process failed!'); return self::ERROR_SIMULATE; } clearstatcache(); // Check if zip file could be opened $dir = $this->_tempDir . $version; if (is_dir($dir)) { $allfiles = app(Filesystem::class)->allFiles($dir); foreach ($allfiles as $rows) { $filename = $rows->getRelativePathname(); $foldername = $this->_installDir . dirname($filename); $absoluteFilename = $this->_installDir . $filename; if (2 == $client || (1 == $client && config('app.framework') == 'platform')) { $foldername = $this->_installDir . 'addons/yun_shop/' . dirname($filename); $absoluteFilename = $this->_installDir . 'addons/yun_shop/' . $filename; } $this->_log->debug(sprintf('Updating file "%s"', $filename)); if (!is_dir($foldername)) { if (!mkdir($foldername, $this->dirPermissions, true)) { $this->_log->error(sprintf('Directory "%s" has to be writeable!', $foldername)); return false; } } // Skip if entry is a directory if (substr($filename, -1, 1) == '/' || substr($filename, -1, 1) == '\\' || substr($filename, -1, 1) == '.') continue; // Read file contents from archive $contents = file_get_contents($rows->getPathname()); if ($contents === false) { $this->_log->error(sprintf('Coud not read zip entry "%s"', $filename)); continue; } // Write to file if (file_exists($absoluteFilename)) { if (!is_writable($absoluteFilename)) { $this->_log->error('Could not overwrite "%s"!', $absoluteFilename); return false; } } else { if (!touch($absoluteFilename)) { $this->_log->error(sprintf('[SIMULATE] The file "%s" could not be created!', $absoluteFilename)); return false; } $this->_log->debug(sprintf('File "%s" created', $absoluteFilename)); } $updateHandle = @fopen($absoluteFilename, 'w'); if (!$updateHandle) { $this->_log->error(sprintf('Could not open file "%s"!', $absoluteFilename)); return false; } if (!empty($contents) && !fwrite($updateHandle, $contents)) { $this->_log->error(sprintf('Could not write to file "%s"!', $absoluteFilename)); return false; } fclose($updateHandle); //If file is a update script, include if ($filename == $this->updateScriptName) { $this->_log->debug(sprintf('Try to include update script "%s"', $absoluteFilename)); require($absoluteFilename); $this->_log->info(sprintf('Update script "%s" included!', $absoluteFilename)); if (!unlink($absoluteFilename)) { $this->_log->warning(sprintf('Could not delete update script "%s"!', $absoluteFilename)); } } } } // TODO $this->_log->notice(sprintf('Update "%s" successfully installed', $version)); return true; } /** * Update to the latest version * * @param bool $simulateInstall Check for directory and file permissions before copying files (Default: true) * @param bool $deleteDownload Delete download after update (Default: true) * * @return mixed integer|bool */ public function update($client = 1, $simulateInstall = true, $deleteDownload = true) { $this->_log->info('Trying to perform update'); // Check for latest version if ($this->_latestVersion === null || count($this->_updates) === 0) $client == 2 ? $this->checkBackUpdate() : $this->checkUpdate(); if ($this->_latestVersion === null || count($this->_updates) === 0) { $this->_log->error('Could not get latest version from server!'); return self::ERROR_VERSION_CHECK; } // Check if current version is up to date if (!$this->newVersionAvailable()) { $this->_log->warning('No update available!'); return self::NO_UPDATE_AVAILABLE; } rsort($this->_updates); foreach ($this->_updates as $key => $update) { if ($key > 0) { break; } $this->_log->debug(sprintf('Update to version "%s"', $update['version'])); // Check for temp directory if (empty($this->_tempDir) || !is_dir($this->_tempDir) || !is_writable($this->_tempDir)) { $this->_log->critical(sprintf('Temporary directory "%s" does not exist or is not writeable!', $this->_tempDir)); return self::ERROR_TEMP_DIR; } // Check for install directory if (empty($this->_installDir) || !is_dir($this->_installDir) || !is_writable($this->_installDir)) { $this->_log->critical(sprintf('Install directory "%s" does not exist or is not writeable!', $this->_installDir)); return self::ERROR_INSTALL_DIR; } $updateFile = $this->_tempDir . $update['version'] . '.zip'; // Download update if (!is_file($updateFile)) { if (!$this->_downloadUpdate_v2($update['url'], $updateFile, $client)) { $this->_log->critical(sprintf('Failed to download update from "%s" to "%s"!', $update['url'], $updateFile)); return self::ERROR_DOWNLOAD_UPDATE; } $this->_log->debug(sprintf('Latest update downloaded to "%s"', $updateFile)); } else { $this->_log->info(sprintf('Latest update already downloaded to "%s"', $updateFile)); } //下载文件MD5校验 if (file_exists($this->_tempDir . 'md5.txt')) { $error = []; $md5 = file_get_contents($this->_tempDir . 'md5.txt'); $segment = explode(PHP_EOL, $md5); foreach ($segment as $val) { if (!empty($val)) { $item = str_replace("\r", '', $val); $rows = explode(':', $item); $file_md5[$rows[0]] = $rows[1]; } } $allfiles = app(Filesystem::class)->allFiles($this->_tempDir); if (empty($allfiles)) { return '更新文件不存在'; } foreach ($allfiles as $file) { $soure_file[$file->getFilename()] = md5_file($file->getRealPath()); } foreach ($file_md5 as $k => $v) { if (!is_null($v) && !empty($soure_file[$k]) && $v != $soure_file[$k]) { $error[$k] = ['source' => $v, 'destination' => $soure_file[$k]]; } } $this->_log->debug('Download zip file successfull'); if (empty($error)) { $default_dir = $client == 2 ? 'framework_frontend' :'frontend'; // Install update $yZip = new YZip(); $yZip->unzip($this->_tempDir, $this->_tempDir); $chk_url = substr(config('auto-update.checkUrl'), strpos(config('auto-update.checkUrl'), '/')+2); $chk_url = substr($chk_url, 0, strpos($chk_url, '/')); $cp_source_path = 'app/auto-update/temp/data/wwwroot/' . $chk_url . '/storage/' . $update['upgrade'] . '/' . $default_dir . '/' . $update['version'] . '_source/'; $cp_destination_path = 'app/auto-update/temp/' . $update['version'] . '/'; if (2 == $client) { //copy 框架index.html到根目录后并删除 if (is_dir(storage_path($cp_source_path))) { $cp_index_path = $cp_source_path . '/index/admin.html'; $cp_des_path = base_path() . '/admin.html'; app(Filesystem::class)->copy(storage_path($cp_index_path), $cp_des_path); app(Filesystem::class)->delete(storage_path($cp_index_path)); app(Filesystem::class)->deleteDirectory(storage_path($cp_index_path . '/index')); } } if (is_dir(storage_path($cp_source_path))) { \Log::debug('copy file start.....', $cp_source_path); app(Filesystem::class)->copyDirectory(storage_path($cp_source_path), storage_path($cp_destination_path)); app(Filesystem::class)->copy(storage_path($cp_destination_path . '/index/index.html'), storage_path($cp_destination_path . '/index.html')); app(Filesystem::class)->delete(storage_path($cp_destination_path . '/index/index.html')); app(Filesystem::class)->deleteDirectory(storage_path($cp_destination_path . '/index')); \Log::debug('copy file end.....'); } $result = $this->_install_v2($updateFile, $simulateInstall, $update['version'], $client); if ($result === true) { $this->runOnEachUpdateFinishCallbacks($update['version']); if ($deleteDownload) { $this->_log->debug(sprintf('Trying to delete update file "%s" after successfull update', $updateFile)); if (@$this->deldir($this->_tempDir)) { $this->_log->info(sprintf('Update file "%s" deleted after successfull update', $updateFile)); } else { $this->_log->error(sprintf('Could not delete update file "%s" after successfull update!', $updateFile)); return self::ERROR_DELETE_TEMP_UPDATE; } } } else { if ($deleteDownload) { $this->_log->debug(sprintf('Trying to delete update file "%s" after failed update', $updateFile)); if (@$this->deldir($this->_tempDir)) { $this->_log->info(sprintf('Update file "%s" deleted after failed update', $updateFile)); } else { $this->_log->error(sprintf('Could not delete update file "%s" after failed update!', $updateFile)); } } return $result; } $this->runOnAllUpdateFinishCallbacks($this->getVersionsToUpdate()); return true; } else { \Log::debug('-----下载文件校验失败-----', $error); return '下载文件校验失败'; } } else { return '校验文件不存在'; } } } /** * Add slash at the end of the path. * * @param string $dir * @return string */ public function addTrailingSlash($dir) { if (substr($dir, -1) != DIRECTORY_SEPARATOR) $dir = $dir . DIRECTORY_SEPARATOR; return $dir; } /** * @param array $callback */ public function onEachUpdateFinish($callback) { $this->onEachUpdateFinishCallbacks[] = $callback; } /** * @param array $callback */ public function setOnAllUpdateFinishCallbacks($callback) { $this->onAllUpdateFinishCallbacks[] = $callback; } public function runOnEachUpdateFinishCallbacks($updateVersion) { foreach ($this->onEachUpdateFinishCallbacks as $callback) { call_user_func($callback, $updateVersion); } } public function runOnAllUpdateFinishCallbacks($updatedVersions) { foreach ($this->onAllUpdateFinishCallbacks as $callback) { call_user_func($callback, $updatedVersions); } } public function checkBackUpdate() { $domain = rtrim(request()->getHost(), '/'); $this->authCode($domain); $code = authModel::orderBy('id', 'desc')->value('code'); $this->_log->notice('Back Checking for a new update...'); $versions = null; // $this->_cache->get('update-versions'); // Create absolute url to update file $updateFile = $this->_updateUrl . '/' . $this->_updateFile . '/' . $code; // Check if cache is empty if ($versions === null || $versions === false) { $this->_log->debug(sprintf('Get new updates from %s', $updateFile)); // Read update file from update server //$update = @file_get_contents($updateFile, $this->_useBasicAuth()); $data = [ 'vendor' => $this->getDirsByPath('vendor'), 'domain' => $domain ]; $update = Curl::to($updateFile) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->withData($data) ->asJsonResponse(true) ->get(); if (is_array($update)) { // return $this->checkDomain($update->domain); } if ($update === false) { $this->_log->info(sprintf('Could not download update file "%s"!', $updateFile)); return false; } return $update; } } public function checkBackDownload($data) { $code = authModel::orderBy('id', 'desc')->value('code'); $this->_log->notice('Back Checking for a new download...'); $versions = null; // $this->_cache->get('update-versions'); // Create absolute url to update file $updateFile = $this->_updateUrl . '/' . $this->_updateFile . '/' . $code; // Check if cache is empty if ($versions === null || $versions === false) { $this->_log->debug(sprintf('Get new updates from %s', $updateFile)); $download = Curl::to($updateFile) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->withData($data) ->asJsonResponse(true) ->get(); if ($download === false) { $this->_log->info(sprintf('Could not download update file "%s"!', $updateFile)); return false; } return $download; } } public function getDirsByPath($path, Filesystem $filesystem = null) { $dirs = []; if (is_null($filesystem)) { $filesystem = app(Filesystem::class); } if ($all_dir = $filesystem->directories(base_path($path))) { if (!is_null($all_dir)) { foreach ($all_dir as $dir) { $dirs[] = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR)+1); } } } return $dirs; } private function checkDomain($domain) { if (!preg_match($_SERVER['HTTP_HOST'], $domain)) { if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { return 'unknown'; } redirect(yzWebFullUrl('update.pirate'))->send(); } } private function deldir($dir) { //先删除目录下的文件: $dh = opendir($dir); while ($file = readdir($dh)) { if ($file != "." && $file != "..") { $fullpath = $dir . "/" . $file; if (!is_dir($fullpath)) { unlink($fullpath); } else { $this->deldir($fullpath); } } } closedir($dh); //删除当前文件夹: if (rmdir($dir)) { return true; } else { return false; } } public function isPluginExists($url, $message = '') { $content = Curl::to($url) ->asJsonResponse(true) ->get(); if(!$content['isExists']) { $this->_log->error($message . $content['message']); } return $content; } private function authCode($domain) { $url = $this->_updateUrl . '/code.json/' . $domain; $data = [ 'domain' => rtrim(request()->getHost(), '/') ]; Curl::to($url) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->withData($data) ->asJsonResponse(true) ->get(); } public function remoteSystemVersion() { $updateFile = $this->_updateUrl . '/' . $this->_updateFile; $update = Curl::to($updateFile) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->get(); return $update; } public function showLog($page) { $updateFile = $this->_updateUrl . '/' . $this->_updateFile; $log = Curl::to($updateFile) ->withHeader( "Authorization: Basic " . base64_encode("{$this->_username}:{$this->_password}") ) ->withData(['page' => $page]) ->get(); return $log; } }