update_guide.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. <?php
  2. /**
  3. * 本文件用于从镜像服务器获取升级信息与文件
  4. * 并由用户自行控制升级
  5. *
  6. * @version $Id: vote_main.php 1 23:54 2010年7月20日Z tianya $
  7. * @package DedeCMS.Administrator
  8. * @copyright Copyright (c) 2007 - 2010, DesDev, Inc.
  9. * @license http://help.dedecms.com/usersguide/license.html
  10. * @link http://www.dedecms.com
  11. */
  12. require(dirname(__FILE__).'/config.php');
  13. CheckPurview('sys_Edit');
  14. @set_time_limit(0);
  15. require(DEDEINC.'/inc/inc_fun_funAdmin.php');
  16. require(DEDEINC.'/dedehttpdown.class.php');
  17. function TestWriteAble($d)
  18. {
  19. $tfile = '_dedet.txt';
  20. $fp = @fopen($d.$tfile,'w');
  21. if(!$fp) {
  22. return false;
  23. }
  24. else {
  25. fclose($fp);
  26. $rs = @unlink($d.'/'.$tfile);
  27. return true;
  28. }
  29. }
  30. function GetDirName($filename)
  31. {
  32. $dirname = '../'.preg_replace("#[\\\\\/]{1,}#", '/', $filename);
  33. $dirname = preg_replace("#([^\/]*)$#", '', $dirname);
  34. return $dirname;
  35. }
  36. function TestIsFileDir($dirname)
  37. {
  38. $dirs = array('name'=>'', 'isdir'=>FALSE, 'writeable'=>FALSE);
  39. $dirs['name'] = $dirname;
  40. if(is_dir($dirname))
  41. {
  42. $dirs['isdir'] = TRUE;
  43. $dirs['writeable'] = TestWriteAble($dirname);
  44. }
  45. return $dirs;
  46. }
  47. function MkTmpDir($tmpdir,$filename)
  48. {
  49. $basedir = DEDEDATA.'/'.$tmpdir;
  50. $dirname = trim(preg_replace("#[\\\\\/]{1,}#", '/', $filename));
  51. $dirname = preg_replace("#([^\/]*)$#","",$dirname);
  52. if(!is_dir($basedir))
  53. {
  54. mkdir($basedir,0777);
  55. }
  56. if($dirname=='')
  57. {
  58. return TRUE;
  59. }
  60. $dirs = explode('/', $dirname);
  61. $curdir = $basedir;
  62. foreach($dirs as $d)
  63. {
  64. $d = trim($d);
  65. if(empty($d)) continue;
  66. $curdir = $curdir.'/'.$d;
  67. if(!is_dir($curdir))
  68. {
  69. mkdir($curdir, 0777) or die($curdir);
  70. }
  71. }
  72. return TRUE;
  73. }
  74. if(empty($dopost)) $dopost = 'test';
  75. //当前软件版本锁定文件
  76. $verLockFile = DEDEDATA.'/admin/ver.txt';
  77. $fp = fopen($verLockFile,'r');
  78. $upTime = trim(fread($fp,64));
  79. fclose($fp);
  80. $oktime = substr($upTime,0,4).'-'.substr($upTime,4,2).'-'.substr($upTime,6,2);
  81. /**
  82. 用AJAX获取最新版本信息
  83. function _Test() { }
  84. */
  85. if($dopost=='test')
  86. {
  87. if(empty($auto)) $auto = 'yes';
  88. AjaxHead();
  89. //下载远程数据
  90. $dhd = new DedeHttpDown();
  91. $dhd->OpenUrl(UPDATEHOST.'verinfo.txt');
  92. $verlist = trim($dhd->GetHtml());
  93. $dhd->Close();
  94. if($cfg_soft_lang=='utf-8')
  95. {
  96. $verlist = gb2utf8($verlist);
  97. }
  98. $verlist = preg_replace("#[\r\n]{1,}#", "\n", $verlist);
  99. $verlists = explode("\n", $verlist);
  100. //分析数据
  101. $updateVers = array();
  102. $upitems = $lastTime = '';
  103. $n = 0;
  104. foreach($verlists as $verstr)
  105. {
  106. if( empty($verstr) || preg_match("#^\/\/#", $verstr) )
  107. {
  108. continue ;
  109. }
  110. list($vtime, $vlang, $issafe, $vmsg) = explode(',', $verstr);
  111. $vtime = trim($vtime);
  112. $vlang = trim($vlang);
  113. $issafe = trim($issafe);
  114. $vmsg = trim($vmsg);
  115. if($vtime > $upTime && $vlang==$cfg_soft_lang)
  116. {
  117. $updateVers[$n]['issafe'] = $issafe;
  118. $updateVers[$n]['vmsg'] = $vmsg;
  119. $upitems .= ($upitems=='' ? $vtime : ','.$vtime);
  120. $lastTime = $vtime;
  121. $updateVers[$n]['vtime'] = substr($vtime,0,4).'-'.substr($vtime,4,2).'-'.substr($vtime,6,2);
  122. $n++;
  123. }
  124. }
  125. //echo "<xmp>";
  126. //判断是否需要更新,并返回适合的结果
  127. if($n==0)
  128. {
  129. $offUrl = SpGetNewInfo();
  130. echo "<div class='query-btn ue-clear'><b class='clear'>你系统版本最后更新时间为:{$oktime},当前没有可用的更新</b>\r\n";
  131. echo "<iframe name='stafrm' src='{$offUrl}&uptime={$oktime}' frameborder='0' id='stafrm' width='98%' height='50'></iframe></div>";
  132. }
  133. else
  134. {
  135. if ('no' == $auto) {
  136. $offUrl = SpGetNewInfo();
  137. echo "<div class='query-btn ue-clear'><b>你系统版本最后更新时间为:{$oktime} </b><br/><a href='javascript:LoadUpdateInfos();' class='confirm'>进行在线更新</a><a href='sys_repair.php' class='clear'>系统错误修复</a>";
  138. echo "<iframe name='stafrm' src='{$offUrl}&uptime={$oktime}' frameborder='0' id='stafrm' width='98%' height='50'></iframe></div>";
  139. exit();
  140. }
  141. echo "<div style='width:98%'><form name='fup' action='update_guide.php' method='post' onsubmit='ShowWaitDiv()'>\r\n";
  142. echo "<input type='hidden' name='dopost' value='getlist' />\r\n";
  143. echo "<input type='hidden' name='vtime' value='$lastTime' />\r\n";
  144. echo "<input type='hidden' name='upitems' value='$upitems' />\r\n";
  145. echo "<div class='upinfotitle'>你系统版本最后更新时间为:{$oktime},当前可用的更新有:</div>\r\n";
  146. foreach($updateVers as $vers)
  147. {
  148. $style = '';
  149. if($vers['issafe']==1)
  150. {
  151. $style = "color:red;";
  152. }
  153. echo "<div style='{$style}' class='verline'>【".($vers['issafe']==1 ? "安全更新" : "普通更新")."】";
  154. echo $vers['vtime'].",更新说明:{$vers['vmsg']}</div>\r\n";
  155. }
  156. echo "<div style='line-height:32px'><input type='submit' name='sb1' value=' 点击此获取所有更新文件,然后选择安装 ' class='np coolbg' style='cursor:pointer' />\r\n";
  157. echo " &nbsp; <input type='button' name='sb2' value=' 忽略这些更新 ' onclick='SkipReload({$lastTime})' class='np coolbg' style='cursor:pointer' /></div>\r\n";
  158. echo "</form></div>";
  159. }
  160. //echo "</xmp>";
  161. exit();
  162. }
  163. /**
  164. 忽略某个日期前的升级
  165. function _Skip() { }
  166. */
  167. else if($dopost=='skip')
  168. {
  169. AjaxHead();
  170. $fp = fopen($verLockFile, 'w');
  171. fwrite($fp, $vtime);
  172. fclose($fp);
  173. $offUrl = SpGetNewInfo();
  174. echo "<div class='updatedvt'><b>你系统版本最后更新时间为:{$oktime},当前没有可用的更新。</b></div>\r\n";
  175. echo "<iframe name='stafrm' src='{$offUrl}&uptime={$oktime}' frameborder='0' id='stafrm' width='100%' height='60'></iframe>";
  176. exit();
  177. }
  178. else if($dopost=='skipback')
  179. {
  180. $fp = fopen($verLockFile, 'w');
  181. fwrite($fp, $vtime);
  182. fclose($fp);
  183. ShowMsg("成功跳过这些更新!", "index_body.php");
  184. exit();
  185. }
  186. /**
  187. 获取升级文件列表
  188. function _GetList() { }
  189. */
  190. else if($dopost=='getlist')
  191. {
  192. $upitemsArr = explode(',', $upitems);
  193. rsort($upitemsArr);
  194. $tmpdir = substr(md5($cfg_cookie_encode), 0, 16);
  195. $dhd = new DedeHttpDown();
  196. $fileArr = array();
  197. $f = 0;
  198. foreach($upitemsArr as $upitem)
  199. {
  200. $durl = UPDATEHOST.$cfg_soft_lang.'/'.$upitem.'.file.txt';
  201. $dhd->OpenUrl($durl);
  202. $filelist = $dhd->GetHtml();
  203. $filelist = trim( preg_replace("#[\r\n]{1,}#", "\n", $filelist) );
  204. if(!empty($filelist))
  205. {
  206. $filelists = explode("\n", $filelist);
  207. foreach($filelists as $filelist)
  208. {
  209. $filelist = trim($filelist);
  210. if(empty($filelist)) continue;
  211. $fs = explode(',', $filelist);
  212. if( empty($fs[1]) )
  213. {
  214. $fs[1] = $upitem." 常规功能更新文件";
  215. }
  216. if(!isset($fileArr[$fs[0]]))
  217. {
  218. $fileArr[$fs[0]] = $upitem." ".trim($fs[1]);
  219. $f++;
  220. }
  221. }
  222. }
  223. }
  224. $dhd->Close();
  225. $allFileList = '';
  226. if($f==0)
  227. {
  228. $allFileList = "<font color='green'><b>没发现可用的文件列表信息,可能是官方服务器存在问题,请稍后再尝试!</b></font>";
  229. }
  230. else
  231. {
  232. $allFileList .= "<div style='width:98%'><form name='fup' action='update_guide.php' method='post'>\r\n";
  233. $allFileList .= "<input type='hidden' name='vtime' value='$vtime' />\r\n";
  234. $allFileList .= "<input type='hidden' name='dopost' value='getfiles' />\r\n";
  235. $allFileList .= "<input type='hidden' name='upitems' value='$upitems' />\r\n";
  236. $allFileList .= "<div class='upinfotitle'>以下是需要下载的更新文件(路径相对于DedeCMS的根目录):</div>\r\n";
  237. $filelists = explode("\n",$filelist);
  238. foreach($fileArr as $k=>$v)
  239. {
  240. $allFileList .= "<div class='verline'><input type='checkbox' name='files[]' value='{$k}' checked='checked' /> $k({$v})</div>\r\n";
  241. }
  242. $allFileList .= "<div class='verline'>";
  243. $allFileList .= "文件临时存放目录:../data/<input type='text' name='tmpdir' style='width:200px' value='$tmpdir' /><br />\r\n";
  244. $allFileList .= "<input type='checkbox' name='skipnodir' value='1' checked='checked' /> 跳过系统中没有的文件夹(通常是可选模块的补丁)</div>\r\n";
  245. $allFileList .= "<div style='line-height:36px;background:#F8FEDA'>&nbsp;\r\n";
  246. $allFileList .= "<input type='submit' name='sb1' value=' 下载并应用这些补丁 ' class='np coolbg' style='cursor:pointer' />\r\n";
  247. $allFileList .="</form></div>";
  248. }
  249. include DedeInclude('templets/update_guide_getlist.htm');
  250. exit();
  251. }
  252. /**
  253. 下载文件(保存需下载内容列表)
  254. function _GetFiles() { }
  255. */
  256. else if($dopost=='getfilesstart')
  257. {
  258. //update_guide.php?dopost=down&curfile=0
  259. $msg = "如果检测时发现你没安装模块的文件夹有错误,可不必理会<br />";
  260. $msg .= "<a href=update_guide.php?dopost=down&curfile=0>确认目录状态都正常后,请点击开始下载文件&gt;&gt;</a><br />";
  261. ShowMsg($msg,"javascript:;");
  262. exit();
  263. }
  264. else if($dopost=='getfiles')
  265. {
  266. $cacheFiles = DEDEDATA.'/cache/updatetmp.inc';
  267. $skipnodir = (isset($skipnodir) ? 1 : 0);
  268. $adminDir = preg_replace("#(.*)[\/\\\\]#", "", dirname(__FILE__));
  269. if(!isset($files))
  270. {
  271. $doneStr = "<p align='center' style='color:red'><br />你没有指定任何需要下载更新的文件,是否跳过这些更新?<br /><br />";
  272. $doneStr .= "<a href='update_guide.php?dopost=skipback&vtime=$vtime' class='np coolbg'>[跳过这些更新]</a> &nbsp; ";
  273. $doneStr .= "<a href='index_body.php' class='np coolbg'>[保留提示以后再进行操作]</a></p>";
  274. }
  275. else
  276. {
  277. $fp = fopen($cacheFiles, 'w');
  278. fwrite($fp, '<'.'?php'."\r\n");
  279. fwrite($fp, '$tmpdir = "'.$tmpdir.'";'."\r\n");
  280. fwrite($fp, '$vtime = '.$vtime.';'."\r\n");
  281. $dirs = array();
  282. $i = -1;
  283. foreach($files as $filename)
  284. {
  285. $tfilename = $filename;
  286. if( preg_match("#^admin\/#i", $filename) )
  287. {
  288. $tfilename = preg_replace("#^admin\/#", $adminDir.'/', $filename);
  289. }
  290. $curdir = GetDirName($tfilename);
  291. if( !isset($dirs[$curdir]) )
  292. {
  293. $dirs[$curdir] = TestIsFileDir($curdir);
  294. }
  295. if($skipnodir==1 && $dirs[$curdir]['isdir'] == FALSE)
  296. {
  297. continue;
  298. }
  299. else {
  300. @mkdir($curdir, 0777);
  301. $dirs[$curdir] = TestIsFileDir($curdir);
  302. }
  303. $i++;
  304. fwrite($fp, '$files['.$i.'] = "'.$filename.'";'."\r\n");
  305. }
  306. fwrite($fp, '$fileConut = '.$i.';'."\r\n");
  307. $items = explode(',', $upitems);
  308. foreach($items as $sqlfile)
  309. {
  310. fwrite($fp,'$sqls[] = "'.$sqlfile.'.sql";'."\r\n");
  311. }
  312. fwrite($fp, '?'.'>');
  313. fclose($fp);
  314. $dirinfos = '';
  315. if($i > -1)
  316. {
  317. $dirinfos = '<tr bgcolor="#ffffff"><td colspan="2">';
  318. $dirinfos .= "本次升级需要在下面文件夹写入更新文件,请注意文件夹是否有写入权限:<br />\r\n";
  319. foreach($dirs as $curdir)
  320. {
  321. $dirinfos .= $curdir['name']." 状态:".($curdir['writeable'] ? "[√正常]" : "<font color='red'>[×不可写]</font>")."<br />\r\n";
  322. }
  323. $dirinfos .= "</td></tr>\r\n";
  324. }
  325. $doneStr = "<iframe name='stafrm' src='update_guide.php?dopost=getfilesstart' frameborder='0' id='stafrm' width='100%' height='100%'></iframe>\r\n";
  326. }
  327. include DedeInclude('templets/update_guide_getfiles.htm');
  328. exit();
  329. }
  330. /**
  331. 下载文件,具体操作步骤
  332. function _Down() { }
  333. */
  334. else if($dopost=='down')
  335. {
  336. $cacheFiles = DEDEDATA.'/cache/updatetmp.inc';
  337. require_once($cacheFiles);
  338. if(empty($startup))
  339. {
  340. if($fileConut==-1 || $curfile > $fileConut)
  341. {
  342. ShowMsg("已下载所有文件,开始下载数据库升级文件...","update_guide.php?dopost=down&startup=1");
  343. exit();
  344. }
  345. //检查临时文件保存目录是否可用
  346. MkTmpDir($tmpdir, $files[$curfile]);
  347. $downfile = UPDATEHOST.$cfg_soft_lang.'/source/'.$files[$curfile];
  348. $dhd = new DedeHttpDown();
  349. $dhd->OpenUrl($downfile);
  350. $dhd->SaveToBin(DEDEDATA.'/'.$tmpdir.'/'.$files[$curfile]);
  351. $dhd->Close();
  352. ShowMsg("成功下载并保存文件:{$files[$curfile]}; 继续下载下一个文件。","update_guide.php?dopost=down&curfile=".($curfile+1));
  353. exit();
  354. }
  355. else
  356. {
  357. MkTmpDir($tmpdir, 'sql.txt');
  358. $dhd = new DedeHttpDown();
  359. $ct = '';
  360. foreach($sqls as $sql)
  361. {
  362. $downfile = UPDATEHOST.$cfg_soft_lang.'/'.$sql;
  363. $dhd->OpenUrl($downfile);
  364. // 请求成功才拼接 by 小虎哥
  365. if (200 == intval($dhd->m_httphead['http-code'])) {
  366. $ct .= $dhd->GetHtml();
  367. }
  368. // --end
  369. }
  370. $dhd->Close();
  371. $truefile = DEDEDATA.'/'.$tmpdir.'/sql.txt';
  372. $fp = fopen($truefile, 'w');
  373. fwrite($fp, $ct);
  374. fclose($fp);
  375. ShowMsg("完成所有远程文件获取操作:<a href='update_guide.php?dopost=apply'>&lt;&lt;点击此开始直接升级&gt;&gt;</a><br />你也可以直接使用[../data/{$tmpdir}]目录的文件手动升级。","javascript:;");
  376. exit();
  377. }
  378. exit();
  379. }
  380. /**
  381. 应用升级
  382. function _ApplyUpdate() { }
  383. */
  384. else if($dopost=='apply')
  385. {
  386. $cacheFiles = DEDEDATA.'/cache/updatetmp.inc';
  387. require_once($cacheFiles);
  388. if(empty($step))
  389. {
  390. $truefile = DEDEDATA.'/'.$tmpdir.'/sql.txt';
  391. $fp = fopen($truefile, 'r');
  392. $sql = @fread($fp, filesize($truefile));
  393. fclose($fp);
  394. if(!empty($sql))
  395. {
  396. $mysql_version = $dsql->GetVersion(true);
  397. $sql = preg_replace('#ENGINE=MyISAM#i', 'TYPE=MyISAM', $sql);
  398. $sql41tmp = 'ENGINE=MyISAM DEFAULT CHARSET='.$cfg_db_language;
  399. if($mysql_version >= 4.1)
  400. {
  401. $sql = preg_replace('#TYPE=MyISAM#i', $sql41tmp, $sql);
  402. }
  403. $sqls = explode(";\r\n", $sql);
  404. foreach($sqls as $sql)
  405. {
  406. if(trim($sql)!='')
  407. {
  408. $dsql->ExecuteNoneQuery(trim($sql));
  409. }
  410. }
  411. }
  412. ShowMsg("完成数据库更新,现在开始复制文件。","update_guide.php?dopost=apply&step=1");
  413. exit();
  414. }
  415. else
  416. {
  417. $sDir = DEDEDATA."/$tmpdir";
  418. $tDir = DEDEROOT;
  419. $badcp = 0;
  420. $adminDir = preg_replace("#(.*)[\/\\\\]#", "", dirname(__FILE__));
  421. if(isset($files) && is_array($files))
  422. {
  423. foreach($files as $f)
  424. {
  425. if(preg_match('#^admin#', $f))
  426. {
  427. $tf = preg_replace('#^admin#', $adminDir, $f);
  428. }
  429. else {
  430. $tf = $f;
  431. }
  432. if(file_exists($sDir.'/'.$f))
  433. {
  434. $rs = @copy($sDir.'/'.$f, $tDir.'/'.$tf);
  435. if($rs) {
  436. unlink($sDir.'/'.$f);
  437. }
  438. else {
  439. $badcp++;
  440. }
  441. }
  442. }
  443. }
  444. $fp = fopen($verLockFile,'w');
  445. fwrite($fp,$vtime);
  446. fclose($fp);
  447. $badmsg = '!';
  448. if($badcp > 0)
  449. {
  450. $badmsg = ",其中失败 {$badcp} 个文件,<br />请从临时目录[../data/{$tmpdir}]中取出这几个文件手动升级。";
  451. }
  452. ShowMsg("成功完成升级{$badmsg}","javascript:;");
  453. exit();
  454. }
  455. }