diff --git a/.gitignore b/.gitignore index 6ad14d206163763202e8bc4ae8bd269c52bda931..f70efa66584272e181a6fadc9ee689cda535c22d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /conf/words.aspell /conf/lang/* /conf/plugin_lang/* +/conf/plugins.local.* .htaccess *.swp *.bak diff --git a/conf/plugins.protected.php b/conf/plugins.protected.php new file mode 100644 index 0000000000000000000000000000000000000000..26eb8888b75bc29fea03f0d34dcbe042fa5690d3 --- /dev/null +++ b/conf/plugins.protected.php @@ -0,0 +1,11 @@ +<?php +/** + * This file configures the enabled/disabled status of plugins, which are also protected + * from changes by the extention manager. These settings will override any local settings. + * It is not recommended to change this file, as it is overwritten on DokuWiki upgrades. + */ +$plugins['acl'] = 1; +$plugins['plugin'] = 1; +$plugins['config'] = 1; +$plugins['usermanager'] = 1; +$plugins['revert'] = 1; diff --git a/inc/config_cascade.php b/inc/config_cascade.php index 48ed5a000b36d77db56dfb2610089ade8b3d1775..c01778e99f552e8a1cbf48556ffcf5eb668f203a 100644 --- a/inc/config_cascade.php +++ b/inc/config_cascade.php @@ -64,6 +64,11 @@ $config_cascade = array_merge( 'plainauth.users' => array( 'default' => DOKU_CONF.'users.auth.php', ), + + 'plugins' => array( + 'local' => array(DOKU_CONF.'plugins.local.php'), + 'protected' => array(DOKU_CONF.'plugins.protected.php'), + ), ), $config_cascade ); diff --git a/inc/infoutils.php b/inc/infoutils.php index 786661d01d69eb478ce3cf92bf126e875d6639a1..f1deec66b2d999ea325339edb4f0847216fef1d8 100644 --- a/inc/infoutils.php +++ b/inc/infoutils.php @@ -66,8 +66,8 @@ function getVersionData(){ $chunk = fread($fh,2000); fclose($fh); $chunk = trim($chunk); - $chunk = array_pop(explode("\n",$chunk)); //last log line - $chunk = array_shift(explode("\t",$chunk)); //strip commit msg + $chunk = @array_pop(explode("\n",$chunk)); //last log line + $chunk = @array_shift(explode("\t",$chunk)); //strip commit msg $chunk = explode(" ",$chunk); array_pop($chunk); //strip timezone $date = date('Y-m-d',array_pop($chunk)); diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 6a02bbe0b6d6fb3cddf9f579418317c53bfe227a..ab6a88497084c0fda835cdfabd21bf77e106065e 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -361,4 +361,6 @@ $lang['js']['media_drop'] = 'Drop files here to upload'; $lang['js']['media_cancel'] = 'remove'; $lang['js']['media_overwrt'] = 'Overwrite existing files'; +$lang['plugin_install_err'] = "Plugin installed incorrectly. Rename plugin directory '%s' to '%s'."; + //Setup VIM: ex: et ts=2 : diff --git a/inc/plugincontroller.class.php b/inc/plugincontroller.class.php index ea5725d47938b8d09460bdb18b1288ba3e6e4490..734331c94a6500823e0bd431292795c9e09a9153 100644 --- a/inc/plugincontroller.class.php +++ b/inc/plugincontroller.class.php @@ -11,11 +11,16 @@ if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); class Doku_Plugin_Controller { - var $list_enabled = array(); - var $list_disabled = array(); var $list_bytype = array(); + var $tmp_plugins = array(); + var $plugin_cascade = array('default'=>array(),'local'=>array(),'protected'=>array()); + var $last_local_config_file = ''; - function Doku_Plugin_Controller() { + /** + * Populates the master list of plugins + */ + function __construct() { + $this->loadConfig(); $this->_populateMasterList(); } @@ -37,7 +42,7 @@ class Doku_Plugin_Controller { // request the complete list if (!$type) { - return $all ? array_merge($this->list_enabled,$this->list_disabled) : $this->list_enabled; + return $all ? array_keys($this->tmp_plugins) : array_keys(array_filter($this->tmp_plugins)); } if (!isset($this->list_bytype[$type]['enabled'])) { @@ -61,9 +66,11 @@ class Doku_Plugin_Controller { * @param $disabled bool true to load even disabled plugins * @return objectreference the plugin object or null on failure */ - function &load($type,$name,$new=false,$disabled=false){ + function load($type,$name,$new=false,$disabled=false){ + //we keep all loaded plugins available in global scope for reuse global $DOKU_PLUGINS; + global $lang; list($plugin,$component) = $this->_splitName($name); @@ -85,12 +92,12 @@ class Doku_Plugin_Controller { //construct class and instantiate if (!class_exists($class, true)) { + # the plugin might be in the wrong directory $dir = $this->get_directory($plugin); $inf = confToHash(DOKU_PLUGIN."$dir/plugin.info.txt"); if($inf['base'] && $inf['base'] != $plugin){ - msg("Plugin installed incorrectly. Rename plugin directory '". - hsc($plugin)."' to '".hsc($inf['base'])."'.",-1); + msg(sprintf($lang['plugin_install_err'],hsc($plugin),hsc($inf['base'])),-1); } return null; } @@ -100,30 +107,28 @@ class Doku_Plugin_Controller { } function isdisabled($plugin) { - return (array_search($plugin, $this->list_enabled) === false); + return empty($this->tmp_plugins[$plugin]); } - function enable($plugin) { - if (array_search($plugin, $this->list_disabled) !== false) { - return @unlink(DOKU_PLUGIN.$plugin.'/disabled'); - } - return false; + function disable($plugin) { + if(array_key_exists($plugin,$this->plugin_cascade['protected'])) return false; + $this->tmp_plugins[$plugin] = 0; + return $this->saveList(); } - function disable($plugin) { - if (array_search($plugin, $this->list_enabled) !== false) { - return @touch(DOKU_PLUGIN.$plugin.'/disabled'); - } - return false; + function enable($plugin) { + if(array_key_exists($plugin,$this->plugin_cascade['protected'])) return false; + $this->tmp_plugins[$plugin] = 1; + return $this->saveList(); } function get_directory($plugin) { return $plugin; } - function _populateMasterList() { - global $conf; - if ($dh = opendir(DOKU_PLUGIN)) { + protected function _populateMasterList() { + if ($dh = @opendir(DOKU_PLUGIN)) { + $all_plugins = array(); while (false !== ($plugin = readdir($dh))) { if ($plugin[0] == '.') continue; // skip hidden entries if (is_file(DOKU_PLUGIN.$plugin)) continue; // skip files, we're only interested in directories @@ -132,19 +137,119 @@ class Doku_Plugin_Controller { // the plugin was disabled by rc2009-01-26 // disabling mechanism was changed back very soon again // to keep everything simple we just skip the plugin completely - }elseif(@file_exists(DOKU_PLUGIN.$plugin.'/disabled') || - ($plugin === 'plugin' && isset($conf['pluginmanager']) && - !$conf['pluginmanager'])){ - $this->list_disabled[] = $plugin; + } elseif (@file_exists(DOKU_PLUGIN.$plugin.'/disabled')) { + // treat this as a default disabled plugin(over-rideable by the plugin manager) + // deprecated 2011-09-10 (usage of disabled files) + if (empty($this->plugin_cascade['local'][$plugin])) { + $all_plugins[$plugin] = 0; + } else { + $all_plugins[$plugin] = 1; + } + $this->plugin_cascade['default'][$plugin] = 0; + + } elseif ((array_key_exists($plugin,$this->tmp_plugins) && $this->tmp_plugins[$plugin] == 0) || + ($plugin === 'plugin' && isset($conf['pluginmanager']) && !$conf['pluginmanager'])){ + $all_plugins[$plugin] = 0; + + } elseif ((array_key_exists($plugin,$this->tmp_plugins) && $this->tmp_plugins[$plugin] == 1)) { + $all_plugins[$plugin] = 1; } else { - $this->list_enabled[] = $plugin; + $all_plugins[$plugin] = 1; } } + $this->tmp_plugins = $all_plugins; + if (!file_exists($this->last_local_config_file)) { + $this->saveList(true); + } + } + } + + protected function checkRequire($files) { + $plugins = array(); + foreach($files as $file) { + if(file_exists($file)) { + @include_once($file); + } + } + return $plugins; + } + + function getCascade() { + return $this->plugin_cascade; + } + + /** + * Save the current list of plugins + */ + function saveList($forceSave = false) { + global $conf; + + if (empty($this->tmp_plugins)) return false; + + // Rebuild list of local settings + $local_plugins = $this->rebuildLocal(); + if($local_plugins != $this->plugin_cascade['local'] || $forceSave) { + $file = $this->last_local_config_file; + $out = "<?php\n/*\n * Local plugin enable/disable settings\n * Auto-generated through plugin/extension manager\n *\n". + " * NOTE: Plugins will not be added to this file unless there is a need to override a default setting. Plugins are\n". + " * enabled by default, unless having a 'disabled' file in their plugin folder.\n */\n"; + foreach ($local_plugins as $plugin => $value) { + $out .= "\$plugins['$plugin'] = $value;\n"; + } + // backup current file (remove any existing backup) + if (@file_exists($file)) { + $backup = $file.'.bak'; + if (@file_exists($backup)) @unlink($backup); + if (!@copy($file,$backup)) return false; + if ($conf['fperm']) chmod($backup, $conf['fperm']); + } + //check if can open for writing, else restore + return io_saveFile($file,$out); + } + return false; + } + + /** + * Rebuild the set of local plugins + * @return array array of plugins to be saved in end($config_cascade['plugins']['local']) + */ + function rebuildLocal() { + //assign to local variable to avoid overwriting + $backup = $this->tmp_plugins; + //Can't do anything about protected one so rule them out completely + $local_default = array_diff_key($backup,$this->plugin_cascade['protected']); + //Diff between local+default and default + //gives us the ones we need to check and save + $diffed_ones = array_diff_key($local_default,$this->plugin_cascade['default']); + //The ones which we are sure of (list of 0s not in default) + $sure_plugins = array_filter($diffed_ones,array($this,'negate')); + //the ones in need of diff + $conflicts = array_diff_key($local_default,$diffed_ones); + //The final list + return array_merge($sure_plugins,array_diff_assoc($conflicts,$this->plugin_cascade['default'])); + } + + /** + * Build the list of plugins and cascade + * + */ + function loadConfig() { + global $config_cascade; + foreach(array('default','protected') as $type) { + if(array_key_exists($type,$config_cascade['plugins'])) + $this->plugin_cascade[$type] = $this->checkRequire($config_cascade['plugins'][$type]); } + $local = $config_cascade['plugins']['local']; + $this->last_local_config_file = array_pop($local); + $this->plugin_cascade['local'] = $this->checkRequire(array($this->last_local_config_file)); + if(is_array($local)) { + $this->plugin_cascade['default'] = array_merge($this->plugin_cascade['default'],$this->checkRequire($local)); + } + $this->tmp_plugins = array_merge($this->plugin_cascade['default'],$this->plugin_cascade['local'],$this->plugin_cascade['protected']); } function _getListByType($type, $enabled) { - $master_list = $enabled ? $this->list_enabled : $this->list_disabled; + $master_list = $enabled ? array_keys(array_filter($this->tmp_plugins)) : array_keys(array_filter($this->tmp_plugins,array($this,'negate'))); $plugins = array(); foreach ($master_list as $plugin) { @@ -169,11 +274,13 @@ class Doku_Plugin_Controller { } function _splitName($name) { - if (array_search($name, $this->list_enabled + $this->list_disabled) === false) { + if (array_search($name, array_keys($this->tmp_plugins)) === false) { return explode('_',$name,2); } return array($name,''); } - + function negate($input) { + return !(bool) $input; + } } diff --git a/inc/pluginutils.php b/inc/pluginutils.php index 85bcaee1e80b09dcfb234b718a65d1503e7a2a95..53cfedf82b6edeb7df2c2efdcfb28205df9f3507 100644 --- a/inc/pluginutils.php +++ b/inc/pluginutils.php @@ -16,7 +16,7 @@ function plugin_list($type='',$all=false) { global $plugin_controller; return $plugin_controller->getList($type,$all); } -function &plugin_load($type,$name,$new=false,$disabled=false) { +function plugin_load($type,$name,$new=false,$disabled=false) { global $plugin_controller; return $plugin_controller->load($type,$name,$new,$disabled); } @@ -36,3 +36,7 @@ function plugin_directory($plugin) { global $plugin_controller; return $plugin_controller->get_directory($plugin); } +function plugin_getcascade() { + global $plugin_controller; + return $plugin_controller->getCascade(); +} diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php index 53f6db0cc99ebd0d0f427335e45bce23ff6117b9..a6b0624bce42a9e83da72e7bfdb9bceedb62c49a 100644 --- a/lib/plugins/acl/admin.php +++ b/lib/plugins/acl/admin.php @@ -30,20 +30,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { var $usersgroups = array(); var $specials = array(); - /** - * return some info - */ - function getInfo(){ - return array( - 'author' => 'Andreas Gohr', - 'email' => 'andi@splitbrain.org', - 'date' => '2011-04-16', - 'name' => 'ACL Manager', - 'desc' => 'Manage Page Access Control Lists', - 'url' => 'http://dokuwiki.org/plugin:acl', - ); - } - /** * return prompt for admin menu */ diff --git a/lib/plugins/acl/plugin.info.txt b/lib/plugins/acl/plugin.info.txt new file mode 100644 index 0000000000000000000000000000000000000000..f108a239068ae11190e952aef725ff40befcce28 --- /dev/null +++ b/lib/plugins/acl/plugin.info.txt @@ -0,0 +1,6 @@ +author Andreas Gohr +email andi@splitbrain.org +date 2011-04-16 +name ACL Manager +desc Manage Page Access Control Lists +url http://dokuwiki.org/plugin:acl diff --git a/lib/plugins/config/admin.php b/lib/plugins/config/admin.php index e24f3b87b3c3d146aa900533cd4e07f2831198af..64906171d3340ceb85da8270ab02bb693a48dfb2 100644 --- a/lib/plugins/config/admin.php +++ b/lib/plugins/config/admin.php @@ -32,21 +32,6 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { var $_session_started = false; var $_localised_prompts = false; - /** - * return some info - */ - function getInfo(){ - - return array( - 'author' => 'Christopher Smith', - 'email' => 'chris@jalakai.co.uk', - 'date' => '2007-08-05', - 'name' => 'Configuration Manager', - 'desc' => "Manage Dokuwiki's Configuration Settings", - 'url' => 'http://dokuwiki.org/plugin:config', - ); - } - function getMenuSort() { return 100; } /** diff --git a/lib/plugins/config/plugin.info.txt b/lib/plugins/config/plugin.info.txt new file mode 100644 index 0000000000000000000000000000000000000000..ace4889b6c4f8a147dfa617eea5a570eed4dc087 --- /dev/null +++ b/lib/plugins/config/plugin.info.txt @@ -0,0 +1,6 @@ +author Christopher Smith +email chris@jalakai.co.uk +date 2007-08-05 +name Configuration Manager +desc Manage Dokuwiki's Configuration Settings +url http://dokuwiki.org/plugin:config diff --git a/lib/plugins/info/plugin.info.txt b/lib/plugins/info/plugin.info.txt new file mode 100644 index 0000000000000000000000000000000000000000..2432225f1f744564101bb38136f9a6961c8c0431 --- /dev/null +++ b/lib/plugins/info/plugin.info.txt @@ -0,0 +1,6 @@ +author Andreas Gohr +email andi@splitbrain.org +date 2008-09-12 +name Info Plugin +desc Displays information about various DokuWiki internals +url http://dokuwiki.org/plugin:info diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php index e188e2488d363f636289daf3273bd2756d860366..2aaf1395f6f6bbac99fbf32fbad904f61bf0e526 100644 --- a/lib/plugins/revert/admin.php +++ b/lib/plugins/revert/admin.php @@ -20,20 +20,6 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { $this->setupLocale(); } - /** - * return some info - */ - function getInfo(){ - return array( - 'author' => 'Andreas Gohr', - 'email' => 'andi@splitbrain.org', - 'date' => '2008-12-10', - 'name' => 'Revert Manager', - 'desc' => 'Allows you to mass revert recent edits', - 'url' => 'http://dokuwiki.org/plugin:revert', - ); - } - /** * access for managers */ diff --git a/lib/plugins/revert/plugin.info.txt b/lib/plugins/revert/plugin.info.txt new file mode 100644 index 0000000000000000000000000000000000000000..5bb6f34138303e9c62a980c16b69fec0e0cfb073 --- /dev/null +++ b/lib/plugins/revert/plugin.info.txt @@ -0,0 +1,6 @@ +author Andreas Gohr +email andi@splitbrain.org +date 2008-12-10 +name Revert Manager +desc Allows you to mass revert recent edits +url http://dokuwiki.org/plugin:revert diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index e40ee9b7e69a58aa6bd05c8e2d1f2b5edc64d8e2..8e90be0935e48d0c74ef2c9b79d15eed5192904f 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -51,20 +51,6 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { } } - /** - * return some info - */ - function getInfo(){ - - return array( - 'author' => 'Chris Smith', - 'email' => 'chris@jalakai.co.uk', - 'date' => '2008-09-17', - 'name' => 'User Manager', - 'desc' => 'Manage users '.$this->disabled, - 'url' => 'http://dokuwiki.org/plugin:usermanager', - ); - } /** * return prompt for admin menu */ diff --git a/lib/plugins/usermanager/plugin.info.txt b/lib/plugins/usermanager/plugin.info.txt new file mode 100644 index 0000000000000000000000000000000000000000..7ec5fafd52558c1a9dc2aeadd4f774501d0aa51d --- /dev/null +++ b/lib/plugins/usermanager/plugin.info.txt @@ -0,0 +1,6 @@ +author Chris Smith +email chris@jalakai.co.uk +date 2008-09-17 +name User Manager +desc Manage users +url http://dokuwiki.org/plugin:usermanager