AdminUpdateController.class.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. namespace Api\Controller;
  3. use Think\Controller;
  4. class AdminUpdateController extends BaseController {
  5. //检测showdoc版本更新
  6. public function checkUpdate(){
  7. //获取当前版本
  8. $text = file_get_contents("../composer.json");
  9. $composer = json_decode($text, true);
  10. $version = $composer['version'] ;
  11. $url = "https://www.showdoc.cc/server/api/open/checkUpdate";
  12. $ch = curl_init();
  13. $timeout = 2;
  14. curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
  15. curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  16. curl_setopt ( $ch, CURLOPT_POST, true );
  17. curl_setopt ( $ch, CURLOPT_POSTFIELDS, "version={$version}" );
  18. curl_setopt($ch,CURLOPT_URL,$url);
  19. $sContent = curl_exec($ch);
  20. curl_close($ch);
  21. echo $sContent ;
  22. }
  23. // 下载更新代码包
  24. public function download(){
  25. $this->checkLogin();
  26. $this->checkAdmin();
  27. set_time_limit(1000);
  28. ini_set('memory_limit','500M');
  29. $new_version = I("new_version") ;
  30. $file_url = I("file_url") ;
  31. $version_num = str_replace("v","",$new_version) ;
  32. $showdoc_path = "../" ;
  33. // 进行文件读写权限检查
  34. if(!$this->new_is_writeable($showdoc_path)
  35. || !$this->new_is_writeable($showdoc_path."Sqlite/" )
  36. || !$this->new_is_writeable($showdoc_path."web/" )
  37. || !$this->new_is_writeable($showdoc_path."web/index.php" )
  38. || !$this->new_is_writeable($showdoc_path."server/" )
  39. || !$this->new_is_writeable($showdoc_path."server/vendor/autoload.php" )
  40. || !$this->new_is_writeable($showdoc_path."server/Application/Api" )
  41. ){
  42. $this->sendError(10101,'请手动给showdoc安装目录下的所有文件可写权限,否则程序无法覆盖旧文件');
  43. return ;
  44. }
  45. $temp_dir = sys_get_temp_dir()."/showdoc_update/";
  46. $zip_file = $temp_dir.'showdoc-'.$version_num.'.zip' ;
  47. mkdir($temp_dir) ;
  48. unlink($zip_file);
  49. $file = file_get_contents($file_url);
  50. file_put_contents($zip_file,$file);
  51. $zip = new \ZipArchive();
  52. $flag = $zip->open($zip_file);
  53. if($flag!==true){
  54. $this->sendError(10101,'下载更新压缩包失败');
  55. return ;
  56. }
  57. $zip->extractTo($temp_dir);
  58. $flag = $zip->close();
  59. $zip_file_subpath = $temp_dir.'showdoc-'.$version_num."/" ;
  60. if(file_exists($zip_file_subpath.'composer.json') && file_exists($zip_file_subpath.'web/index.php') && file_exists($zip_file_subpath.'server/vendor/autoload.php') ){
  61. //echo $zip_file_subpath.'存在';
  62. // 移动目录到upload/update
  63. $this->copydir($zip_file_subpath ,$showdoc_path.'Public/Uploads/update/' );
  64. $this->deldir($temp_dir);
  65. $this->sendResult(array());
  66. }else{
  67. $this->sendError(10101,'下载更新压缩包后,解压的文件缺失');
  68. return ;
  69. }
  70. }
  71. // 执行升级操作,升级覆盖文件
  72. public function updateFiles(){
  73. $this->checkLogin();
  74. $this->checkAdmin();
  75. set_time_limit(1000);
  76. ini_set('memory_limit','500M');
  77. $showdoc_path = "../" ;
  78. // 进行文件读写权限检查
  79. if(!$this->new_is_writeable($showdoc_path)
  80. || !$this->new_is_writeable($showdoc_path."Sqlite/" )
  81. || !$this->new_is_writeable($showdoc_path."web/" )
  82. || !$this->new_is_writeable($showdoc_path."web/index.php" )
  83. || !$this->new_is_writeable($showdoc_path."server/" )
  84. || !$this->new_is_writeable($showdoc_path."server/vendor/autoload.php" )
  85. || !$this->new_is_writeable($showdoc_path."server/Application/Api" )
  86. ){
  87. $this->sendError(10101,'请手动给showdoc安装目录下的所有文件可写权限,否则程序无法覆盖旧文件');
  88. return ;
  89. }
  90. if(file_exists($showdoc_path.'Public/Uploads/update/composer.json') && file_exists($showdoc_path.'Public/Uploads/update/server/vendor/autoload.php') ){
  91. $text = file_get_contents($showdoc_path."composer.json");
  92. $composer = json_decode($text, true);
  93. $cur_version = $composer['version'] ;
  94. $cur_version = str_replace("v","",$cur_version) ;
  95. $text = file_get_contents($showdoc_path."Public/Uploads/update/composer.json");
  96. $composer = json_decode($text, true);
  97. $update_version = $composer['version'] ;
  98. $update_version = str_replace("v","",$update_version) ;
  99. if(version_compare($update_version,$cur_version) > 0 ){
  100. //复制数据库文件备份
  101. $bak_name = $showdoc_path.'Sqlite/showdoc.db.bak.'.date("Y-m-d-H-i-s").'.php';
  102. copy($showdoc_path.'Sqlite/showdoc.db.php', $bak_name);
  103. // 目录覆盖
  104. $this->copydir($showdoc_path.'Public/Uploads/update/',$showdoc_path);
  105. // 用备份的数据库还原
  106. copy($bak_name, $showdoc_path.'Sqlite/showdoc.db.php' );
  107. $this->deldir($showdoc_path.'Public/Uploads/update/') ;
  108. // echo '升级成功!' ;
  109. $this->sendResult(array());
  110. }else{
  111. // echo '不需要升级';
  112. $this->sendError(10101,'版本号显示不需要升级');
  113. }
  114. }else{
  115. $this->sendError(10101,'升级文件不存在');
  116. }
  117. }
  118. /**
  119. * 复制到目录
  120. * $dirsrc 原目录
  121. * $dirto 目标目录
  122. *
  123. */
  124. private function copydir($dirsrc, $dirto) {
  125. //如果原来的文件存在, 是不是一个目录
  126. if(file_exists($dirto)) {
  127. if(!is_dir($dirto)) {
  128. echo "目标不是一个目录, 不能copy进去<br>";
  129. exit;
  130. }
  131. }else{
  132. mkdir($dirto);
  133. }
  134. $dir = opendir($dirsrc);
  135. while($filename = readdir($dir)) {
  136. if($filename != "." && $filename !="..") {
  137. $srcfile = $dirsrc."/".$filename; //原文件
  138. $tofile = $dirto."/".$filename; //目标文件
  139. if(is_dir($srcfile)) {
  140. $this->copydir($srcfile, $tofile); //递归处理所有子目录
  141. }else{
  142. copy($srcfile, $tofile);
  143. }
  144. }
  145. }
  146. }
  147. // 删除文件夹及文件夹下所有的文件
  148. private function deldir($dir) {
  149. //先删除目录下的文件:
  150. $dh = opendir($dir);
  151. while ($file = readdir($dh)) {
  152. if($file != "." && $file!="..") {
  153. $fullpath = $dir."/".$file;
  154. if(!is_dir($fullpath)) {
  155. unlink($fullpath);
  156. } else {
  157. $this->deldir($fullpath);
  158. }
  159. }
  160. }
  161. closedir($dh);
  162. //删除当前文件夹:
  163. if(rmdir($dir)) {
  164. return true;
  165. } else {
  166. return false;
  167. }
  168. }
  169. /**
  170. * 判断 文件/目录 是否可写(取代系统自带的 is_writeable 函数)
  171. *
  172. * @param string $file 文件/目录
  173. * @return boolean
  174. */
  175. private function new_is_writeable($file) {
  176. if (is_dir($file)){
  177. $dir = $file;
  178. if ($fp = @fopen("$dir/test.txt", 'w')) {
  179. @fclose($fp);
  180. @unlink("$dir/test.txt");
  181. $writeable = 1;
  182. } else {
  183. $writeable = 0;
  184. }
  185. } else {
  186. if ($fp = @fopen($file, 'a+')) {
  187. @fclose($fp);
  188. $writeable = 1;
  189. } else {
  190. $writeable = 0;
  191. }
  192. }
  193. return $writeable;
  194. }
  195. }