AdminUpdateController.class.php 7.8 KB

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