* Date: 2018-4-3 */ namespace app\admin\controller; use think\Controller; use think\Db; use think\response\Json; use app\admin\model; class Upgrade extends Controller { /** * 析构函数 */ function __construct() { parent::__construct(); function_exists('set_time_limit') && set_time_limit(0); @ini_set('memory_limit','-1'); // @ini_set('memory_limit', '1024M'); // 设置内存大小 // @ini_set("max_execution_time", "0"); // 请求超时时间 0 为不限时 // @ini_set('default_socket_timeout', 3600); // 设置 file_get_contents 请求超时时间 官方的说明,似乎没有不限时间的选项,也就是不能填0,你如果填0,那么socket就会立即返回失败, $this->assign('version', getCmsVersion()); } public function welcome() { $sys_info['os'] = PHP_OS; $sys_info['zlib'] = function_exists('gzclose') ? 'YES' : 'NO';//zlib $sys_info['safe_mode'] = (boolean) ini_get('safe_mode') ? 'YES' : 'NO';//safe_mode = Off $sys_info['timezone'] = function_exists("date_default_timezone_get") ? date_default_timezone_get() : "no_timezone"; $sys_info['curl'] = function_exists('curl_init') ? 'YES' : 'NO'; $sys_info['web_server'] = $_SERVER['SERVER_SOFTWARE']; $sys_info['phpv'] = phpversion(); $sys_info['ip'] = GetHostByName($_SERVER['SERVER_NAME']); $sys_info['fileupload'] = @ini_get('file_uploads') ? ini_get('upload_max_filesize') :'unknown'; $sys_info['max_ex_time'] = @ini_get("max_execution_time").'s'; //脚本最大执行时间 $sys_info['set_time_limit'] = function_exists("set_time_limit") ? true : false; $sys_info['domain'] = request()->host(); $sys_info['memory_limit'] = ini_get('memory_limit'); $sys_info['version'] = file_get_contents(DATA_PATH.'conf/version.txt'); $mysqlinfo = Db::query("SELECT VERSION() as version"); $sys_info['mysql_version'] = $mysqlinfo[0]['version']; if(function_exists("gd_info")){ $gd = gd_info(); $sys_info['gdinfo'] = $gd['GD Version']; }else { $sys_info['gdinfo'] = "未知"; } $globalTpCache = tpCache('global'); $upgradeLogic = new \app\admin\logic\UpgradeLogic(); $sys_info['curent_version'] = $upgradeLogic->curent_version; //当前程序版本 $sys_info['web_name'] = !empty($globalTpCache['web_name']) ? $globalTpCache['web_name'] : ''; $this->assign('sys_info', $sys_info); $upgradeMsg = $upgradeLogic->checkVersion(); //升级包消息 $this->assign('upgradeMsg',$upgradeMsg); if (isset($globalTpCache['web_show_popup_upgrade']) && 2 == $globalTpCache['web_show_popup_upgrade'] && $this->php_servicemeal <= 0) { $globalTpCache['web_show_popup_upgrade'] = -1; } $this->assign('web_show_popup_upgrade', $globalTpCache['web_show_popup_upgrade']); $this->assign('global', $globalTpCache); return $this->fetch(); } /** * 一键升级 */ public function OneKeyUpgrade(){ header('Content-Type:application/json; charset=utf-8'); function_exists('set_time_limit') && set_time_limit(0); /*权限控制 by 小虎哥*/ $admin_info = session('admin_info'); if (0 < intval($admin_info['role_id'])) { $auth_role_info = $admin_info['auth_role_info']; if (!empty($auth_role_info) && intval($auth_role_info['online_update']) <= 0) { $this->error('您没有操作权限,请联系超级管理员分配权限'); } } /*--end*/ $curent_version = getCmsVersion(); $upgradeLogic = new \app\admin\logic\UpgradeLogic(); $data = $upgradeLogic->OneKeyUpgrade(); //升级包消息 if (1 <= intval($data['code'])) { adminLog("系统在线升级:{$curent_version} -> ".getCmsVersion()); $this->success($data['msg'], null, ['code'=>$data['code']]); } else { $code = 0; $msg = '升级异常,请排查问题!'; if (is_array($data)) { isset($data['code']) && $code = $data['code']; isset($data['msg']) && $msg = $data['msg']; } $this->error($msg, null, ['code'=>$code]); } } /** * 设置弹窗更新-不再提醒 */ public function setPopupUpgrade() { $show_popup_upgrade = input('param.show_popup_upgrade/s', '1'); $inc_type = 'web'; tpCache($inc_type, array($inc_type.'_show_popup_upgrade'=>$show_popup_upgrade)); respose(1); } /** * 检测目录权限、当前版本的数据库是否与官方一致 */ public function check_authority() { /*------------------检测目录读写权限----------------------*/ $filelist = tpCache('system.system_upgrade_filelist'); $filelist = base64_decode($filelist); $filelist = htmlspecialchars_decode($filelist); $filelist = explode('
', $filelist); $dirs = array(); $i = -1; foreach($filelist as $filename) { $tfilename = $filename; $curdir = $this->GetDirName($tfilename); if (empty($curdir) || !file_exists($curdir)) { continue; } if( !isset($dirs[$curdir]) ) { $dirs[$curdir] = $this->TestIsFileDir($curdir); } if($dirs[$curdir]['isdir'] == FALSE) { continue; } else { @tp_mkdir($curdir, 0777); $dirs[$curdir] = $this->TestIsFileDir($curdir); } $i++; } $is_pass = true; $msg = '检测通过'; if($i > -1) { $n = 0; $dirinfos = ''; foreach($dirs as $curdir) { $dirinfos .= $curdir['name']."  状态:"; if ($curdir['writeable']) { $dirinfos .= "[√正常]"; } else { $is_pass = false; $n++; $dirinfos .= "[×不可写]"; } $dirinfos .= "
"; } $title = "本次升级需要在下面文件夹写入更新文件,已检测站点有 {$n} 处没有写入权限:
"; $title .= "问题分析(如有问题,请咨询技术支持):
"; $title .= "1、检查站点目录的用户组与所有者,禁止是 root ;
"; $title .= "2、检查站点目录的读写权限,一般权限值是 0755 ;
"; $title .= "
涉及更新目录列表如下:
"; $msg = $title . $dirinfos; } /*------------------end----------------------*/ if (true == $is_pass) { /*------------------检测目录读写权限----------------------*/ $values = [ 'version' => getCmsVersion(), ]; $upgradeLogic = new \app\admin\logic\UpgradeLogic; $upgradeLogic->GetKeyData($values); $url = $upgradeLogic->getServiceUrl().'/index.php?m=api&c=Service&a=get_database_txt'; $response = @httpRequest($url, 'POST', $values, [], 5); if (false === $response) { $url = $url.'&'.http_build_query($values); $context = stream_context_set_default(array('http' => array('timeout' => 5,'method'=>'GET'))); $response = @file_get_contents($url, false, $context); } $params = json_decode($response,true); if (false == $params) { $this->error('连接升级服务器超时,请刷新重试!', null, ['code'=>2]); } if (is_array($params)) { if (1 == intval($params['code'])) { /*------------------组合本地数据库信息----------------------*/ $dbtables = Db::query('SHOW TABLE STATUS'); $local_database = array(); foreach ($dbtables as $k => $v) { $table = $v['Name']; if (preg_match('/^'.PREFIX.'/i', $table)) { $local_database[$table] = [ 'name' => $table, 'field' => [], ]; } } /*------------------end----------------------*/ /*------------------组合官方远程数据库信息----------------------*/ $info = $params['info']; $info = preg_replace("#[\r\n]{1,}#", "\n", $info); $infos = explode("\n", $info); $infolists = []; foreach ($infos as $key => $val) { if (!empty($val)) { $arr = explode('|', $val); $infolists[$arr[0]] = $val; } } /*------------------end----------------------*/ /*------------------校验数据库是否合格----------------------*/ foreach ([1] as $testk => $testv) { // 对比数据表数量 if (count($local_database) < count($infolists)) { $is_pass = false; break; } // 对比数据表字段数量 foreach ($infolists as $k1 => $v1) { $arr1 = explode('|', $v1); if (1 >= count($arr1)) { continue; // 忽略不对比的数据表 } $fieldArr = explode(',', $arr1[1]); $table = preg_replace('/^ey_/i', PREFIX, $arr1[0]); $local_fields = Db::getFields($table); // 本地数据表字段列表 $local_database[$table]['field'] = $local_fields; if (count($local_fields) < count($fieldArr)) { $is_pass = false; break; } } if (false == $is_pass) break; } /*------------------end----------------------*/ } else if (2 == intval($params['code'])) { $this->error('官方缺少版本号'.getCmsVersion().'的数据库比较文件!', null, ['code'=>2]); } } if (true == $is_pass) { $this->success($msg); } else { $this->error('当前数据库结构与官方不一致,请查看官方解决教程!', null, ['code'=>2]); } /*------------------end----------------------*/ } else { $this->error($msg, null, ['code'=>1]); } } /** * 获取文件的目录路径 * @param string $filename 文件路径+文件名 * @return string */ private function GetDirName($filename) { $dirname = preg_replace("#[\\\\\/]{1,}#", '/', $filename); $dirname = preg_replace("#([^\/]*)$#", '', $dirname); $dirname = preg_replace('/^data\/backup\/tpl\//i', '', $dirname); return $dirname; } /** * 测试目录路径是否有读写权限 * @param string $dirname 文件目录路径 * @return array */ private function TestIsFileDir($dirname) { $dirs = array('name'=>'', 'isdir'=>FALSE, 'writeable'=>FALSE); $dirs['name'] = $dirname; tp_mkdir($dirname); if(is_dir($dirname)) { $dirs['isdir'] = TRUE; $dirs['writeable'] = $this->TestWriteAble($dirname); } return $dirs; } /** * 测试目录路径是否有写入权限 * @param string $d 目录路劲 * @return boolean */ private function TestWriteAble($d) { $tfile = '_eyout.txt'; $fp = @fopen($d.$tfile,'w'); if(!$fp) { if (@is_writable($d)) { return true; } return false; } else { fclose($fp); $rs = @unlink($d.$tfile); return true; } } }