| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- <?php
- /**
- * The model file of client module of XXB.
- *
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd., www.zentao.net)
- * @license ZOSL (https://zpl.pub/page/zoslv1.html)
- * @author Gang Liu <liugang@cnezsoft.com>
- * @package client
- * @version $Id$
- * @link https://xuanim.com
- */
- class clientModel extends model
- {
- /**
- * Get a client by id.
- *
- * @param int $clientID
- * @access public
- * @return object | bool
- */
- public function getByID($clientID)
- {
- $client = $this->dao->select('*')->from(TABLE_IM_CLIENT)->where('id')->eq($clientID)->fetch();
- if(empty($client)) return false;
- $client->downloads = json_decode($client->downloads, true);
- return $client;
- }
- /**
- * Get a client by version.
- *
- * @param string $version
- * @access public
- * @return object | bool
- */
- public function getByVersion($version)
- {
- $client = $this->dao->select('*')->from(TABLE_IM_CLIENT)->where('version')->eq($version)->fetch();
- if(empty($client)) return false;
- $client->downloads = json_decode($client->downloads, true);
- return $client;
- }
- /**
- * Get client list.
- *
- * @access public
- * @return array
- */
- public function getList()
- {
- return $this->dao->select('*')->from(TABLE_IM_CLIENT)->orderBy('id_desc')->fetchAll();
- }
- /**
- * Get xxc current version from xuan.im.
- *
- * @access public
- * @return array
- */
- public function getXxcVersionFromWebsite()
- {
- $this->loadModel('setting');
- $now = helper::now();
- $xxcUpdateInfo = $this->setting->getItem('owner=system&module=common§ion=client&key=xxcUpdateInfo');
- if(!empty($xxcUpdateInfo))
- {
- $xxcInfo = json_decode($xxcUpdateInfo, false);
- $prevGetDate = $xxcInfo->updateDate;
- if(helper::diffDate($now, $prevGetDate) <= $this->config->client->expirationDays) return $xxcInfo->version;
- }
- $currentVersion = $this->getCurrentVersion();
- $apiUrl = sprintf($this->config->client->upgradeApi, $currentVersion->version);
- $jsonData = file_get_contents($apiUrl);
- $serverVersions = json_decode($jsonData);
- if(empty($serverVersions)) return false;
- $xxcVersion = $serverVersions[0]->xxcVersion;
- if(!empty($xxcVersion))
- {
- $xxcUpdateInfo = new stdclass();
- $xxcUpdateInfo->version = $xxcVersion;
- $xxcUpdateInfo->updateDate = $now;
- $this->setting->setItem('system.common.client.xxcUpdateInfo', json_encode($xxcUpdateInfo));
- }
- return $xxcVersion;
- }
- /**
- * Create a client.
- *
- * @access public
- * @return bool
- */
- public function create()
- {
- $client = fixer::input('post')
- ->add('createdBy', $this->app->user->account)
- ->add('createdDate', helper::now())
- ->get();
- if(empty($client->version)) dao::$errors['version'][] = sprintf($this->lang->error->notempty, $this->lang->client->version);
- if($client->version && !preg_match("/([0-9]+)((?:\.[0-9]+)?)((?:\.[0-9]+)?)(?:[\s\-\+]?)((?:[a-z]+)?)((?:\.?[0-9]+)?)/i", $client->version)) dao::$errors['version'][] = $this->lang->client->wrongVersion;
- foreach($client->downloads as $os => $url)
- {
- if(!empty($url) && (!validater::checkURL($url) || !preg_match("/\.zip$/", $url))) dao::$errors[$os][] = sprintf($this->lang->client->urlError, zget($this->lang->client->zipList, $os) . $this->lang->client->downloadLink);
- }
- if(dao::isError()) return false;
- $client->downloads = helper::jsonEncode($client->downloads);
- $this->dao->insert(TABLE_IM_CLIENT)->data($client)->autoCheck()->exec();
- return !dao::isError();
- }
- /**
- * Create or edit a client by account.
- * @param $version
- * @param $link
- * @param $os
- * @return bool
- */
- public function edit($version, $link, $os)
- {
- $client = $this->getByVersion($version);
- if($client)
- {
- $client->downloads[$os] = $link;
- $client->editedBy = $this->app->user->account;
- $client->editedDate = helper::now();
- $client->downloads = helper::jsonEncode( $client->downloads);
- $this->dao->update(TABLE_IM_CLIENT)->data($client)->where('id')->eq($client->id)->exec();
- }
- else
- {
- $client = new stdClass();
- $client->status = 'wait';
- $client->version = $version;
- $client->strategy = 'optional';
- $client->downloads = helper::jsonEncode(array($os => $link));
- $client->createdBy = $this->app->user->account;
- $client->createdDate = helper::now();
- $this->dao->insert(TABLE_IM_CLIENT)->data($client)->autoCheck()->exec();
- $client->id = $this->dao->lastInsertID();
- }
- if(dao::isError()) return false;
- return $client;
- }
- /**
- * Update a client.
- *
- * @param int $clientID
- * @access public
- * @return bool
- */
- public function update($clientID)
- {
- $client = fixer::input('post')
- ->add('editedBy', $this->app->user->account)
- ->add('editedDate', helper::now())
- ->get();
- if(empty($client->version)) dao::$errors['version'][] = sprintf($this->lang->error->notempty, $this->lang->client->version);
- if($client->version && !preg_match("/([0-9]+)((?:\.[0-9]+)?)((?:\.[0-9]+)?)(?:[\s\-\+]?)((?:[a-z]+)?)((?:\.?[0-9]+)?)/i", $client->version)) dao::$errors['version'][] = $this->lang->client->wrongVersion;
- foreach($client->downloads as $os => $url)
- {
- if(!empty($url) && (!validater::checkURL($url) || !preg_match("/\.zip$/", $url))) dao::$errors[$os][] = sprintf($this->lang->client->urlError, zget($this->lang->client->zipList, $os) . $this->lang->client->downloadLink);
- }
- if(dao::isError()) return false;
- $client->downloads = helper::jsonEncode($client->downloads);
- $this->dao->update(TABLE_IM_CLIENT)->data($client)->autoCheck()->where('id')->eq($clientID)->exec();
- return !dao::isError();
- }
- /**
- * Get current version
- * @access public
- * @return object | bool
- */
- public function getCurrentVersion()
- {
- $currentVersion = $this->dao->select('*')->from(TABLE_IM_CLIENT)->where('status')->eq('released')->orderBy('id_desc')->limit(1)->fetch();
- if(dao::isError()) return false;
- return $currentVersion ?: json_decode('{"version": "'.$this->config->xuanxuan->version.'"}');
- }
- /**
- * Check if a client need upgrade.
- *
- * @param string $version
- * @access public
- * @return object | bool
- */
- public function getUpgrade($version)
- {
- $latestUpgradesIDQuery = $this->dao->select('MAX(id)')->from(TABLE_IM_CLIENT)
- ->where('status')->eq('released')->groupBy('strategy')
- ->get();
- $latestUpgradesObjectQuery = $this->dao->select('t1.downloads, t1.strategy, t1.version, t1.changeLog')->from(TABLE_IM_CLIENT)->alias('t1')
- ->leftJoin("($latestUpgradesIDQuery)")->alias('t2')->on('t1.id = t2.`MAX(id)`')
- ->get();
- $latestUpgradesObjectQuery = str_replace(' LEFT JOIN ', ' INNER JOIN ', $latestUpgradesObjectQuery);
- $latestUpgrades = $this->dao->query($latestUpgradesObjectQuery)->fetchAll();
- if(empty($latestUpgrades)) return false;
- foreach($latestUpgrades as $upgrade)
- {
- $upgrade->readme = $upgrade->changeLog;
- unset($upgrade->changeLog);
- $downloads = json_decode($upgrade->downloads);
- if(isset($downloads->linux32zip)) $downloads->linux32 = $downloads->linux32zip;
- if(isset($downloads->linux64zip)) $downloads->linux64 = $downloads->linux64zip;
- if(isset($downloads->macOSzip)) $downloads->mac64 = $downloads->macOSzip;
- if(isset($downloads->win32zip)) $downloads->win32 = $downloads->win32zip;
- if(isset($downloads->win64zip)) $downloads->win64 = $downloads->win64zip;
- unset($downloads->linux32zip);
- unset($downloads->linux64zip);
- unset($downloads->macOSzip);
- unset($downloads->win32zip);
- unset($downloads->win64zip);
- $upgrade->downloads = $downloads;
- }
- $optionalUpgrade = current(array_filter($latestUpgrades, function($upgrade) {return $upgrade->strategy == 'optional';}));
- $forcedUpgrade = current(array_filter($latestUpgrades, function($upgrade) {return $upgrade->strategy == 'force';}));
- if($forcedUpgrade && version_compare(helper::formatVersion($version), helper::formatVersion($forcedUpgrade->version)) == -1)
- {
- if(version_compare(helper::formatVersion($version), '3.0.0-alpha.1') == -1)
- {
- $semver = helper::formatVersion($forcedUpgrade->version);
- if(strpos($semver, '-') !== false)
- {
- $versions = explode('-', $semver);
- $forcedUpgrade->version = $versions[0];
- }
- else
- {
- $forcedUpgrade->version = $semver;
- }
- }
- return $forcedUpgrade;
- }
- elseif($optionalUpgrade && version_compare($version, $optionalUpgrade->version) == -1) return $optionalUpgrade;
- return false;
- }
- /**
- * Download zip package.
- * @param $version
- * @param $link
- * @return bool | string
- */
- public function downloadZipPackage($version, $link)
- {
- ignore_user_abort(true);
- set_time_limit(0);
- if(empty($version) || empty($link)) return false;
- $dir = "data/client/" . $version . '/';
- $link = helper::safe64Decode($link);
- $file = basename($link);
- if(!is_dir($this->app->wwwRoot . $dir))
- {
- mkdir($this->app->wwwRoot . $dir, 0755, true);
- }
- if(!is_dir($this->app->wwwRoot . $dir)) return false;
- if(file_exists($this->app->wwwRoot . $dir . $file))
- {
- return commonModel::getSysURL() . $this->config->webRoot . $dir . $file;
- }
- ob_clean();
- ob_end_flush();
- $local = fopen($this->app->wwwRoot . $dir . $file, 'w');
- $remote = fopen($link, 'rb');
- if($remote === false) return false;
- while(!feof($remote))
- {
- $buffer = fread($remote, 4096);
- fwrite($local, $buffer);
- }
- fclose($local);
- fclose($remote);
- return commonModel::getSysURL() . $this->config->webRoot . $dir . $file;
- }
- /**
- * Fetch client zip packages for current version.
- *
- * @param string $osList comma separated os list
- * @access public
- * @return void
- */
- public function fetchCurrentClient($osList = 'win64')
- {
- ignore_user_abort(true);
- set_time_limit(0);
- $osList = explode(',', $osList);
- $version = $this->config->xuanxuan->version;
- $downloadDir = "{$this->app->wwwRoot}data/client/$version/";
- if(!is_dir($downloadDir)) mkdir($downloadDir, 0755, true);
- /* Lock for single download process. */
- if(file_exists($downloadDir . 'downloading')) return 'downloading';
- touch($downloadDir . 'downloading');
- $errors = array();
- foreach($osList as $os)
- {
- $fileName = "xuanxuan.$version.$os.zip";
- $localPath = $downloadDir . $fileName;
- if(file_exists($localPath)) continue;
- $downloadLink = "{$this->config->client->downloadLinkPrefix}$version/$fileName";
- $downloadHandle = fopen($downloadLink, 'rb');
- $localFileHandle = fopen($localPath, 'w');
- if($downloadHandle === false)
- {
- $errors[] = $downloadLink;
- continue;
- }
- while(!feof($downloadHandle))
- {
- $buffer = fread($downloadHandle, 4096);
- fwrite($localFileHandle, $buffer);
- }
- fclose($localFileHandle);
- fclose($downloadHandle);
- }
- /* Unlock. */
- unlink($downloadDir . 'downloading');
- return empty($errors) ? 'error' : 'done';
- }
- /**
- * Pack current server config into packages.
- *
- * @param string $osList comma separated os list
- * @param bool $repack
- * @access public
- * @return void
- */
- public function packServerConfig($osList = 'win64', $repack = false)
- {
- ignore_user_abort(true);
- set_time_limit(0);
- $osList = explode(',', $osList);
- $version = $this->config->xuanxuan->version;
- $downloadDir = "{$this->app->wwwRoot}data/client/$version/";
- $packageDir = "{$this->app->wwwRoot}data/client/$version/_common/";
- if(!is_dir($packageDir)) mkdir($packageDir, 0755, true);
- /* Lock for single packing process. */
- if(file_exists($packageDir . 'packing')) return 'packing';
- touch($packageDir . 'packing');
- /* Write server address into config file. */
- $loginInfo = new stdclass();
- $loginInfo->ui = new stdclass();
- $loginInfo->ui->defaultUser = new stdclass();
- $loginInfo->ui->defaultUser->server = $this->config->xuanxuan->server;
- $loginInfo = json_encode($loginInfo);
- $loginFile = $packageDir . 'config.json';
- file_put_contents($loginFile, $loginInfo);
- define('PCLZIP_TEMPORARY_DIR', $packageDir);
- $this->app->loadClass('pclzip', true);
- $errors = array();
- foreach($osList as $os)
- {
- $fileName = "xuanxuan.$version.$os.zip";
- $packagePath = $packageDir . $fileName;
- if(file_exists($packagePath) && !$repack) continue;
- $localPath = $downloadDir . $fileName;
- if(!file_exists($localPath))
- {
- $errors[] = "$localPath does not exist.";
- continue;
- }
- $copyResult = copy($localPath, $packagePath);
- if($copyResult === false)
- {
- $errors[] = "cannot copy $localPath to $packagePath.";
- continue;
- }
- $archive = new pclzip($packagePath);
- if($os == 'mac') $result = $archive->add($loginFile, PCLZIP_OPT_REMOVE_ALL_PATH, PCLZIP_OPT_ADD_PATH, 'xuanxuan.app/Contents/Resources/build-in');
- if($os != 'mac') $result = $archive->add($loginFile, PCLZIP_OPT_REMOVE_ALL_PATH, PCLZIP_OPT_ADD_PATH, 'xuanxuan/resources/build-in');
- if($result != 0) $errors[] = $archive->errorInfo(true);
- }
- unlink($loginFile);
- /* Unlock. */
- unlink($packageDir . 'packing');
- return empty($errors) ? 'error' : 'done';
- }
- /**
- * Get download link texts.
- *
- * @param string $osList
- * @access public
- * @return void
- */
- public function getLinks($osList)
- {
- $osList = explode(',', $osList);
- $version = $this->config->xuanxuan->version;
- $linksText = '';
- foreach($osList as $os) $linksText .= $this->lang->client->osList[$os] . ': ' . commonModel::getSysURL() . $this->config->webRoot . "data/client/$version/_common/xuanxuan.$version.$os.zip\n";
- return $linksText;
- }
- }
|