[ Index ] |
|
Code source de DokuWiki 2006-11-06 |
1 <?php 2 /** 3 * Plugin management functions 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Christopher Smith <chris@jalakai.co.uk> 7 */ 8 // must be run within Dokuwiki 9 if(!defined('DOKU_INC')) die(); 10 11 // todo 12 // - maintain a history of file modified 13 // - allow a plugin to contain extras to be copied to the current template (extra/tpl/) 14 // - to images (lib/images/) [ not needed, should go in lib/plugin/images/ ] 15 16 if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 17 require_once (DOKU_PLUGIN.'admin.php'); 18 19 //--------------------------[ GLOBALS ]------------------------------------------------ 20 // note: probably should be dokuwiki wide globals, where they can be accessed by pluginutils.php 21 // global $plugin_types; 22 // $plugin_types = array('syntax', 'admin'); 23 24 // plugins that are an integral part of dokuwiki, they shouldn't be disabled or deleted 25 global $plugin_protected; 26 $plugin_protected = array('acl','plugin','config','info','usermanager'); 27 28 /** 29 * All DokuWiki plugins to extend the admin function 30 * need to inherit from this class 31 */ 32 class admin_plugin_plugin extends DokuWiki_Admin_Plugin { 33 34 var $disabled = 0; 35 var $plugin = ''; 36 var $cmd = ''; 37 var $handler = NULL; 38 39 var $functions = array('delete','update',/*'settings',*/'info'); // require a plugin name 40 var $commands = array('manage','download','enable'); // don't require a plugin name 41 var $plugin_list = array(); 42 43 var $msg = ''; 44 var $error = ''; 45 46 function admin_plugin_plugin() { 47 global $conf; 48 $this->disabled = (isset($conf['pluginmanager']) && ($conf['pluginmanager'] == 0)); 49 } 50 51 /** 52 * return some info 53 */ 54 function getInfo(){ 55 $disabled = ($this->disabled) ? '(disabled)' : ''; 56 57 return array( 58 'author' => 'Christopher Smith', 59 'email' => 'chris@jalakai.co.uk', 60 'date' => '2005-08-10', 61 'name' => 'Plugin Manager', 62 'desc' => "Manage Plugins, including automated plugin installer $disabled", 63 'url' => 'http://wiki.splitbrain.org/plugin:adminplugin', 64 ); 65 } 66 67 /** 68 * return prompt for admin menu 69 */ 70 function getMenuText($language) { 71 72 if (!$this->disabled) 73 return parent::getMenuText($language); 74 75 return ''; 76 } 77 78 /** 79 * return sort order for position in admin menu 80 */ 81 function getMenuSort() { 82 return 20; 83 } 84 85 /** 86 * handle user request 87 */ 88 function handle() { 89 90 if ($this->disabled) return; 91 92 // enable direct access to language strings 93 $this->setupLocale(); 94 95 // $this->plugin = $_REQUEST['plugin']; 96 // $this->cmd = $_REQUEST['fn']; 97 // if (is_array($this->cmd)) $this->cmd = key($this->cmd); 98 99 $fn = $_REQUEST['fn']; 100 if (is_array($fn)) { 101 $this->cmd = key($fn); 102 $this->plugin = is_array($fn[$this->cmd]) ? key($fn[$this->cmd]) : null; 103 } else { 104 $this->cmd = $fn; 105 $this->plugin = null; 106 } 107 108 $this->plugin_list = plugin_list('', true); 109 sort($this->plugin_list); 110 111 // verify $_REQUEST vars 112 if (in_array($this->cmd, $this->commands)) { 113 $this->plugin = ''; 114 } else if (!in_array($this->cmd, $this->functions) || !in_array($this->plugin, $this->plugin_list)) { 115 $this->cmd = 'manage'; 116 $this->plugin = ''; 117 } 118 119 // create object to handle the command 120 $class = "ap_".$this->cmd; 121 if (!class_exists($class)) $class = 'ap_manage'; 122 123 $this->handler = & new $class($this, $this->plugin); 124 $this->msg = $this->handler->process(); 125 } 126 127 /** 128 * output appropriate html 129 */ 130 function html() { 131 132 if ($this->disabled) return; 133 134 // enable direct access to language strings 135 $this->setupLocale(); 136 137 if ($this->handler === NULL) $this->handler = & new ap_manage($this, $this->plugin); 138 if (!$this->plugin_list) { 139 $this->plugin_list = plugin_list('',true); 140 sort($this->plugin_list); 141 } 142 143 ptln('<div id="plugin__manager">'); 144 $this->handler->html(); 145 ptln('</div><!-- #plugin_manager -->'); 146 } 147 148 } 149 150 class ap_manage { 151 152 var $manager = NULL; 153 var $lang = array(); 154 var $plugin = ''; 155 var $downloaded = array(); 156 157 function ap_manage(&$manager, $plugin) { 158 $this->manager = & $manager; 159 $this->plugin = $plugin; 160 $this->lang = & $manager->lang; 161 } 162 163 function process() { 164 return ''; 165 } 166 167 function html() { 168 print $this->manager->locale_xhtml('admin_plugin'); 169 $this->html_menu(); 170 } 171 172 // build our standard menu 173 function html_menu($listPlugins = true) { 174 global $ID; 175 176 ptln('<div class="pm_menu">'); 177 178 ptln('<div class="common">'); 179 ptln(' <h2>'.$this->lang['download'].'</h2>'); 180 ptln(' <form action="'.wl($ID).'" method="post">'); 181 ptln(' <fieldset class="hidden">',4); 182 ptln(' <input type="hidden" name="do" value="admin" />'); 183 ptln(' <input type="hidden" name="page" value="plugin" />'); 184 ptln(' </fieldset>'); 185 ptln(' <fieldset>'); 186 ptln(' <legend>'.$this->lang['download'].'</legend>'); 187 ptln(' <label for="dw__url">'.$this->lang['url'].'<input name="url" id="dw__url" class="edit" type="text" maxlength="200" /></label>'); 188 ptln(' <input type="submit" class="button" name="fn[download]" value="'.$this->lang['btn_download'].'" />'); 189 ptln(' </fieldset>'); 190 ptln(' </form>'); 191 ptln('</div>'); 192 193 if ($listPlugins) { 194 ptln('<h2>'.$this->lang['manage'].'</h2>'); 195 196 ptln('<form action="'.wl($ID).'" method="post" class="plugins">'); 197 // ptln(' <div class="plugins">'); 198 199 ptln(' <fieldset class="hidden">'); 200 ptln(' <input type="hidden" name="do" value="admin" />'); 201 ptln(' <input type="hidden" name="page" value="plugin" />'); 202 ptln(' </fieldset>'); 203 204 $this->html_pluginlist(); 205 206 ptln(' <fieldset class="buttons">'); 207 ptln(' <input type="submit" class="button" name="fn[enable]" value="'.$this->lang['btn_enable'].'" />'); 208 ptln(' </fieldset>'); 209 210 // ptln(' </div>'); 211 ptln('</form>'); 212 } 213 214 ptln('</div>'); 215 } 216 217 function html_pluginlist() { 218 global $ID; 219 global $plugin_protected; 220 221 foreach ($this->manager->plugin_list as $plugin) { 222 223 $disabled = plugin_isdisabled($plugin); 224 $protected = in_array($plugin,$plugin_protected); 225 226 $checked = ($disabled) ? '' : ' checked="checked"'; 227 $check_disabled = ($protected) ? ' disabled="disabled"' : ''; 228 229 // determine display class(es) 230 $class = array(); 231 if (in_array($plugin, $this->downloaded)) $class[] = 'new'; 232 if ($disabled) $class[] = 'disabled'; 233 if ($protected) $class[] = 'protected'; 234 235 $class = count($class) ? ' class="'.join(' ', $class).'"' : ''; 236 237 ptln(' <fieldset'.$class.'>'); 238 ptln(' <legend>'.$plugin.'</legend>'); 239 ptln(' <input type="checkbox" class="enable" name="enabled[]" value="'.$plugin.'"'.$checked.$check_disabled.' />'); 240 ptln(' <h3 class="legend">'.$plugin.'</h3>'); 241 242 $this->html_button($plugin, 'info', false, 6); 243 if (in_array('settings', $this->manager->functions)) { 244 $this->html_button($plugin, 'settings', !@file_exists(DOKU_PLUGIN.$plugin.'/settings.php'), 6); 245 } 246 $this->html_button($plugin, 'update', !$this->plugin_readlog($plugin, 'url'), 6); 247 $this->html_button($plugin, 'delete', $protected, 6); 248 249 ptln(' </fieldset>'); 250 } 251 } 252 253 function html_button($plugin, $btn, $disabled=false, $indent=0) { 254 $disabled = ($disabled) ? 'disabled="disabled"' : ''; 255 ptln('<input type="submit" class="button" '.$disabled.' name="fn['.$btn.']['.$plugin.']" value="'.$this->lang['btn_'.$btn].'" />',$indent); 256 } 257 258 /** 259 * Refresh plugin list 260 */ 261 function refresh() { 262 263 $this->manager->plugin_list = plugin_list('',true); 264 sort($this->manager->plugin_list); 265 266 // expire dokuwiki caches 267 // touching local.php expires wiki page, JS and CSS caches 268 @touch(DOKU_CONF.'local.php'); 269 270 // update latest plugin date - FIXME 271 return (!$this->manager->error); 272 } 273 274 function download($url, $overwrite=false) { 275 global $lang; 276 277 // check the url 278 $matches = array(); 279 if (!preg_match("/[^\/]*$/", $url, $matches) || !$matches[0]) { 280 $this->manager->error = $this->lang['error_badurl']."\n"; 281 return false; 282 } 283 284 $file = $matches[0]; 285 $folder = "p".md5($file.date('r')); // tmp folder name - will be empty (should really make sure it doesn't already exist) 286 $tmp = DOKU_PLUGIN."tmp/$folder"; 287 288 if (!ap_mkdir($tmp)) { 289 $this->manager->error = $this->lang['error_dir_create']."\n"; 290 return false; 291 } 292 293 if (!$file = io_download($url, "$tmp/", true, $file)) { 294 $this->manager->error = sprintf($this->lang['error_download'],$url)."\n"; 295 } 296 297 if (!$this->manager->error && !ap_decompress("$tmp/$file", $tmp)) { 298 $this->manager->error = sprintf($this->lang['error_decompress'],$file)."\n"; 299 } 300 301 // search tmp/$folder for the folder(s) that has been created 302 // move that folder(s) to lib/plugins/ 303 if (!$this->manager->error) { 304 if ($dh = @opendir("$tmp/")) { 305 while (false !== ($f = readdir($dh))) { 306 if ($f == '.' || $f == '..' || $f == 'tmp') continue; 307 if (!is_dir("$tmp/$f")) continue; 308 309 // check to make sure we aren't overwriting anything 310 if (!$overwrite && @file_exists(DOKU_PLUGIN."/$f")) { 311 // remember our settings, ask the user to confirm overwrite, FIXME 312 continue; 313 } 314 315 $instruction = @file_exists(DOKU_PLUGIN."/$f") ? 'update' : 'install'; 316 317 if (ap_copy("$tmp/$f", DOKU_PLUGIN.$f)) { 318 $this->downloaded[] = $f; 319 $this->plugin_writelog($f, $instruction, array($url)); 320 } else { 321 $this->manager->error .= sprintf($lang['error_copy']."\n", $f); 322 } 323 } 324 closedir($dh); 325 } else { 326 $this->manager->error = $this->lang['error']."\n"; 327 } 328 } 329 330 // cleanup 331 if ($folder && is_dir(DOKU_PLUGIN."tmp/$folder")) ap_delete(DOKU_PLUGIN."tmp/$folder"); 332 333 if (!$this->manager->error) { 334 $this->refresh(); 335 return true; 336 } 337 338 return false; 339 } 340 341 // log 342 function plugin_writelog($plugin, $cmd, $data) { 343 344 $file = DOKU_PLUGIN.$plugin.'/manager.dat'; 345 346 switch ($cmd) { 347 case 'install' : 348 $url = $data[0]; 349 $date = date('r'); 350 if (!$fp = @fopen($file, 'w')) return; 351 fwrite($fp, "installed=$date\nurl=$url\n"); 352 fclose($fp); 353 break; 354 355 case 'update' : 356 $date = date('r'); 357 if (!$fp = @fopen($file, 'a')) return; 358 fwrite($fp, "updated=$date\n"); 359 fclose($fp); 360 break; 361 } 362 } 363 364 function plugin_readlog($plugin, $field) { 365 static $log = array(); 366 $file = DOKU_PLUGIN.$plugin.'/manager.dat'; 367 368 if (!isset($log[$plugin])) { 369 $tmp = @file_get_contents($file); 370 if (!$tmp) return ''; 371 $log[$plugin] = & $tmp; 372 } 373 374 if ($field == 'ALL') { 375 return $log[$plugin]; 376 } 377 378 $match = array(); 379 if (preg_match_all('/'.$field.'=(.*)$/m',$log[$plugin], $match)) 380 return implode("\n", $match[1]); 381 382 return ''; 383 } 384 } 385 386 class ap_download extends ap_manage { 387 388 var $overwrite = false; 389 390 function process() { 391 global $lang; 392 393 $plugin_url = $_REQUEST['url']; 394 $this->download($plugin_url, $this->overwrite); 395 return ''; 396 } 397 398 function html() { 399 parent::html(); 400 401 ptln('<div class="pm_info">'); 402 ptln('<h2>'.$this->lang['downloading'].'</h2>'); 403 404 if ($this->manager->error) { 405 ptln('<div class="error">'.str_replace("\n","<br />",$this->manager->error).'</div>'); 406 } else if (count($this->downloaded) == 1) { 407 ptln('<p>'.sprintf($this->lang['downloaded'],$this->downloaded[0]).'</p>'); 408 } else if (count($this->downloaded)) { // more than one plugin in the download 409 ptln('<p>'.$this->lang['downloads'].'</p>'); 410 ptln('<ul>'); 411 foreach ($this->downloaded as $plugin) { 412 ptln('<li><div class="li">'.$plugin.'</div></li>',2); 413 } 414 ptln('</ul>'); 415 } else { // none found in download 416 ptln('<p>'.$this->lang['download_none'].'</p>'); 417 } 418 ptln('</div>'); 419 } 420 421 } 422 423 class ap_delete extends ap_manage { 424 425 function process() { 426 427 if (!ap_delete(DOKU_PLUGIN.$this->manager->plugin)) { 428 $this->manager->error = sprintf($this->lang['error_delete'],$this->manager->plugin); 429 } else { 430 $this->refresh(); 431 } 432 } 433 434 function html() { 435 parent::html(); 436 437 ptln('<div class="pm_info">'); 438 ptln('<h2>'.$this->lang['deleting'].'</h2>'); 439 440 if ($this->manager->error) { 441 ptln('<div class="error">'.str_replace("\n","<br />",$this->manager->error).'</div>'); 442 } else { 443 ptln('<p>'.sprintf($this->lang['deleted'],$this->plugin).'</p>'); 444 } 445 ptln('</div>'); 446 } 447 } 448 449 class ap_info extends ap_manage { 450 451 var $plugin_info = array(); // the plugin itself 452 var $details = array(); // any component plugins 453 454 function process() { 455 456 // sanity check 457 if (!$this->manager->plugin) { return; } 458 459 $component_list = ap_plugin_components($this->manager->plugin); 460 usort($component_list, 'ap_component_sort'); 461 462 foreach ($component_list as $component) { 463 if ($obj = & plugin_load($component['type'],$component['name']) === NULL) continue; 464 465 $this->details[] = array_merge($obj->getInfo(), array('type' => $component['type'])); 466 unset($obj); 467 } 468 469 // review details to simplify things 470 foreach($this->details as $info) { 471 foreach($info as $item => $value) { 472 if (!isset($this->plugin_info[$item])) { $this->plugin_info[$item] = $value; continue; } 473 if ($this->plugin_info[$item] != $value) $this->plugin_info[$item] = ''; 474 } 475 } 476 } 477 478 function html() { 479 480 // output the standard menu stuff 481 parent::html(); 482 483 // sanity check 484 if (!$this->manager->plugin) { return; } 485 486 ptln('<div class="pm_info">'); 487 ptln("<h2>".$this->manager->getLang('plugin')." {$this->manager->plugin}</h2>"); 488 489 // collect pertinent information from the log 490 $installed = $this->plugin_readlog($this->manager->plugin, 'installed'); 491 $source = $this->plugin_readlog($this->manager->plugin, 'url'); 492 $updated = $this->plugin_readlog($this->manager->plugin, 'updated'); 493 if (strrpos($updated, "\n") !== false) $updated = substr($updated, strrpos($updated, "\n")+1); 494 495 ptln("<dl>",2); 496 ptln("<dt>".$this->manager->getLang('source').'</dt><dd>'.($source ? $source : $this->manager->getLang('unknown'))."</dd>",4); 497 ptln("<dt>".$this->manager->getLang('installed').'</dt><dd>'.($installed ? $installed : $this->manager->getLang('unknown'))."</dd>",4); 498 if ($updated) ptln("<dt>".$this->manager->getLang('lastupdate').'</dt><dd>'.$updated."</dd>",4); 499 ptln("</dl>",2); 500 501 if (count($this->details) == 0) { 502 ptln("<p>".$this->manager->getLang('noinfo')."</p>",2); 503 } else { 504 505 ptln("<dl>",2); 506 if ($this->plugin_info['name']) ptln("<dt>".$this->manager->getLang('name')."</dt><dd>".$this->out($this->plugin_info['name'])."</dd>",4); 507 if ($this->plugin_info['date']) ptln("<dt>".$this->manager->getLang('date')."</dt><dd>".$this->out($this->plugin_info['date'])."</dd>",4); 508 if ($this->plugin_info['type']) ptln("<dt>".$this->manager->getLang('type')."</dt><dd>".$this->out($this->plugin_info['type'])."</dd>",4); 509 if ($this->plugin_info['desc']) ptln("<dt>".$this->manager->getLang('desc')."</dt><dd>".$this->out($this->plugin_info['desc'])."</dd>",4); 510 if ($this->plugin_info['author']) ptln("<dt>".$this->manager->getLang('author')."</dt><dd>".$this->manager->email($this->plugin_info['email'], $this->plugin_info['author'])."</dd>",4); 511 if ($this->plugin_info['url']) ptln("<dt>".$this->manager->getLang('www')."</dt><dd>".$this->manager->external_link($this->plugin_info['url'], '', 'urlextern')."</dd>",4); 512 ptln("</dl>",2); 513 514 if (count($this->details) > 1) { 515 ptln("<h3>".$this->manager->getLang('components')."</h3>",2); 516 ptln("<div>",2); 517 518 foreach ($this->details as $info) { 519 520 ptln("<dl>",4); 521 ptln("<dt>".$this->manager->getLang('name')."</dt><dd>".$this->out($info['name'])."</dd>",6); 522 if (!$this->plugin_info['date']) ptln("<dt>".$this->manager->getLang('date')."</dt><dd>".$this->out($info['date'])."</dd>",6); 523 if (!$this->plugin_info['type']) ptln("<dt>".$this->manager->getLang('type')."</dt><dd>".$this->out($info['type'])."</dd>",6); 524 if (!$this->plugin_info['desc']) ptln("<dt>".$this->manager->getLang('desc')."</dt><dd>".$this->out($info['desc'])."</dd>",6); 525 if (!$this->plugin_info['author']) ptln("<dt>".$this->manager->getLang('author')."</dt><dd>".$this->manager->email($info['email'], $info['author'])."</dd>",6); 526 if (!$this->plugin_info['url']) ptln("<dt>".$this->manager->getLang('www')."</dt><dd>".$this->manager->external_link($info['url'], '', 'urlextern')."</dd>",6); 527 ptln("</dl>",4); 528 529 } 530 ptln("</div>",2); 531 } 532 } 533 ptln("</div>"); 534 } 535 536 // simple output filter, make html entities safe and convert new lines to <br /> 537 function out($text) { 538 return str_replace("\n",'<br />',htmlentities($text)); 539 } 540 541 } 542 543 //--------------[ to do ]--------------------------------------- 544 class ap_update extends ap_manage { 545 546 var $overwrite = true; 547 548 function process() { 549 global $lang; 550 551 $plugin_url = $this->plugin_readlog($this->plugin, 'url'); 552 $this->download($plugin_url, $this->overwrite); 553 return ''; 554 } 555 556 function html() { 557 parent::html(); 558 559 ptln('<div class="pm_info">'); 560 ptln('<h2>'.$this->lang['updating'].'</h2>'); 561 562 if ($this->manager->error) { 563 ptln('<div class="error">'.str_replace("\n","<br />", $this->manager->error).'</div>'); 564 } else if (count($this->downloaded) == 1) { 565 ptln('<p>'.sprintf($this->lang['updated'],$this->downloaded[0]).'</p>'); 566 } else if (count($this->downloaded)) { // more than one plugin in the download 567 ptln('<p>'.$this->lang['updates'].'</p>'); 568 ptln('<ul>'); 569 foreach ($this->downloaded as $plugin) { 570 ptln('<li><div class="li">'.$plugin.'</div></li>',2); 571 } 572 ptln('</ul>'); 573 } else { // none found in download 574 ptln('<p>'.$this->lang['update_none'].'</p>'); 575 } 576 ptln('</div>'); 577 } 578 } 579 class ap_settings extends ap_manage {} 580 581 class ap_enable extends ap_manage { 582 583 var $enabled = array(); 584 585 function process() { 586 global $plugin_protected; 587 588 $this->enabled = isset($_REQUEST['enabled']) ? $_REQUEST['enabled'] : array(); 589 590 foreach ($this->manager->plugin_list as $plugin) { 591 if (in_array($plugin, $plugin_protected)) continue; 592 593 $new = in_array($plugin, $this->enabled); 594 $old = !plugin_isdisabled($plugin); 595 596 if ($new != $old) { 597 switch ($new) { 598 // enable plugin 599 case true : plugin_enable($plugin); break; 600 case false: plugin_disable($plugin); break; 601 } 602 } 603 } 604 605 // refresh plugins, including expiring any dokuwiki cache(s) 606 $this->refresh(); 607 } 608 609 } 610 611 //--------------[ utilities ]----------------------------------- 612 613 function is_css($f) { return (substr($f, -4) == '.css'); } 614 615 // generate an admin plugin href 616 function apl($pl, $fn) { 617 global $ID; 618 return wl($ID,"do=admin&page=plugin".($pl?"&plugin=$pl":"").($fn?"&fn=$fn":"")); 619 } 620 621 // decompress wrapper 622 function ap_decompress($file, $target) { 623 624 // decompression library doesn't like target folders ending in "/" 625 if (substr($target, -1) == "/") $target = substr($target, 0, -1); 626 $ext = substr($file, strrpos($file,'.')+1); 627 628 // .tar, .tar.bz, .tar.gz, .tgz 629 if (in_array($ext, array('tar','bz','bz2','gz','tgz'))) { 630 631 require_once(DOKU_PLUGIN."plugin/inc/tarlib.class.php"); 632 633 if (strpos($ext, 'bz') !== false) $compress_type = COMPRESS_BZIP; 634 else if (strpos($ext,'gz') !== false) $compress_type = COMPRESS_GZIP; 635 else $compress_type = COMPRESS_NONE; 636 637 $tar = new CompTar($file, $compress_type); 638 $ok = $tar->Extract(FULL_ARCHIVE, $target, '', 0777); 639 640 // FIXME sort something out for handling tar error messages meaningfully 641 return ($ok<0?false:true); 642 643 } else if ($ext == 'zip') { 644 645 require_once(DOKU_PLUGIN."plugin/inc/zip.lib.php"); 646 647 $zip = new zip(); 648 $ok = $zip->Extract($file, $target); 649 650 // FIXME sort something out for handling zip error messages meaningfully 651 return ($ok==-1?false:true); 652 653 } else if ($ext == "rar") { 654 // not yet supported -- fix me 655 return false; 656 } 657 658 // unsupported file type 659 return false; 660 } 661 662 // possibly should use io_MakeFileDir, not sure about using its method of error handling 663 function ap_mkdir($d) { 664 global $conf; 665 666 $ok = io_mkdir_p($d); 667 return $ok; 668 } 669 670 // copy with recursive sub-directory support 671 function ap_copy($src, $dst) { 672 global $conf; 673 674 if (is_dir($src)) { 675 if (!$dh = @opendir($src)) return false; 676 677 if ($ok = ap_mkdir($dst)) { 678 while ($ok && (false !== ($f = readdir($dh)))) { 679 if ($f == '..' || $f == '.') continue; 680 $ok = ap_copy("$src/$f", "$dst/$f"); 681 } 682 } 683 684 closedir($dh); 685 return $ok; 686 687 } else { 688 $exists = @file_exists($dst); 689 690 if (!@copy($src,$dst)) return false; 691 if (!$exists && !empty($conf['fperm'])) chmod($dst, $conf['fperm']); 692 @touch($dst,filemtime($src)); 693 } 694 695 return true; 696 } 697 698 // delete, with recursive sub-directory support 699 function ap_delete($path) { 700 701 if (!is_string($path) || $path == "") return false; 702 703 if (is_dir($path)) { 704 if (!$dh = @opendir($path)) return false; 705 706 while ($f = readdir($dh)) { 707 if ($f == '..' || $f == '.') continue; 708 ap_delete("$path/$f"); 709 } 710 711 closedir($dh); 712 return @rmdir($path); 713 } else { 714 return @unlink($path); 715 } 716 717 return false; 718 } 719 720 // return a list (name & type) of all the component plugins that make up this plugin 721 // can this move to pluginutils? 722 function ap_plugin_components($plugin) { 723 724 global $plugin_types; 725 726 $components = array(); 727 $path = DOKU_PLUGIN.$plugin.'/'; 728 729 foreach ($plugin_types as $type) { 730 if (@file_exists($path.$type.'.php')) { $components[] = array('name'=>$plugin, 'type'=>$type); continue; } 731 732 if ($dh = @opendir($path.$type.'/')) { 733 while (false !== ($cp = readdir($dh))) { 734 if ($cp == '.' || $cp == '..' || strtolower(substr($cp,-4)) != '.php') continue; 735 $components[] = array('name'=>$plugin.'_'.substr($cp, 0, -4), 'type'=>$type); 736 } 737 closedir($dh); 738 } 739 } 740 return $components; 741 } 742 743 function ap_component_sort($a, $b) { 744 if ($a['name'] == $b['name']) return 0; 745 return ($a['name'] < $b['name']) ? -1 : 1; 746 } 747
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Tue Apr 3 20:47:31 2007 | par Balluche grâce à PHPXref 0.7 |