class.plugins.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. # ***** BEGIN LICENSE BLOCK *****
  3. # This file is part of DotClear.
  4. # Copyright (c) 2004 Olivier Meunier and contributors. All rights
  5. # reserved.
  6. #
  7. # DotClear is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # DotClear is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with DotClear; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. #
  21. # ***** END LICENSE BLOCK *****
  22. /*
  23. Classe de gestion des plugins et des thèmes
  24. */
  25. class plugins
  26. {
  27. var $location;
  28. var $type;
  29. var $_xml;
  30. var $p_list = array();
  31. function plugins($location,$type='plugin')
  32. {
  33. if (is_dir($location)) {
  34. $this->location = $location.'/';
  35. } else {
  36. $this->location = NULL;
  37. }
  38. $this->type = $type;
  39. }
  40. function getPlugins($active_only=true)
  41. {
  42. if (($list_files = $this->_readDir()) !== false)
  43. {
  44. $this->p_list = array();
  45. foreach ($list_files as $entry => $pfile)
  46. {
  47. if (($info = $this->_getPluginInfo($pfile)) !== false) {
  48. if (($active_only && $info['active']) || !$active_only) {
  49. $this->p_list[$entry] = $info;
  50. }
  51. }
  52. }
  53. ksort($this->p_list);
  54. return true;
  55. }
  56. else
  57. {
  58. return false;
  59. }
  60. }
  61. function getPluginsList()
  62. {
  63. return $this->p_list;
  64. }
  65. function getFunctions($f='functions.php')
  66. {
  67. $res = array();
  68. if (($list_files = $this->_readDir()) !== false)
  69. {
  70. foreach ($list_files as $entry => $pfile)
  71. {
  72. if (file_exists(dirname($pfile).'/'.$f)) {
  73. $res[] = dirname($pfile).'/'.$f;
  74. }
  75. }
  76. }
  77. return $res;
  78. }
  79. function loadCallbacks()
  80. {
  81. $res['onPost'] = array();
  82. $ires = array_keys($res);
  83. foreach ($this->p_list as $k => $v)
  84. {
  85. # Chargement des fichiers events.php
  86. if (file_exists($this->location.$k.'/events.php'))
  87. {
  88. require_once $this->location.$k.'/events.php';
  89. foreach ($v['callbacks'] as $f)
  90. {
  91. if (in_array($f[0],$ires))
  92. {
  93. $pf = explode('::',$f[1]);
  94. if (count($pf) == 2 && is_callable($pf)) {
  95. $res[$f[0]][] = $pf;
  96. }
  97. }
  98. }
  99. }
  100. }
  101. return $res;
  102. }
  103. function loadl10n($p)
  104. {
  105. if (defined('DC_LANG')) {
  106. if (dc_encoding == 'UTF-8') {
  107. l10n::set($this->location.$p.'/l10n/'.DC_LANG.'-utf8/main');
  108. } else {
  109. l10n::set($this->location.$p.'/l10n/'.DC_LANG.'/main');
  110. }
  111. }
  112. }
  113. function switchStatus($p)
  114. {
  115. $xml_path = $this->location.$p.'/desc.xml';
  116. $p_info = $this->_getPluginInfo($xml_path);
  117. $xml = implode('',file($xml_path));
  118. $active = (integer) !$p_info['active'];
  119. $xml = preg_replace('|(<'.$this->type.'[^>]*?active=)"([^"]+)([^>]*>)|ms',
  120. '$1"'.$active.'$3',$xml);
  121. if (!files::putContent($xml_path,$xml)) {
  122. return false;
  123. }
  124. return true;
  125. }
  126. /* Installation d'un plugin */
  127. function install($url)
  128. {
  129. $dest = $this->location.'/'.basename($url);
  130. if (($err = files::copyRemote($url,$dest)) !== true)
  131. {
  132. return $err;
  133. }
  134. else
  135. {
  136. if (($content = @implode('',@gzfile($dest))) === false) {
  137. return __('Cannot open file');
  138. } else {
  139. if (($list = unserialize($content)) === false)
  140. {
  141. return __('Plugin not valid');
  142. }
  143. else
  144. {
  145. if (is_dir($this->location.'/'.$list['name']))
  146. {
  147. /*if (files::deltree($this->location.'/'.$list['name']) === false)
  148. {
  149. return 'Impossible de supprimer le plugin existant';
  150. }*/
  151. unlink($dest);
  152. return __('This plugin still exists. Delete it before.');
  153. }
  154. foreach ($list['dirs'] as $d)
  155. {
  156. mkdir ($this->location.'/'.$d,fileperms($this->location));
  157. chmod($this->location.'/'.$d,fileperms($this->location));
  158. }
  159. foreach ($list['files'] as $f => $v)
  160. {
  161. $v = base64_decode($v);
  162. $fp = fopen($this->location.'/'.$f,'w');
  163. fwrite($fp,$v,strlen($v));
  164. fclose($fp);
  165. chmod($this->location.'/'.$f,fileperms($this->location) & ~0111);
  166. }
  167. unlink($dest);
  168. }
  169. }
  170. }
  171. return true;
  172. }
  173. /* Lecture d'un répertoire à la recherche des desc.xml */
  174. function _readDir()
  175. {
  176. if ($this->location === NULL) {
  177. return false;
  178. }
  179. $res = array();
  180. $d = dir($this->location);
  181. # Liste du répertoire des plugins
  182. while (($entry = $d->read()) !== false)
  183. {
  184. if ($entry != '.' && $entry != '..' &&
  185. is_dir($this->location.$entry) && file_exists($this->location.$entry.'/desc.xml'))
  186. {
  187. $res[$entry] = $this->location.$entry.'/desc.xml';
  188. }
  189. }
  190. return $res;
  191. }
  192. function _getPluginInfo($p)
  193. {
  194. if (file_exists($p))
  195. {
  196. $this->_current_tag_cdata = '';
  197. $this->_p_info = array('name'=>NULL,'version'=>NULL,
  198. 'active'=>NULL,'author'=>NULL,'label'=>NULL,
  199. 'desc'=>NULL,'callbacks'=>array());
  200. $this->_xml = xml_parser_create('ISO-8859-1');
  201. xml_parser_set_option($this->_xml, XML_OPTION_CASE_FOLDING, false);
  202. xml_set_object($this->_xml, $this);
  203. xml_set_element_handler($this->_xml,'_openTag','_closeTag');
  204. xml_set_character_data_handler($this->_xml, '_cdata');
  205. xml_parse($this->_xml,implode('',file($p)));
  206. xml_parser_free($this->_xml);
  207. if (!empty($this->_p_info['name'])) {
  208. return $this->_p_info;
  209. } else {
  210. return false;
  211. }
  212. }
  213. }
  214. function _openTag($p,$tag,$attr)
  215. {
  216. if ($tag == $this->type && !empty($attr['name']))
  217. {
  218. $this->_p_info['name'] = $attr['name'];
  219. $this->_p_info['version'] = (!empty($attr['version'])) ? $attr['version'] : NULL;
  220. $this->_p_info['active'] = (!empty($attr['active'])) ? (boolean) $attr['active'] : false;
  221. }
  222. if ($tag == 'callback') {
  223. $this->_p_info['callbacks'][] = array($attr['event'],$attr['function']);
  224. }
  225. }
  226. function _closeTag($p,$tag)
  227. {
  228. switch ($tag)
  229. {
  230. case 'author':
  231. case 'label':
  232. case 'desc':
  233. $this->_p_info[$tag] = $this->_current_tag_cdata;
  234. break;
  235. }
  236. }
  237. function _cdata($p,$cdata)
  238. {
  239. $this->_current_tag_cdata = $cdata;
  240. }
  241. }
  242. ?>