index.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <?php
  2. defined('IN_PHPCMS') or exit('No permission resources.');
  3. pc_base::load_app_class('admin', 'admin', 0);
  4. class index extends admin {
  5. private $_filearr = array('api', 'phpcms', 'statics', '');
  6. //md5验证地址
  7. private $_upgrademd5 = 'http://www.phpcms.cn/upgrademd5/';
  8. //补丁地址
  9. private $_patchurl = 'http://download.phpcms.cn/v9/9.0/patch/';
  10. public function __construct() {
  11. parent::__construct();
  12. }
  13. public function init() {
  14. $patch_charset = str_replace('-', '', CHARSET);
  15. $upgrade_path_base = $this->_patchurl.$patch_charset.'/';
  16. //获取当前版本
  17. $current_version = pc_base::load_config('version');
  18. $pathlist_str = @file_get_contents($upgrade_path_base);
  19. $pathlist = $allpathlist = array();
  20. $key = -1;
  21. //获取压缩包列表
  22. preg_match_all("/\"(patch_[\w_]+\.zip)\"/", $pathlist_str, $allpathlist);
  23. $allpathlist = $allpathlist[1];
  24. //获取可供当前版本升级的压缩包
  25. foreach($allpathlist as $k=>$v) {
  26. if(strstr($v, 'patch_'.$current_version['pc_release'])) {
  27. $key = $k;
  28. break;
  29. }
  30. }
  31. $key = $key < 0 ? 9999 : $key;
  32. foreach($allpathlist as $k=>$v) {
  33. if($k >= $key) {
  34. $pathlist[$k] = $v;
  35. }
  36. }
  37. //开始升级
  38. if(!empty($_GET['s'])) {
  39. if(empty($_GET['do'])) {
  40. showmessage(L('upgradeing'), '?m=upgrade&c=index&a=init&s=1&do=1&cover='.$_GET['cover']);
  41. }
  42. //检查服务器是否支持zip
  43. if(empty($pathlist)) {
  44. showmessage(L('upgrade_success'), '?m=upgrade&c=index&a=checkfile');
  45. }
  46. //创建缓存文件夹
  47. if(!file_exists(CACHE_PATH.'caches_upgrade')) {
  48. @mkdir(CACHE_PATH.'caches_upgrade');
  49. }
  50. //根据版本下载zip升级包,解压覆盖
  51. pc_base::load_app_class('pclzip', 'upgrade', 0);
  52. foreach($pathlist as $k=>$v) {
  53. //远程压缩包地址
  54. $upgradezip_url = $upgrade_path_base.$v;
  55. //保存到本地地址
  56. $upgradezip_path = CACHE_PATH.'caches_upgrade'.DIRECTORY_SEPARATOR.$v;
  57. //解压路径
  58. $upgradezip_source_path = CACHE_PATH.'caches_upgrade'.DIRECTORY_SEPARATOR.basename($v,".zip");
  59. //下载压缩包
  60. @file_put_contents($upgradezip_path, @file_get_contents($upgradezip_url));
  61. //解压缩
  62. $archive = new PclZip($upgradezip_path);
  63. if($archive->extract(PCLZIP_OPT_PATH, $upgradezip_source_path, PCLZIP_OPT_REPLACE_NEWER) == 0) {
  64. die("Error : ".$archive->errorInfo(true));
  65. }
  66. //拷贝gbk/upload文件夹到根目录
  67. $copy_from = $upgradezip_source_path.DIRECTORY_SEPARATOR.$patch_charset.DIRECTORY_SEPARATOR.'upload'.DIRECTORY_SEPARATOR;
  68. $copy_to = PHPCMS_PATH;
  69. $this->copyfailnum = 0;
  70. $this->copydir($copy_from, $copy_to, $_GET['cover']);
  71. //检查文件操作权限,是否复制成功
  72. if($this->copyfailnum > 0) {
  73. //如果失败,恢复当前版本
  74. @file_put_contents(CACHE_PATH.'configs'.DIRECTORY_SEPARATOR.'version.php', '<?php return '.var_export($current_version, true).';?>');
  75. showmessage(L('please_check_filepri'));
  76. }
  77. //执行sql
  78. //sql目录地址
  79. $sql_path = CACHE_PATH.'caches_upgrade'.DIRECTORY_SEPARATOR.basename($v,".zip").DIRECTORY_SEPARATOR.$patch_charset.DIRECTORY_SEPARATOR.'upgrade'.DIRECTORY_SEPARATOR.'ext'.DIRECTORY_SEPARATOR;
  80. $file_list = glob($sql_path.'*');
  81. if(!empty($file_list)) {
  82. foreach ($file_list as $fk=>$fv) {
  83. if(in_array(strtolower(substr($fv, -3, 3)), array('php', 'sql'))) {
  84. if (strtolower(substr($file_list[$fk], -3, 3)) == 'sql' && $data = file_get_contents($file_list[$fk])) {
  85. $model_name = substr(basename($fv), 0, -4);
  86. if (!$db = pc_base::load_model($model_name.'_model')) {
  87. showmessage($model_name.L('lost'), '?m=upgrade&c=index&a=init&s=1');
  88. }
  89. $mysql_server_version = $db->version();
  90. $dbcharset = pc_base::load_config('database','default');
  91. $dbcharset = $dbcharset['charset'];
  92. $sqls = explode(';', $data);
  93. foreach ($sqls as $sql) {
  94. if (empty($sql)) continue;
  95. if(mysql_get_server_info > '4.1' && $dbcharset) {
  96. $sql = preg_replace("/TYPE=(InnoDB|MyISAM|MEMORY)( DEFAULT CHARSET=[^; ]+)?/", "TYPE=\\1 DEFAULT CHARSET=".$dbcharset,$sql);
  97. }
  98. $db->query($sql);
  99. }
  100. } elseif (strtolower(substr($file_list[$fk], -3, 3)) == 'php' && file_exists($file_list[$fk])) {
  101. include $file_list[$fk];
  102. //同步菜单语言包
  103. if (strtolower(basename($file_list[$fk])) == 'system_menu.lang.php' && file_exists($file_list[$fk])) {
  104. include $file_list[$fk];
  105. $new_lan = $LANG;
  106. unset($LANG);
  107. $lang = pc_base::load_config('system','lang');
  108. $menu_lan_file = PC_PATH.'languages'.DIRECTORY_SEPARATOR.$lang.DIRECTORY_SEPARATOR.'system_menu.lang.php';
  109. include $menu_lan_file;
  110. $original_lan = $LANG;
  111. unset($LANG);
  112. $diff_lan = array_diff($new_lan, $original_lan);
  113. $content = file_get_contents($menu_lan_file);
  114. $content = substr($content,0,-2);
  115. $data = '';
  116. foreach ($diff_lan as $lk => $l) {
  117. $data .= "\$LANG['".$lk."'] = '".$l."';\n\r";
  118. }
  119. $data = $content.$data."?>";
  120. file_put_contents($menu_lan_file, $data);
  121. }
  122. }
  123. }
  124. }
  125. }
  126. //读取版本号写入version.php文件
  127. //配置文件地址
  128. $configpath = CACHE_PATH.'caches_upgrade'.DIRECTORY_SEPARATOR.basename($v,".zip").DIRECTORY_SEPARATOR.$patch_charset.DIRECTORY_SEPARATOR.'upgrade'.DIRECTORY_SEPARATOR.'config.php';
  129. if(file_exists($configpath)) {
  130. $config_arr = include $configpath;
  131. $version_arr = array('pc_version'=>$config_arr['to_version'], 'pc_release'=>$config_arr['to_release']);
  132. //版本文件地址
  133. $version_filepath = CACHE_PATH.'configs'.DIRECTORY_SEPARATOR.'version.php';
  134. @file_put_contents($version_filepath, '<?php return '.var_export($version_arr, true).';?>');
  135. }
  136. //删除文件
  137. @unlink($upgradezip_path);
  138. //删除文件夹
  139. $this->deletedir($upgradezip_source_path);
  140. //提示语
  141. $tmp_k = $k + 1;
  142. if(!empty($pathlist[$tmp_k])) {
  143. $next_update = '<br />'.L('upgradeing').basename($pathlist[$tmp_k],".zip");
  144. } else {
  145. $next_update;
  146. }
  147. //文件校验是否升级成功
  148. showmessage(basename($v,".zip").L('upgrade_success').$next_update, '?m=upgrade&c=index&a=init&s=1&do=1&cover='.$_GET['cover']);
  149. }
  150. } else {
  151. include $this->admin_tpl('upgrade_index');
  152. }
  153. }
  154. //检查文件md5值
  155. public function checkfile() {
  156. if(!empty($_GET['do'])) {
  157. $this->md5_arr = array();
  158. $this->_pc_readdir(".");
  159. //读取phpcms接口
  160. $current_version = pc_base::load_config('version');
  161. $phpcms_md5 = @file_get_contents($this->_upgrademd5.$current_version['pc_release'].'_'.CHARSET.".php");
  162. $phpcms_md5_arr = json_decode($phpcms_md5, 1);
  163. //计算数组差集
  164. $diff = array_diff($phpcms_md5_arr, $this->md5_arr);
  165. //丢失文件列表
  166. $lostfile = array();
  167. foreach($phpcms_md5_arr as $k=>$v) {
  168. if(!in_array($k, array_keys($this->md5_arr))) {
  169. $lostfile[] = $k;
  170. unset($diff[$k]);
  171. }
  172. }
  173. //未知文件列表
  174. $unknowfile = array_diff(array_keys($this->md5_arr), array_keys($phpcms_md5_arr));
  175. include $this->admin_tpl('check_file');
  176. } else {
  177. showmessage(L('begin_checkfile'), '?m=upgrade&c=index&a=checkfile&do=1&menuid='.$_GET['menuid']);
  178. }
  179. }
  180. private function _pc_readdir($path='') {
  181. $dir_arr = explode('/', dirname($path));
  182. if(is_dir($path)) {
  183. $handler = opendir($path);
  184. while(($filename = @readdir($handler)) !== false) {
  185. if(substr($filename, 0, 1) != ".") {
  186. $this->_pc_readdir($path.'/'.$filename);
  187. }
  188. }
  189. closedir($handler);
  190. } else {
  191. if (dirname($path) == '.' || (isset($dir_arr[1]) && in_array($dir_arr[1], $this->_filearr))) {
  192. $this->md5_arr[base64_encode($path)] = md5_file($path);
  193. }
  194. }
  195. }
  196. public function copydir($dirfrom, $dirto, $cover='') {
  197. //如果遇到同名文件无法复制,则直接退出
  198. if(is_file($dirto)){
  199. die(L('have_no_pri').$dirto);
  200. }
  201. //如果目录不存在,则建立之
  202. if(!file_exists($dirto)){
  203. mkdir($dirto);
  204. }
  205. $handle = opendir($dirfrom); //打开当前目录
  206. //循环读取文件
  207. while(false !== ($file = readdir($handle))) {
  208. if($file != '.' && $file != '..'){ //排除"."和"."
  209. //生成源文件名
  210. $filefrom = $dirfrom.DIRECTORY_SEPARATOR.$file;
  211. //生成目标文件名
  212. $fileto = $dirto.DIRECTORY_SEPARATOR.$file;
  213. if(is_dir($filefrom)){ //如果是子目录,则进行递归操作
  214. $this->copydir($filefrom, $fileto, $cover);
  215. } else { //如果是文件,则直接用copy函数复制
  216. if(!empty($cover)) {
  217. if(!copy($filefrom, $fileto)) {
  218. $this->copyfailnum++;
  219. echo L('copy').$filefrom.L('to').$fileto.L('failed')."<br />";
  220. }
  221. } else {
  222. if(fileext($fileto) == 'html' && file_exists($fileto)) {
  223. } else {
  224. if(!copy($filefrom, $fileto)) {
  225. $this->copyfailnum++;
  226. echo L('copy').$filefrom.L('to').$fileto.L('failed')."<br />";
  227. }
  228. }
  229. }
  230. }
  231. }
  232. }
  233. }
  234. function deletedir($dirname){
  235. $result = false;
  236. if(! is_dir($dirname)){
  237. echo " $dirname is not a dir!";
  238. exit(0);
  239. }
  240. $handle = opendir($dirname); //打开目录
  241. while(($file = readdir($handle)) !== false) {
  242. if($file != '.' && $file != '..'){ //排除"."和"."
  243. $dir = $dirname.DIRECTORY_SEPARATOR.$file;
  244. //$dir是目录时递归调用deletedir,是文件则直接删除
  245. is_dir($dir) ? $this->deletedir($dir) : unlink($dir);
  246. }
  247. }
  248. closedir($handle);
  249. $result = rmdir($dirname) ? true : false;
  250. return $result;
  251. }
  252. }