国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

656 satır
21KB

  1. <?php if(!defined('DEDEINC')) exit("Request Error!");
  2. /**
  3. * 织梦模块类
  4. *
  5. * @version $Id: dedemodule.class.php 1 10:31 2010年7月6日Z tianya $
  6. * @package DedeCMS.Libraries
  7. * @copyright Copyright (c) 2007 - 2020, DesDev, Inc.
  8. * @license http://help.dedecms.com/usersguide/license.html
  9. * @link http://www.dedecms.com
  10. */
  11. require_once(DEDEINC.'/charset.func.php');
  12. require_once(DEDEINC.'/dedeatt.class.php');
  13. require_once(DEDEINC.'/dedehttpdown.class.php');
  14. class DedeModule
  15. {
  16. var $modulesPath;
  17. var $modulesUrl;
  18. var $modules;
  19. var $fileListNames;
  20. var $sysLang;
  21. var $moduleLang;
  22. function __construct($modulespath='',$modulesUrl='')
  23. {
  24. global $cfg_soft_lang;
  25. $this->sysLang = $this->moduleLang = $cfg_soft_lang;
  26. $this->fileListNames = array();
  27. $this->modulesPath = $modulespath;
  28. $this->modulesUrl = $modulesUrl;
  29. }
  30. function DedeModule($modulespath='')
  31. {
  32. $this->__construct($modulespath);
  33. }
  34. /**
  35. * 枚举系统里已经存在的模块(缓存功能实际上只作hash与文件名的解析,在此不特别处理)
  36. *
  37. * @access public
  38. * @param string $moduletype 模块类型
  39. * @return string
  40. */
  41. function GetModuleList($moduletype='')
  42. {
  43. if(is_array($this->modules)) return $this->modules;
  44. $dh = dir($this->modulesPath) or die("没找到模块目录:({$this->modulesPath})!");
  45. $fp = @fopen($this->modulesPath.'/modulescache.php','w') or die('读取文件权限出错,目录文件'.$this->modulesPath.'/modulescache.php不可写!');
  46. fwrite($fp, "<"."?php\r\n");
  47. fwrite($fp, "global \$allmodules;\r\n");
  48. while($filename = $dh->read())
  49. {
  50. if(preg_match("/\.xml$/i", $filename))
  51. {
  52. $minfos = $this->GetModuleInfo(str_replace('.xml','',$filename));
  53. if(isset($minfos['moduletype']) && $moduletype!='' && $moduletype!=$minfos['moduletype'])
  54. {
  55. continue;
  56. }
  57. if($minfos['hash']!='')
  58. {
  59. $this->modules[$minfos['hash']] = $minfos;
  60. fwrite($fp, '$'."GLOBALS['allmodules']['{$minfos['hash']}']='{$filename}';\r\n");
  61. }
  62. }
  63. }
  64. fwrite($fp,'?'.'>');
  65. fclose($fp);
  66. $dh->Close();
  67. return $this->modules;
  68. }
  69. /**
  70. * 从远程获取模块信息
  71. *
  72. * @access public
  73. * @param string $moduletype 模块类型
  74. * @return string
  75. */
  76. function GetModuleUrlList($moduletype='',$url='')
  77. {
  78. $dh = dir($this->modulesPath) or die("没找到模块目录:({$this->modulesPath})!");
  79. $fp = @fopen($this->modulesPath.'/modulescache.php','w') or die('读取文件权限出错,目录文件'.$this->modulesPath.'/modulescache.php不可写!');
  80. $cachefile = DEDEDATA.'/module/moduleurllist.txt';
  81. $remotelist = '';
  82. if(file_exists($cachefile) && (filemtime($cachefile) + 60 * 30) > time())
  83. {
  84. // 30分钟本地缓存一次
  85. $remotelist = file_get_contents($cachefile);
  86. } else {
  87. $del = new DedeHttpDown();
  88. $del->OpenUrl($url);
  89. $remotelist = $del->GetHtml();
  90. PutFile($cachefile, $remotelist);
  91. }
  92. if(empty($remotelist)) return false;
  93. $modules = unserialize($remotelist);
  94. if(empty($moduletype)){
  95. return $modules;
  96. }
  97. $return = array();
  98. foreach($modules as $arrow=>$data) {
  99. if($data['moduletype']==$moduletype)
  100. $return[] = $data;
  101. }
  102. return $return;
  103. }
  104. /**
  105. * 转换编码
  106. *
  107. * @access public
  108. * @param string $str 字符串
  109. * @return string
  110. */
  111. function AppCode(&$str)
  112. {
  113. if($this->moduleLang==$this->sysLang)
  114. {
  115. return $str;
  116. }
  117. else
  118. {
  119. if($this->sysLang=='utf-8')
  120. {
  121. if($this->moduleLang=='gbk') return gb2utf8($str);
  122. if($this->moduleLang=='big5') return gb2utf8(big52gb($str));
  123. }
  124. else if($this->sysLang=='gbk')
  125. {
  126. if($this->moduleLang=='utf-8') return utf82gb($str);
  127. if($this->moduleLang=='big5') return big52gb($str);
  128. }
  129. else if($this->sysLang=='big5')
  130. {
  131. if($this->moduleLang=='utf-8') return gb2big5(utf82gb($str));
  132. if($this->moduleLang=='gbk') return gb2big5($str);
  133. }
  134. else
  135. {
  136. return $str;
  137. }
  138. }
  139. }
  140. /**
  141. * 获得指定hash的模块文件
  142. *
  143. * @access public
  144. * @param string $hash hash文件
  145. * @return string
  146. */
  147. function GetHashFile($hash)
  148. {
  149. include_once($this->modulesPath.'/modulescache.php');
  150. if(isset($GLOBALS['allmodules'][$hash])) return $GLOBALS['allmodules'][$hash];
  151. else return $hash.'.xml';
  152. }
  153. /**
  154. * 获得某模块的基本信息
  155. *
  156. * @access public
  157. * @param string $hash hash
  158. * @param string $ftype 文件类型
  159. * @return string
  160. */
  161. function GetModuleInfo($hash, $ftype='hash')
  162. {
  163. if($ftype=='file') $filename = $hash;
  164. else if(!empty($this->modulesUrl)) {
  165. $filename = $this->modulesUrl.$hash.'.xml';
  166. }else $filename = $this->modulesPath.'/'.$this->GetHashFile($hash);
  167. $start = 0;
  168. $minfos = array();
  169. $minfos['name']=$minfos['team']=$minfos['time']=$minfos['email']=$minfos['url']='';
  170. $minfos['hash']=$minfos['indexname']=$minfos['indexurl']='';
  171. $minfos['ismember']=$minfos['autosetup']=$minfos['autodel']=0;
  172. //$minfos['filename'] = $filename;
  173. if(empty($this->modulesUrl)){
  174. $minfos['filesize'] = filesize($filename)/1024;
  175. $minfos['filesize'] = number_format($minfos['filesize'],2,'.','').' Kb';
  176. }
  177. $fp = fopen($filename,'r') or die("文件 {$filename} 不存在或不可读!");
  178. $n = 0;
  179. while(!feof($fp))
  180. {
  181. $n++;
  182. if($n > 30) break;
  183. $line = fgets($fp,256);
  184. if($start==0)
  185. { if(preg_match("/<baseinfo/is",$line)) $start = 1; }
  186. else
  187. {
  188. if(preg_match("/<\/baseinfo/is",$line)) break;
  189. $line = trim($line);
  190. list($skey,$svalue) = explode('=',$line);
  191. $skey = trim($skey);
  192. $minfos[$skey] = $svalue;
  193. }
  194. }
  195. fclose($fp);
  196. if(isset($minfos['lang'])) $this->moduleLang = trim($minfos['lang']);
  197. else $this->moduleLang = 'gbk';
  198. if($this->sysLang=='gb2312') $this->sysLang = 'gbk';
  199. if($this->moduleLang=='gb2312') $this->moduleLang = 'gbk';
  200. if($this->sysLang != $this->moduleLang)
  201. {
  202. foreach($minfos as $k=>$v) $minfos[$k] = $this->AppCode($v);
  203. }
  204. return $minfos;
  205. }
  206. /**
  207. * 获得某模块的基本信息
  208. *
  209. * @access public
  210. * @param string $hash hash
  211. * @param string $ftype 文件类型
  212. * @return string
  213. */
  214. function GetFileXml($hash, $ftype='hash')
  215. {
  216. if($ftype=='file') $filename = $hash;
  217. else $filename = $this->modulesPath.'/'.$this->GetHashFile($hash);
  218. $filexml = '';
  219. $fp = fopen($filename,'r') or die("文件 {$filename} 不存在或不可读!");
  220. $start = 0;
  221. while(!feof($fp))
  222. {
  223. $line = fgets($fp,1024);
  224. if($start==0)
  225. {
  226. if(preg_match("/<modulefiles/is",$line))
  227. {
  228. $filexml .= $line;
  229. $start = 1;
  230. }
  231. continue;
  232. }
  233. else
  234. {
  235. $filexml .= $line;
  236. }
  237. }
  238. fclose($fp);
  239. return $filexml;
  240. }
  241. /**
  242. * 获得系统文件的内容
  243. * 指安装、删除、协议文件
  244. *
  245. * @access public
  246. * @param string $hashcode hash码
  247. * @param string $ntype 文件类型
  248. * @param string $enCode 是否加密
  249. * @return string
  250. */
  251. function GetSystemFile($hashcode, $ntype, $enCode=TRUE)
  252. {
  253. $this->GetModuleInfo($hashcode,$ntype);
  254. $start = FALSE;
  255. $filename = $this->modulesPath.'/'.$this->GetHashFile($hashcode);
  256. $fp = fopen($filename,'r') or die("文件 {$filename} 不存在或不可读!");
  257. $okdata = '';
  258. while(!feof($fp))
  259. {
  260. $line = fgets($fp,1024);
  261. if(!$start)
  262. {
  263. // 2011-6-7 修复模块打包程序中上传安装程序生成为空白文件(by:华强)
  264. if(preg_match("#<{$ntype}>#i", $line)) $start = TRUE;
  265. }
  266. else
  267. {
  268. if(preg_match("#<\/{$ntype}#i", $line)) break;
  269. $okdata .= $line;
  270. unset($line);
  271. }
  272. }
  273. fclose($fp);
  274. $okdata = trim($okdata);
  275. if(!empty($okdata) && $enCode) $okdata = base64_decode($okdata);
  276. $okdata = $this->AppCode($okdata);
  277. return $okdata;
  278. }
  279. /**
  280. * 把某系统文件转换为文件
  281. *
  282. * @access public
  283. * @param string $hashcode hash码
  284. * @param string $ntype 文件类型
  285. * @return string 返回文件名
  286. */
  287. function WriteSystemFile($hashcode, $ntype)
  288. {
  289. $filename = $hashcode."-{$ntype}.php";
  290. $fname = $this->modulesPath.'/'.$filename;
  291. $filect = $this->GetSystemFile($hashcode,$ntype);
  292. $fp = fopen($fname,'w') or die('生成 {$ntype} 文件失败!');
  293. fwrite($fp,$filect);
  294. fclose($fp);
  295. return $filename;
  296. }
  297. /**
  298. * 删除系统文件
  299. *
  300. * @access public
  301. * @param string $hashcode hash码
  302. * @param string $ntype 文件类型
  303. * @return void
  304. */
  305. function DelSystemFile($hashcode,$ntype)
  306. {
  307. $filename = $this->modulesPath.'/'.$hashcode."-{$ntype}.php";
  308. unlink($filename);
  309. }
  310. /**
  311. * 检查是否已经存在指定的模块
  312. *
  313. * @access public
  314. * @param string $hashcode hash码
  315. * @return bool 如果存在则返回True,否则为False
  316. */
  317. function HasModule($hashcode)
  318. {
  319. $modulefile = $this->modulesPath.'/'.$this->GetHashFile($hashcode);
  320. if(file_exists($modulefile) && !is_dir($modulefile)) return TRUE;
  321. else return FALSE;
  322. }
  323. /**
  324. * 读取文件,返回编码后的文件内容
  325. *
  326. * @access public
  327. * @param string $filename 文件名
  328. * @param string $isremove 是否删除
  329. * @return string
  330. */
  331. function GetEncodeFile($filename,$isremove=FALSE)
  332. {
  333. $fp = fopen($filename,'r') or die("文件 {$filename} 不存在或不可读!");
  334. $str = @fread($fp,filesize($filename));
  335. fclose($fp);
  336. if($isremove) @unlink($filename);
  337. if(!empty($str)) return base64_encode($str);
  338. else return '';
  339. }
  340. /**
  341. * 获取模块包里的文件名列表
  342. *
  343. * @access public
  344. * @param string $hashcode hash码
  345. * @return string 返回文件列表
  346. */
  347. function GetFileLists($hashcode)
  348. {
  349. $dap = new DedeAttParse();
  350. $filelists = array();
  351. $modulefile = $this->modulesPath.'/'.$this->GetHashFile($hashcode);
  352. $fp = fopen($modulefile,'r') or die("文件 {$modulefile} 不存在或不可读!");
  353. $i = 0;
  354. while(!feof($fp))
  355. {
  356. $line = fgets($fp,1024);
  357. if(preg_match("/^[\s]{0,}<file/i",$line))
  358. {
  359. $i++;
  360. $line = trim(preg_replace("/[><]/","",$line));
  361. $dap->SetSource($line);
  362. $filelists[$i]['type'] = $dap->CAtt->GetAtt('type');
  363. $filelists[$i]['name'] = $dap->CAtt->GetAtt('name');
  364. }
  365. }
  366. fclose($fp);
  367. return $filelists;
  368. }
  369. /**
  370. * 删除已安装模块附带的文件
  371. *
  372. * @access public
  373. * @param string $hashcode hash码
  374. * @param string $isreplace 是否替换
  375. * @return string
  376. */
  377. function DeleteFiles($hashcode,$isreplace=0)
  378. {
  379. if($isreplace==0) return TRUE;
  380. else
  381. {
  382. $dap = new DedeAttParse();
  383. $modulefile = $this->modulesPath.'/'.$this->GetHashFile($hashcode);
  384. $fp = fopen($modulefile,'r') or die("文件 {$modulefile} 不存在或不可读!");
  385. $i = 0;
  386. $dirs = '';
  387. while(!feof($fp))
  388. {
  389. $line = fgets($fp,1024);
  390. if(preg_match("/^[\s]{0,}<file/i",$line))
  391. {
  392. $i++;
  393. $line = trim(preg_replace("/[><]/","",$line));
  394. $dap->SetSource($line);
  395. $filetype = $dap->CAtt->GetAtt('type');
  396. $filename = $dap->CAtt->GetAtt('name');
  397. $filename = str_replace("\\","/",$filename);
  398. if($filetype=='dir'){ $dirs[] = $filename; }
  399. else{ @unlink($filename); }
  400. }
  401. }
  402. $okdirs = array();
  403. if(is_array($dirs)){
  404. $st = count($dirs) -1;
  405. for($i=$st;$i>=0;$i--){ @rmdir($dirs[$i]); }
  406. }
  407. fclose($fp);
  408. }
  409. return TRUE;
  410. }
  411. /**
  412. * 把模块包里的文件写入服务器
  413. *
  414. * @access public
  415. * @param string $hashcode hash码
  416. * @param string $isreplace 是否替换
  417. * @return string
  418. */
  419. function WriteFiles($hashcode, $isreplace=3)
  420. {
  421. global $AdminBaseDir;
  422. $dap = new DedeAttParse();
  423. $modulefile = $this->modulesPath.'/'.$this->GetHashFile($hashcode);
  424. $fp = fopen($modulefile,'r') or die("文件 {$modulefile} 不存在或不可读!");
  425. $i = 0;
  426. while(!feof($fp))
  427. {
  428. $line = fgets($fp,1024);
  429. if( preg_match("/^[\s]{0,}<file/i",$line) )
  430. {
  431. $i++;
  432. $line = trim(preg_replace("/[><]/","",$line));
  433. $dap->SetSource($line);
  434. $filetype = $dap->CAtt->GetAtt('type');
  435. $filename = $dap->CAtt->GetAtt('name');
  436. $filename = str_replace("\\","/",$filename);
  437. if(!empty($AdminBaseDir)) $filename = $AdminBaseDir.$filename;
  438. if($filetype=='dir')
  439. {
  440. if(!is_dir($filename))
  441. {
  442. @mkdir($filename,$GLOBALS['cfg_dir_purview']);
  443. }
  444. @chmod($filename,$GLOBALS['cfg_dir_purview']);
  445. }
  446. else
  447. {
  448. $this->TestDir($filename);
  449. if($isreplace==0) continue;
  450. if($isreplace==3)
  451. {
  452. if(is_file($filename))
  453. {
  454. $copyname = @preg_replace("/([^\/]{1,}$)/","bak-$1",$filename);
  455. @copy($filename,$copyname);
  456. }
  457. }
  458. if(!empty($filename))
  459. {
  460. $fw = fopen($filename,'w') or die("写入文件 {$filename} 失败,请检查相关目录的权限!");
  461. $ct = '';
  462. while(!feof($fp))
  463. {
  464. $l = fgets($fp,1024);
  465. if(preg_match("/^[\s]{0,}<\/file/i",trim($l))){ break; }
  466. $ct .= $l;
  467. }
  468. $ct = base64_decode($ct);
  469. if($this->sysLang!=$this->moduleLang)
  470. {
  471. //转换内码
  472. if(preg_match('/\.(xml|php|inc|txt|htm|html|shtml|tpl|css)$/', $filename))
  473. {
  474. $ct = $this->AppCode($ct);
  475. }
  476. //转换HTML编码标识
  477. if(preg_match('/\.(php|htm|html|shtml|inc|tpl)$/i', $filename))
  478. {
  479. if($this->sysLang=='big5') $charset = 'charset=big5';
  480. else if($this->sysLang=='utf-8') $charset = 'charset=gb2312';
  481. else $charset = 'charset=gb2312';
  482. $ct = preg_match("/charset=([a-z0-9-]*)/i", $charset, $ct);
  483. }
  484. }
  485. fwrite($fw,$ct);
  486. fclose($fw);
  487. }
  488. }
  489. }
  490. }
  491. fclose($fp);
  492. return TRUE;
  493. }
  494. /**
  495. * 测试某文件的文件夹是否创建
  496. *
  497. * @access public
  498. * @param string $filename 文件名称
  499. * @return string
  500. */
  501. function TestDir($filename)
  502. {
  503. $fs = explode('/',$filename);
  504. $fn = count($fs) - 1 ;
  505. $ndir = '';
  506. for($i=0;$i < $fn;$i++)
  507. {
  508. if($ndir!='') $ndir = $ndir.'/'.$fs[$i];
  509. else $ndir = $fs[$i];
  510. $rs = @is_dir($ndir);
  511. if( !$rs ) {
  512. @mkdir($ndir,$GLOBALS['cfg_dir_purview']);
  513. @chmod($ndir,$GLOBALS['cfg_dir_purview']);
  514. }
  515. }
  516. return TRUE;
  517. }
  518. /**
  519. * 获取某个目录或文件的打包数据
  520. *
  521. * @access public
  522. * @param string $basedir 基本目录
  523. * @param string $f
  524. * @param string $fp 文件指针
  525. * @return bool
  526. */
  527. function MakeEncodeFile($basedir,$f,$fp)
  528. {
  529. $this->fileListNames = array();
  530. $this->MakeEncodeFileRun($basedir,$f,$fp);
  531. return TRUE;
  532. }
  533. /**
  534. * 测试目标文件
  535. *
  536. * @access public
  537. * @param string $basedir 基本目录
  538. * @param string $f
  539. * @return bool
  540. */
  541. function MakeEncodeFileTest($basedir,$f)
  542. {
  543. $this->fileListNames = array();
  544. $this->MakeEncodeFileRunTest($basedir,$f);
  545. return TRUE;
  546. }
  547. /**
  548. * 检测某个目录或文件的打包数据,递归
  549. *
  550. * @access public
  551. * @param string $basedir 基本目录
  552. * @param string $f
  553. * @return void
  554. */
  555. function MakeEncodeFileRunTest($basedir,$f)
  556. {
  557. $filename = $basedir.'/'.$f;
  558. if(isset($this->fileListNames[$f])) return;
  559. else if(preg_match("/Thumbs\.db/i",$f)) return;
  560. else $this->fileListNames[$f] = 1;
  561. $fileList = '';
  562. if(!file_exists($filename))
  563. {
  564. ShowMsg("文件或文件夹: {$filename} 不存在,无法进行编译!","-1");
  565. exit();
  566. }
  567. if(is_dir($filename))
  568. {
  569. $dh = dir($filename);
  570. while($filename = $dh->read())
  571. {
  572. if($filename[0]=='.' || strtolower($filename)=='cvs') continue;
  573. $nfilename = $f.'/'.$filename;
  574. $this->MakeEncodeFileRunTest($basedir,$nfilename);
  575. }
  576. }
  577. }
  578. /**
  579. * 获取个目录或文件的打包数据,递归
  580. *
  581. * @access public
  582. * @param string $basedir 基本目录
  583. * @param string $f
  584. * @param string $fp 文件指针
  585. * @return string
  586. */
  587. function MakeEncodeFileRun($basedir,$f,$fp)
  588. {
  589. $filename = $basedir.'/'.$f;
  590. if(isset($this->fileListNames[$f])) return;
  591. else if(preg_match("#Thumbs\.db#i", $f)) return;
  592. else $this->fileListNames[$f] = 1;
  593. $fileList = '';
  594. if(is_dir($filename))
  595. {
  596. $fileList .= "<file type='dir' name='$f'>\r\n";
  597. $fileList .= "</file>\r\n";
  598. fwrite($fp,$fileList);
  599. $dh = dir($filename);
  600. while($filename = $dh->read())
  601. {
  602. if($filename[0]=='.' || strtolower($filename)=='cvs') continue;
  603. $nfilename = $f.'/'.$filename;
  604. $this->MakeEncodeFileRun($basedir,$nfilename,$fp);
  605. }
  606. }
  607. else
  608. {
  609. $fileList .= "<file type='file' name='$f'>\r\n";
  610. $fileList .= $this->GetEncodeFile($filename);
  611. $fileList .= "\r\n</file>\r\n";
  612. fwrite($fp,$fileList);
  613. }
  614. }
  615. /**
  616. * 清理
  617. *
  618. * @access public
  619. * @return void
  620. */
  621. function Clear()
  622. {
  623. unset($this->modules);
  624. unset($this->fileList);
  625. unset($this->fileListNames);
  626. }
  627. }//End Class