diff options
Diffstat (limited to 'lib')
94 files changed, 5301 insertions, 5033 deletions
diff --git a/lib/exe/css.php b/lib/exe/css.php index 19ae5570e..40de4b828 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -6,7 +6,10 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +use dokuwiki\Cache\Cache; +use dokuwiki\Extension\Event; + +if(!defined('DOKU_INC')) define('DOKU_INC', __DIR__ .'/../../'); if(!defined('NOSESSION')) define('NOSESSION',true); // we do not use a session or authentication here (better caching) if(!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT',1); // we gzip ourself here if(!defined('NL')) define('NL',"\n"); @@ -67,7 +70,8 @@ function css_out(){ // load jQuery-UI theme if ($mediatype == 'screen') { - $files[DOKU_INC.'lib/scripts/jquery/jquery-ui-theme/smoothness.css'] = DOKU_BASE.'lib/scripts/jquery/jquery-ui-theme/'; + $files[DOKU_INC.'lib/scripts/jquery/jquery-ui-theme/smoothness.css'] = + DOKU_BASE.'lib/scripts/jquery/jquery-ui-theme/'; } // load plugin styles $files = array_merge($files, css_pluginstyles($mediatype)); @@ -84,7 +88,7 @@ function css_out(){ // Let plugins decide to either put more styles here or to remove some $media_files[$mediatype] = css_filewrapper($mediatype, $files); - $CSSEvt = new Doku_Event('CSS_STYLES_INCLUDED', $media_files[$mediatype]); + $CSSEvt = new Event('CSS_STYLES_INCLUDED', $media_files[$mediatype]); // Make it preventable. if ( $CSSEvt->advise_before() ) { @@ -99,8 +103,17 @@ function css_out(){ } // The generated script depends on some dynamic options - $cache = new cache('styles'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].$INPUT->bool('preview').DOKU_BASE.$tpl.$type,'.css'); - $cache->_event = 'CSS_CACHE_USE'; + $cache = new Cache( + 'styles' . + $_SERVER['HTTP_HOST'] . + $_SERVER['SERVER_PORT'] . + $INPUT->bool('preview') . + DOKU_BASE . + $tpl . + $type, + '.css' + ); + $cache->setEvent('CSS_CACHE_USE'); // check cache age & handle conditional request // This may exit if a cache can be used @@ -114,7 +127,7 @@ function css_out(){ // plugins decide whether to include the DW default styles. // This can be done by preventing the Default. $media_files['DW_DEFAULT'] = css_filewrapper('DW_DEFAULT'); - trigger_event('CSS_STYLES_INCLUDED', $media_files['DW_DEFAULT'], 'css_defaultstyles'); + Event::createAndTrigger('CSS_STYLES_INCLUDED', $media_files['DW_DEFAULT'], 'css_defaultstyles'); // build the stylesheet foreach ($mediatypes as $mediatype) { @@ -454,18 +467,13 @@ class DokuCssFile { */ public function replacements($match) { - // not a relative url? - no adjustment required - if (preg_match('#^(/|data:|https?://)#',$match[3])) { + if (preg_match('#^(/|data:|https?://)#', $match[3])) { // not a relative url? - no adjustment required return $match[0]; - } - // a less file import? - requires a file system location - else if (substr($match[3],-5) == '.less') { + } elseif (substr($match[3], -5) == '.less') { // a less file import? - requires a file system location if ($match[3]{0} != '/') { $match[3] = $this->getRelativePath() . '/' . $match[3]; } - } - // everything else requires a url adjustment - else { + } else { // everything else requires a url adjustment $match[3] = $this->location . $match[3]; } @@ -547,18 +555,50 @@ function css_compress($css){ $css = preg_replace('/ ?: /',':',$css); // number compression - $css = preg_replace('/([: ])0+(\.\d+?)0*((?:pt|pc|in|mm|cm|em|ex|px)\b|%)(?=[^\{]*[;\}])/', '$1$2$3', $css); // "0.1em" to ".1em", "1.10em" to "1.1em" - $css = preg_replace('/([: ])\.(0)+((?:pt|pc|in|mm|cm|em|ex|px)\b|%)(?=[^\{]*[;\}])/', '$1$2', $css); // ".0em" to "0" - $css = preg_replace('/([: ]0)0*(\.0*)?((?:pt|pc|in|mm|cm|em|ex|px)(?=[^\{]*[;\}])\b|%)/', '$1', $css); // "0.0em" to "0" - $css = preg_replace('/([: ]\d+)(\.0*)((?:pt|pc|in|mm|cm|em|ex|px)(?=[^\{]*[;\}])\b|%)/', '$1$3', $css); // "1.0em" to "1em" - $css = preg_replace('/([: ])0+(\d+|\d*\.\d+)((?:pt|pc|in|mm|cm|em|ex|px)(?=[^\{]*[;\}])\b|%)/', '$1$2$3', $css); // "001em" to "1em" + $css = preg_replace( + '/([: ])0+(\.\d+?)0*((?:pt|pc|in|mm|cm|em|ex|px)\b|%)(?=[^\{]*[;\}])/', + '$1$2$3', + $css + ); // "0.1em" to ".1em", "1.10em" to "1.1em" + $css = preg_replace( + '/([: ])\.(0)+((?:pt|pc|in|mm|cm|em|ex|px)\b|%)(?=[^\{]*[;\}])/', + '$1$2', + $css + ); // ".0em" to "0" + $css = preg_replace( + '/([: ]0)0*(\.0*)?((?:pt|pc|in|mm|cm|em|ex|px)(?=[^\{]*[;\}])\b|%)/', + '$1', + $css + ); // "0.0em" to "0" + $css = preg_replace( + '/([: ]\d+)(\.0*)((?:pt|pc|in|mm|cm|em|ex|px)(?=[^\{]*[;\}])\b|%)/', + '$1$3', + $css + ); // "1.0em" to "1em" + $css = preg_replace( + '/([: ])0+(\d+|\d*\.\d+)((?:pt|pc|in|mm|cm|em|ex|px)(?=[^\{]*[;\}])\b|%)/', + '$1$2$3', + $css + ); // "001em" to "1em" // shorten attributes (1em 1em 1em 1em -> 1em) - $css = preg_replace('/(?<![\w\-])((?:margin|padding|border|border-(?:width|radius)):)([\w\.]+)( \2)+(?=[;\}]| !)/', '$1$2', $css); // "1em 1em 1em 1em" to "1em" - $css = preg_replace('/(?<![\w\-])((?:margin|padding|border|border-(?:width)):)([\w\.]+) ([\w\.]+) \2 \3(?=[;\}]| !)/', '$1$2 $3', $css); // "1em 2em 1em 2em" to "1em 2em" + $css = preg_replace( + '/(?<![\w\-])((?:margin|padding|border|border-(?:width|radius)):)([\w\.]+)( \2)+(?=[;\}]| !)/', + '$1$2', + $css + ); // "1em 1em 1em 1em" to "1em" + $css = preg_replace( + '/(?<![\w\-])((?:margin|padding|border|border-(?:width)):)([\w\.]+) ([\w\.]+) \2 \3(?=[;\}]| !)/', + '$1$2 $3', + $css + ); // "1em 2em 1em 2em" to "1em 2em" // shorten colors - $css = preg_replace("/#([0-9a-fA-F]{1})\\1([0-9a-fA-F]{1})\\2([0-9a-fA-F]{1})\\3(?=[^\{]*[;\}])/", "#\\1\\2\\3", $css); + $css = preg_replace( + "/#([0-9a-fA-F]{1})\\1([0-9a-fA-F]{1})\\2([0-9a-fA-F]{1})\\3(?=[^\{]*[;\}])/", + "#\\1\\2\\3", + $css + ); return $css; } diff --git a/lib/exe/detail.php b/lib/exe/detail.php index ec1a9b874..a6cffa770 100644 --- a/lib/exe/detail.php +++ b/lib/exe/detail.php @@ -1,4 +1,7 @@ <?php + +use dokuwiki\Extension\Event; + if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); define('DOKU_MEDIADETAIL',1); require_once(DOKU_INC.'inc/init.php'); @@ -12,31 +15,17 @@ $REV = $INPUT->int('rev'); $INFO = array_merge(pageinfo(),mediainfo()); $tmp = array(); -trigger_event('DETAIL_STARTED', $tmp); +Event::createAndTrigger('DETAIL_STARTED', $tmp); //close session session_write_close(); -if($conf['allowdebug'] && $INPUT->has('debug')){ - print '<pre>'; - foreach(explode(' ','basedir userewrite baseurl useslash') as $x){ - print '$'."conf['$x'] = '".$conf[$x]."';\n"; - } - foreach(explode(' ','DOCUMENT_ROOT HTTP_HOST SCRIPT_FILENAME PHP_SELF '. - 'REQUEST_URI SCRIPT_NAME PATH_INFO PATH_TRANSLATED') as $x){ - print '$'."_SERVER['$x'] = '".$_SERVER[$x]."';\n"; - } - print "getID('media'): ".getID('media')."\n"; - print "getID('media',false): ".getID('media',false)."\n"; - print '</pre>'; -} - $ERROR = false; // check image permissions $AUTH = auth_quickaclcheck($IMG); if($AUTH >= AUTH_READ){ // check if image exists - $SRC = mediaFN($IMG,$REV); + $SRC = mediaFN($IMG,$REV); if(!file_exists($SRC)){ //doesn't exist! http_status(404); diff --git a/lib/exe/fetch.php b/lib/exe/fetch.php index 933367e35..5c5ae899b 100644 --- a/lib/exe/fetch.php +++ b/lib/exe/fetch.php @@ -6,6 +6,8 @@ * @author Andreas Gohr <andi@splitbrain.org> */ +use dokuwiki\Extension\Event; + if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/../../'); if (!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT', 1); require_once(DOKU_INC.'inc/init.php'); @@ -14,7 +16,7 @@ session_write_close(); //close session require_once(DOKU_INC.'inc/fetch.functions.php'); if (defined('SIMPLE_TEST')) { - $INPUT = new Input(); + $INPUT = new \dokuwiki\Input\Input(); } // BEGIN main @@ -56,7 +58,7 @@ if (defined('SIMPLE_TEST')) { ); // handle the file status - $evt = new Doku_Event('FETCH_MEDIA_STATUS', $data); + $evt = new Event('FETCH_MEDIA_STATUS', $data); if($evt->advise_before()) { // redirects if($data['status'] > 300 && $data['status'] <= 304) { @@ -87,7 +89,7 @@ if (defined('SIMPLE_TEST')) { } // finally send the file to the client - $evt = new Doku_Event('MEDIA_SENDFILE', $data); + $evt = new Event('MEDIA_SENDFILE', $data); if($evt->advise_before()) { sendFile($data['file'], $data['mime'], $data['download'], $data['cache'], $data['ispublic'], $data['orig']); } diff --git a/lib/exe/jquery.php b/lib/exe/jquery.php index f32aef7d3..13c0c1639 100644 --- a/lib/exe/jquery.php +++ b/lib/exe/jquery.php @@ -1,5 +1,7 @@ <?php +use dokuwiki\Cache\Cache; + if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__) . '/../../'); if(!defined('NOSESSION')) define('NOSESSION', true); // we do not use a session or authentication here (better caching) if(!defined('NL')) define('NL', "\n"); @@ -19,7 +21,7 @@ jquery_out(); * uses cache or fills it */ function jquery_out() { - $cache = new cache('jquery', '.js'); + $cache = new Cache('jquery', '.js'); $files = array( DOKU_INC . 'lib/scripts/jquery/jquery.min.js', DOKU_INC . 'lib/scripts/jquery/jquery-ui.min.js', diff --git a/lib/exe/js.php b/lib/exe/js.php index 81afaf053..ae6a6366f 100644 --- a/lib/exe/js.php +++ b/lib/exe/js.php @@ -6,7 +6,10 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +use dokuwiki\Cache\Cache; +use dokuwiki\Extension\Event; + +if(!defined('DOKU_INC')) define('DOKU_INC', __DIR__ .'/../../'); if(!defined('NOSESSION')) define('NOSESSION',true); // we do not use a session or authentication here (better caching) if(!defined('NL')) define('NL',"\n"); if(!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT',1); // we gzip ourself here @@ -73,11 +76,11 @@ function js_out(){ } // Let plugins decide to either put more scripts here or to remove some - trigger_event('JS_SCRIPT_LIST', $files); + Event::createAndTrigger('JS_SCRIPT_LIST', $files); // The generated script depends on some dynamic options - $cache = new cache('scripts'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].md5(serialize($files)),'.js'); - $cache->_event = 'JS_CACHE_USE'; + $cache = new Cache('scripts'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].md5(serialize($files)),'.js'); + $cache->setEvent('JS_CACHE_USE'); $cache_files = array_merge($files, getConfigFiles('main')); $cache_files[] = __FILE__; @@ -90,18 +93,21 @@ function js_out(){ // start output buffering and build the script ob_start(); - $json = new JSON(); // add some global variables print "var DOKU_BASE = '".DOKU_BASE."';"; print "var DOKU_TPL = '".tpl_basedir($tpl)."';"; - print "var DOKU_COOKIE_PARAM = " . $json->encode( + print "var DOKU_COOKIE_PARAM = " . json_encode( array( 'path' => empty($conf['cookiedir']) ? DOKU_REL : $conf['cookiedir'], 'secure' => $conf['securecookie'] && is_ssl() )).";"; // FIXME: Move those to JSINFO - print "Object.defineProperty(window, 'DOKU_UHN', { get: function() { console.warn('Using DOKU_UHN is deprecated. Please use JSINFO.useHeadingNavigation instead'); return JSINFO.useHeadingNavigation; } });"; - print "Object.defineProperty(window, 'DOKU_UHC', { get: function() { console.warn('Using DOKU_UHC is deprecated. Please use JSINFO.useHeadingContent instead'); return JSINFO.useHeadingContent; } });"; + print "Object.defineProperty(window, 'DOKU_UHN', { get: function() {". + "console.warn('Using DOKU_UHN is deprecated. Please use JSINFO.useHeadingNavigation instead');". + "return JSINFO.useHeadingNavigation; } });"; + print "Object.defineProperty(window, 'DOKU_UHC', { get: function() {". + "console.warn('Using DOKU_UHC is deprecated. Please use JSINFO.useHeadingContent instead');". + "return JSINFO.useHeadingContent; } });"; // load JS specific translations $lang['js']['plugins'] = js_pluginstrings(); @@ -109,7 +115,7 @@ function js_out(){ if(!empty($templatestrings)) { $lang['js']['template'] = $templatestrings; } - echo 'LANG = '.$json->encode($lang['js']).";\n"; + echo 'LANG = '.json_encode($lang['js']).";\n"; // load toolbar toolbar_JSdefines('toolbar'); @@ -170,7 +176,7 @@ function js_load($file){ // is it a include_once? if($match[1]){ - $base = utf8_basename($ifile); + $base = \dokuwiki\Utf8\PhpString::basename($ifile); if(array_key_exists($base, $loaded) && $loaded[$base] === true){ $data = str_replace($match[0], '' ,$data); continue; diff --git a/lib/exe/mediamanager.php b/lib/exe/mediamanager.php index 722254423..b43cff745 100644 --- a/lib/exe/mediamanager.php +++ b/lib/exe/mediamanager.php @@ -1,4 +1,7 @@ <?php + +use dokuwiki\Extension\Event; + if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); define('DOKU_MEDIAMANAGER',1); @@ -38,7 +41,7 @@ $AUTH = $INFO['perm']; // shortcut for historical reasons $tmp = array(); - trigger_event('MEDIAMANAGER_STARTED', $tmp); + Event::createAndTrigger('MEDIAMANAGER_STARTED', $tmp); session_write_close(); //close session // do not display the manager if user does not have read access diff --git a/lib/exe/xmlrpc.php b/lib/exe/xmlrpc.php index 3046f47e9..dc0438ee1 100644 --- a/lib/exe/xmlrpc.php +++ b/lib/exe/xmlrpc.php @@ -1,67 +1,15 @@ <?php -if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); - -require_once(DOKU_INC.'inc/init.php'); -session_write_close(); //close session - -if(!$conf['remote']) die((new IXR_Error(-32605, "XML-RPC server not enabled."))->getXml()); - /** - * Contains needed wrapper functions and registers all available - * XMLRPC functions. + * XMLRPC API backend */ -class dokuwiki_xmlrpc_server extends IXR_Server { - protected $remote; - - /** - * Constructor. Register methods and run Server - */ - public function __construct(){ - $this->remote = new RemoteAPI(); - $this->remote->setDateTransformation(array($this, 'toDate')); - $this->remote->setFileTransformation(array($this, 'toFile')); - parent::__construct(); - } - /** - * @param string $methodname - * @param array $args - * @return IXR_Error|mixed - */ - public function call($methodname, $args){ - try { - $result = $this->remote->call($methodname, $args); - return $result; - } catch (RemoteAccessDeniedException $e) { - if (!isset($_SERVER['REMOTE_USER'])) { - http_status(401); - return new IXR_Error(-32603, "server error. not authorized to call method $methodname"); - } else { - http_status(403); - return new IXR_Error(-32604, "server error. forbidden to call the method $methodname"); - } - } catch (RemoteException $e) { - return new IXR_Error($e->getCode(), $e->getMessage()); - } - } +use dokuwiki\Remote\XmlRpcServer; - /** - * @param string|int $data iso date(yyyy[-]mm[-]dd[ hh:mm[:ss]]) or timestamp - * @return IXR_Date - */ - public function toDate($data) { - return new IXR_Date($data); - } +if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/../../'); - /** - * @param string $data - * @return IXR_Base64 - */ - public function toFile($data) { - return new IXR_Base64($data); - } -} +require_once(DOKU_INC.'inc/init.php'); +session_write_close(); //close session -$server = new dokuwiki_xmlrpc_server(); +if(!$conf['remote']) die((new IXR_Error(-32605, "XML-RPC server not enabled."))->getXml()); -// vim:ts=4:sw=4:et: +$server = new XmlRpcServer(); diff --git a/lib/plugins/acl/action.php b/lib/plugins/acl/action.php index 1d6d05b80..86e587093 100644 --- a/lib/plugins/acl/action.php +++ b/lib/plugins/acl/action.php @@ -6,13 +6,11 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - /** * Register handler */ -class action_plugin_acl extends DokuWiki_Action_Plugin { +class action_plugin_acl extends DokuWiki_Action_Plugin +{ /** * Registers a callback function for a given event @@ -20,10 +18,10 @@ class action_plugin_acl extends DokuWiki_Action_Plugin { * @param Doku_Event_Handler $controller DokuWiki's event controller object * @return void */ - public function register(Doku_Event_Handler $controller) { - - $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_acl'); + public function register(Doku_Event_Handler $controller) + { + $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxCallAcl'); } /** @@ -33,9 +31,9 @@ class action_plugin_acl extends DokuWiki_Action_Plugin { * @param mixed $param empty * @return void */ - - public function handle_ajax_call_acl(Doku_Event $event, $param) { - if($event->data !== 'plugin_acl') { + public function handleAjaxCallAcl(Doku_Event $event, $param) + { + if ($event->data !== 'plugin_acl') { return; } $event->stopPropagation(); @@ -46,12 +44,11 @@ class action_plugin_acl extends DokuWiki_Action_Plugin { /** @var $acl admin_plugin_acl */ $acl = plugin_load('admin', 'acl'); - - if(!$acl->isAccessibleByCurrentUser()) { + if (!$acl->isAccessibleByCurrentUser()) { echo 'for admins only'; return; } - if(!checkSecurityToken()) { + if (!checkSecurityToken()) { echo 'CRSF Attack'; return; } @@ -62,26 +59,27 @@ class action_plugin_acl extends DokuWiki_Action_Plugin { $ajax = $INPUT->str('ajax'); header('Content-Type: text/html; charset=utf-8'); - if($ajax == 'info') { - $acl->_html_info(); - } elseif($ajax == 'tree') { - + if ($ajax == 'info') { + $acl->printInfo(); + } elseif ($ajax == 'tree') { $ns = $INPUT->str('ns'); - if($ns == '*') { + if ($ns == '*') { $ns = ''; } $ns = cleanID($ns); $lvl = count(explode(':', $ns)); $ns = utf8_encodeFN(str_replace(':', '/', $ns)); - $data = $acl->_get_tree($ns, $ns); + $data = $acl->makeTree($ns, $ns); - foreach(array_keys($data) as $item) { + foreach (array_keys($data) as $item) { $data[$item]['level'] = $lvl + 1; } echo html_buildlist( - $data, 'acl', array($acl, '_html_list_acl'), - array($acl, '_html_li_acl') + $data, + 'acl', + array($acl, 'makeTreeItem'), + array($acl, 'makeListItem') ); } } diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php index 4ee0fde7e..b0b0ffc85 100644 --- a/lib/plugins/acl/admin.php +++ b/lib/plugins/acl/admin.php @@ -7,16 +7,15 @@ * @author Anika Henke <anika@selfthinker.org> (concepts) * @author Frank Schubert <frank@schokilade.de> (old version) */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); /** * All DokuWiki plugins to extend the admin function * need to inherit from this class */ -class admin_plugin_acl extends DokuWiki_Admin_Plugin { - var $acl = null; - var $ns = null; +class admin_plugin_acl extends DokuWiki_Admin_Plugin +{ + public $acl = null; + protected $ns = null; /** * The currently selected item, associative array with id and type. * Populated from (in this order): @@ -25,22 +24,24 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * $ns * $ID */ - var $current_item = null; - var $who = ''; - var $usersgroups = array(); - var $specials = array(); + protected $current_item = null; + protected $who = ''; + protected $usersgroups = array(); + protected $specials = array(); /** * return prompt for admin menu */ - function getMenuText($language) { + public function getMenuText($language) + { return $this->getLang('admin_acl'); } /** * return sort order for position in admin menu */ - function getMenuSort() { + public function getMenuSort() + { return 1; } @@ -51,7 +52,8 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function handle() { + public function handle() + { global $AUTH_ACL; global $ID; global $auth; @@ -62,9 +64,9 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { $AUTH_ACL = file($config_cascade['acl']['default']); // namespace given? - if($INPUT->str('ns') == '*'){ + if ($INPUT->str('ns') == '*') { $this->ns = '*'; - }else{ + } else { $this->ns = cleanID($INPUT->str('ns')); } @@ -80,78 +82,78 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { // user or group choosen? $who = trim($INPUT->str('acl_w')); - if($INPUT->str('acl_t') == '__g__' && $who){ - $this->who = '@'.ltrim($auth->cleanGroup($who),'@'); - }elseif($INPUT->str('acl_t') == '__u__' && $who){ - $this->who = ltrim($who,'@'); - if($this->who != '%USER%' && $this->who != '%GROUP%'){ #keep wildcard as is + if ($INPUT->str('acl_t') == '__g__' && $who) { + $this->who = '@'.ltrim($auth->cleanGroup($who), '@'); + } elseif ($INPUT->str('acl_t') == '__u__' && $who) { + $this->who = ltrim($who, '@'); + if ($this->who != '%USER%' && $this->who != '%GROUP%') { #keep wildcard as is $this->who = $auth->cleanUser($this->who); } - }elseif($INPUT->str('acl_t') && + } elseif ($INPUT->str('acl_t') && $INPUT->str('acl_t') != '__u__' && - $INPUT->str('acl_t') != '__g__'){ + $INPUT->str('acl_t') != '__g__') { $this->who = $INPUT->str('acl_t'); - }elseif($who){ + } elseif ($who) { $this->who = $who; } // handle modifications - if($INPUT->has('cmd') && checkSecurityToken()){ + if ($INPUT->has('cmd') && checkSecurityToken()) { $cmd = $INPUT->extract('cmd')->str('cmd'); // scope for modifications - if($this->ns){ - if($this->ns == '*'){ + if ($this->ns) { + if ($this->ns == '*') { $scope = '*'; - }else{ + } else { $scope = $this->ns.':*'; } - }else{ + } else { $scope = $ID; } - if($cmd == 'save' && $scope && $this->who && $INPUT->has('acl')){ + if ($cmd == 'save' && $scope && $this->who && $INPUT->has('acl')) { // handle additions or single modifications - $this->_acl_del($scope, $this->who); - $this->_acl_add($scope, $this->who, $INPUT->int('acl')); - }elseif($cmd == 'del' && $scope && $this->who){ + $this->deleteACL($scope, $this->who); + $this->addACL($scope, $this->who, $INPUT->int('acl')); + } elseif ($cmd == 'del' && $scope && $this->who) { // handle single deletions - $this->_acl_del($scope, $this->who); - }elseif($cmd == 'update'){ + $this->deleteACL($scope, $this->who); + } elseif ($cmd == 'update') { $acl = $INPUT->arr('acl'); // handle update of the whole file - foreach($INPUT->arr('del') as $where => $names){ + foreach ($INPUT->arr('del') as $where => $names) { // remove all rules marked for deletion - foreach($names as $who) + foreach ($names as $who) unset($acl[$where][$who]); } // prepare lines $lines = array(); // keep header - foreach($AUTH_ACL as $line){ - if($line{0} == '#'){ + foreach ($AUTH_ACL as $line) { + if ($line{0} == '#') { $lines[] = $line; - }else{ + } else { break; } } // re-add all rules - foreach($acl as $where => $opt){ - foreach($opt as $who => $perm){ + foreach ($acl as $where => $opt) { + foreach ($opt as $who => $perm) { if ($who[0]=='@') { if ($who!='@ALL') { - $who = '@'.ltrim($auth->cleanGroup($who),'@'); + $who = '@'.ltrim($auth->cleanGroup($who), '@'); } - } elseif ($who != '%USER%' && $who != '%GROUP%'){ #keep wildcard as is + } elseif ($who != '%USER%' && $who != '%GROUP%') { #keep wildcard as is $who = $auth->cleanUser($who); } - $who = auth_nameencode($who,true); + $who = auth_nameencode($who, true); $lines[] = "$where\t$who\t$perm\n"; } } // save it - io_saveFile($config_cascade['acl']['default'], join('',$lines)); + io_saveFile($config_cascade['acl']['default'], join('', $lines)); } // reload ACL config @@ -159,7 +161,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { } // initialize ACL array - $this->_init_acl_config(); + $this->initAclConfig(); } /** @@ -171,24 +173,25 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * @author Frank Schubert <frank@schokilade.de> * @author Andreas Gohr <andi@splitbrain.org> */ - function html() { + public function html() + { echo '<div id="acl_manager">'.NL; echo '<h1>'.$this->getLang('admin_acl').'</h1>'.NL; echo '<div class="level1">'.NL; echo '<div id="acl__tree">'.NL; - $this->_html_explorer(); + $this->makeExplorer(); echo '</div>'.NL; echo '<div id="acl__detail">'.NL; - $this->_html_detail(); + $this->printDetail(); echo '</div>'.NL; echo '</div>'.NL; echo '<div class="clearer"></div>'; echo '<h2>'.$this->getLang('current').'</h2>'.NL; echo '<div class="level2">'.NL; - $this->_html_table(); + $this->printAclTable(); echo '</div>'.NL; echo '<div class="footnotes"><div class="fn">'.NL; @@ -204,15 +207,16 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _get_opts($addopts=null){ + protected function getLinkOptions($addopts = null) + { $opts = array( 'do'=>'admin', 'page'=>'acl', ); - if($this->ns) $opts['ns'] = $this->ns; - if($this->who) $opts['acl_w'] = $this->who; + if ($this->ns) $opts['ns'] = $this->ns; + if ($this->who) $opts['acl_w'] = $this->who; - if(is_null($addopts)) return $opts; + if (is_null($addopts)) return $opts; return array_merge($opts, $addopts); } @@ -221,54 +225,61 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_explorer(){ + protected function makeExplorer() + { global $conf; global $ID; global $lang; $ns = $this->ns; - if(empty($ns)){ - $ns = dirname(str_replace(':','/',$ID)); - if($ns == '.') $ns =''; - }elseif($ns == '*'){ + if (empty($ns)) { + $ns = dirname(str_replace(':', '/', $ID)); + if ($ns == '.') $ns =''; + } elseif ($ns == '*') { $ns =''; } - $ns = utf8_encodeFN(str_replace(':','/',$ns)); + $ns = utf8_encodeFN(str_replace(':', '/', $ns)); - $data = $this->_get_tree($ns); + $data = $this->makeTree($ns); // wrap a list with the root level around the other namespaces array_unshift($data, array( 'level' => 0, 'id' => '*', 'type' => 'd', 'open' =>'true', 'label' => '['.$lang['mediaroot'].']')); - echo html_buildlist($data,'acl', - array($this,'_html_list_acl'), - array($this,'_html_li_acl')); - + echo html_buildlist( + $data, + 'acl', + array($this, 'makeTreeItem'), + array($this, 'makeListItem') + ); } /** * get a combined list of media and page files * + * also called via AJAX + * * @param string $folder an already converted filesystem folder of the current namespace - * @param string $limit limit the search to this folder + * @param string $limit limit the search to this folder + * @return array */ - function _get_tree($folder,$limit=''){ + public function makeTree($folder, $limit = '') + { global $conf; // read tree structure from pages and media $data = array(); - search($data,$conf['datadir'],'search_index',array('ns' => $folder),$limit); + search($data, $conf['datadir'], 'search_index', array('ns' => $folder), $limit); $media = array(); - search($media,$conf['mediadir'],'search_index',array('ns' => $folder, 'nofiles' => true),$limit); - $data = array_merge($data,$media); + search($media, $conf['mediadir'], 'search_index', array('ns' => $folder, 'nofiles' => true), $limit); + $data = array_merge($data, $media); unset($media); // combine by sorting and removing duplicates - usort($data,array($this,'_tree_sort')); + usort($data, array($this, 'treeSort')); $count = count($data); - if($count>0) for($i=1; $i<$count; $i++){ - if($data[$i-1]['id'] == $data[$i]['id'] && $data[$i-1]['type'] == $data[$i]['type']) { + if ($count>0) for ($i=1; $i<$count; $i++) { + if ($data[$i-1]['id'] == $data[$i]['id'] && $data[$i-1]['type'] == $data[$i]['type']) { unset($data[$i]); $i++; // duplicate found, next $i can't be a duplicate, so skip forward one } @@ -281,7 +292,8 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * Sorts the combined trees of media and page files */ - function _tree_sort($a,$b){ + public function treeSort($a, $b) + { // handle the trivial cases first if ($a['id'] == '') return -1; if ($b['id'] == '') return 1; @@ -315,6 +327,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { // before that other part. if (empty($a_ids)) return ($a['type'] == 'd') ? -1 : 1; if (empty($b_ids)) return ($b['type'] == 'd') ? 1 : -1; + return 0; //shouldn't happen } /** @@ -323,20 +336,21 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_detail(){ + protected function printDetail() + { global $ID; echo '<form action="'.wl().'" method="post" accept-charset="utf-8"><div class="no">'.NL; echo '<div id="acl__user">'; echo $this->getLang('acl_perms').' '; - $inl = $this->_html_select(); - echo '<input type="text" name="acl_w" class="edit" value="'.(($inl)?'':hsc(ltrim($this->who,'@'))).'" />'.NL; + $inl = $this->makeSelect(); + echo '<input type="text" name="acl_w" class="edit" value="'.(($inl)?'':hsc(ltrim($this->who, '@'))).'" />'.NL; echo '<button type="submit">'.$this->getLang('btn_select').'</button>'.NL; echo '</div>'.NL; echo '<div id="acl__info">'; - $this->_html_info(); + $this->printInfo(); echo '</div>'; echo '<input type="hidden" name="ns" value="'.hsc($this->ns).'" />'.NL; @@ -349,23 +363,26 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { /** * Print info and editor + * + * also loaded via Ajax */ - function _html_info(){ + public function printInfo() + { global $ID; - if($this->who){ - $current = $this->_get_exact_perm(); + if ($this->who) { + $current = $this->getExactPermisson(); // explain current permissions - $this->_html_explain($current); + $this->printExplanation($current); // load editor - $this->_html_acleditor($current); - }else{ + $this->printAclEditor($current); + } else { echo '<p>'; - if($this->ns){ - printf($this->getLang('p_choose_ns'),hsc($this->ns)); - }else{ - printf($this->getLang('p_choose_id'),hsc($ID)); + if ($this->ns) { + printf($this->getLang('p_choose_ns'), hsc($this->ns)); + } else { + printf($this->getLang('p_choose_id'), hsc($ID)); } echo '</p>'; @@ -378,21 +395,22 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_acleditor($current){ + protected function printAclEditor($current) + { global $lang; echo '<fieldset>'; - if(is_null($current)){ + if (is_null($current)) { echo '<legend>'.$this->getLang('acl_new').'</legend>'; - }else{ + } else { echo '<legend>'.$this->getLang('acl_mod').'</legend>'; } - echo $this->_html_checkboxes($current,empty($this->ns),'acl'); + echo $this->makeCheckboxes($current, empty($this->ns), 'acl'); - if(is_null($current)){ + if (is_null($current)) { echo '<button type="submit" name="cmd[save]">'.$lang['btn_save'].'</button>'.NL; - }else{ + } else { echo '<button type="submit" name="cmd[save]">'.$lang['btn_update'].'</button>'.NL; echo '<button type="submit" name="cmd[del]">'.$lang['btn_delete'].'</button>'.NL; } @@ -405,7 +423,8 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_explain($current){ + protected function printExplanation($current) + { global $ID; global $auth; @@ -413,69 +432,69 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { $ns = $this->ns; // prepare where to check - if($ns){ - if($ns == '*'){ + if ($ns) { + if ($ns == '*') { $check='*'; - }else{ + } else { $check=$ns.':*'; } - }else{ + } else { $check = $ID; } // prepare who to check - if($who{0} == '@'){ + if ($who{0} == '@') { $user = ''; - $groups = array(ltrim($who,'@')); - }else{ + $groups = array(ltrim($who, '@')); + } else { $user = $who; $info = $auth->getUserData($user); - if($info === false){ + if ($info === false) { $groups = array(); - }else{ + } else { $groups = $info['grps']; } } // check the permissions - $perm = auth_aclcheck($check,$user,$groups); + $perm = auth_aclcheck($check, $user, $groups); // build array of named permissions $names = array(); - if($perm){ - if($ns){ - if($perm >= AUTH_DELETE) $names[] = $this->getLang('acl_perm16'); - if($perm >= AUTH_UPLOAD) $names[] = $this->getLang('acl_perm8'); - if($perm >= AUTH_CREATE) $names[] = $this->getLang('acl_perm4'); + if ($perm) { + if ($ns) { + if ($perm >= AUTH_DELETE) $names[] = $this->getLang('acl_perm16'); + if ($perm >= AUTH_UPLOAD) $names[] = $this->getLang('acl_perm8'); + if ($perm >= AUTH_CREATE) $names[] = $this->getLang('acl_perm4'); } - if($perm >= AUTH_EDIT) $names[] = $this->getLang('acl_perm2'); - if($perm >= AUTH_READ) $names[] = $this->getLang('acl_perm1'); + if ($perm >= AUTH_EDIT) $names[] = $this->getLang('acl_perm2'); + if ($perm >= AUTH_READ) $names[] = $this->getLang('acl_perm1'); $names = array_reverse($names); - }else{ + } else { $names[] = $this->getLang('acl_perm0'); } // print permission explanation echo '<p>'; - if($user){ - if($ns){ - printf($this->getLang('p_user_ns'),hsc($who),hsc($ns),join(', ',$names)); - }else{ - printf($this->getLang('p_user_id'),hsc($who),hsc($ID),join(', ',$names)); + if ($user) { + if ($ns) { + printf($this->getLang('p_user_ns'), hsc($who), hsc($ns), join(', ', $names)); + } else { + printf($this->getLang('p_user_id'), hsc($who), hsc($ID), join(', ', $names)); } - }else{ - if($ns){ - printf($this->getLang('p_group_ns'),hsc(ltrim($who,'@')),hsc($ns),join(', ',$names)); - }else{ - printf($this->getLang('p_group_id'),hsc(ltrim($who,'@')),hsc($ID),join(', ',$names)); + } else { + if ($ns) { + printf($this->getLang('p_group_ns'), hsc(ltrim($who, '@')), hsc($ns), join(', ', $names)); + } else { + printf($this->getLang('p_group_id'), hsc(ltrim($who, '@')), hsc($ID), join(', ', $names)); } } echo '</p>'; // add note if admin - if($perm == AUTH_ADMIN){ + if ($perm == AUTH_ADMIN) { echo '<p>'.$this->getLang('p_isadmin').'</p>'; - }elseif(is_null($current)){ + } elseif (is_null($current)) { echo '<p>'.$this->getLang('p_inherited').'</p>'; } } @@ -488,46 +507,57 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_list_acl($item){ + protected function makeTreeItem($item) + { $ret = ''; // what to display - if(!empty($item['label'])){ + if (!empty($item['label'])) { $base = $item['label']; - }else{ + } else { $base = ':'.$item['id']; - $base = substr($base,strrpos($base,':')+1); + $base = substr($base, strrpos($base, ':')+1); } // highlight? - if( ($item['type']== $this->current_item['type'] && $item['id'] == $this->current_item['id'])) { + if (($item['type']== $this->current_item['type'] && $item['id'] == $this->current_item['id'])) { $cl = ' cur'; } else { $cl = ''; } // namespace or page? - if($item['type']=='d'){ - if($item['open']){ + if ($item['type']=='d') { + if ($item['open']) { $img = DOKU_BASE.'lib/images/minus.gif'; $alt = '−'; - }else{ + } else { $img = DOKU_BASE.'lib/images/plus.gif'; $alt = '+'; } $ret .= '<img src="'.$img.'" alt="'.$alt.'" />'; - $ret .= '<a href="'.wl('',$this->_get_opts(array('ns'=>$item['id'],'sectok'=>getSecurityToken()))).'" class="idx_dir'.$cl.'">'; + $ret .= '<a href="'. + wl('', $this->getLinkOptions(array('ns'=> $item['id'], 'sectok'=>getSecurityToken()))). + '" class="idx_dir'.$cl.'">'; $ret .= $base; $ret .= '</a>'; - }else{ - $ret .= '<a href="'.wl('',$this->_get_opts(array('id'=>$item['id'],'ns'=>'','sectok'=>getSecurityToken()))).'" class="wikilink1'.$cl.'">'; + } else { + $ret .= '<a href="'. + wl('', $this->getLinkOptions(array('id'=> $item['id'], 'ns'=>'', 'sectok'=>getSecurityToken()))). + '" class="wikilink1'.$cl.'">'; $ret .= noNS($item['id']); $ret .= '</a>'; } return $ret; } - - function _html_li_acl($item){ + /** + * List Item formatter + * + * @param array $item + * @return string + */ + public function makeListItem($item) + { return '<li class="level' . $item['level'] . ' ' . ($item['open'] ? 'open' : 'closed') . '">'; } @@ -538,7 +568,8 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _init_acl_config(){ + public function initAclConfig() + { global $AUTH_ACL; global $conf; $acl_config=array(); @@ -547,20 +578,24 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { // get special users and groups $this->specials[] = '@ALL'; $this->specials[] = '@'.$conf['defaultgroup']; - if($conf['manager'] != '!!not set!!'){ - $this->specials = array_merge($this->specials, - array_map('trim', - explode(',',$conf['manager']))); + if ($conf['manager'] != '!!not set!!') { + $this->specials = array_merge( + $this->specials, + array_map( + 'trim', + explode(',', $conf['manager']) + ) + ); } $this->specials = array_filter($this->specials); $this->specials = array_unique($this->specials); sort($this->specials); - foreach($AUTH_ACL as $line){ - $line = trim(preg_replace('/#.*$/','',$line)); //ignore comments - if(!$line) continue; + foreach ($AUTH_ACL as $line) { + $line = trim(preg_replace('/#.*$/', '', $line)); //ignore comments + if (!$line) continue; - $acl = preg_split('/[ \t]+/',$line); + $acl = preg_split('/[ \t]+/', $line); //0 is pagename, 1 is user, 2 is acl $acl[1] = rawurldecode($acl[1]); @@ -568,7 +603,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { // store non-special users and groups for later selection dialog $ug = $acl[1]; - if(in_array($ug,$this->specials)) continue; + if (in_array($ug, $this->specials)) continue; $usersgroups[] = $ug; } @@ -585,14 +620,15 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_table(){ + protected function printAclTable() + { global $lang; global $ID; echo '<form action="'.wl().'" method="post" accept-charset="utf-8"><div class="no">'.NL; - if($this->ns){ + if ($this->ns) { echo '<input type="hidden" name="ns" value="'.hsc($this->ns).'" />'.NL; - }else{ + } else { echo '<input type="hidden" name="id" value="'.hsc($ID).'" />'.NL; } echo '<input type="hidden" name="acl_w" value="'.hsc($this->who).'" />'.NL; @@ -607,29 +643,29 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { echo '<th>'.$this->getLang('perm').'<sup><a id="fnt__1" class="fn_top" href="#fn__1">1)</a></sup></th>'; echo '<th>'.$lang['btn_delete'].'</th>'; echo '</tr>'; - foreach($this->acl as $where => $set){ - foreach($set as $who => $perm){ + foreach ($this->acl as $where => $set) { + foreach ($set as $who => $perm) { echo '<tr>'; echo '<td>'; - if(substr($where,-1) == '*'){ + if (substr($where, -1) == '*') { echo '<span class="aclns">'.hsc($where).'</span>'; $ispage = false; - }else{ + } else { echo '<span class="aclpage">'.hsc($where).'</span>'; $ispage = true; } echo '</td>'; echo '<td>'; - if($who{0} == '@'){ + if ($who{0} == '@') { echo '<span class="aclgroup">'.hsc($who).'</span>'; - }else{ + } else { echo '<span class="acluser">'.hsc($who).'</span>'; } echo '</td>'; echo '<td>'; - echo $this->_html_checkboxes($perm,$ispage,'acl['.$where.']['.$who.']'); + echo $this->makeCheckboxes($perm, $ispage, 'acl['.$where.']['.$who.']'); echo '</td>'; echo '<td class="check">'; @@ -655,21 +691,22 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _get_exact_perm(){ + protected function getExactPermisson() + { global $ID; - if($this->ns){ - if($this->ns == '*'){ + if ($this->ns) { + if ($this->ns == '*') { $check = '*'; - }else{ + } else { $check = $this->ns.':*'; } - }else{ + } else { $check = $ID; } - if(isset($this->acl[$check][$this->who])){ + if (isset($this->acl[$check][$this->who])) { return $this->acl[$check][$this->who]; - }else{ + } else { return null; } } @@ -679,13 +716,14 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Frank Schubert <frank@schokilade.de> */ - function _acl_add($acl_scope, $acl_user, $acl_level){ + public function addACL($acl_scope, $acl_user, $acl_level) + { global $config_cascade; - $acl_user = auth_nameencode($acl_user,true); + $acl_user = auth_nameencode($acl_user, true); // max level for pagenames is edit - if(strpos($acl_scope,'*') === false) { - if($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT; + if (strpos($acl_scope, '*') === false) { + if ($acl_level > AUTH_EDIT) $acl_level = AUTH_EDIT; } $new_acl = "$acl_scope\t$acl_user\t$acl_level\n"; @@ -698,11 +736,12 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Frank Schubert <frank@schokilade.de> */ - function _acl_del($acl_scope, $acl_user){ + public function deleteACL($acl_scope, $acl_user) + { global $config_cascade; - $acl_user = auth_nameencode($acl_user,true); + $acl_user = auth_nameencode($acl_user, true); - $acl_pattern = '^'.preg_quote($acl_scope,'/').'[ \t]+'.$acl_user.'[ \t]+[0-8].*$'; + $acl_pattern = '^'.preg_quote($acl_scope, '/').'[ \t]+'.$acl_user.'[ \t]+[0-8].*$'; return io_deleteFromFile($config_cascade['acl']['default'], "/$acl_pattern/", true); } @@ -713,15 +752,16 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * @author Frank Schubert <frank@schokilade.de> * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_checkboxes($setperm,$ispage,$name){ + protected function makeCheckboxes($setperm, $ispage, $name) + { global $lang; static $label = 0; //number labels $ret = ''; - if($ispage && $setperm > AUTH_EDIT) $setperm = AUTH_EDIT; + if ($ispage && $setperm > AUTH_EDIT) $setperm = AUTH_EDIT; - foreach(array(AUTH_NONE,AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm){ + foreach (array(AUTH_NONE,AUTH_READ,AUTH_EDIT,AUTH_CREATE,AUTH_UPLOAD,AUTH_DELETE) as $perm) { $label += 1; //general checkbox attributes @@ -730,11 +770,11 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { 'name' => $name, 'value' => $perm ); //dynamic attributes - if(!is_null($setperm) && $setperm == $perm) $atts['checked'] = 'checked'; - if($ispage && $perm > AUTH_EDIT){ + if (!is_null($setperm) && $setperm == $perm) $atts['checked'] = 'checked'; + if ($ispage && $perm > AUTH_EDIT) { $atts['disabled'] = 'disabled'; $class = ' class="disabled"'; - }else{ + } else { $class = ''; } @@ -752,21 +792,21 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - function _html_select(){ + protected function makeSelect() + { $inlist = false; $usel = ''; $gsel = ''; - if($this->who && - !in_array($this->who,$this->usersgroups) && - !in_array($this->who,$this->specials)){ - - if($this->who{0} == '@'){ + if ($this->who && + !in_array($this->who, $this->usersgroups) && + !in_array($this->who, $this->specials)) { + if ($this->who{0} == '@') { $gsel = ' selected="selected"'; - }else{ + } else { $usel = ' selected="selected"'; } - }else{ + } else { $inlist = true; } @@ -775,17 +815,17 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { echo ' <option value="__u__" class="acluser"'.$usel.'>'.$this->getLang('acl_user').'</option>'.NL; if (!empty($this->specials)) { echo ' <optgroup label=" ">'.NL; - foreach($this->specials as $ug){ - if($ug == $this->who){ + foreach ($this->specials as $ug) { + if ($ug == $this->who) { $sel = ' selected="selected"'; $inlist = true; - }else{ + } else { $sel = ''; } - if($ug{0} == '@'){ + if ($ug{0} == '@') { echo ' <option value="'.hsc($ug).'" class="aclgroup"'.$sel.'>'.hsc($ug).'</option>'.NL; - }else{ + } else { echo ' <option value="'.hsc($ug).'" class="acluser"'.$sel.'>'.hsc($ug).'</option>'.NL; } } @@ -793,17 +833,17 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { } if (!empty($this->usersgroups)) { echo ' <optgroup label=" ">'.NL; - foreach($this->usersgroups as $ug){ - if($ug == $this->who){ + foreach ($this->usersgroups as $ug) { + if ($ug == $this->who) { $sel = ' selected="selected"'; $inlist = true; - }else{ + } else { $sel = ''; } - if($ug{0} == '@'){ + if ($ug{0} == '@') { echo ' <option value="'.hsc($ug).'" class="aclgroup"'.$sel.'>'.hsc($ug).'</option>'.NL; - }else{ + } else { echo ' <option value="'.hsc($ug).'" class="acluser"'.$sel.'>'.hsc($ug).'</option>'.NL; } } diff --git a/lib/plugins/acl/remote.php b/lib/plugins/acl/remote.php index 27c5c162a..31a8cde53 100644 --- a/lib/plugins/acl/remote.php +++ b/lib/plugins/acl/remote.php @@ -1,16 +1,20 @@ <?php +use dokuwiki\Remote\AccessDeniedException; + /** * Class remote_plugin_acl */ -class remote_plugin_acl extends DokuWiki_Remote_Plugin { +class remote_plugin_acl extends DokuWiki_Remote_Plugin +{ /** * Returns details about the remote plugin methods * - * @return array Information about all provided methods. {@see RemoteAPI} + * @return array Information about all provided methods. {@see dokuwiki\Remote\RemoteAPI} */ - public function _getMethods() { + public function _getMethods() + { return array( 'listAcls' => array( 'args' => array(), @@ -34,16 +38,20 @@ class remote_plugin_acl extends DokuWiki_Remote_Plugin { /** * List all ACL config entries * - * @throws RemoteAccessDeniedException + * @throws AccessDeniedException * @return dictionary {Scope: ACL}, where ACL = dictionnary {user/group: permissions_int} */ - public function listAcls(){ - if(!auth_isadmin()) { - throw new RemoteAccessDeniedException('You are not allowed to access ACLs, superuser permission is required', 114); + public function listAcls() + { + if (!auth_isadmin()) { + throw new AccessDeniedException( + 'You are not allowed to access ACLs, superuser permission is required', + 114 + ); } /** @var admin_plugin_acl $apa */ $apa = plugin_load('admin', 'acl'); - $apa->_init_acl_config(); + $apa->initAclConfig(); return $apa->acl; } @@ -53,17 +61,21 @@ class remote_plugin_acl extends DokuWiki_Remote_Plugin { * @param string $scope * @param string $user * @param int $level see also inc/auth.php - * @throws RemoteAccessDeniedException + * @throws AccessDeniedException * @return bool */ - public function addAcl($scope, $user, $level){ - if(!auth_isadmin()) { - throw new RemoteAccessDeniedException('You are not allowed to access ACLs, superuser permission is required', 114); + public function addAcl($scope, $user, $level) + { + if (!auth_isadmin()) { + throw new AccessDeniedException( + 'You are not allowed to access ACLs, superuser permission is required', + 114 + ); } /** @var admin_plugin_acl $apa */ $apa = plugin_load('admin', 'acl'); - return $apa->_acl_add($scope, $user, $level); + return $apa->addACL($scope, $user, $level); } /** @@ -71,17 +83,20 @@ class remote_plugin_acl extends DokuWiki_Remote_Plugin { * * @param string $scope * @param string $user - * @throws RemoteAccessDeniedException + * @throws AccessDeniedException * @return bool */ - public function delAcl($scope, $user){ - if(!auth_isadmin()) { - throw new RemoteAccessDeniedException('You are not allowed to access ACLs, superuser permission is required', 114); + public function delAcl($scope, $user) + { + if (!auth_isadmin()) { + throw new AccessDeniedException( + 'You are not allowed to access ACLs, superuser permission is required', + 114 + ); } /** @var admin_plugin_acl $apa */ $apa = plugin_load('admin', 'acl'); - return $apa->_acl_del($scope, $user); + return $apa->deleteACL($scope, $user); } } - diff --git a/lib/plugins/action.php b/lib/plugins/action.php index 23d94a509..a3cbec722 100644 --- a/lib/plugins/action.php +++ b/lib/plugins/action.php @@ -1,25 +1,2 @@ <?php -/** - * Action Plugin Prototype - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Christopher Smith <chris@jalakai.co.uk> - */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -/** - * All DokuWiki plugins to interfere with the event system - * need to inherit from this class - */ -class DokuWiki_Action_Plugin extends DokuWiki_Plugin { - - /** - * Registers a callback function for a given event - * - * @param Doku_Event_Handler $controller - */ - public function register(Doku_Event_Handler $controller) { - trigger_error('register() not implemented in '.get_class($this), E_USER_WARNING); - } -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/admin.php b/lib/plugins/admin.php index 9554ce511..a3cbec722 100644 --- a/lib/plugins/admin.php +++ b/lib/plugins/admin.php @@ -1,119 +1,2 @@ <?php -/** - * Admin Plugin Prototype - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Christopher Smith <chris@jalakai.co.uk> - */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -/** - * All DokuWiki plugins to extend the admin function - * need to inherit from this class - */ -class DokuWiki_Admin_Plugin extends DokuWiki_Plugin { - - /** - * Return the text that is displayed at the main admin menu - * (Default localized language string 'menu' is returned, override this function for setting another name) - * - * @param string $language language code - * @return string menu string - */ - public function getMenuText($language) { - $menutext = $this->getLang('menu'); - if (!$menutext) { - $info = $this->getInfo(); - $menutext = $info['name'].' ...'; - } - return $menutext; - } - - /** - * Return the path to the icon being displayed in the main admin menu. - * By default it tries to find an 'admin.svg' file in the plugin directory. - * (Override this function for setting another image) - * - * Important: you have to return a single path, monochrome SVG icon! It has to be - * under 2 Kilobytes! - * - * We recommend icons from https://materialdesignicons.com/ or to use a matching - * style. - * - * @return string full path to the icon file - */ - public function getMenuIcon() { - $plugin = $this->getPluginName(); - return DOKU_PLUGIN . $plugin . '/admin.svg'; - } - - /** - * Determine position in list in admin window - * Lower values are sorted up - * - * @return int - */ - public function getMenuSort() { - return 1000; - } - - /** - * Carry out required processing - */ - public function handle() { - trigger_error('handle() not implemented in '.get_class($this), E_USER_WARNING); - } - - /** - * Output html of the admin page - */ - public function html() { - trigger_error('html() not implemented in '.get_class($this), E_USER_WARNING); - } - - /** - * Checks if access should be granted to this admin plugin - * - * @return bool true if the current user may access this admin plugin - */ - public function isAccessibleByCurrentUser() { - $data = []; - $data['instance'] = $this; - $data['hasAccess'] = false; - - $event = new Doku_Event('ADMINPLUGIN_ACCESS_CHECK', $data); - if($event->advise_before()) { - if ($this->forAdminOnly()) { - $data['hasAccess'] = auth_isadmin(); - } else { - $data['hasAccess'] = auth_ismanager(); - } - } - $event->advise_after(); - - return $data['hasAccess']; - } - - /** - * Return true for access only by admins (config:superuser) or false if managers are allowed as well - * - * @return bool - */ - public function forAdminOnly() { - return true; - } - - /** - * Return array with ToC items. Items can be created with the html_mktocitem() - * - * @see html_mktocitem() - * @see tpl_toc() - * - * @return array - */ - public function getTOC(){ - return array(); - } -} -//Setup VIM: ex: et ts=4 : +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/auth.php b/lib/plugins/auth.php index 0cd965b72..a3cbec722 100644 --- a/lib/plugins/auth.php +++ b/lib/plugins/auth.php @@ -1,438 +1,2 @@ <?php -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -/** - * Auth Plugin Prototype - * - * foundation authorisation class - * all auth classes should inherit from this class - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Chris Smith <chris@jalakai.co.uk> - * @author Jan Schumann <js@jschumann-it.com> - */ -class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { - public $success = true; - - /** - * Possible things an auth backend module may be able to - * do. The things a backend can do need to be set to true - * in the constructor. - */ - protected $cando = array( - 'addUser' => false, // can Users be created? - 'delUser' => false, // can Users be deleted? - 'modLogin' => false, // can login names be changed? - 'modPass' => false, // can passwords be changed? - 'modName' => false, // can real names be changed? - 'modMail' => false, // can emails be changed? - 'modGroups' => false, // can groups be changed? - 'getUsers' => false, // can a (filtered) list of users be retrieved? - 'getUserCount' => false, // can the number of users be retrieved? - 'getGroups' => false, // can a list of available groups be retrieved? - 'external' => false, // does the module do external auth checking? - 'logout' => true, // can the user logout again? (eg. not possible with HTTP auth) - ); - - /** - * Constructor. - * - * Carry out sanity checks to ensure the object is - * able to operate. Set capabilities in $this->cando - * array here - * - * For future compatibility, sub classes should always include a call - * to parent::__constructor() in their constructors! - * - * Set $this->success to false if checks fail - * - * @author Christopher Smith <chris@jalakai.co.uk> - */ - public function __construct() { - // the base class constructor does nothing, derived class - // constructors do the real work - } - - /** - * Available Capabilities. [ DO NOT OVERRIDE ] - * - * For introspection/debugging - * - * @author Christopher Smith <chris@jalakai.co.uk> - * @return array - */ - public function getCapabilities(){ - return array_keys($this->cando); - } - - /** - * Capability check. [ DO NOT OVERRIDE ] - * - * Checks the capabilities set in the $this->cando array and - * some pseudo capabilities (shortcutting access to multiple - * ones) - * - * ususal capabilities start with lowercase letter - * shortcut capabilities start with uppercase letter - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $cap the capability to check - * @return bool - */ - public function canDo($cap) { - switch($cap) { - case 'Profile': - // can at least one of the user's properties be changed? - return ($this->cando['modPass'] || - $this->cando['modName'] || - $this->cando['modMail']); - break; - case 'UserMod': - // can at least anything be changed? - return ($this->cando['modPass'] || - $this->cando['modName'] || - $this->cando['modMail'] || - $this->cando['modLogin'] || - $this->cando['modGroups'] || - $this->cando['modMail']); - break; - default: - // print a helping message for developers - if(!isset($this->cando[$cap])) { - msg("Check for unknown capability '$cap' - Do you use an outdated Plugin?", -1); - } - return $this->cando[$cap]; - } - } - - /** - * Trigger the AUTH_USERDATA_CHANGE event and call the modification function. [ DO NOT OVERRIDE ] - * - * You should use this function instead of calling createUser, modifyUser or - * deleteUsers directly. The event handlers can prevent the modification, for - * example for enforcing a user name schema. - * - * @author Gabriel Birke <birke@d-scribe.de> - * @param string $type Modification type ('create', 'modify', 'delete') - * @param array $params Parameters for the createUser, modifyUser or deleteUsers method. The content of this array depends on the modification type - * @return bool|null|int Result from the modification function or false if an event handler has canceled the action - */ - public function triggerUserMod($type, $params) { - $validTypes = array( - 'create' => 'createUser', - 'modify' => 'modifyUser', - 'delete' => 'deleteUsers' - ); - if(empty($validTypes[$type])) { - return false; - } - - $result = false; - $eventdata = array('type' => $type, 'params' => $params, 'modification_result' => null); - $evt = new Doku_Event('AUTH_USER_CHANGE', $eventdata); - if($evt->advise_before(true)) { - $result = call_user_func_array(array($this, $validTypes[$type]), $evt->data['params']); - $evt->data['modification_result'] = $result; - } - $evt->advise_after(); - unset($evt); - return $result; - } - - /** - * Log off the current user [ OPTIONAL ] - * - * Is run in addition to the ususal logoff method. Should - * only be needed when trustExternal is implemented. - * - * @see auth_logoff() - * @author Andreas Gohr <andi@splitbrain.org> - */ - public function logOff() { - } - - /** - * Do all authentication [ OPTIONAL ] - * - * Set $this->cando['external'] = true when implemented - * - * If this function is implemented it will be used to - * authenticate a user - all other DokuWiki internals - * will not be used for authenticating, thus - * implementing the checkPass() function is not needed - * anymore. - * - * The function can be used to authenticate against third - * party cookies or Apache auth mechanisms and replaces - * the auth_login() function - * - * The function will be called with or without a set - * username. If the Username is given it was called - * from the login form and the given credentials might - * need to be checked. If no username was given it - * the function needs to check if the user is logged in - * by other means (cookie, environment). - * - * The function needs to set some globals needed by - * DokuWiki like auth_login() does. - * - * @see auth_login() - * @author Andreas Gohr <andi@splitbrain.org> - * - * @param string $user Username - * @param string $pass Cleartext Password - * @param bool $sticky Cookie should not expire - * @return bool true on successful auth - */ - public function trustExternal($user, $pass, $sticky = false) { - /* some example: - - global $USERINFO; - global $conf; - $sticky ? $sticky = true : $sticky = false; //sanity check - - // do the checking here - - // set the globals if authed - $USERINFO['name'] = 'FIXME'; - $USERINFO['mail'] = 'FIXME'; - $USERINFO['grps'] = array('FIXME'); - $_SERVER['REMOTE_USER'] = $user; - $_SESSION[DOKU_COOKIE]['auth']['user'] = $user; - $_SESSION[DOKU_COOKIE]['auth']['pass'] = $pass; - $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; - return true; - - */ - } - - /** - * Check user+password [ MUST BE OVERRIDDEN ] - * - * Checks if the given user exists and the given - * plaintext password is correct - * - * May be ommited if trustExternal is used. - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user the user name - * @param string $pass the clear text password - * @return bool - */ - public function checkPass($user, $pass) { - msg("no valid authorisation system in use", -1); - return false; - } - - /** - * Return user info [ MUST BE OVERRIDDEN ] - * - * Returns info about the given user needs to contain - * at least these fields: - * - * name string full name of the user - * mail string email address of the user - * grps array list of groups the user is in - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user the user name - * @param bool $requireGroups whether or not the returned data must include groups - * @return false|array containing user data or false - */ - public function getUserData($user, $requireGroups=true) { - if(!$this->cando['external']) msg("no valid authorisation system in use", -1); - return false; - } - - /** - * Create a new User [implement only where required/possible] - * - * Returns false if the user already exists, null when an error - * occurred and true if everything went well. - * - * The new user HAS TO be added to the default group by this - * function! - * - * Set addUser capability when implemented - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user - * @param string $pass - * @param string $name - * @param string $mail - * @param null|array $grps - * @return bool|null - */ - public function createUser($user, $pass, $name, $mail, $grps = null) { - msg("authorisation method does not allow creation of new users", -1); - return null; - } - - /** - * Modify user data [implement only where required/possible] - * - * Set the mod* capabilities according to the implemented features - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param string $user nick of the user to be changed - * @param array $changes array of field/value pairs to be changed (password will be clear text) - * @return bool - */ - public function modifyUser($user, $changes) { - msg("authorisation method does not allow modifying of user data", -1); - return false; - } - - /** - * Delete one or more users [implement only where required/possible] - * - * Set delUser capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param array $users - * @return int number of users deleted - */ - public function deleteUsers($users) { - msg("authorisation method does not allow deleting of users", -1); - return 0; - } - - /** - * Return a count of the number of user which meet $filter criteria - * [should be implemented whenever retrieveUsers is implemented] - * - * Set getUserCount capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param array $filter array of field/pattern pairs, empty array for no filter - * @return int - */ - public function getUserCount($filter = array()) { - msg("authorisation method does not provide user counts", -1); - return 0; - } - - /** - * Bulk retrieval of user data [implement only where required/possible] - * - * Set getUsers capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param int $start index of first user to be returned - * @param int $limit max number of users to be returned, 0 for unlimited - * @param array $filter array of field/pattern pairs, null for no filter - * @return array list of userinfo (refer getUserData for internal userinfo details) - */ - public function retrieveUsers($start = 0, $limit = 0, $filter = null) { - msg("authorisation method does not support mass retrieval of user data", -1); - return array(); - } - - /** - * Define a group [implement only where required/possible] - * - * Set addGroup capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param string $group - * @return bool - */ - public function addGroup($group) { - msg("authorisation method does not support independent group creation", -1); - return false; - } - - /** - * Retrieve groups [implement only where required/possible] - * - * Set getGroups capability when implemented - * - * @author Chris Smith <chris@jalakai.co.uk> - * @param int $start - * @param int $limit - * @return array - */ - public function retrieveGroups($start = 0, $limit = 0) { - msg("authorisation method does not support group list retrieval", -1); - return array(); - } - - /** - * Return case sensitivity of the backend [OPTIONAL] - * - * When your backend is caseinsensitive (eg. you can login with USER and - * user) then you need to overwrite this method and return false - * - * @return bool - */ - public function isCaseSensitive() { - return true; - } - - /** - * Sanitize a given username [OPTIONAL] - * - * This function is applied to any user name that is given to - * the backend and should also be applied to any user name within - * the backend before returning it somewhere. - * - * This should be used to enforce username restrictions. - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $user username - * @return string the cleaned username - */ - public function cleanUser($user) { - return $user; - } - - /** - * Sanitize a given groupname [OPTIONAL] - * - * This function is applied to any groupname that is given to - * the backend and should also be applied to any groupname within - * the backend before returning it somewhere. - * - * This should be used to enforce groupname restrictions. - * - * Groupnames are to be passed without a leading '@' here. - * - * @author Andreas Gohr <andi@splitbrain.org> - * @param string $group groupname - * @return string the cleaned groupname - */ - public function cleanGroup($group) { - return $group; - } - - /** - * Check Session Cache validity [implement only where required/possible] - * - * DokuWiki caches user info in the user's session for the timespan defined - * in $conf['auth_security_timeout']. - * - * This makes sure slow authentication backends do not slow down DokuWiki. - * This also means that changes to the user database will not be reflected - * on currently logged in users. - * - * To accommodate for this, the user manager plugin will touch a reference - * file whenever a change is submitted. This function compares the filetime - * of this reference file with the time stored in the session. - * - * This reference file mechanism does not reflect changes done directly in - * the backend's database through other means than the user manager plugin. - * - * Fast backends might want to return always false, to force rechecks on - * each page load. Others might want to use their own checking here. If - * unsure, do not override. - * - * @param string $user - The username - * @author Andreas Gohr <andi@splitbrain.org> - * @return bool - */ - public function useSessionCache($user) { - global $conf; - return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= @filemtime($conf['cachedir'].'/sessionpurge')); - } -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/authad/action.php b/lib/plugins/authad/action.php index bc0f90c7e..a9fc01c1b 100644 --- a/lib/plugins/authad/action.php +++ b/lib/plugins/authad/action.php @@ -6,22 +6,20 @@ * @author Andreas Gohr <gohr@cosmocode.de> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - /** * Class action_plugin_addomain */ -class action_plugin_authad extends DokuWiki_Action_Plugin { +class action_plugin_authad extends DokuWiki_Action_Plugin +{ /** * Registers a callback function for a given event */ - public function register(Doku_Event_Handler $controller) { - - $controller->register_hook('AUTH_LOGIN_CHECK', 'BEFORE', $this, 'handle_auth_login_check'); - $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handle_html_loginform_output'); + public function register(Doku_Event_Handler $controller) + { + $controller->register_hook('AUTH_LOGIN_CHECK', 'BEFORE', $this, 'handleAuthLoginCheck'); + $controller->register_hook('HTML_LOGINFORM_OUTPUT', 'BEFORE', $this, 'handleHtmlLoginformOutput'); } /** @@ -30,17 +28,18 @@ class action_plugin_authad extends DokuWiki_Action_Plugin { * @param Doku_Event $event * @param array $param */ - public function handle_auth_login_check(Doku_Event &$event, $param) { + public function handleAuthLoginCheck(Doku_Event $event, $param) + { global $INPUT; /** @var auth_plugin_authad $auth */ global $auth; - if(!is_a($auth, 'auth_plugin_authad')) return; // AD not even used + if (!is_a($auth, 'auth_plugin_authad')) return; // AD not even used - if($INPUT->str('dom')) { + if ($INPUT->str('dom')) { $usr = $auth->cleanUser($event->data['user']); - $dom = $auth->_userDomain($usr); - if(!$dom) { + $dom = $auth->getUserDomain($usr); + if (!$dom) { $usr = "$usr@".$INPUT->str('dom'); } $INPUT->post->set('u', $usr); @@ -54,26 +53,27 @@ class action_plugin_authad extends DokuWiki_Action_Plugin { * @param Doku_Event $event * @param array $param */ - public function handle_html_loginform_output(Doku_Event &$event, $param) { + public function handleHtmlLoginformOutput(Doku_Event $event, $param) + { global $INPUT; /** @var auth_plugin_authad $auth */ global $auth; - if(!is_a($auth, 'auth_plugin_authad')) return; // AD not even used - $domains = $auth->_getConfiguredDomains(); - if(count($domains) <= 1) return; // no choice at all + if (!is_a($auth, 'auth_plugin_authad')) return; // AD not even used + $domains = $auth->getConfiguredDomains(); + if (count($domains) <= 1) return; // no choice at all /** @var Doku_Form $form */ $form =& $event->data; // any default? $dom = ''; - if($INPUT->has('u')) { + if ($INPUT->has('u')) { $usr = $auth->cleanUser($INPUT->str('u')); - $dom = $auth->_userDomain($usr); + $dom = $auth->getUserDomain($usr); // update user field value - if($dom) { - $usr = $auth->_userName($usr); + if ($dom) { + $usr = $auth->getUserName($usr); $pos = $form->findElementByAttribute('name', 'u'); $ele =& $form->getElementAt($pos); $ele['value'] = $usr; @@ -85,7 +85,6 @@ class action_plugin_authad extends DokuWiki_Action_Plugin { $pos = $form->findElementByAttribute('name', 'p'); $form->insertElement($pos + 1, $element); } - } -// vim:ts=4:sw=4:et:
\ No newline at end of file +// vim:ts=4:sw=4:et: diff --git a/lib/plugins/authad/auth.php b/lib/plugins/authad/auth.php index 50f708456..684a6ed69 100644 --- a/lib/plugins/authad/auth.php +++ b/lib/plugins/authad/auth.php @@ -1,9 +1,4 @@ <?php -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -require_once(DOKU_PLUGIN.'authad/adLDAP/adLDAP.php'); -require_once(DOKU_PLUGIN.'authad/adLDAP/classes/adLDAPUtils.php'); /** * Active Directory authentication backend for DokuWiki @@ -41,7 +36,8 @@ require_once(DOKU_PLUGIN.'authad/adLDAP/classes/adLDAPUtils.php'); * @author Andreas Gohr <andi@splitbrain.org> * @author Jan Schumann <js@schumann-it.com> */ -class auth_plugin_authad extends DokuWiki_Auth_Plugin { +class auth_plugin_authad extends DokuWiki_Auth_Plugin +{ /** * @var array hold connection data for a specific AD domain @@ -66,52 +62,55 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { /** * @var array filter patterns for listing users */ - protected $_pattern = array(); + protected $pattern = array(); - protected $_actualstart = 0; + protected $actualstart = 0; - protected $_grpsusers = array(); + protected $grpsusers = array(); /** * Constructor */ - public function __construct() { + public function __construct() + { global $INPUT; parent::__construct(); + require_once(DOKU_PLUGIN.'authad/adLDAP/adLDAP.php'); + require_once(DOKU_PLUGIN.'authad/adLDAP/classes/adLDAPUtils.php'); + // we load the config early to modify it a bit here $this->loadConfig(); // additional information fields - if(isset($this->conf['additional'])) { + if (isset($this->conf['additional'])) { $this->conf['additional'] = str_replace(' ', '', $this->conf['additional']); $this->conf['additional'] = explode(',', $this->conf['additional']); } else $this->conf['additional'] = array(); // ldap extension is needed - if(!function_exists('ldap_connect')) { - if($this->conf['debug']) + if (!function_exists('ldap_connect')) { + if ($this->conf['debug']) msg("AD Auth: PHP LDAP extension not found.", -1); $this->success = false; return; } // Prepare SSO - if(!empty($_SERVER['REMOTE_USER'])) { - + if (!empty($_SERVER['REMOTE_USER'])) { // make sure the right encoding is used - if($this->getConf('sso_charset')) { + if ($this->getConf('sso_charset')) { $_SERVER['REMOTE_USER'] = iconv($this->getConf('sso_charset'), 'UTF-8', $_SERVER['REMOTE_USER']); - } elseif(!utf8_check($_SERVER['REMOTE_USER'])) { + } elseif (!\dokuwiki\Utf8\Clean::isUtf8($_SERVER['REMOTE_USER'])) { $_SERVER['REMOTE_USER'] = utf8_encode($_SERVER['REMOTE_USER']); } // trust the incoming user - if($this->conf['sso']) { + if ($this->conf['sso']) { $_SERVER['REMOTE_USER'] = $this->cleanUser($_SERVER['REMOTE_USER']); // we need to simulate a login - if(empty($_COOKIE[DOKU_COOKIE])) { + if (empty($_COOKIE[DOKU_COOKIE])) { $INPUT->set('u', $_SERVER['REMOTE_USER']); $INPUT->set('p', 'sso_only'); } @@ -130,10 +129,11 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string $cap * @return bool */ - public function canDo($cap) { + public function canDo($cap) + { //capabilities depend on config, which may change depending on domain - $domain = $this->_userDomain($_SERVER['REMOTE_USER']); - $this->_loadServerConfig($domain); + $domain = $this->getUserDomain($_SERVER['REMOTE_USER']); + $this->loadServerConfig($domain); return parent::canDo($cap); } @@ -149,16 +149,22 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string $pass * @return bool */ - public function checkPass($user, $pass) { - if($_SERVER['REMOTE_USER'] && + public function checkPass($user, $pass) + { + if ($_SERVER['REMOTE_USER'] && $_SERVER['REMOTE_USER'] == $user && $this->conf['sso'] ) return true; - $adldap = $this->_adldap($this->_userDomain($user)); - if(!$adldap) return false; + $adldap = $this->initAdLdap($this->getUserDomain($user)); + if (!$adldap) return false; - return $adldap->authenticate($this->_userName($user), $pass); + try { + return $adldap->authenticate($this->getUserName($user), $pass); + } catch (adLDAPException $e) { + // shouldn't really happen + return false; + } } /** @@ -186,14 +192,15 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param bool $requireGroups (optional) - ignored, groups are always supplied by this plugin * @return array */ - public function getUserData($user, $requireGroups=true) { + public function getUserData($user, $requireGroups = true) + { global $conf; global $lang; global $ID; - $adldap = $this->_adldap($this->_userDomain($user)); - if(!$adldap) return false; + $adldap = $this->initAdLdap($this->getUserDomain($user)); + if (!$adldap) return array(); - if($user == '') return array(); + if ($user == '') return array(); $fields = array('mail', 'displayname', 'samaccountname', 'lastpwd', 'pwdlastset', 'useraccountcontrol'); @@ -203,8 +210,8 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { $fields = array_filter($fields); //get info for given user - $result = $adldap->user()->info($this->_userName($user), $fields); - if($result == false){ + $result = $adldap->user()->info($this->getUserName($user), $fields); + if ($result == false) { return array(); } @@ -220,52 +227,56 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { $info['expires'] = !($result[0]['useraccountcontrol'][0] & 0x10000); //ADS_UF_DONT_EXPIRE_PASSWD // additional information - foreach($this->conf['additional'] as $field) { - if(isset($result[0][strtolower($field)])) { + foreach ($this->conf['additional'] as $field) { + if (isset($result[0][strtolower($field)])) { $info[$field] = $result[0][strtolower($field)][0]; } } // handle ActiveDirectory memberOf - $info['grps'] = $adldap->user()->groups($this->_userName($user),(bool) $this->opts['recursive_groups']); + $info['grps'] = $adldap->user()->groups($this->getUserName($user), (bool) $this->opts['recursive_groups']); - if(is_array($info['grps'])) { - foreach($info['grps'] as $ndx => $group) { + if (is_array($info['grps'])) { + foreach ($info['grps'] as $ndx => $group) { $info['grps'][$ndx] = $this->cleanGroup($group); } } // always add the default group to the list of groups - if(!is_array($info['grps']) || !in_array($conf['defaultgroup'], $info['grps'])) { + if (!is_array($info['grps']) || !in_array($conf['defaultgroup'], $info['grps'])) { $info['grps'][] = $conf['defaultgroup']; } // add the user's domain to the groups - $domain = $this->_userDomain($user); - if($domain && !in_array("domain-$domain", (array) $info['grps'])) { + $domain = $this->getUserDomain($user); + if ($domain && !in_array("domain-$domain", (array) $info['grps'])) { $info['grps'][] = $this->cleanGroup("domain-$domain"); } // check expiry time - if($info['expires'] && $this->conf['expirywarn']){ - $expiry = $adldap->user()->passwordExpiry($user); - if(is_array($expiry)){ - $info['expiresat'] = $expiry['expiryts']; - $info['expiresin'] = round(($info['expiresat'] - time())/(24*60*60)); - - // if this is the current user, warn him (once per request only) - if(($_SERVER['REMOTE_USER'] == $user) && - ($info['expiresin'] <= $this->conf['expirywarn']) && - !$this->msgshown - ) { - $msg = sprintf($this->getLang('authpwdexpire'), $info['expiresin']); - if($this->canDo('modPass')) { - $url = wl($ID, array('do'=> 'profile')); - $msg .= ' <a href="'.$url.'">'.$lang['btn_profile'].'</a>'; + if ($info['expires'] && $this->conf['expirywarn']) { + try { + $expiry = $adldap->user()->passwordExpiry($user); + if (is_array($expiry)) { + $info['expiresat'] = $expiry['expiryts']; + $info['expiresin'] = round(($info['expiresat'] - time())/(24*60*60)); + + // if this is the current user, warn him (once per request only) + if (($_SERVER['REMOTE_USER'] == $user) && + ($info['expiresin'] <= $this->conf['expirywarn']) && + !$this->msgshown + ) { + $msg = sprintf($this->getLang('authpwdexpire'), $info['expiresin']); + if ($this->canDo('modPass')) { + $url = wl($ID, array('do'=> 'profile')); + $msg .= ' <a href="'.$url.'">'.$lang['btn_profile'].'</a>'; + } + msg($msg); + $this->msgshown = true; } - msg($msg); - $this->msgshown = true; } + } catch (adLDAPException $e) { + // ignore. should usually not happen } } @@ -281,11 +292,12 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string $group * @return string */ - public function cleanGroup($group) { + public function cleanGroup($group) + { $group = str_replace('\\', '', $group); $group = str_replace('#', '', $group); $group = preg_replace('[\s]', '_', $group); - $group = utf8_strtolower(trim($group)); + $group = \dokuwiki\Utf8\PhpString::strtolower(trim($group)); return $group; } @@ -298,27 +310,28 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string $user * @return string */ - public function cleanUser($user) { + public function cleanUser($user) + { $domain = ''; // get NTLM or Kerberos domain part list($dom, $user) = explode('\\', $user, 2); - if(!$user) $user = $dom; - if($dom) $domain = $dom; + if (!$user) $user = $dom; + if ($dom) $domain = $dom; list($user, $dom) = explode('@', $user, 2); - if($dom) $domain = $dom; + if ($dom) $domain = $dom; // clean up both - $domain = utf8_strtolower(trim($domain)); - $user = utf8_strtolower(trim($user)); + $domain = \dokuwiki\Utf8\PhpString::strtolower(trim($domain)); + $user = \dokuwiki\Utf8\PhpString::strtolower(trim($user)); // is this a known, valid domain? if not discard - if(!is_array($this->conf[$domain])) { + if (!is_array($this->conf[$domain])) { $domain = ''; } // reattach domain - if($domain) $user = "$user@$domain"; + if ($domain) $user = "$user@$domain"; return $user; } @@ -327,7 +340,8 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * * @return bool */ - public function isCaseSensitive() { + public function isCaseSensitive() + { return false; } @@ -337,11 +351,12 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param array $filter * @return string */ - protected function _constructSearchString($filter){ - if (!$filter){ + protected function constructSearchString($filter) + { + if (!$filter) { return '*'; } - $adldapUtils = new adLDAPUtils($this->_adldap(null)); + $adldapUtils = new adLDAPUtils($this->initAdLdap(null)); $result = '*'; if (isset($filter['name'])) { $result .= ')(displayname=*' . $adldapUtils->ldapSlashes($filter['name']) . '*'; @@ -366,32 +381,41 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param array $filter $filter array of field/pattern pairs, empty array for no filter * @return int number of users */ - public function getUserCount($filter = array()) { - $adldap = $this->_adldap(null); - if(!$adldap) { + public function getUserCount($filter = array()) + { + $adldap = $this->initAdLdap(null); + if (!$adldap) { dbglog("authad/auth.php getUserCount(): _adldap not set."); return -1; } if ($filter == array()) { $result = $adldap->user()->all(); } else { - $searchString = $this->_constructSearchString($filter); + $searchString = $this->constructSearchString($filter); $result = $adldap->user()->all(false, $searchString); if (isset($filter['grps'])) { $this->users = array_fill_keys($result, false); + /** @var admin_plugin_usermanager $usermanager */ $usermanager = plugin_load("admin", "usermanager", false); $usermanager->setLastdisabled(true); - if (!isset($this->_grpsusers[$this->_filterToString($filter)])){ - $this->_fillGroupUserArray($filter,$usermanager->getStart() + 3*$usermanager->getPagesize()); - } elseif (count($this->_grpsusers[$this->_filterToString($filter)]) < $usermanager->getStart() + 3*$usermanager->getPagesize()) { - $this->_fillGroupUserArray($filter,$usermanager->getStart() + 3*$usermanager->getPagesize() - count($this->_grpsusers[$this->_filterToString($filter)])); + if (!isset($this->grpsusers[$this->filterToString($filter)])) { + $this->fillGroupUserArray($filter, $usermanager->getStart() + 3*$usermanager->getPagesize()); + } elseif (count($this->grpsusers[$this->filterToString($filter)]) < + $usermanager->getStart() + 3*$usermanager->getPagesize() + ) { + $this->fillGroupUserArray( + $filter, + $usermanager->getStart() + + 3*$usermanager->getPagesize() - + count($this->grpsusers[$this->filterToString($filter)]) + ); } - $result = $this->_grpsusers[$this->_filterToString($filter)]; + $result = $this->grpsusers[$this->filterToString($filter)]; } else { + /** @var admin_plugin_usermanager $usermanager */ $usermanager = plugin_load("admin", "usermanager", false); $usermanager->setLastdisabled(false); } - } if (!$result) { @@ -407,7 +431,8 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param array $filter * @return string */ - protected function _filterToString ($filter) { + protected function filterToString($filter) + { $result = ''; if (isset($filter['user'])) { $result .= 'user-' . $filter['user']; @@ -433,24 +458,25 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param int $numberOfAdds additional number of users requested * @return int number of Users actually add to Array */ - protected function _fillGroupUserArray($filter, $numberOfAdds){ - $this->_grpsusers[$this->_filterToString($filter)]; + protected function fillGroupUserArray($filter, $numberOfAdds) + { + $this->grpsusers[$this->filterToString($filter)]; $i = 0; $count = 0; - $this->_constructPattern($filter); + $this->constructPattern($filter); foreach ($this->users as $user => &$info) { - if($i++ < $this->_actualstart) { + if ($i++ < $this->actualstart) { continue; } - if($info === false) { + if ($info === false) { $info = $this->getUserData($user); } - if($this->_filter($user, $info)) { - $this->_grpsusers[$this->_filterToString($filter)][$user] = $info; - if(($numberOfAdds > 0) && (++$count >= $numberOfAdds)) break; + if ($this->filter($user, $info)) { + $this->grpsusers[$this->filterToString($filter)][$user] = $info; + if (($numberOfAdds > 0) && (++$count >= $numberOfAdds)) break; } } - $this->_actualstart = $i; + $this->actualstart = $i; return $count; } @@ -464,13 +490,14 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param array $filter array of field/pattern pairs, null for no filter * @return array userinfo (refer getUserData for internal userinfo details) */ - public function retrieveUsers($start = 0, $limit = 0, $filter = array()) { - $adldap = $this->_adldap(null); - if(!$adldap) return false; + public function retrieveUsers($start = 0, $limit = 0, $filter = array()) + { + $adldap = $this->initAdLdap(null); + if (!$adldap) return array(); - if(!$this->users) { + if (!$this->users) { //get info for given user - $result = $adldap->user()->all(false, $this->_constructSearchString($filter)); + $result = $adldap->user()->all(false, $this->constructSearchString($filter)); if (!$result) return array(); $this->users = array_fill_keys($result, false); } @@ -480,34 +507,40 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { $result = array(); if (!isset($filter['grps'])) { + /** @var admin_plugin_usermanager $usermanager */ $usermanager = plugin_load("admin", "usermanager", false); $usermanager->setLastdisabled(false); - $this->_constructPattern($filter); - foreach($this->users as $user => &$info) { - if($i++ < $start) { + $this->constructPattern($filter); + foreach ($this->users as $user => &$info) { + if ($i++ < $start) { continue; } - if($info === false) { + if ($info === false) { $info = $this->getUserData($user); } $result[$user] = $info; - if(($limit > 0) && (++$count >= $limit)) break; + if (($limit > 0) && (++$count >= $limit)) break; } } else { + /** @var admin_plugin_usermanager $usermanager */ $usermanager = plugin_load("admin", "usermanager", false); $usermanager->setLastdisabled(true); - if (!isset($this->_grpsusers[$this->_filterToString($filter)]) || count($this->_grpsusers[$this->_filterToString($filter)]) < ($start+$limit)) { - $this->_fillGroupUserArray($filter,$start+$limit - count($this->_grpsusers[$this->_filterToString($filter)]) +1); + if (!isset($this->grpsusers[$this->filterToString($filter)]) || + count($this->grpsusers[$this->filterToString($filter)]) < ($start+$limit) + ) { + $this->fillGroupUserArray( + $filter, + $start+$limit - count($this->grpsusers[$this->filterToString($filter)]) +1 + ); } - if (!$this->_grpsusers[$this->_filterToString($filter)]) return false; - foreach($this->_grpsusers[$this->_filterToString($filter)] as $user => &$info) { - if($i++ < $start) { + if (!$this->grpsusers[$this->filterToString($filter)]) return array(); + foreach ($this->grpsusers[$this->filterToString($filter)] as $user => &$info) { + if ($i++ < $start) { continue; } $result[$user] = $info; - if(($limit > 0) && (++$count >= $limit)) break; + if (($limit > 0) && (++$count >= $limit)) break; } - } return $result; } @@ -519,45 +552,46 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param array $changes array of field/value pairs to be changed * @return bool */ - public function modifyUser($user, $changes) { + public function modifyUser($user, $changes) + { $return = true; - $adldap = $this->_adldap($this->_userDomain($user)); - if(!$adldap) { + $adldap = $this->initAdLdap($this->getUserDomain($user)); + if (!$adldap) { msg($this->getLang('connectfail'), -1); return false; } // password changing - if(isset($changes['pass'])) { + if (isset($changes['pass'])) { try { - $return = $adldap->user()->password($this->_userName($user),$changes['pass']); + $return = $adldap->user()->password($this->getUserName($user), $changes['pass']); } catch (adLDAPException $e) { if ($this->conf['debug']) msg('AD Auth: '.$e->getMessage(), -1); $return = false; } - if(!$return) msg($this->getLang('passchangefail'), -1); + if (!$return) msg($this->getLang('passchangefail'), -1); } // changing user data $adchanges = array(); - if(isset($changes['name'])) { + if (isset($changes['name'])) { // get first and last name $parts = explode(' ', $changes['name']); $adchanges['surname'] = array_pop($parts); $adchanges['firstname'] = join(' ', $parts); $adchanges['display_name'] = $changes['name']; } - if(isset($changes['mail'])) { + if (isset($changes['mail'])) { $adchanges['email'] = $changes['mail']; } - if(count($adchanges)) { + if (count($adchanges)) { try { - $return = $return & $adldap->user()->modify($this->_userName($user),$adchanges); + $return = $return & $adldap->user()->modify($this->getUserName($user), $adchanges); } catch (adLDAPException $e) { if ($this->conf['debug']) msg('AD Auth: '.$e->getMessage(), -1); $return = false; } - if(!$return) msg($this->getLang('userchangefail'), -1); + if (!$return) msg($this->getLang('userchangefail'), -1); } return $return; @@ -573,20 +607,21 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string|null $domain The AD domain to use * @return adLDAP|bool true if a connection was established */ - protected function _adldap($domain) { - if(is_null($domain) && is_array($this->opts)) { + protected function initAdLdap($domain) + { + if (is_null($domain) && is_array($this->opts)) { $domain = $this->opts['domain']; } - $this->opts = $this->_loadServerConfig((string) $domain); - if(isset($this->adldap[$domain])) return $this->adldap[$domain]; + $this->opts = $this->loadServerConfig((string) $domain); + if (isset($this->adldap[$domain])) return $this->adldap[$domain]; // connect try { $this->adldap[$domain] = new adLDAP($this->opts); return $this->adldap[$domain]; - } catch(adLDAPException $e) { - if($this->conf['debug']) { + } catch (Exception $e) { + if ($this->conf['debug']) { msg('AD Auth: '.$e->getMessage(), -1); } $this->success = false; @@ -601,7 +636,8 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string $user * @return string */ - public function _userDomain($user) { + public function getUserDomain($user) + { list(, $domain) = explode('@', $user, 2); return $domain; } @@ -612,7 +648,8 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string $user * @return string */ - public function _userName($user) { + public function getUserName($user) + { list($name) = explode('@', $user, 2); return $name; } @@ -623,14 +660,15 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param string $domain current AD domain * @return array */ - protected function _loadServerConfig($domain) { + protected function loadServerConfig($domain) + { // prepare adLDAP standard configuration $opts = $this->conf; $opts['domain'] = $domain; // add possible domain specific configuration - if($domain && is_array($this->conf[$domain])) foreach($this->conf[$domain] as $key => $val) { + if ($domain && is_array($this->conf[$domain])) foreach ($this->conf[$domain] as $key => $val) { $opts[$key] = $val; } @@ -640,23 +678,27 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { $opts['domain_controllers'] = array_filter($opts['domain_controllers']); // compatibility with old option name - if(empty($opts['admin_username']) && !empty($opts['ad_username'])) $opts['admin_username'] = $opts['ad_username']; - if(empty($opts['admin_password']) && !empty($opts['ad_password'])) $opts['admin_password'] = $opts['ad_password']; + if (empty($opts['admin_username']) && !empty($opts['ad_username'])) { + $opts['admin_username'] = $opts['ad_username']; + } + if (empty($opts['admin_password']) && !empty($opts['ad_password'])) { + $opts['admin_password'] = $opts['ad_password']; + } $opts['admin_password'] = conf_decodeString($opts['admin_password']); // deobfuscate // we can change the password if SSL is set - if($opts['use_ssl'] || $opts['use_tls']) { + if ($opts['use_ssl'] || $opts['use_tls']) { $this->cando['modPass'] = true; } else { $this->cando['modPass'] = false; } // adLDAP expects empty user/pass as NULL, we're less strict FS#2781 - if(empty($opts['admin_username'])) $opts['admin_username'] = null; - if(empty($opts['admin_password'])) $opts['admin_password'] = null; + if (empty($opts['admin_username'])) $opts['admin_username'] = null; + if (empty($opts['admin_password'])) $opts['admin_password'] = null; // user listing needs admin priviledges - if(!empty($opts['admin_username']) && !empty($opts['admin_password'])) { + if (!empty($opts['admin_username']) && !empty($opts['admin_password'])) { $this->cando['getUsers'] = true; } else { $this->cando['getUsers'] = false; @@ -672,16 +714,17 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * * @return array associative array(key => domain) */ - public function _getConfiguredDomains() { + public function getConfiguredDomains() + { $domains = array(); - if(empty($this->conf['account_suffix'])) return $domains; // not configured yet + if (empty($this->conf['account_suffix'])) return $domains; // not configured yet // add default domain, using the name from account suffix $domains[''] = ltrim($this->conf['account_suffix'], '@'); // find additional domains - foreach($this->conf as $key => $val) { - if(is_array($val) && isset($val['account_suffix'])) { + foreach ($this->conf as $key => $val) { + if (is_array($val) && isset($val['account_suffix'])) { $domains[$key] = ltrim($val['account_suffix'], '@'); } } @@ -701,14 +744,15 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * @param array $info * @return bool */ - protected function _filter($user, $info) { - foreach($this->_pattern as $item => $pattern) { - if($item == 'user') { - if(!preg_match($pattern, $user)) return false; - } else if($item == 'grps') { - if(!count(preg_grep($pattern, $info['grps']))) return false; + protected function filter($user, $info) + { + foreach ($this->pattern as $item => $pattern) { + if ($item == 'user') { + if (!preg_match($pattern, $user)) return false; + } elseif ($item == 'grps') { + if (!count(preg_grep($pattern, $info['grps']))) return false; } else { - if(!preg_match($pattern, $info[$item])) return false; + if (!preg_match($pattern, $info[$item])) return false; } } return true; @@ -721,10 +765,11 @@ class auth_plugin_authad extends DokuWiki_Auth_Plugin { * * @param array $filter */ - protected function _constructPattern($filter) { - $this->_pattern = array(); - foreach($filter as $item => $pattern) { - $this->_pattern[$item] = '/'.str_replace('/', '\/', $pattern).'/i'; // allow regex characters + protected function constructPattern($filter) + { + $this->pattern = array(); + foreach ($filter as $item => $pattern) { + $this->pattern[$item] = '/'.str_replace('/', '\/', $pattern).'/i'; // allow regex characters } } } diff --git a/lib/plugins/authldap/auth.php b/lib/plugins/authldap/auth.php index 059611052..68d1dad60 100644 --- a/lib/plugins/authldap/auth.php +++ b/lib/plugins/authldap/auth.php @@ -1,6 +1,4 @@ <?php -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); /** * LDAP authentication backend @@ -10,8 +8,9 @@ if(!defined('DOKU_INC')) die(); * @author Chris Smith <chris@jalakaic.co.uk> * @author Jan Schumann <js@schumann-it.com> */ -class auth_plugin_authldap extends DokuWiki_Auth_Plugin { - /* @var resource $con holds the LDAP connection*/ +class auth_plugin_authldap extends DokuWiki_Auth_Plugin +{ + /* @var resource $con holds the LDAP connection */ protected $con = null; /* @var int $bound What type of connection does already exist? */ @@ -20,18 +19,19 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { /* @var array $users User data cache */ protected $users = null; - /* @var array $_pattern User filter pattern */ - protected $_pattern = null; + /* @var array $pattern User filter pattern */ + protected $pattern = null; /** * Constructor */ - public function __construct() { + public function __construct() + { parent::__construct(); // ldap extension is needed - if(!function_exists('ldap_connect')) { - $this->_debug("LDAP err: PHP LDAP extension not found.", -1, __LINE__, __FILE__); + if (!function_exists('ldap_connect')) { + $this->debug("LDAP err: PHP LDAP extension not found.", -1, __LINE__, __FILE__); $this->success = false; return; } @@ -47,73 +47,72 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { * plaintext password is correct by trying to bind * to the LDAP server * - * @author Andreas Gohr <andi@splitbrain.org> * @param string $user * @param string $pass * @return bool + * @author Andreas Gohr <andi@splitbrain.org> */ - public function checkPass($user, $pass) { + public function checkPass($user, $pass) + { // reject empty password - if(empty($pass)) return false; - if(!$this->_openLDAP()) return false; + if (empty($pass)) return false; + if (!$this->openLDAP()) return false; // indirect user bind - if($this->getConf('binddn') && $this->getConf('bindpw')) { + if ($this->getConf('binddn') && $this->getConf('bindpw')) { // use superuser credentials - if(!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) { - $this->_debug('LDAP bind as superuser: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if (!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) { + $this->debug('LDAP bind as superuser: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); return false; } $this->bound = 2; - } else if($this->getConf('binddn') && + } elseif ($this->getConf('binddn') && $this->getConf('usertree') && $this->getConf('userfilter') ) { // special bind string - $dn = $this->_makeFilter( + $dn = $this->makeFilter( $this->getConf('binddn'), - array('user'=> $user, 'server'=> $this->getConf('server')) + array('user' => $user, 'server' => $this->getConf('server')) ); - - } else if(strpos($this->getConf('usertree'), '%{user}')) { + } elseif (strpos($this->getConf('usertree'), '%{user}')) { // direct user bind - $dn = $this->_makeFilter( + $dn = $this->makeFilter( $this->getConf('usertree'), - array('user'=> $user, 'server'=> $this->getConf('server')) + array('user' => $user, 'server' => $this->getConf('server')) ); - } else { // Anonymous bind - if(!@ldap_bind($this->con)) { + if (!@ldap_bind($this->con)) { msg("LDAP: can not bind anonymously", -1); - $this->_debug('LDAP anonymous bind: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + $this->debug('LDAP anonymous bind: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); return false; } } // Try to bind to with the dn if we have one. - if(!empty($dn)) { + if (!empty($dn)) { // User/Password bind - if(!@ldap_bind($this->con, $dn, $pass)) { - $this->_debug("LDAP: bind with $dn failed", -1, __LINE__, __FILE__); - $this->_debug('LDAP user dn bind: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if (!@ldap_bind($this->con, $dn, $pass)) { + $this->debug("LDAP: bind with $dn failed", -1, __LINE__, __FILE__); + $this->debug('LDAP user dn bind: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); return false; } $this->bound = 1; return true; } else { // See if we can find the user - $info = $this->_getUserData($user, true); - if(empty($info['dn'])) { + $info = $this->fetchUserData($user, true); + if (empty($info['dn'])) { return false; } else { $dn = $info['dn']; } // Try to bind with the dn provided - if(!@ldap_bind($this->con, $dn, $pass)) { - $this->_debug("LDAP: bind with $dn failed", -1, __LINE__, __FILE__); - $this->_debug('LDAP user bind: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if (!@ldap_bind($this->con, $dn, $pass)) { + $this->debug("LDAP: bind with $dn failed", -1, __LINE__, __FILE__); + $this->debug('LDAP user bind: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); return false; } $this->bound = 1; @@ -138,113 +137,119 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { * uid string Posix User ID * inbind bool for internal use - avoid loop in binding * - * @author Andreas Gohr <andi@splitbrain.org> - * @author Trouble - * @author Dan Allen <dan.j.allen@gmail.com> + * @param string $user + * @param bool $requireGroups (optional) - ignored, groups are always supplied by this plugin + * @return array containing user data or false * @author <evaldas.auryla@pheur.org> * @author Stephane Chazelas <stephane.chazelas@emerson.com> * @author Steffen Schoch <schoch@dsb.net> * - * @param string $user - * @param bool $requireGroups (optional) - ignored, groups are always supplied by this plugin - * @return array containing user data or false + * @author Andreas Gohr <andi@splitbrain.org> + * @author Trouble + * @author Dan Allen <dan.j.allen@gmail.com> */ - public function getUserData($user, $requireGroups=true) { - return $this->_getUserData($user); + public function getUserData($user, $requireGroups = true) + { + return $this->fetchUserData($user); } /** - * @param string $user - * @param bool $inbind authldap specific, true if in bind phase + * @param string $user + * @param bool $inbind authldap specific, true if in bind phase * @return array containing user data or false */ - protected function _getUserData($user, $inbind = false) { + protected function fetchUserData($user, $inbind = false) + { global $conf; - if(!$this->_openLDAP()) return false; + if (!$this->openLDAP()) return array(); // force superuser bind if wanted and not bound as superuser yet - if($this->getConf('binddn') && $this->getConf('bindpw') && $this->bound < 2) { + if ($this->getConf('binddn') && $this->getConf('bindpw') && $this->bound < 2) { // use superuser credentials - if(!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) { - $this->_debug('LDAP bind as superuser: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); - return false; + if (!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) { + $this->debug('LDAP bind as superuser: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); + return array(); } $this->bound = 2; - } elseif($this->bound == 0 && !$inbind) { + } elseif ($this->bound == 0 && !$inbind) { // in some cases getUserData is called outside the authentication workflow // eg. for sending email notification on subscribed pages. This data might not // be accessible anonymously, so we try to rebind the current user here list($loginuser, $loginsticky, $loginpass) = auth_getCookie(); - if($loginuser && $loginpass) { + if ($loginuser && $loginpass) { $loginpass = auth_decrypt($loginpass, auth_cookiesalt(!$loginsticky, true)); $this->checkPass($loginuser, $loginpass); } } $info = array(); - $info['user'] = $user; - $this->_debug('LDAP user to find: '.htmlspecialchars($info['user']), 0, __LINE__, __FILE__); + $info['user'] = $user; + $this->debug('LDAP user to find: ' . hsc($info['user']), 0, __LINE__, __FILE__); $info['server'] = $this->getConf('server'); - $this->_debug('LDAP Server: '.htmlspecialchars($info['server']), 0, __LINE__, __FILE__); - + $this->debug('LDAP Server: ' . hsc($info['server']), 0, __LINE__, __FILE__); //get info for given user - $base = $this->_makeFilter($this->getConf('usertree'), $info); - if($this->getConf('userfilter')) { - $filter = $this->_makeFilter($this->getConf('userfilter'), $info); + $base = $this->makeFilter($this->getConf('usertree'), $info); + if ($this->getConf('userfilter')) { + $filter = $this->makeFilter($this->getConf('userfilter'), $info); } else { $filter = "(ObjectClass=*)"; } - $this->_debug('LDAP Filter: '.htmlspecialchars($filter), 0, __LINE__, __FILE__); + $this->debug('LDAP Filter: ' . hsc($filter), 0, __LINE__, __FILE__); + + $this->debug('LDAP user search: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); + $this->debug('LDAP search at: ' . hsc($base . ' ' . $filter), 0, __LINE__, __FILE__); + $sr = $this->ldapSearch($this->con, $base, $filter, $this->getConf('userscope'), $this->getConf('attributes')); - $this->_debug('LDAP user search: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); - $this->_debug('LDAP search at: '.htmlspecialchars($base.' '.$filter), 0, __LINE__, __FILE__); - $sr = $this->_ldapsearch($this->con, $base, $filter, $this->getConf('userscope'), $this->getConf('attributes')); - $result = @ldap_get_entries($this->con, $sr); + $result = @ldap_get_entries($this->con, $sr); // if result is not an array - if(!is_array($result)) { - // no objects found - $this->_debug('LDAP search returned non-array result: '.htmlspecialchars(print($result)), -1, __LINE__, __FILE__); - return false; + if (!is_array($result)) { + // no objects found + $this->debug('LDAP search returned non-array result: ' . hsc(print($result)), -1, __LINE__, __FILE__); + return array(); } - // Don't accept more or less than one response - if ($result['count'] != 1) { - $this->_debug('LDAP search returned '.htmlspecialchars($result['count']).' results while it should return 1!', -1, __LINE__, __FILE__); - //for($i = 0; $i < $result["count"]; $i++) { - //$this->_debug('result: '.htmlspecialchars(print_r($result[$i])), 0, __LINE__, __FILE__); - //} - return false; - } - + // Don't accept more or less than one response + if ($result['count'] != 1) { + $this->debug( + 'LDAP search returned ' . hsc($result['count']) . ' results while it should return 1!', + -1, + __LINE__, + __FILE__ + ); + //for($i = 0; $i < $result["count"]; $i++) { + //$this->_debug('result: '.hsc(print_r($result[$i])), 0, __LINE__, __FILE__); + //} + return array(); + } - $this->_debug('LDAP search found single result !', 0, __LINE__, __FILE__); + $this->debug('LDAP search found single result !', 0, __LINE__, __FILE__); $user_result = $result[0]; ldap_free_result($sr); // general user info - $info['dn'] = $user_result['dn']; - $info['gid'] = $user_result['gidnumber'][0]; + $info['dn'] = $user_result['dn']; + $info['gid'] = $user_result['gidnumber'][0]; $info['mail'] = $user_result['mail'][0]; $info['name'] = $user_result['cn'][0]; $info['grps'] = array(); // overwrite if other attribs are specified. - if(is_array($this->getConf('mapping'))) { - foreach($this->getConf('mapping') as $localkey => $key) { - if(is_array($key)) { + if (is_array($this->getConf('mapping'))) { + foreach ($this->getConf('mapping') as $localkey => $key) { + if (is_array($key)) { // use regexp to clean up user_result // $key = array($key=>$regexp), only handles the first key-value $regexp = current($key); $key = key($key); - if($user_result[$key]) foreach($user_result[$key] as $grpkey => $grp) { - if($grpkey !== 'count' && preg_match($regexp, $grp, $match)) { - if($localkey == 'grps') { + if ($user_result[$key]) foreach ($user_result[$key] as $grpkey => $grp) { + if ($grpkey !== 'count' && preg_match($regexp, $grp, $match)) { + if ($localkey == 'grps') { $info[$localkey][] = $match[1]; } else { $info[$localkey] = $match[1]; @@ -259,38 +264,44 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { $user_result = array_merge($info, $user_result); //get groups for given user if grouptree is given - if($this->getConf('grouptree') || $this->getConf('groupfilter')) { - $base = $this->_makeFilter($this->getConf('grouptree'), $user_result); - $filter = $this->_makeFilter($this->getConf('groupfilter'), $user_result); - $sr = $this->_ldapsearch($this->con, $base, $filter, $this->getConf('groupscope'), array($this->getConf('groupkey'))); - $this->_debug('LDAP group search: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); - $this->_debug('LDAP search at: '.htmlspecialchars($base.' '.$filter), 0, __LINE__, __FILE__); - - if(!$sr) { + if ($this->getConf('grouptree') || $this->getConf('groupfilter')) { + $base = $this->makeFilter($this->getConf('grouptree'), $user_result); + $filter = $this->makeFilter($this->getConf('groupfilter'), $user_result); + $sr = $this->ldapSearch( + $this->con, + $base, + $filter, + $this->getConf('groupscope'), + array($this->getConf('groupkey')) + ); + $this->debug('LDAP group search: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); + $this->debug('LDAP search at: ' . hsc($base . ' ' . $filter), 0, __LINE__, __FILE__); + + if (!$sr) { msg("LDAP: Reading group memberships failed", -1); - return false; + return array(); } $result = ldap_get_entries($this->con, $sr); ldap_free_result($sr); - if(is_array($result)) foreach($result as $grp) { - if(!empty($grp[$this->getConf('groupkey')])) { + if (is_array($result)) foreach ($result as $grp) { + if (!empty($grp[$this->getConf('groupkey')])) { $group = $grp[$this->getConf('groupkey')]; - if(is_array($group)){ + if (is_array($group)) { $group = $group[0]; } else { - $this->_debug('groupkey did not return a detailled result', 0, __LINE__, __FILE__); + $this->debug('groupkey did not return a detailled result', 0, __LINE__, __FILE__); } - if($group === '') continue; + if ($group === '') continue; - $this->_debug('LDAP usergroup: '.htmlspecialchars($group), 0, __LINE__, __FILE__); + $this->debug('LDAP usergroup: ' . hsc($group), 0, __LINE__, __FILE__); $info['grps'][] = $group; } } } // always add the default group to the list of groups - if(!$info['grps'] or !in_array($conf['defaultgroup'], $info['grps'])) { + if (!$info['grps'] or !in_array($conf['defaultgroup'], $info['grps'])) { $info['grps'][] = $conf['defaultgroup']; } return $info; @@ -299,57 +310,66 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { /** * Definition of the function modifyUser in order to modify the password * - * @param string $user nick of the user to be changed - * @param array $changes array of field/value pairs to be changed (password will be clear text) + * @param string $user nick of the user to be changed + * @param array $changes array of field/value pairs to be changed (password will be clear text) * @return bool true on success, false on error */ - - function modifyUser($user,$changes){ + public function modifyUser($user, $changes) + { // open the connection to the ldap - if(!$this->_openLDAP()){ - $this->_debug('LDAP cannot connect: '. htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if (!$this->openLDAP()) { + $this->debug('LDAP cannot connect: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); return false; } // find the information about the user, in particular the "dn" - $info = $this->getUserData($user,true); - if(empty($info['dn'])) { - $this->_debug('LDAP cannot find your user dn', 0, __LINE__, __FILE__); + $info = $this->getUserData($user, true); + if (empty($info['dn'])) { + $this->debug('LDAP cannot find your user dn', 0, __LINE__, __FILE__); return false; } $dn = $info['dn']; // find the old password of the user - list($loginuser,$loginsticky,$loginpass) = auth_getCookie(); + list($loginuser, $loginsticky, $loginpass) = auth_getCookie(); if ($loginuser !== null) { // the user is currently logged in $secret = auth_cookiesalt(!$loginsticky, true); - $pass = auth_decrypt($loginpass, $secret); + $pass = auth_decrypt($loginpass, $secret); // bind with the ldap - if(!@ldap_bind($this->con, $dn, $pass)){ - $this->_debug('LDAP user bind failed: '. htmlspecialchars($dn) .': '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if (!@ldap_bind($this->con, $dn, $pass)) { + $this->debug( + 'LDAP user bind failed: ' . hsc($dn) . ': ' . hsc(ldap_error($this->con)), + 0, + __LINE__, + __FILE__ + ); return false; } } elseif ($this->getConf('binddn') && $this->getConf('bindpw')) { // we are changing the password on behalf of the user (eg: forgotten password) // bind with the superuser ldap - if (!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))){ - $this->_debug('LDAP bind as superuser: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if (!@ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw')))) { + $this->debug('LDAP bind as superuser: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); return false; } - } - else { + } else { return false; // no otherway } // Generate the salted hashed password for LDAP - $phash = new PassHash(); + $phash = new \dokuwiki\PassHash(); $hash = $phash->hash_ssha($changes['pass']); // change the password - if(!@ldap_mod_replace($this->con, $dn,array('userpassword' => $hash))){ - $this->_debug('LDAP mod replace failed: '. htmlspecialchars($dn) .': '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if (!@ldap_mod_replace($this->con, $dn, array('userpassword' => $hash))) { + $this->debug( + 'LDAP mod replace failed: ' . hsc($dn) . ': ' . hsc(ldap_error($this->con)), + 0, + __LINE__, + __FILE__ + ); return false; } @@ -361,56 +381,58 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { * * @return bool */ - public function isCaseSensitive() { + public function isCaseSensitive() + { return false; } /** * Bulk retrieval of user data * - * @author Dominik Eckelmann <dokuwiki@cosmocode.de> - * @param int $start index of first user to be returned - * @param int $limit max number of users to be returned - * @param array $filter array of field/pattern pairs, null for no filter + * @param int $start index of first user to be returned + * @param int $limit max number of users to be returned + * @param array $filter array of field/pattern pairs, null for no filter * @return array of userinfo (refer getUserData for internal userinfo details) + * @author Dominik Eckelmann <dokuwiki@cosmocode.de> */ - function retrieveUsers($start = 0, $limit = 0, $filter = array()) { - if(!$this->_openLDAP()) return false; + public function retrieveUsers($start = 0, $limit = 0, $filter = array()) + { + if (!$this->openLDAP()) return array(); - if(is_null($this->users)) { + if (is_null($this->users)) { // Perform the search and grab all their details - if($this->getConf('userfilter')) { + if ($this->getConf('userfilter')) { $all_filter = str_replace('%{user}', '*', $this->getConf('userfilter')); } else { $all_filter = "(ObjectClass=*)"; } - $sr = ldap_search($this->con, $this->getConf('usertree'), $all_filter); - $entries = ldap_get_entries($this->con, $sr); + $sr = ldap_search($this->con, $this->getConf('usertree'), $all_filter); + $entries = ldap_get_entries($this->con, $sr); $users_array = array(); - $userkey = $this->getConf('userkey'); - for($i = 0; $i < $entries["count"]; $i++) { + $userkey = $this->getConf('userkey'); + for ($i = 0; $i < $entries["count"]; $i++) { array_push($users_array, $entries[$i][$userkey][0]); } asort($users_array); $result = $users_array; - if(!$result) return array(); + if (!$result) return array(); $this->users = array_fill_keys($result, false); } - $i = 0; + $i = 0; $count = 0; - $this->_constructPattern($filter); + $this->constructPattern($filter); $result = array(); - foreach($this->users as $user => &$info) { - if($i++ < $start) { + foreach ($this->users as $user => &$info) { + if ($i++ < $start) { continue; } - if($info === false) { + if ($info === false) { $info = $this->getUserData($user); } - if($this->_filter($user, $info)) { + if ($this->filter($user, $info)) { $result[$user] = $info; - if(($limit > 0) && (++$count >= $limit)) break; + if (($limit > 0) && (++$count >= $limit)) break; } } return $result; @@ -422,23 +444,24 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { * Used by auth_getUserData to make the filter * strings for grouptree and groupfilter * - * @author Troels Liebe Bentsen <tlb@rapanden.dk> - * @param string $filter ldap search filter with placeholders - * @param array $placeholders placeholders to fill in + * @param string $filter ldap search filter with placeholders + * @param array $placeholders placeholders to fill in * @return string + * @author Troels Liebe Bentsen <tlb@rapanden.dk> */ - protected function _makeFilter($filter, $placeholders) { + protected function makeFilter($filter, $placeholders) + { preg_match_all("/%{([^}]+)/", $filter, $matches, PREG_PATTERN_ORDER); //replace each match - foreach($matches[1] as $match) { + foreach ($matches[1] as $match) { //take first element if array - if(is_array($placeholders[$match])) { + if (is_array($placeholders[$match])) { $value = $placeholders[$match][0]; } else { $value = $placeholders[$match]; } - $value = $this->_filterEscape($value); - $filter = str_replace('%{'.$match.'}', $value, $filter); + $value = $this->filterEscape($value); + $filter = str_replace('%{' . $match . '}', $value, $filter); } return $filter; } @@ -446,20 +469,21 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { /** * return true if $user + $info match $filter criteria, false otherwise * + * @param string $user the user's login name + * @param array $info the user's userinfo array + * @return bool * @author Chris Smith <chris@jalakai.co.uk> * - * @param string $user the user's login name - * @param array $info the user's userinfo array - * @return bool */ - protected function _filter($user, $info) { - foreach($this->_pattern as $item => $pattern) { - if($item == 'user') { - if(!preg_match($pattern, $user)) return false; - } else if($item == 'grps') { - if(!count(preg_grep($pattern, $info['grps']))) return false; + protected function filter($user, $info) + { + foreach ($this->pattern as $item => $pattern) { + if ($item == 'user') { + if (!preg_match($pattern, $user)) return false; + } elseif ($item == 'grps') { + if (!count(preg_grep($pattern, $info['grps']))) return false; } else { - if(!preg_match($pattern, $info[$item])) return false; + if (!preg_match($pattern, $info[$item])) return false; } } return true; @@ -468,15 +492,16 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { /** * Set the filter pattern * - * @author Chris Smith <chris@jalakai.co.uk> - * * @param $filter * @return void + * @author Chris Smith <chris@jalakai.co.uk> + * */ - protected function _constructPattern($filter) { - $this->_pattern = array(); - foreach($filter as $item => $pattern) { - $this->_pattern[$item] = '/'.str_replace('/', '\/', $pattern).'/i'; // allow regex characters + protected function constructPattern($filter) + { + $this->pattern = array(); + foreach ($filter as $item => $pattern) { + $this->pattern[$item] = '/' . str_replace('/', '\/', $pattern) . '/i'; // allow regex characters } } @@ -485,16 +510,17 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { * * Ported from Perl's Net::LDAP::Util escape_filter_value * - * @author Andreas Gohr - * @param string $string + * @param string $string * @return string + * @author Andreas Gohr */ - protected function _filterEscape($string) { + protected function filterEscape($string) + { // see https://github.com/adldap/adLDAP/issues/22 return preg_replace_callback( '/([\x00-\x1F\*\(\)\\\\])/', function ($matches) { - return "\\".join("", unpack("H2", $matches[1])); + return "\\" . join("", unpack("H2", $matches[1])); }, $string ); @@ -506,22 +532,23 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - protected function _openLDAP() { - if($this->con) return true; // connection already established + protected function openLDAP() + { + if ($this->con) return true; // connection already established - if($this->getConf('debug')) { - ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7); + if ($this->getConf('debug')) { + ldap_set_option(null, LDAP_OPT_DEBUG_LEVEL, 7); } $this->bound = 0; - $port = $this->getConf('port'); - $bound = false; + $port = $this->getConf('port'); + $bound = false; $servers = explode(',', $this->getConf('server')); - foreach($servers as $server) { - $server = trim($server); + foreach ($servers as $server) { + $server = trim($server); $this->con = @ldap_connect($server, $port); - if(!$this->con) { + if (!$this->con) { continue; } @@ -534,62 +561,64 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { */ //set protocol version and dependend options - if($this->getConf('version')) { - if(!@ldap_set_option( - $this->con, LDAP_OPT_PROTOCOL_VERSION, + if ($this->getConf('version')) { + if (!@ldap_set_option( + $this->con, + LDAP_OPT_PROTOCOL_VERSION, $this->getConf('version') ) ) { - msg('Setting LDAP Protocol version '.$this->getConf('version').' failed', -1); - $this->_debug('LDAP version set: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + msg('Setting LDAP Protocol version ' . $this->getConf('version') . ' failed', -1); + $this->debug('LDAP version set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); } else { //use TLS (needs version 3) - if($this->getConf('starttls')) { - if(!@ldap_start_tls($this->con)) { + if ($this->getConf('starttls')) { + if (!@ldap_start_tls($this->con)) { msg('Starting TLS failed', -1); - $this->_debug('LDAP TLS set: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + $this->debug('LDAP TLS set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); } } // needs version 3 - if($this->getConf('referrals') > -1) { - if(!@ldap_set_option( - $this->con, LDAP_OPT_REFERRALS, + if ($this->getConf('referrals') > -1) { + if (!@ldap_set_option( + $this->con, + LDAP_OPT_REFERRALS, $this->getConf('referrals') ) ) { msg('Setting LDAP referrals failed', -1); - $this->_debug('LDAP referal set: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + $this->debug('LDAP referal set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); } } } } //set deref mode - if($this->getConf('deref')) { - if(!@ldap_set_option($this->con, LDAP_OPT_DEREF, $this->getConf('deref'))) { - msg('Setting LDAP Deref mode '.$this->getConf('deref').' failed', -1); - $this->_debug('LDAP deref set: '.htmlspecialchars(ldap_error($this->con)), 0, __LINE__, __FILE__); + if ($this->getConf('deref')) { + if (!@ldap_set_option($this->con, LDAP_OPT_DEREF, $this->getConf('deref'))) { + msg('Setting LDAP Deref mode ' . $this->getConf('deref') . ' failed', -1); + $this->debug('LDAP deref set: ' . hsc(ldap_error($this->con)), 0, __LINE__, __FILE__); } } /* As of PHP 5.3.0 we can set timeout to speedup skipping of invalid servers */ - if(defined('LDAP_OPT_NETWORK_TIMEOUT')) { + if (defined('LDAP_OPT_NETWORK_TIMEOUT')) { ldap_set_option($this->con, LDAP_OPT_NETWORK_TIMEOUT, 1); } - if($this->getConf('binddn') && $this->getConf('bindpw')) { + if ($this->getConf('binddn') && $this->getConf('bindpw')) { $bound = @ldap_bind($this->con, $this->getConf('binddn'), conf_decodeString($this->getConf('bindpw'))); $this->bound = 2; } else { $bound = @ldap_bind($this->con); } - if($bound) { + if ($bound) { break; } } - if(!$bound) { + if (!$bound) { msg("LDAP: couldn't connect to LDAP server", -1); - $this->_debug(ldap_error($this->con), 0, __LINE__, __FILE__); + $this->debug(ldap_error($this->con), 0, __LINE__, __FILE__); return false; } @@ -600,34 +629,54 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { /** * Wraps around ldap_search, ldap_list or ldap_read depending on $scope * - * @author Andreas Gohr <andi@splitbrain.org> - * @param resource $link_identifier - * @param string $base_dn - * @param string $filter - * @param string $scope can be 'base', 'one' or 'sub' + * @param resource $link_identifier + * @param string $base_dn + * @param string $filter + * @param string $scope can be 'base', 'one' or 'sub' * @param null|array $attributes - * @param int $attrsonly - * @param int $sizelimit + * @param int $attrsonly + * @param int $sizelimit * @return resource + * @author Andreas Gohr <andi@splitbrain.org> */ - protected function _ldapsearch($link_identifier, $base_dn, $filter, $scope = 'sub', $attributes = null, - $attrsonly = 0, $sizelimit = 0) { - if(is_null($attributes)) $attributes = array(); - - if($scope == 'base') { + protected function ldapSearch( + $link_identifier, + $base_dn, + $filter, + $scope = 'sub', + $attributes = null, + $attrsonly = 0, + $sizelimit = 0 + ) + { + if (is_null($attributes)) $attributes = array(); + + if ($scope == 'base') { return @ldap_read( - $link_identifier, $base_dn, $filter, $attributes, - $attrsonly, $sizelimit + $link_identifier, + $base_dn, + $filter, + $attributes, + $attrsonly, + $sizelimit ); - } elseif($scope == 'one') { + } elseif ($scope == 'one') { return @ldap_list( - $link_identifier, $base_dn, $filter, $attributes, - $attrsonly, $sizelimit + $link_identifier, + $base_dn, + $filter, + $attributes, + $attrsonly, + $sizelimit ); } else { return @ldap_search( - $link_identifier, $base_dn, $filter, $attributes, - $attrsonly, $sizelimit + $link_identifier, + $base_dn, + $filter, + $attributes, + $attrsonly, + $sizelimit ); } } @@ -636,14 +685,14 @@ class auth_plugin_authldap extends DokuWiki_Auth_Plugin { * Wrapper around msg() but outputs only when debug is enabled * * @param string $message - * @param int $err - * @param int $line + * @param int $err + * @param int $line * @param string $file * @return void */ - protected function _debug($message, $err, $line, $file) { - if(!$this->getConf('debug')) return; + protected function debug($message, $err, $line, $file) + { + if (!$this->getConf('debug')) return; msg($message, $err, $line, $file); } - } diff --git a/lib/plugins/authpdo/_test/sqlite.test.php b/lib/plugins/authpdo/_test/sqlite.test.php index 35b612604..89cc9f60d 100644 --- a/lib/plugins/authpdo/_test/sqlite.test.php +++ b/lib/plugins/authpdo/_test/sqlite.test.php @@ -10,8 +10,8 @@ class testable_auth_plugin_authpdo extends auth_plugin_authpdo { return 'authpdo'; } - public function _selectGroups() { - return parent::_selectGroups(); + public function selectGroups() { + return parent::selectGroups(); } public function addGroup($group) { @@ -96,7 +96,7 @@ class sqlite_plugin_authpdo_test extends DokuWikiTest { public function test_internals() { $auth = new testable_auth_plugin_authpdo(); - $groups = $auth->_selectGroups(); + $groups = $auth->selectGroups(); $this->assertArrayHasKey('user', $groups); $this->assertEquals(1, $groups['user']['gid']); $this->assertArrayHasKey('admin', $groups); @@ -104,7 +104,7 @@ class sqlite_plugin_authpdo_test extends DokuWikiTest { $ok = $auth->addGroup('test'); $this->assertTrue($ok); - $groups = $auth->_selectGroups(); + $groups = $auth->selectGroups(); $this->assertArrayHasKey('test', $groups); $this->assertEquals(3, $groups['test']['gid']); } diff --git a/lib/plugins/authpdo/auth.php b/lib/plugins/authpdo/auth.php index 12263b7b9..9c0968e30 100644 --- a/lib/plugins/authpdo/auth.php +++ b/lib/plugins/authpdo/auth.php @@ -6,13 +6,11 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - /** * Class auth_plugin_authpdo */ -class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { +class auth_plugin_authpdo extends DokuWiki_Auth_Plugin +{ /** @var PDO */ protected $pdo; @@ -23,17 +21,18 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { /** * Constructor. */ - public function __construct() { + public function __construct() + { parent::__construct(); // for compatibility - if(!class_exists('PDO')) { - $this->_debug('PDO extension for PHP not found.', -1, __LINE__); + if (!class_exists('PDO')) { + $this->debugMsg('PDO extension for PHP not found.', -1, __LINE__); $this->success = false; return; } - if(!$this->getConf('dsn')) { - $this->_debug('No DSN specified', -1, __LINE__); + if (!$this->getConf('dsn')) { + $this->debugMsg('No DSN specified', -1, __LINE__); $this->success = false; return; } @@ -49,15 +48,15 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // we want exceptions, not error codes ) ); - } catch(PDOException $e) { - $this->_debug($e); + } catch (PDOException $e) { + $this->debugMsg($e); msg($this->getLang('connectfail'), -1); $this->success = false; return; } // can Users be created? - $this->cando['addUser'] = $this->_chkcnf( + $this->cando['addUser'] = $this->checkConfig( array( 'select-user', 'select-user-groups', @@ -69,7 +68,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { ); // can Users be deleted? - $this->cando['delUser'] = $this->_chkcnf( + $this->cando['delUser'] = $this->checkConfig( array( 'select-user', 'select-user-groups', @@ -80,7 +79,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { ); // can login names be changed? - $this->cando['modLogin'] = $this->_chkcnf( + $this->cando['modLogin'] = $this->checkConfig( array( 'select-user', 'select-user-groups', @@ -89,7 +88,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { ); // can passwords be changed? - $this->cando['modPass'] = $this->_chkcnf( + $this->cando['modPass'] = $this->checkConfig( array( 'select-user', 'select-user-groups', @@ -98,7 +97,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { ); // can real names be changed? - $this->cando['modName'] = $this->_chkcnf( + $this->cando['modName'] = $this->checkConfig( array( 'select-user', 'select-user-groups', @@ -107,7 +106,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { ); // can real email be changed? - $this->cando['modMail'] = $this->_chkcnf( + $this->cando['modMail'] = $this->checkConfig( array( 'select-user', 'select-user-groups', @@ -116,7 +115,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { ); // can groups be changed? - $this->cando['modGroups'] = $this->_chkcnf( + $this->cando['modGroups'] = $this->checkConfig( array( 'select-user', 'select-user-groups', @@ -128,21 +127,21 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { ); // can a filtered list of users be retrieved? - $this->cando['getUsers'] = $this->_chkcnf( + $this->cando['getUsers'] = $this->checkConfig( array( 'list-users' ) ); // can the number of users be retrieved? - $this->cando['getUserCount'] = $this->_chkcnf( + $this->cando['getUserCount'] = $this->checkConfig( array( 'count-users' ) ); // can a list of available groups be retrieved? - $this->cando['getGroups'] = $this->_chkcnf( + $this->cando['getGroups'] = $this->checkConfig( array( 'select-groups' ) @@ -154,28 +153,29 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { /** * Check user+password * - * @param string $user the user name - * @param string $pass the clear text password + * @param string $user the user name + * @param string $pass the clear text password * @return bool */ - public function checkPass($user, $pass) { + public function checkPass($user, $pass) + { - $userdata = $this->_selectUser($user); - if($userdata == false) return false; + $userdata = $this->selectUser($user); + if ($userdata == false) return false; // password checking done in SQL? - if($this->_chkcnf(array('check-pass'))) { + if ($this->checkConfig(array('check-pass'))) { $userdata['clear'] = $pass; $userdata['hash'] = auth_cryptPassword($pass); - $result = $this->_query($this->getConf('check-pass'), $userdata); - if($result === false) return false; + $result = $this->query($this->getConf('check-pass'), $userdata); + if ($result === false) return false; return (count($result) == 1); } // we do password checking on our own - if(isset($userdata['hash'])) { + if (isset($userdata['hash'])) { // hashed password - $passhash = new PassHash(); + $passhash = new \dokuwiki\PassHash(); return $passhash->verify_hash($pass, $userdata['hash']); } else { // clear text password in the database O_o @@ -193,20 +193,21 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * mail string email addres of the user * grps array list of groups the user is in * - * @param string $user the user name - * @param bool $requireGroups whether or not the returned data must include groups + * @param string $user the user name + * @param bool $requireGroups whether or not the returned data must include groups * @return array|bool containing user data or false */ - public function getUserData($user, $requireGroups = true) { - $data = $this->_selectUser($user); - if($data == false) return false; + public function getUserData($user, $requireGroups = true) + { + $data = $this->selectUser($user); + if ($data == false) return false; - if(isset($data['hash'])) unset($data['hash']); - if(isset($data['clean'])) unset($data['clean']); + if (isset($data['hash'])) unset($data['hash']); + if (isset($data['clean'])) unset($data['clean']); - if($requireGroups) { - $data['grps'] = $this->_selectUserGroups($data); - if($data['grps'] === false) return false; + if ($requireGroups) { + $data['grps'] = $this->selectUserGroups($data); + if ($data['grps'] === false) return false; } return $data; @@ -223,23 +224,24 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * * Set addUser capability when implemented * - * @param string $user - * @param string $clear - * @param string $name - * @param string $mail - * @param null|array $grps + * @param string $user + * @param string $clear + * @param string $name + * @param string $mail + * @param null|array $grps * @return bool|null */ - public function createUser($user, $clear, $name, $mail, $grps = null) { + public function createUser($user, $clear, $name, $mail, $grps = null) + { global $conf; - if(($info = $this->getUserData($user, false)) !== false) { + if (($info = $this->getUserData($user, false)) !== false) { msg($this->getLang('userexists'), -1); return false; // user already exists } // prepare data - if($grps == null) $grps = array(); + if ($grps == null) $grps = array(); array_unshift($grps, $conf['defaultgroup']); $grps = array_unique($grps); $hash = auth_cryptPassword($clear); @@ -249,25 +251,25 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { $this->pdo->beginTransaction(); { // insert the user - $ok = $this->_query($this->getConf('insert-user'), $userdata); - if($ok === false) goto FAIL; + $ok = $this->query($this->getConf('insert-user'), $userdata); + if ($ok === false) goto FAIL; $userdata = $this->getUserData($user, false); - if($userdata === false) goto FAIL; + if ($userdata === false) goto FAIL; // create all groups that do not exist, the refetch the groups - $allgroups = $this->_selectGroups(); - foreach($grps as $group) { - if(!isset($allgroups[$group])) { + $allgroups = $this->selectGroups(); + foreach ($grps as $group) { + if (!isset($allgroups[$group])) { $ok = $this->addGroup($group); - if($ok === false) goto FAIL; + if ($ok === false) goto FAIL; } } - $allgroups = $this->_selectGroups(); + $allgroups = $this->selectGroups(); // add user to the groups - foreach($grps as $group) { - $ok = $this->_joinGroup($userdata, $allgroups[$group]); - if($ok === false) goto FAIL; + foreach ($grps as $group) { + $ok = $this->joinGroup($userdata, $allgroups[$group]); + if ($ok === false) goto FAIL; } } $this->pdo->commit(); @@ -276,7 +278,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { // something went wrong, rollback FAIL: $this->pdo->rollBack(); - $this->_debug('Transaction rolled back', 0, __LINE__); + $this->debugMsg('Transaction rolled back', 0, __LINE__); msg($this->getLang('writefail'), -1); return null; // return error } @@ -284,11 +286,12 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { /** * Modify user data * - * @param string $user nick of the user to be changed - * @param array $changes array of field/value pairs to be changed (password will be clear text) + * @param string $user nick of the user to be changed + * @param array $changes array of field/value pairs to be changed (password will be clear text) * @return bool */ - public function modifyUser($user, $changes) { + public function modifyUser($user, $changes) + { // secure everything in transaction $this->pdo->beginTransaction(); { @@ -297,64 +300,64 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { unset($olddata['grps']); // changing the user name? - if(isset($changes['user'])) { - if($this->getUserData($changes['user'], false)) goto FAIL; + if (isset($changes['user'])) { + if ($this->getUserData($changes['user'], false)) goto FAIL; $params = $olddata; $params['newlogin'] = $changes['user']; - $ok = $this->_query($this->getConf('update-user-login'), $params); - if($ok === false) goto FAIL; + $ok = $this->query($this->getConf('update-user-login'), $params); + if ($ok === false) goto FAIL; } // changing the password? - if(isset($changes['pass'])) { + if (isset($changes['pass'])) { $params = $olddata; $params['clear'] = $changes['pass']; $params['hash'] = auth_cryptPassword($changes['pass']); - $ok = $this->_query($this->getConf('update-user-pass'), $params); - if($ok === false) goto FAIL; + $ok = $this->query($this->getConf('update-user-pass'), $params); + if ($ok === false) goto FAIL; } // changing info? - if(isset($changes['mail']) || isset($changes['name'])) { + if (isset($changes['mail']) || isset($changes['name'])) { $params = $olddata; - if(isset($changes['mail'])) $params['mail'] = $changes['mail']; - if(isset($changes['name'])) $params['name'] = $changes['name']; + if (isset($changes['mail'])) $params['mail'] = $changes['mail']; + if (isset($changes['name'])) $params['name'] = $changes['name']; - $ok = $this->_query($this->getConf('update-user-info'), $params); - if($ok === false) goto FAIL; + $ok = $this->query($this->getConf('update-user-info'), $params); + if ($ok === false) goto FAIL; } // changing groups? - if(isset($changes['grps'])) { - $allgroups = $this->_selectGroups(); + if (isset($changes['grps'])) { + $allgroups = $this->selectGroups(); // remove membership for previous groups - foreach($oldgroups as $group) { - if(!in_array($group, $changes['grps']) && isset($allgroups[$group])) { - $ok = $this->_leaveGroup($olddata, $allgroups[$group]); - if($ok === false) goto FAIL; + foreach ($oldgroups as $group) { + if (!in_array($group, $changes['grps']) && isset($allgroups[$group])) { + $ok = $this->leaveGroup($olddata, $allgroups[$group]); + if ($ok === false) goto FAIL; } } // create all new groups that are missing $added = 0; - foreach($changes['grps'] as $group) { - if(!isset($allgroups[$group])) { + foreach ($changes['grps'] as $group) { + if (!isset($allgroups[$group])) { $ok = $this->addGroup($group); - if($ok === false) goto FAIL; + if ($ok === false) goto FAIL; $added++; } } // reload group info - if($added > 0) $allgroups = $this->_selectGroups(); + if ($added > 0) $allgroups = $this->selectGroups(); // add membership for new groups - foreach($changes['grps'] as $group) { - if(!in_array($group, $oldgroups)) { - $ok = $this->_joinGroup($olddata, $allgroups[$group]); - if($ok === false) goto FAIL; + foreach ($changes['grps'] as $group) { + if (!in_array($group, $oldgroups)) { + $ok = $this->joinGroup($olddata, $allgroups[$group]); + if ($ok === false) goto FAIL; } } } @@ -366,7 +369,7 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { // something went wrong, rollback FAIL: $this->pdo->rollBack(); - $this->_debug('Transaction rolled back', 0, __LINE__); + $this->debugMsg('Transaction rolled back', 0, __LINE__); msg($this->getLang('writefail'), -1); return false; // return error } @@ -376,13 +379,14 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * * Set delUser capability when implemented * - * @param array $users + * @param array $users * @return int number of users deleted */ - public function deleteUsers($users) { + public function deleteUsers($users) + { $count = 0; - foreach($users as $user) { - if($this->_deleteUser($user)) $count++; + foreach ($users as $user) { + if ($this->deleteUser($user)) $count++; } return $count; } @@ -392,40 +396,41 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * * Set getUsers capability when implemented * - * @param int $start index of first user to be returned - * @param int $limit max number of users to be returned - * @param array $filter array of field/pattern pairs, null for no filter + * @param int $start index of first user to be returned + * @param int $limit max number of users to be returned + * @param array $filter array of field/pattern pairs, null for no filter * @return array list of userinfo (refer getUserData for internal userinfo details) */ - public function retrieveUsers($start = 0, $limit = -1, $filter = null) { - if($limit < 0) $limit = 10000; // we don't support no limit - if(is_null($filter)) $filter = array(); - - if(isset($filter['grps'])) $filter['group'] = $filter['grps']; - foreach(array('user', 'name', 'mail', 'group') as $key) { - if(!isset($filter[$key])) { + public function retrieveUsers($start = 0, $limit = -1, $filter = null) + { + if ($limit < 0) $limit = 10000; // we don't support no limit + if (is_null($filter)) $filter = array(); + + if (isset($filter['grps'])) $filter['group'] = $filter['grps']; + foreach (array('user', 'name', 'mail', 'group') as $key) { + if (!isset($filter[$key])) { $filter[$key] = '%'; } else { $filter[$key] = '%' . $filter[$key] . '%'; } } - $filter['start'] = (int) $start; - $filter['end'] = (int) $start + $limit; - $filter['limit'] = (int) $limit; + $filter['start'] = (int)$start; + $filter['end'] = (int)$start + $limit; + $filter['limit'] = (int)$limit; - $result = $this->_query($this->getConf('list-users'), $filter); - if(!$result) return array(); + $result = $this->query($this->getConf('list-users'), $filter); + if (!$result) return array(); $users = array(); - if(is_array($result)){ - foreach($result as $row) { - if(!isset($row['user'])) { - $this->_debug("list-users statement did not return 'user' attribute", -1, __LINE__); + if (is_array($result)) { + foreach ($result as $row) { + if (!isset($row['user'])) { + $this->debugMsg("list-users statement did not return 'user' attribute", -1, __LINE__); return array(); } $users[] = $this->getUserData($row['user']); } - }else{ - $this->_debug("list-users statement did not return a list of result", -1, __LINE__); + } else { + $this->debugMsg("list-users statement did not return a list of result", -1, __LINE__); } return $users; } @@ -433,26 +438,27 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { /** * Return a count of the number of user which meet $filter criteria * - * @param array $filter array of field/pattern pairs, empty array for no filter + * @param array $filter array of field/pattern pairs, empty array for no filter * @return int */ - public function getUserCount($filter = array()) { - if(is_null($filter)) $filter = array(); + public function getUserCount($filter = array()) + { + if (is_null($filter)) $filter = array(); - if(isset($filter['grps'])) $filter['group'] = $filter['grps']; - foreach(array('user', 'name', 'mail', 'group') as $key) { - if(!isset($filter[$key])) { + if (isset($filter['grps'])) $filter['group'] = $filter['grps']; + foreach (array('user', 'name', 'mail', 'group') as $key) { + if (!isset($filter[$key])) { $filter[$key] = '%'; } else { $filter[$key] = '%' . $filter[$key] . '%'; } } - $result = $this->_query($this->getConf('count-users'), $filter); - if(!$result || !isset($result[0]['count'])) { - $this->_debug("Statement did not return 'count' attribute", -1, __LINE__); + $result = $this->query($this->getConf('count-users'), $filter); + if (!$result || !isset($result[0]['count'])) { + $this->debugMsg("Statement did not return 'count' attribute", -1, __LINE__); } - return (int) $result[0]['count']; + return (int)$result[0]['count']; } /** @@ -461,12 +467,13 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param string $group * @return bool */ - public function addGroup($group) { + public function addGroup($group) + { $sql = $this->getConf('insert-group'); - $result = $this->_query($sql, array(':group' => $group)); - $this->_clearGroupCache(); - if($result === false) return false; + $result = $this->query($sql, array(':group' => $group)); + $this->clearGroupCache(); + if ($result === false) return false; return true; } @@ -475,15 +482,16 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * * Set getGroups capability when implemented * - * @param int $start - * @param int $limit + * @param int $start + * @param int $limit * @return array */ - public function retrieveGroups($start = 0, $limit = 0) { - $groups = array_keys($this->_selectGroups()); - if($groups === false) return array(); + public function retrieveGroups($start = 0, $limit = 0) + { + $groups = array_keys($this->selectGroups()); + if ($groups === false) return array(); - if(!$limit) { + if (!$limit) { return array_splice($groups, $start); } else { return array_splice($groups, $start, $limit); @@ -496,38 +504,39 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param string $user the user name * @return bool|array user data, false on error */ - protected function _selectUser($user) { + protected function selectUser($user) + { $sql = $this->getConf('select-user'); - $result = $this->_query($sql, array(':user' => $user)); - if(!$result) return false; + $result = $this->query($sql, array(':user' => $user)); + if (!$result) return false; - if(count($result) > 1) { - $this->_debug('Found more than one matching user', -1, __LINE__); + if (count($result) > 1) { + $this->debugMsg('Found more than one matching user', -1, __LINE__); return false; } $data = array_shift($result); $dataok = true; - if(!isset($data['user'])) { - $this->_debug("Statement did not return 'user' attribute", -1, __LINE__); + if (!isset($data['user'])) { + $this->debugMsg("Statement did not return 'user' attribute", -1, __LINE__); $dataok = false; } - if(!isset($data['hash']) && !isset($data['clear']) && !$this->_chkcnf(array('check-pass'))) { - $this->_debug("Statement did not return 'clear' or 'hash' attribute", -1, __LINE__); + if (!isset($data['hash']) && !isset($data['clear']) && !$this->checkConfig(array('check-pass'))) { + $this->debugMsg("Statement did not return 'clear' or 'hash' attribute", -1, __LINE__); $dataok = false; } - if(!isset($data['name'])) { - $this->_debug("Statement did not return 'name' attribute", -1, __LINE__); + if (!isset($data['name'])) { + $this->debugMsg("Statement did not return 'name' attribute", -1, __LINE__); $dataok = false; } - if(!isset($data['mail'])) { - $this->_debug("Statement did not return 'mail' attribute", -1, __LINE__); + if (!isset($data['mail'])) { + $this->debugMsg("Statement did not return 'mail' attribute", -1, __LINE__); $dataok = false; } - if(!$dataok) return false; + if (!$dataok) return false; return $data; } @@ -537,22 +546,23 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param string $user * @return bool true when the user was deleted */ - protected function _deleteUser($user) { + protected function deleteUser($user) + { $this->pdo->beginTransaction(); { $userdata = $this->getUserData($user); - if($userdata === false) goto FAIL; - $allgroups = $this->_selectGroups(); + if ($userdata === false) goto FAIL; + $allgroups = $this->selectGroups(); // remove group memberships (ignore errors) - foreach($userdata['grps'] as $group) { - if(isset($allgroups[$group])) { - $this->_leaveGroup($userdata, $allgroups[$group]); + foreach ($userdata['grps'] as $group) { + if (isset($allgroups[$group])) { + $this->leaveGroup($userdata, $allgroups[$group]); } } - $ok = $this->_query($this->getConf('delete-user'), $userdata); - if($ok === false) goto FAIL; + $ok = $this->query($this->getConf('delete-user'), $userdata); + if ($ok === false) goto FAIL; } $this->pdo->commit(); return true; @@ -568,23 +578,24 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param array $userdata The userdata as returned by _selectUser() * @return array|bool list of group names, false on error */ - protected function _selectUserGroups($userdata) { + protected function selectUserGroups($userdata) + { global $conf; $sql = $this->getConf('select-user-groups'); - $result = $this->_query($sql, $userdata); - if($result === false) return false; + $result = $this->query($sql, $userdata); + if ($result === false) return false; $groups = array($conf['defaultgroup']); // always add default config - if(is_array($result)){ - foreach($result as $row) { - if(!isset($row['group'])) { - $this->_debug("No 'group' field returned in select-user-groups statement"); + if (is_array($result)) { + foreach ($result as $row) { + if (!isset($row['group'])) { + $this->debugMsg("No 'group' field returned in select-user-groups statement", -1, __LINE__); return false; } $groups[] = $row['group']; } - }else{ - $this->_debug("select-user-groups statement did not return a list of result", -1, __LINE__); + } else { + $this->debugMsg("select-user-groups statement did not return a list of result", -1, __LINE__); } $groups = array_unique($groups); @@ -597,18 +608,19 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * * @return array|bool list of all available groups and their properties */ - protected function _selectGroups() { - if($this->groupcache) return $this->groupcache; + protected function selectGroups() + { + if ($this->groupcache) return $this->groupcache; $sql = $this->getConf('select-groups'); - $result = $this->_query($sql); - if($result === false) return false; + $result = $this->query($sql); + if ($result === false) return false; $groups = array(); - if(is_array($result)){ - foreach($result as $row) { - if(!isset($row['group'])) { - $this->_debug("No 'group' field returned from select-groups statement", -1, __LINE__); + if (is_array($result)) { + foreach ($result as $row) { + if (!isset($row['group'])) { + $this->debugMsg("No 'group' field returned from select-groups statement", -1, __LINE__); return false; } @@ -616,8 +628,8 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { $group = $row['group']; $groups[$group] = $row; } - }else{ - $this->_debug("select-groups statement did not return a list of result", -1, __LINE__); + } else { + $this->debugMsg("select-groups statement did not return a list of result", -1, __LINE__); } ksort($groups); @@ -627,7 +639,8 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { /** * Remove all entries from the group cache */ - protected function _clearGroupCache() { + protected function clearGroupCache() + { $this->groupcache = null; } @@ -638,11 +651,12 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param array $groupdata all the group data * @return bool */ - protected function _joinGroup($userdata, $groupdata) { + protected function joinGroup($userdata, $groupdata) + { $data = array_merge($userdata, $groupdata); $sql = $this->getConf('join-group'); - $result = $this->_query($sql, $data); - if($result === false) return false; + $result = $this->query($sql, $data); + if ($result === false) return false; return true; } @@ -653,11 +667,12 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param array $groupdata all the group data * @return bool */ - protected function _leaveGroup($userdata, $groupdata) { + protected function leaveGroup($userdata, $groupdata) + { $data = array_merge($userdata, $groupdata); $sql = $this->getConf('leave-group'); - $result = $this->_query($sql, $data); - if($result === false) return false; + $result = $this->query($sql, $data); + if ($result === false) return false; return true; } @@ -668,10 +683,11 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param array $arguments Named parameters to be used in the statement * @return array|int|bool The result as associative array for SELECTs, affected rows for others, false on error */ - protected function _query($sql, $arguments = array()) { + protected function query($sql, $arguments = array()) + { $sql = trim($sql); - if(empty($sql)) { - $this->_debug('No SQL query given', -1, __LINE__); + if (empty($sql)) { + $this->debugMsg('No SQL query given', -1, __LINE__); return false; } @@ -681,13 +697,13 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { $result = false; try { // prepare parameters - we only use those that exist in the SQL - foreach($arguments as $key => $value) { - if(is_array($value)) continue; - if(is_object($value)) continue; - if($key[0] != ':') $key = ":$key"; // prefix with colon if needed - if(strpos($sql, $key) === false) continue; // skip if parameter is missing + foreach ($arguments as $key => $value) { + if (is_array($value)) continue; + if (is_object($value)) continue; + if ($key[0] != ':') $key = ":$key"; // prefix with colon if needed + if (strpos($sql, $key) === false) continue; // skip if parameter is missing - if(is_int($value)) { + if (is_int($value)) { $sth->bindValue($key, $value, PDO::PARAM_INT); } else { $sth->bindValue($key, $value); @@ -699,29 +715,29 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { // only report last line's result $hasnextrowset = true; $currentsql = $sql; - while($hasnextrowset){ - if(strtolower(substr($currentsql, 0, 6)) == 'select') { + while ($hasnextrowset) { + if (strtolower(substr($currentsql, 0, 6)) == 'select') { $result = $sth->fetchAll(); } else { $result = $sth->rowCount(); } $semi_pos = strpos($currentsql, ';'); - if($semi_pos){ - $currentsql = trim(substr($currentsql, $semi_pos+1)); + if ($semi_pos) { + $currentsql = trim(substr($currentsql, $semi_pos + 1)); } - try{ + try { $hasnextrowset = $sth->nextRowset(); // run next rowset - }catch(PDOException $rowset_e){ + } catch (PDOException $rowset_e) { $hasnextrowset = false; // driver does not support multi-rowset, should be executed in one time } } - } catch(Exception $e) { + } catch (Exception $e) { // report the caller's line $trace = debug_backtrace(); $line = $trace[0]['line']; - $dsql = $this->_debugSQL($sql, $params, !defined('DOKU_UNITTEST')); - $this->_debug($e, -1, $line); - $this->_debug("SQL: <pre>$dsql</pre>", -1, $line); + $dsql = $this->debugSQL($sql, $params, !defined('DOKU_UNITTEST')); + $this->debugMsg($e, -1, $line); + $this->debugMsg("SQL: <pre>$dsql</pre>", -1, $line); } $sth->closeCursor(); $sth = null; @@ -736,17 +752,18 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param int $err * @param int $line */ - protected function _debug($message, $err = 0, $line = 0) { - if(!$this->getConf('debug')) return; - if(is_a($message, 'Exception')) { + protected function debugMsg($message, $err = 0, $line = 0) + { + if (!$this->getConf('debug')) return; + if (is_a($message, 'Exception')) { $err = -1; $msg = $message->getMessage(); - if(!$line) $line = $message->getLine(); + if (!$line) $line = $message->getLine(); } else { $msg = $message; } - if(defined('DOKU_UNITTEST')) { + if (defined('DOKU_UNITTEST')) { printf("\n%s, %s:%d\n", $msg, __FILE__, $line); } else { msg('authpdo: ' . $msg, $err, $line, __FILE__); @@ -756,22 +773,23 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { /** * Check if the given config strings are set * + * @param string[] $keys + * @return bool * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> * - * @param string[] $keys - * @return bool */ - protected function _chkcnf($keys) { - foreach($keys as $key) { + protected function checkConfig($keys) + { + foreach ($keys as $key) { $params = explode(':', $key); $key = array_shift($params); $sql = trim($this->getConf($key)); // check if sql is set - if(!$sql) return false; + if (!$sql) return false; // check if needed params are there - foreach($params as $param) { - if(strpos($sql, ":$param") === false) return false; + foreach ($params as $param) { + if (strpos($sql, ":$param") === false) return false; } } @@ -786,20 +804,21 @@ class auth_plugin_authpdo extends DokuWiki_Auth_Plugin { * @param bool $htmlescape Should the result be escaped for output in HTML? * @return string */ - protected function _debugSQL($sql, $params, $htmlescape = true) { - foreach($params as $key => $val) { - if(is_int($val)) { + protected function debugSQL($sql, $params, $htmlescape = true) + { + foreach ($params as $key => $val) { + if (is_int($val)) { $val = $this->pdo->quote($val, PDO::PARAM_INT); - } elseif(is_bool($val)) { + } elseif (is_bool($val)) { $val = $this->pdo->quote($val, PDO::PARAM_BOOL); - } elseif(is_null($val)) { + } elseif (is_null($val)) { $val = 'NULL'; } else { $val = $this->pdo->quote($val); } $sql = str_replace($key, $val, $sql); } - if($htmlescape) $sql = hsc($sql); + if ($htmlescape) $sql = hsc($sql); return $sql; } } diff --git a/lib/plugins/authpdo/conf/metadata.php b/lib/plugins/authpdo/conf/metadata.php index 7c2ee8cdc..34e60a40e 100644 --- a/lib/plugins/authpdo/conf/metadata.php +++ b/lib/plugins/authpdo/conf/metadata.php @@ -23,5 +23,3 @@ $meta['update-user-pass'] = array('', '_caution' => 'danger'); $meta['insert-group'] = array('', '_caution' => 'danger'); $meta['join-group'] = array('', '_caution' => 'danger'); $meta['leave-group'] = array('', '_caution' => 'danger'); - - diff --git a/lib/plugins/authplain/_test/escaping.test.php b/lib/plugins/authplain/_test/escaping.test.php index a38940e1a..be4d06b4e 100644 --- a/lib/plugins/authplain/_test/escaping.test.php +++ b/lib/plugins/authplain/_test/escaping.test.php @@ -114,14 +114,14 @@ class auth_plugin_authplainharness extends auth_plugin_authplain { * @param boolean $bool */ public function setPregsplit_safe($bool) { - $this->_pregsplit_safe = $bool; + $this->pregsplit_safe = $bool; } /** * @return bool|mixed */ public function getPregsplit_safe(){ - return $this->_pregsplit_safe; + return $this->pregsplit_safe; } /** @@ -129,6 +129,6 @@ class auth_plugin_authplainharness extends auth_plugin_authplain { * @return array */ public function splitUserData($line){ - return $this->_splitUserData($line); + return parent::splitUserData($line); } } diff --git a/lib/plugins/authplain/auth.php b/lib/plugins/authplain/auth.php index ac1c5d5da..421af8847 100644 --- a/lib/plugins/authplain/auth.php +++ b/lib/plugins/authplain/auth.php @@ -1,6 +1,4 @@ <?php -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); /** * Plaintext authentication backend @@ -10,15 +8,16 @@ if(!defined('DOKU_INC')) die(); * @author Chris Smith <chris@jalakai.co.uk> * @author Jan Schumann <js@schumann-it.com> */ -class auth_plugin_authplain extends DokuWiki_Auth_Plugin { +class auth_plugin_authplain extends DokuWiki_Auth_Plugin +{ /** @var array user cache */ protected $users = null; /** @var array filter pattern */ - protected $_pattern = array(); + protected $pattern = array(); /** @var bool safe version of preg_split */ - protected $_pregsplit_safe = false; + protected $pregsplit_safe = false; /** * Constructor @@ -28,14 +27,15 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * * @author Christopher Smith <chris@jalakai.co.uk> */ - public function __construct() { + public function __construct() + { parent::__construct(); global $config_cascade; - if(!@is_readable($config_cascade['plainauth.users']['default'])) { + if (!@is_readable($config_cascade['plainauth.users']['default'])) { $this->success = false; } else { - if(@is_writable($config_cascade['plainauth.users']['default'])) { + if (@is_writable($config_cascade['plainauth.users']['default'])) { $this->cando['addUser'] = true; $this->cando['delUser'] = true; $this->cando['modLogin'] = true; @@ -49,7 +49,7 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { $this->cando['getGroups'] = true; } - $this->_pregsplit_safe = version_compare(PCRE_VERSION,'6.7','>='); + $this->pregsplit_safe = version_compare(PCRE_VERSION, '6.7', '>='); } /** @@ -63,9 +63,10 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param string $pass * @return bool */ - public function checkPass($user, $pass) { + public function checkPass($user, $pass) + { $userinfo = $this->getUserData($user); - if($userinfo === false) return false; + if ($userinfo === false) return false; return auth_verifyPassword($pass, $this->users[$user]['pass']); } @@ -85,8 +86,9 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param bool $requireGroups (optional) ignored by this plugin, grps info always supplied * @return array|false */ - public function getUserData($user, $requireGroups=true) { - if($this->users === null) $this->_loadUserData(); + public function getUserData($user, $requireGroups = true) + { + if ($this->users === null) $this->loadUserData(); return isset($this->users[$user]) ? $this->users[$user] : false; } @@ -102,7 +104,8 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param array $grps list of groups the user is in * @return string */ - protected function _createUserLine($user, $pass, $name, $mail, $grps) { + protected function createUserLine($user, $pass, $name, $mail, $grps) + { $groups = join(',', $grps); $userline = array($user, $pass, $name, $mail, $groups); $userline = str_replace('\\', '\\\\', $userline); // escape \ as \\ @@ -130,12 +133,13 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param array $grps * @return bool|null|string */ - public function createUser($user, $pwd, $name, $mail, $grps = null) { + public function createUser($user, $pwd, $name, $mail, $grps = null) + { global $conf; global $config_cascade; // user mustn't already exist - if($this->getUserData($user) !== false) { + if ($this->getUserData($user) !== false) { msg($this->getLang('userexists'), -1); return false; } @@ -143,12 +147,12 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { $pass = auth_cryptPassword($pwd); // set default group if no groups specified - if(!is_array($grps)) $grps = array($conf['defaultgroup']); + if (!is_array($grps)) $grps = array($conf['defaultgroup']); // prepare user line - $userline = $this->_createUserLine($user, $pass, $name, $mail, $grps); + $userline = $this->createUserLine($user, $pass, $name, $mail, $grps); - if(!io_saveFile($config_cascade['plainauth.users']['default'], $userline, true)) { + if (!io_saveFile($config_cascade['plainauth.users']['default'], $userline, true)) { msg($this->getLang('writefail'), -1); return null; } @@ -165,38 +169,45 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param array $changes array of field/value pairs to be changed (password will be clear text) * @return bool */ - public function modifyUser($user, $changes) { + public function modifyUser($user, $changes) + { global $ACT; global $config_cascade; // sanity checks, user must already exist and there must be something to change - if(($userinfo = $this->getUserData($user)) === false) { + if (($userinfo = $this->getUserData($user)) === false) { msg($this->getLang('usernotexists'), -1); return false; } // don't modify protected users - if(!empty($userinfo['protected'])) { + if (!empty($userinfo['protected'])) { msg(sprintf($this->getLang('protected'), hsc($user)), -1); return false; } - if(!is_array($changes) || !count($changes)) return true; + if (!is_array($changes) || !count($changes)) return true; // update userinfo with new data, remembering to encrypt any password $newuser = $user; - foreach($changes as $field => $value) { - if($field == 'user') { + foreach ($changes as $field => $value) { + if ($field == 'user') { $newuser = $value; continue; } - if($field == 'pass') $value = auth_cryptPassword($value); + if ($field == 'pass') $value = auth_cryptPassword($value); $userinfo[$field] = $value; } - $userline = $this->_createUserLine($newuser, $userinfo['pass'], $userinfo['name'], $userinfo['mail'], $userinfo['grps']); + $userline = $this->createUserLine( + $newuser, + $userinfo['pass'], + $userinfo['name'], + $userinfo['mail'], + $userinfo['grps'] + ); - if(!io_replaceInFile($config_cascade['plainauth.users']['default'], '/^'.$user.':/', $userline, true)) { + if (!io_replaceInFile($config_cascade['plainauth.users']['default'], '/^'.$user.':/', $userline, true)) { msg('There was an error modifying your user data. You may need to register again.', -1); // FIXME, io functions should be fail-safe so existing data isn't lost $ACT = 'register'; @@ -214,24 +225,25 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param array $users array of users to be deleted * @return int the number of users deleted */ - public function deleteUsers($users) { + public function deleteUsers($users) + { global $config_cascade; - if(!is_array($users) || empty($users)) return 0; + if (!is_array($users) || empty($users)) return 0; - if($this->users === null) $this->_loadUserData(); + if ($this->users === null) $this->loadUserData(); $deleted = array(); - foreach($users as $user) { + foreach ($users as $user) { // don't delete protected users - if(!empty($this->users[$user]['protected'])) { + if (!empty($this->users[$user]['protected'])) { msg(sprintf($this->getLang('protected'), hsc($user)), -1); continue; } - if(isset($this->users[$user])) $deleted[] = preg_quote($user, '/'); + if (isset($this->users[$user])) $deleted[] = preg_quote($user, '/'); } - if(empty($deleted)) return 0; + if (empty($deleted)) return 0; $pattern = '/^('.join('|', $deleted).'):/'; if (!io_deleteFromFile($config_cascade['plainauth.users']['default'], $pattern, true)) { @@ -241,7 +253,7 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { // reload the user list and count the difference $count = count($this->users); - $this->_loadUserData(); + $this->loadUserData(); $count -= count($this->users); return $count; } @@ -254,17 +266,18 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param array $filter * @return int */ - public function getUserCount($filter = array()) { + public function getUserCount($filter = array()) + { - if($this->users === null) $this->_loadUserData(); + if ($this->users === null) $this->loadUserData(); - if(!count($filter)) return count($this->users); + if (!count($filter)) return count($this->users); $count = 0; - $this->_constructPattern($filter); + $this->constructPattern($filter); - foreach($this->users as $user => $info) { - $count += $this->_filter($user, $info); + foreach ($this->users as $user => $info) { + $count += $this->filter($user, $info); } return $count; @@ -280,23 +293,24 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param array $filter array of field/pattern pairs * @return array userinfo (refer getUserData for internal userinfo details) */ - public function retrieveUsers($start = 0, $limit = 0, $filter = array()) { + public function retrieveUsers($start = 0, $limit = 0, $filter = array()) + { - if($this->users === null) $this->_loadUserData(); + if ($this->users === null) $this->loadUserData(); ksort($this->users); $i = 0; $count = 0; $out = array(); - $this->_constructPattern($filter); + $this->constructPattern($filter); - foreach($this->users as $user => $info) { - if($this->_filter($user, $info)) { - if($i >= $start) { + foreach ($this->users as $user => $info) { + if ($this->filter($user, $info)) { + if ($i >= $start) { $out[$user] = $info; $count++; - if(($limit > 0) && ($count >= $limit)) break; + if (($limit > 0) && ($count >= $limit)) break; } $i++; } @@ -317,7 +331,7 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { { $groups = []; - if ($this->users === null) $this->_loadUserData(); + if ($this->users === null) $this->loadUserData(); foreach($this->users as $user => $info) { $groups = array_merge($groups, array_diff($info['grps'], $groups)); } @@ -334,7 +348,8 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param string $user * @return string */ - public function cleanUser($user) { + public function cleanUser($user) + { global $conf; return cleanID(str_replace(':', $conf['sepchar'], $user)); } @@ -345,7 +360,8 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param string $group * @return string */ - public function cleanGroup($group) { + public function cleanGroup($group) + { global $conf; return cleanID(str_replace(':', $conf['sepchar'], $group)); } @@ -357,15 +373,16 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * * @author Andreas Gohr <andi@splitbrain.org> */ - protected function _loadUserData() { + protected function loadUserData() + { global $config_cascade; - $this->users = $this->_readUserFile($config_cascade['plainauth.users']['default']); + $this->users = $this->readUserFile($config_cascade['plainauth.users']['default']); // support protected users - if(!empty($config_cascade['plainauth.users']['protected'])) { - $protected = $this->_readUserFile($config_cascade['plainauth.users']['protected']); - foreach(array_keys($protected) as $key) { + if (!empty($config_cascade['plainauth.users']['protected'])) { + $protected = $this->readUserFile($config_cascade['plainauth.users']['protected']); + foreach (array_keys($protected) as $key) { $protected[$key]['protected'] = true; } $this->users = array_merge($this->users, $protected); @@ -380,17 +397,18 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param string $file the file to load data from * @return array */ - protected function _readUserFile($file) { + protected function readUserFile($file) + { $users = array(); - if(!file_exists($file)) return $users; + if (!file_exists($file)) return $users; $lines = file($file); - foreach($lines as $line) { + foreach ($lines as $line) { $line = preg_replace('/#.*$/', '', $line); //ignore comments $line = trim($line); - if(empty($line)) continue; + if (empty($line)) continue; - $row = $this->_splitUserData($line); + $row = $this->splitUserData($line); $row = str_replace('\\:', ':', $row); $row = str_replace('\\\\', '\\', $row); @@ -404,22 +422,29 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { return $users; } - protected function _splitUserData($line){ + /** + * Get the user line split into it's parts + * + * @param string $line + * @return string[] + */ + protected function splitUserData($line) + { // due to a bug in PCRE 6.6, preg_split will fail with the regex we use here // refer github issues 877 & 885 - if ($this->_pregsplit_safe){ + if ($this->pregsplit_safe) { return preg_split('/(?<![^\\\\]\\\\)\:/', $line, 5); // allow for : escaped as \: } $row = array(); $piece = ''; $len = strlen($line); - for($i=0; $i<$len; $i++){ - if ($line[$i]=='\\'){ + for ($i=0; $i<$len; $i++) { + if ($line[$i]=='\\') { $piece .= $line[$i]; $i++; if ($i>=$len) break; - } else if ($line[$i]==':'){ + } elseif ($line[$i]==':') { $row[] = $piece; $piece = ''; continue; @@ -440,14 +465,15 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * @param array $info User's userinfo array * @return bool */ - protected function _filter($user, $info) { - foreach($this->_pattern as $item => $pattern) { - if($item == 'user') { - if(!preg_match($pattern, $user)) return false; - } else if($item == 'grps') { - if(!count(preg_grep($pattern, $info['grps']))) return false; + protected function filter($user, $info) + { + foreach ($this->pattern as $item => $pattern) { + if ($item == 'user') { + if (!preg_match($pattern, $user)) return false; + } elseif ($item == 'grps') { + if (!count(preg_grep($pattern, $info['grps']))) return false; } else { - if(!preg_match($pattern, $info[$item])) return false; + if (!preg_match($pattern, $info[$item])) return false; } } return true; @@ -458,10 +484,11 @@ class auth_plugin_authplain extends DokuWiki_Auth_Plugin { * * @param array $filter */ - protected function _constructPattern($filter) { - $this->_pattern = array(); - foreach($filter as $item => $pattern) { - $this->_pattern[$item] = '/'.str_replace('/', '\/', $pattern).'/i'; // allow regex characters + protected function constructPattern($filter) + { + $this->pattern = array(); + foreach ($filter as $item => $pattern) { + $this->pattern[$item] = '/'.str_replace('/', '\/', $pattern).'/i'; // allow regex characters } } } diff --git a/lib/plugins/cli.php b/lib/plugins/cli.php index 721f54779..a3cbec722 100644 --- a/lib/plugins/cli.php +++ b/lib/plugins/cli.php @@ -1,11 +1,2 @@ <?php - -/** - * Base class for CLI plugins - * - * Provides DokuWiki plugin functionality on top of phpcli - */ -abstract class DokuWiki_CLI_Plugin extends \splitbrain\phpcli\CLI implements DokuWiki_PluginInterface { - use DokuWiki_PluginTrait; - -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/config/_test/configuration.test.php b/lib/plugins/config/_test/ConfigParserTest.php index 7455461a4..b7e33a539 100644 --- a/lib/plugins/config/_test/configuration.test.php +++ b/lib/plugins/config/_test/ConfigParserTest.php @@ -1,31 +1,20 @@ <?php + +namespace dokuwiki\plugin\config\test; + +use dokuwiki\plugin\config\core\ConfigParser; + /** * @group plugin_config * @group admin_plugins * @group plugins * @group bundled_plugins */ - -class plugin_config_configuration_test extends DokuWikiTest { - - private $config = ''; - private $meta = ''; - - /** - * Load config files - */ - function __construct() { - parent::__construct(); - - $this->config = dirname(__FILE__).'/data/config.php'; - $this->meta = dirname(__FILE__).'/data/metadata.php'; - require_once(dirname(__FILE__).'/../settings/config.class.php'); - } +class ConfigParserTest extends \DokuWikiTest { function test_readconfig() { - $confmgr = new configuration($this->meta); - - $conf = $confmgr->_read_config($this->config); + $parser = new ConfigParser(); + $conf = $parser->parse(__DIR__ . '/data/config.php'); // var_dump($conf); @@ -42,9 +31,8 @@ class plugin_config_configuration_test extends DokuWikiTest { } function test_readconfig_onoff() { - $confmgr = new configuration($this->meta); - - $conf = $confmgr->_read_config($this->config); + $parser = new ConfigParser(); + $conf = $parser->parse(__DIR__ . '/data/config.php'); // var_dump($conf); diff --git a/lib/plugins/config/_test/LoaderTest.php b/lib/plugins/config/_test/LoaderTest.php new file mode 100644 index 000000000..0c315842d --- /dev/null +++ b/lib/plugins/config/_test/LoaderTest.php @@ -0,0 +1,79 @@ +<?php + +namespace dokuwiki\plugin\config\test; + +use dokuwiki\plugin\config\core\ConfigParser; +use dokuwiki\plugin\config\core\Loader; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class LoaderTest extends \DokuWikiTest { + + protected $pluginsEnabled = ['testing']; + + /** + * Ensure loading the config meta data works + */ + public function testMetaData() { + $loader = new Loader(new ConfigParser()); + + $meta = $loader->loadMeta(); + $this->assertTrue(is_array($meta)); + + // there should be some defaults + $this->assertArrayHasKey('savedir', $meta); + $this->assertEquals(['savedir', '_caution' => 'danger'], $meta['savedir']); + $this->assertArrayHasKey('proxy____port', $meta); + $this->assertEquals(['numericopt'], $meta['proxy____port']); + + // there should be plugin info + $this->assertArrayHasKey('plugin____testing____plugin_settings_name', $meta); + $this->assertEquals(['fieldset'], $meta['plugin____testing____plugin_settings_name']); + $this->assertArrayHasKey('plugin____testing____schnibble', $meta); + $this->assertEquals(['onoff'], $meta['plugin____testing____schnibble']); + } + + /** + * Ensure loading the defaults work + */ + public function testDefaults() { + $loader = new Loader(new ConfigParser()); + + $conf = $loader->loadDefaults(); + $this->assertTrue(is_array($conf)); + + // basic defaults + $this->assertArrayHasKey('title', $conf); + $this->assertEquals('DokuWiki', $conf['title']); + + // plugin defaults + $this->assertArrayHasKey('plugin____testing____schnibble', $conf); + $this->assertEquals(0, $conf['plugin____testing____schnibble']); + } + + /** + * Ensure language loading works + */ + public function testLangs() { + $loader = new Loader(new ConfigParser()); + + $lang = $loader->loadLangs(); + $this->assertTrue(is_array($lang)); + + // basics are not included in the returned array! + $this->assertArrayNotHasKey('title', $lang); + + // plugin strings + $this->assertArrayHasKey('plugin____testing____plugin_settings_name', $lang); + $this->assertEquals('Testing', $lang['plugin____testing____plugin_settings_name']); + $this->assertArrayHasKey('plugin____testing____schnibble', $lang); + $this->assertEquals( + 'Turns on the schnibble before the frobble is used', + $lang['plugin____testing____schnibble'] + ); + } +} diff --git a/lib/plugins/config/_test/Setting/AbstractSettingTest.php b/lib/plugins/config/_test/Setting/AbstractSettingTest.php new file mode 100644 index 000000000..d18f0ec17 --- /dev/null +++ b/lib/plugins/config/_test/Setting/AbstractSettingTest.php @@ -0,0 +1,99 @@ +<?php + +namespace dokuwiki\plugin\config\test\Setting; + +use dokuwiki\plugin\config\core\Setting\Setting; + +abstract class AbstractSettingTest extends \DokuWikiTest { + + /** @var string the class to test */ + protected $class; + + /** + * Sets up the proper class to test based on the test's class name + * @throws \Exception + */ + public function setUp() { + parent::setUp(); + $class = get_class($this); + $class = substr($class, strrpos($class, '\\') + 1, -4); + $class = 'dokuwiki\\plugin\\config\\core\\Setting\\' . $class; + $this->class = $class; + } + + public function testInitialBasics() { + /** @var Setting $setting */ + $setting = new $this->class('test'); + $this->assertEquals('test', $setting->getKey()); + $this->assertSame(false, $setting->isProtected()); + $this->assertSame(true, $setting->isDefault()); + $this->assertSame(false, $setting->hasError()); + $this->assertSame(false, $setting->shouldBeSaved()); + } + + public function testShouldHaveDefault() { + /** @var Setting $setting */ + $setting = new $this->class('test'); + $this->assertSame(true, $setting->shouldHaveDefault()); + } + + public function testPrettyKey() { + /** @var Setting $setting */ + $setting = new $this->class('test'); + $this->assertEquals('test', $setting->getPrettyKey(false)); + + $setting = new $this->class('test____foo'); + $this->assertEquals('test»foo', $setting->getPrettyKey(false)); + + $setting = new $this->class('test'); + $this->assertEquals( + '<a href="http://www.dokuwiki.org/config:test">test</a>', + $setting->getPrettyKey(true) + ); + + $setting = new $this->class('test____foo'); + $this->assertEquals('test»foo', $setting->getPrettyKey(true)); + + $setting = new $this->class('start'); + $this->assertEquals( + '<a href="http://www.dokuwiki.org/config:startpage">start</a>', + $setting->getPrettyKey(true) + ); + } + + public function testType() { + /** @var Setting $setting */ + $setting = new $this->class('test'); + $this->assertEquals('dokuwiki', $setting->getType()); + + $setting = new $this->class('test_foo'); + $this->assertEquals('dokuwiki', $setting->getType()); + + $setting = new $this->class('plugin____test'); + $this->assertEquals('plugin', $setting->getType()); + + $setting = new $this->class('tpl____test'); + $this->assertEquals('template', $setting->getType()); + } + + public function testCaution() { + /** @var Setting $setting */ + $setting = new $this->class('test'); + $this->assertEquals(false, $setting->caution()); + + $setting = new $this->class('test', ['_caution' => 'warning']); + $this->assertEquals('warning', $setting->caution()); + + $setting = new $this->class('test', ['_caution' => 'danger']); + $this->assertEquals('danger', $setting->caution()); + + $setting = new $this->class('test', ['_caution' => 'security']); + $this->assertEquals('security', $setting->caution()); + + $setting = new $this->class('test', ['_caution' => 'flargh']); + $this->expectException(\RuntimeException::class); + $setting->caution(); + } + + +} diff --git a/lib/plugins/config/_test/Setting/SettingArrayTest.php b/lib/plugins/config/_test/Setting/SettingArrayTest.php new file mode 100644 index 000000000..09dcf1421 --- /dev/null +++ b/lib/plugins/config/_test/Setting/SettingArrayTest.php @@ -0,0 +1,20 @@ +<?php + +namespace dokuwiki\plugin\config\test\Setting; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class SettingArrayTest extends SettingTest { + + /** @inheritdoc */ + public function dataOut() { + return [ + [ ['foo','bar'], "\$conf['test'] = array('foo', 'bar');\n"] + ]; + } + +} diff --git a/lib/plugins/config/_test/Setting/SettingNumericTest.php b/lib/plugins/config/_test/Setting/SettingNumericTest.php new file mode 100644 index 000000000..6248a06b7 --- /dev/null +++ b/lib/plugins/config/_test/Setting/SettingNumericTest.php @@ -0,0 +1,24 @@ +<?php + +namespace dokuwiki\plugin\config\test\Setting; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class SettingNumericTest extends SettingTest { + + /** @inheritdoc */ + public function dataOut() { + return [ + [42, "\$conf['test'] = 42;\n"], + [0, "\$conf['test'] = 0;\n"], + [-42, "\$conf['test'] = -42;\n"], + [-42.13, "\$conf['test'] = -42.13;\n"], + ['12*13', "\$conf['test'] = 12*13;\n"], + ]; + } + +} diff --git a/lib/plugins/config/_test/Setting/SettingNumericoptTest.php b/lib/plugins/config/_test/Setting/SettingNumericoptTest.php new file mode 100644 index 000000000..9d29f31e7 --- /dev/null +++ b/lib/plugins/config/_test/Setting/SettingNumericoptTest.php @@ -0,0 +1,23 @@ +<?php + +namespace dokuwiki\plugin\config\test\Setting; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class SettingNumericoptTest extends SettingNumericTest { + + /** @inheritdoc */ + public function dataOut() { + return array_merge( + parent::dataOut(), + [ + ['', "\$conf['test'] = '';\n"], + ] + ); + } + +} diff --git a/lib/plugins/config/_test/Setting/SettingOnoffTest.php b/lib/plugins/config/_test/Setting/SettingOnoffTest.php new file mode 100644 index 000000000..d6561bdf1 --- /dev/null +++ b/lib/plugins/config/_test/Setting/SettingOnoffTest.php @@ -0,0 +1,72 @@ +<?php + +namespace dokuwiki\plugin\config\test\Setting; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class SettingOnoffTest extends SettingTest { + + /** @inheritdoc */ + public function dataOut() { + return [ + [1, "\$conf['test'] = 1;\n"], + [0, "\$conf['test'] = 0;\n"], + + ['1', "\$conf['test'] = 1;\n"], + ['0', "\$conf['test'] = 0;\n"], + + ['on', "\$conf['test'] = 1;\n"], + ['off', "\$conf['test'] = 0;\n"], + + ['true', "\$conf['test'] = 1;\n"], + ['false', "\$conf['test'] = 0;\n"], + + ['On', "\$conf['test'] = 1;\n"], + ['Off', "\$conf['test'] = 0;\n"], + + ['True', "\$conf['test'] = 1;\n"], + ['False', "\$conf['test'] = 0;\n"], + + [true, "\$conf['test'] = 1;\n"], + [false, "\$conf['test'] = 0;\n"], + + [3, "\$conf['test'] = 1;\n"], + ['3', "\$conf['test'] = 1;\n"], + + ['', "\$conf['test'] = 0;\n"], + [' ', "\$conf['test'] = 0;\n"], + ]; + } + + /** @inheritdoc */ + public function dataShouldBeSaved() { + return [ + [0, null, false], + [1, null, false], + [0, 0, false], + [1, 1, false], + [0, 1, true], + [1, 0, true], + + ['0', '0', false], + ['1', '1', false], + ['0', '1', true], + ['1', '0', true], + + ['0', 0, false], + ['1', 1, false], + ['0', 1, true], + ['1', 0, true], + + [0, '0', false], + [1, '1', false], + [0, '1', true], + [1, '0', true], + ]; + } + +} diff --git a/lib/plugins/config/_test/Setting/SettingStringTest.php b/lib/plugins/config/_test/Setting/SettingStringTest.php new file mode 100644 index 000000000..3d6a71c9d --- /dev/null +++ b/lib/plugins/config/_test/Setting/SettingStringTest.php @@ -0,0 +1,13 @@ +<?php + +namespace dokuwiki\plugin\config\test\Setting; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class SettingStringTest extends SettingTest { + +} diff --git a/lib/plugins/config/_test/Setting/SettingTest.php b/lib/plugins/config/_test/Setting/SettingTest.php new file mode 100644 index 000000000..49e0662e0 --- /dev/null +++ b/lib/plugins/config/_test/Setting/SettingTest.php @@ -0,0 +1,70 @@ +<?php + +namespace dokuwiki\plugin\config\test\Setting; + +use dokuwiki\plugin\config\core\Setting\Setting; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class SettingTest extends AbstractSettingTest { + + /** + * Dataprovider for testOut() + * + * @return array + */ + public function dataOut() { + return [ + ['bar', "\$conf['test'] = 'bar';\n"], + ["foo'bar", "\$conf['test'] = 'foo\\'bar';\n"], + ]; + } + + /** + * Check the output + * + * @param mixed $in The value to initialize the setting with + * @param string $out The expected output (for conf[test]) + * @dataProvider dataOut + */ + public function testOut($in, $out) { + /** @var Setting $setting */ + $setting = new $this->class('test'); + $setting->initialize('ignore', $in); + + $this->assertEquals($out, $setting->out('conf')); + } + + /** + * DataProvider for testShouldBeSaved() + * + * @return array + */ + public function dataShouldBeSaved() { + return [ + ['default', null, false], + ['default', 'default', false], + ['default', 'new', true], + ]; + } + + /** + * Check if shouldBeSaved works as expected + * + * @dataProvider dataShouldBeSaved + * @param mixed $default The default value + * @param mixed $local The current local value + * @param bool $expect The expected outcome + */ + public function testShouldBeSaved($default, $local, $expect) { + /** @var Setting $setting */ + $setting = new $this->class('test'); + $setting->initialize($default, $local, null); + $this->assertSame($expect, $setting->shouldBeSaved()); + } + +} diff --git a/lib/plugins/config/_test/WriterTest.php b/lib/plugins/config/_test/WriterTest.php new file mode 100644 index 000000000..62e4a56d5 --- /dev/null +++ b/lib/plugins/config/_test/WriterTest.php @@ -0,0 +1,63 @@ +<?php + +namespace dokuwiki\plugin\config\test; +use dokuwiki\plugin\config\core\Setting\SettingString; +use dokuwiki\plugin\config\core\Writer; + +/** + * @group plugin_config + * @group admin_plugins + * @group plugins + * @group bundled_plugins + */ +class WriterTest extends \DokuWikiTest { + + public function testSave() { + global $config_cascade; + $config = end($config_cascade['main']['local']); + + $set1 = new SettingString('test1'); + $set1->initialize('foo','bar', null); + $set2 = new SettingString('test2'); + $set2->initialize('foo','foo', null); + $settings = [$set1, $set2]; + $writer = new Writer(); + + // before running, no backup should exist + $this->assertFileExists($config); + $this->assertFileNotExists("$config.bak"); + $old = filesize($config); + + /** @noinspection PhpUnhandledExceptionInspection */ + $writer->save($settings); + + // after running, both should exist + $this->assertFileExists($config); + $this->assertFileExists("$config.bak"); + $this->assertEquals($old, filesize("$config.bak"), 'backup should have size of old file'); + + // check contents + $conf = []; + include $config; + $this->assertArrayHasKey('test1', $conf); + $this->assertEquals('bar', $conf['test1']); + $this->assertArrayNotHasKey('test2', $conf); + + /** @noinspection PhpUnhandledExceptionInspection */ + $writer->save($settings); + $this->assertEquals(filesize($config), filesize("$config.bak")); + } + + public function testTouch() { + global $config_cascade; + $config = end($config_cascade['main']['local']); + $writer = new Writer(); + + $old = filemtime($config); + $this->waitForTick(true); + /** @noinspection PhpUnhandledExceptionInspection */ + $writer->touch(); + clearstatcache($config); + $this->assertGreaterThan($old, filemtime($config)); + } +} diff --git a/lib/plugins/config/admin.php b/lib/plugins/config/admin.php index 2ced6efbd..219612cf1 100644 --- a/lib/plugins/config/admin.php +++ b/lib/plugins/config/admin.php @@ -6,17 +6,11 @@ * @author Christopher Smith <chris@jalakai.co.uk> * @author Ben Coburn <btcoburn@silicodon.net> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); -define('CM_KEYMARKER','____'); // used for settings with multiple dimensions of array indices - -define('PLUGIN_SELF',dirname(__FILE__).'/'); -define('PLUGIN_METADATA',PLUGIN_SELF.'settings/config.metadata.php'); -if(!defined('DOKU_PLUGIN_IMAGES')) define('DOKU_PLUGIN_IMAGES',DOKU_BASE.'lib/plugins/config/images/'); - -require_once(PLUGIN_SELF.'settings/config.class.php'); // main configuration class and generic settings classes -require_once(PLUGIN_SELF.'settings/extra.class.php'); // settings classes specific to these settings +use dokuwiki\plugin\config\core\Configuration; +use dokuwiki\plugin\config\core\Setting\Setting; +use dokuwiki\plugin\config\core\Setting\SettingFieldset; +use dokuwiki\plugin\config\core\Setting\SettingHidden; /** * All DokuWiki plugins to extend the admin function @@ -24,18 +18,17 @@ require_once(PLUGIN_SELF.'settings/extra.class.php'); // settings classes spec */ class admin_plugin_config extends DokuWiki_Admin_Plugin { - protected $_file = PLUGIN_METADATA; - protected $_config = null; - protected $_input = null; - protected $_changed = false; // set to true if configuration has altered - protected $_error = false; - protected $_session_started = false; - protected $_localised_prompts = false; + const IMGDIR = DOKU_BASE . 'lib/plugins/config/images/'; + + /** @var Configuration */ + protected $configuration; + + /** @var bool were there any errors in the submitted data? */ + protected $hasErrors = false; + + /** @var bool have the settings translations been loaded? */ + protected $promptsLocalized = false; - /** - * @return int - */ - public function getMenuSort() { return 100; } /** * handle user request @@ -43,44 +36,33 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { public function handle() { global $ID, $INPUT; - if(!$this->_restore_session() || $INPUT->int('save') != 1 || !checkSecurityToken()) { - $this->_close_session(); - return; - } + // always initialize the configuration + $this->configuration = new Configuration(); - if(is_null($this->_config)) { - $this->_config = new configuration($this->_file); - } - - // don't go any further if the configuration is locked - if($this->_config->locked) { - $this->_close_session(); + if(!$INPUT->bool('save') || !checkSecurityToken()) { return; } - $this->_input = $INPUT->arr('config'); - - foreach ($this->_config->setting as $key => $value){ - $input = isset($this->_input[$key]) ? $this->_input[$key] : null; - if ($this->_config->setting[$key]->update($input)) { - $this->_changed = true; + // don't go any further if the configuration is locked + if($this->configuration->isLocked()) return; + + // update settings and redirect of successful + $ok = $this->configuration->updateSettings($INPUT->arr('config')); + if($ok) { // no errors + try { + if($this->configuration->hasChanged()) { + $this->configuration->save(); + } else { + $this->configuration->touch(); + } + msg($this->getLang('updated'), 1); + } catch(Exception $e) { + msg($this->getLang('error'), -1); } - if ($this->_config->setting[$key]->error()) $this->_error = true; + send_redirect(wl($ID, array('do' => 'admin', 'page' => 'config'), true, '&')); + } else { + $this->hasErrors = true; } - - if ($this->_changed && !$this->_error) { - $this->_config->save_settings($this->getPluginName()); - - // save state & force a page reload to get the new settings to take effect - $_SESSION['PLUGIN_CONFIG'] = array('state' => 'updated', 'time' => time()); - $this->_close_session(); - send_redirect(wl($ID, array('do'=>'admin','page'=>'config'), true, '&')); - exit(); - } elseif(!$this->_error) { - $this->_config->touch_settings(); // just touch to refresh cache - } - - $this->_close_session(); } /** @@ -91,234 +73,137 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { global $lang; global $ID; - if (is_null($this->_config)) { $this->_config = new configuration($this->_file); } $this->setupLocale(true); - print $this->locale_xhtml('intro'); + echo $this->locale_xhtml('intro'); - ptln('<div id="config__manager">'); + echo '<div id="config__manager">'; - if ($this->_config->locked) - ptln('<div class="info">'.$this->getLang('locked').'</div>'); - elseif ($this->_error) - ptln('<div class="error">'.$this->getLang('error').'</div>'); - elseif ($this->_changed) - ptln('<div class="success">'.$this->getLang('updated').'</div>'); + if($this->configuration->isLocked()) { + echo '<div class="info">' . $this->getLang('locked') . '</div>'; + } // POST to script() instead of wl($ID) so config manager still works if // rewrite config is broken. Add $ID as hidden field to remember // current ID in most cases. - ptln('<form id="dw__configform" action="'.script().'" method="post">'); - ptln('<div class="no"><input type="hidden" name="id" value="'.$ID.'" /></div>'); + echo '<form id="dw__configform" action="' . script() . '" method="post">'; + echo '<div class="no"><input type="hidden" name="id" value="' . $ID . '" /></div>'; formSecurityToken(); - $this->_print_h1('dokuwiki_settings', $this->getLang('_header_dokuwiki')); + $this->printH1('dokuwiki_settings', $this->getLang('_header_dokuwiki')); - /** @var setting[] $undefined_settings */ - $undefined_settings = array(); $in_fieldset = false; $first_plugin_fieldset = true; $first_template_fieldset = true; - foreach($this->_config->setting as $setting) { - if (is_a($setting, 'setting_hidden')) { - // skip hidden (and undefined) settings - if ($allow_debug && is_a($setting, 'setting_undefined')) { - $undefined_settings[] = $setting; - } else { - continue; - } - } else if (is_a($setting, 'setting_fieldset')) { + foreach($this->configuration->getSettings() as $setting) { + if(is_a($setting, SettingHidden::class)) { + continue; + } else if(is_a($setting, settingFieldset::class)) { // config setting group - if ($in_fieldset) { - ptln(' </table>'); - ptln(' </div>'); - ptln(' </fieldset>'); + if($in_fieldset) { + echo '</table>'; + echo '</div>'; + echo '</fieldset>'; } else { $in_fieldset = true; } - if ($first_plugin_fieldset && substr($setting->_key, 0, 10)=='plugin'.CM_KEYMARKER) { - $this->_print_h1('plugin_settings', $this->getLang('_header_plugin')); + if($first_plugin_fieldset && $setting->getType() == 'plugin') { + $this->printH1('plugin_settings', $this->getLang('_header_plugin')); $first_plugin_fieldset = false; - } else if ($first_template_fieldset && substr($setting->_key, 0, 7)=='tpl'.CM_KEYMARKER) { - $this->_print_h1('template_settings', $this->getLang('_header_template')); + } else if($first_template_fieldset && $setting->getType() == 'template') { + $this->printH1('template_settings', $this->getLang('_header_template')); $first_template_fieldset = false; } - ptln(' <fieldset id="'.$setting->_key.'">'); - ptln(' <legend>'.$setting->prompt($this).'</legend>'); - ptln(' <div class="table">'); - ptln(' <table class="inline">'); + echo '<fieldset id="' . $setting->getKey() . '">'; + echo '<legend>' . $setting->prompt($this) . '</legend>'; + echo '<div class="table">'; + echo '<table class="inline">'; } else { // config settings - list($label,$input) = $setting->html($this, $this->_error); - - $class = $setting->is_default() ? ' class="default"' : ($setting->is_protected() ? ' class="protected"' : ''); - $error = $setting->error() ? ' class="value error"' : ' class="value"'; - $icon = $setting->caution() ? '<img src="'.DOKU_PLUGIN_IMAGES.$setting->caution().'.png" alt="'.$setting->caution().'" title="'.$this->getLang($setting->caution()).'" />' : ''; - - ptln(' <tr'.$class.'>'); - ptln(' <td class="label">'); - ptln(' <span class="outkey">'.$setting->_out_key(true, true).'</span>'); - ptln(' '.$icon.$label); - ptln(' </td>'); - ptln(' <td'.$error.'>'.$input.'</td>'); - ptln(' </tr>'); + list($label, $input) = $setting->html($this, $this->hasErrors); + + $class = $setting->isDefault() + ? ' class="default"' + : ($setting->isProtected() ? ' class="protected"' : ''); + $error = $setting->hasError() + ? ' class="value error"' + : ' class="value"'; + $icon = $setting->caution() + ? '<img src="' . self::IMGDIR . $setting->caution() . '.png" ' . + 'alt="' . $setting->caution() . '" title="' . $this->getLang($setting->caution()) . '" />' + : ''; + + echo '<tr' . $class . '>'; + echo '<td class="label">'; + echo '<span class="outkey">' . $setting->getPrettyKey() . '</span>'; + echo $icon . $label; + echo '</td>'; + echo '<td' . $error . '>' . $input . '</td>'; + echo '</tr>'; } } - ptln(' </table>'); - ptln(' </div>'); - if ($in_fieldset) { - ptln(' </fieldset>'); + echo '</table>'; + echo '</div>'; + if($in_fieldset) { + echo '</fieldset>'; } // show undefined settings list - if ($allow_debug && !empty($undefined_settings)) { + $undefined_settings = $this->configuration->getUndefined(); + if($allow_debug && !empty($undefined_settings)) { /** * Callback for sorting settings * - * @param setting $a - * @param setting $b + * @param Setting $a + * @param Setting $b * @return int if $a is lower/equal/higher than $b */ - function _setting_natural_comparison($a, $b) { - return strnatcmp($a->_key, $b->_key); + function settingNaturalComparison($a, $b) { + return strnatcmp($a->getKey(), $b->getKey()); } - usort($undefined_settings, '_setting_natural_comparison'); - $this->_print_h1('undefined_settings', $this->getLang('_header_undefined')); - ptln('<fieldset>'); - ptln('<div class="table">'); - ptln('<table class="inline">'); - $undefined_setting_match = array(); + usort($undefined_settings, 'settingNaturalComparison'); + $this->printH1('undefined_settings', $this->getLang('_header_undefined')); + echo '<fieldset>'; + echo '<div class="table">'; + echo '<table class="inline">'; foreach($undefined_settings as $setting) { - if (preg_match('/^(?:plugin|tpl)'.CM_KEYMARKER.'.*?'.CM_KEYMARKER.'(.*)$/', $setting->_key, $undefined_setting_match)) { - $undefined_setting_key = $undefined_setting_match[1]; - } else { - $undefined_setting_key = $setting->_key; - } - ptln(' <tr>'); - ptln(' <td class="label"><span title="$meta[\''.$undefined_setting_key.'\']">$'.$this->_config->_name.'[\''.$setting->_out_key().'\']</span></td>'); - ptln(' <td>'.$this->getLang('_msg_'.get_class($setting)).'</td>'); - ptln(' </tr>'); + list($label, $input) = $setting->html($this); + echo '<tr>'; + echo '<td class="label">' . $label . '</td>'; + echo '<td>' . $input . '</td>'; + echo '</tr>'; } - ptln('</table>'); - ptln('</div>'); - ptln('</fieldset>'); + echo '</table>'; + echo '</div>'; + echo '</fieldset>'; } // finish up form - ptln('<p>'); - ptln(' <input type="hidden" name="do" value="admin" />'); - ptln(' <input type="hidden" name="page" value="config" />'); - - if (!$this->_config->locked) { - ptln(' <input type="hidden" name="save" value="1" />'); - ptln(' <button type="submit" name="submit" accesskey="s">'.$lang['btn_save'].'</button>'); - ptln(' <button type="reset">'.$lang['btn_reset'].'</button>'); - } - - ptln('</p>'); - - ptln('</form>'); - ptln('</div>'); - } - - /** - * @return boolean true - proceed with handle, false - don't proceed - */ - protected function _restore_session() { - - // dokuwiki closes the session before act_dispatch. $_SESSION variables are all set, - // however they can't be changed without starting the session again - if (!headers_sent()) { - session_start(); - $this->_session_started = true; + echo '<p>'; + echo '<input type="hidden" name="do" value="admin" />'; + echo '<input type="hidden" name="page" value="config" />'; + + if(!$this->configuration->isLocked()) { + echo '<input type="hidden" name="save" value="1" />'; + echo '<button type="submit" name="submit" accesskey="s">' . $lang['btn_save'] . '</button>'; + echo '<button type="reset">' . $lang['btn_reset'] . '</button>'; } - if (!isset($_SESSION['PLUGIN_CONFIG'])) return true; + echo '</p>'; - $session = $_SESSION['PLUGIN_CONFIG']; - unset($_SESSION['PLUGIN_CONFIG']); - - // still valid? - if (time() - $session['time'] > 120) return true; - - switch ($session['state']) { - case 'updated' : - $this->_changed = true; - return false; - } - - return true; - } - - protected function _close_session() { - if ($this->_session_started) session_write_close(); + echo '</form>'; + echo '</div>'; } /** * @param bool $prompts */ - public function setupLocale($prompts=false) { - + public function setupLocale($prompts = false) { parent::setupLocale(); - if (!$prompts || $this->_localised_prompts) return; - - $this->_setup_localised_plugin_prompts(); - $this->_localised_prompts = true; - - } - - /** - * @return bool - */ - protected function _setup_localised_plugin_prompts() { - global $conf; - - $langfile = '/lang/'.$conf['lang'].'/settings.php'; - $enlangfile = '/lang/en/settings.php'; - - if ($dh = opendir(DOKU_PLUGIN)) { - while (false !== ($plugin = readdir($dh))) { - if ($plugin == '.' || $plugin == '..' || $plugin == 'tmp' || $plugin == 'config') continue; - if (is_file(DOKU_PLUGIN.$plugin)) continue; - - if (file_exists(DOKU_PLUGIN.$plugin.$enlangfile)){ - $lang = array(); - @include(DOKU_PLUGIN.$plugin.$enlangfile); - if ($conf['lang'] != 'en') @include(DOKU_PLUGIN.$plugin.$langfile); - foreach ($lang as $key => $value){ - $this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.$key] = $value; - } - } - - // fill in the plugin name if missing (should exist for plugins with settings) - if (!isset($this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'])) { - $this->lang['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'] = - ucwords(str_replace('_', ' ', $plugin)); - } - } - closedir($dh); - } - - // the same for the active template - $tpl = $conf['template']; - - if (file_exists(tpl_incdir().$enlangfile)){ - $lang = array(); - @include(tpl_incdir().$enlangfile); - if ($conf['lang'] != 'en') @include(tpl_incdir().$langfile); - foreach ($lang as $key => $value){ - $this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.$key] = $value; - } - } - - // fill in the template name if missing (should exist for templates with settings) - if (!isset($this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'])) { - $this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'] = - ucwords(str_replace('_', ' ', $tpl)); - } - - return true; + if(!$prompts || $this->promptsLocalized) return; + $this->lang = array_merge($this->lang, $this->configuration->getLangs()); + $this->promptsLocalized = true; } /** @@ -329,76 +214,69 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { * @return array */ public function getTOC() { - if (is_null($this->_config)) { $this->_config = new configuration($this->_file); } $this->setupLocale(true); $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here. + $toc = array(); + $check = false; - // gather toc data - $has_undefined = false; - $toc = array('conf'=>array(), 'plugin'=>array(), 'template'=>null); - foreach($this->_config->setting as $setting) { - if (is_a($setting, 'setting_fieldset')) { - if (substr($setting->_key, 0, 10)=='plugin'.CM_KEYMARKER) { - $toc['plugin'][] = $setting; - } else if (substr($setting->_key, 0, 7)=='tpl'.CM_KEYMARKER) { - $toc['template'] = $setting; - } else { - $toc['conf'][] = $setting; - } - } else if (!$has_undefined && is_a($setting, 'setting_undefined')) { - $has_undefined = true; + // gather settings data into three sub arrays + $labels = ['dokuwiki' => [], 'plugin' => [], 'template' => []]; + foreach($this->configuration->getSettings() as $setting) { + if(is_a($setting, SettingFieldset::class)) { + $labels[$setting->getType()][] = $setting; } } - // build toc - $t = array(); - - $check = false; + // top header $title = $this->getLang('_configuration_manager'); - $t[] = html_mktocitem(sectionID($title, $check), $title, 1); - $t[] = html_mktocitem('dokuwiki_settings', $this->getLang('_header_dokuwiki'), 1); - /** @var setting $setting */ - foreach($toc['conf'] as $setting) { - $name = $setting->prompt($this); - $t[] = html_mktocitem($setting->_key, $name, 2); - } - if (!empty($toc['plugin'])) { - $t[] = html_mktocitem('plugin_settings', $this->getLang('_header_plugin'), 1); - } - foreach($toc['plugin'] as $setting) { - $name = $setting->prompt($this); - $t[] = html_mktocitem($setting->_key, $name, 2); - } - if (isset($toc['template'])) { - $t[] = html_mktocitem('template_settings', $this->getLang('_header_template'), 1); - $setting = $toc['template']; - $name = $setting->prompt($this); - $t[] = html_mktocitem($setting->_key, $name, 2); + $toc[] = html_mktocitem(sectionID($title, $check), $title, 1); + + // main entries + foreach(['dokuwiki', 'plugin', 'template'] as $section) { + if(empty($labels[$section])) continue; // no entries, skip + + // create main header + $toc[] = html_mktocitem( + $section . '_settings', + $this->getLang('_header_' . $section), + 1 + ); + + // create sub headers + foreach($labels[$section] as $setting) { + /** @var SettingFieldset $setting */ + $name = $setting->prompt($this); + $toc[] = html_mktocitem($setting->getKey(), $name, 2); + } } - if ($has_undefined && $allow_debug) { - $t[] = html_mktocitem('undefined_settings', $this->getLang('_header_undefined'), 1); + + // undefined settings if allowed + if(count($this->configuration->getUndefined()) && $allow_debug) { + $toc[] = html_mktocitem('undefined_settings', $this->getLang('_header_undefined'), 1); } - return $t; + return $toc; } /** * @param string $id * @param string $text */ - protected function _print_h1($id, $text) { - ptln('<h1 id="'.$id.'">'.$text.'</h1>'); + protected function printH1($id, $text) { + echo '<h1 id="' . $id . '">' . $text . '</h1>'; } /** * Adds a translation to this plugin's language array * + * Used by some settings to set up dynamic translations + * * @param string $key * @param string $value */ public function addLang($key, $value) { - if (!$this->localised) $this->setupLocale(); + if(!$this->localised) $this->setupLocale(); $this->lang[$key] = $value; } } diff --git a/lib/plugins/config/core/ConfigParser.php b/lib/plugins/config/core/ConfigParser.php new file mode 100644 index 000000000..9e79b96f3 --- /dev/null +++ b/lib/plugins/config/core/ConfigParser.php @@ -0,0 +1,90 @@ +<?php + +namespace dokuwiki\plugin\config\core; + +/** + * A naive PHP file parser + * + * This parses our very simple config file in PHP format. We use this instead of simply including + * the file, because we want to keep expressions such as 24*60*60 as is. + * + * @author Chris Smith <chris@jalakai.co.uk> + */ +class ConfigParser { + /** @var string variable to parse from the file */ + protected $varname = 'conf'; + /** @var string the key to mark sub arrays */ + protected $keymarker = Configuration::KEYMARKER; + + /** + * Parse the given PHP file into an array + * + * When the given files does not exist, this returns an empty array + * + * @param string $file + * @return array + */ + public function parse($file) { + if(!file_exists($file)) return array(); + + $config = array(); + $contents = @php_strip_whitespace($file); + $pattern = '/\$' . $this->varname . '\[[\'"]([^=]+)[\'"]\] ?= ?(.*?);(?=[^;]*(?:\$' . $this->varname . '|$))/s'; + $matches = array(); + preg_match_all($pattern, $contents, $matches, PREG_SET_ORDER); + + for($i = 0; $i < count($matches); $i++) { + $value = $matches[$i][2]; + + // merge multi-dimensional array indices using the keymarker + $key = preg_replace('/.\]\[./', $this->keymarker, $matches[$i][1]); + + // handle arrays + if(preg_match('/^array ?\((.*)\)/', $value, $match)) { + $arr = explode(',', $match[1]); + + // remove quotes from quoted strings & unescape escaped data + $len = count($arr); + for($j = 0; $j < $len; $j++) { + $arr[$j] = trim($arr[$j]); + $arr[$j] = $this->readValue($arr[$j]); + } + + $value = $arr; + } else { + $value = $this->readValue($value); + } + + $config[$key] = $value; + } + + return $config; + } + + /** + * Convert php string into value + * + * @param string $value + * @return bool|string + */ + protected function readValue($value) { + $removequotes_pattern = '/^(\'|")(.*)(?<!\\\\)\1$/s'; + $unescape_pairs = array( + '\\\\' => '\\', + '\\\'' => '\'', + '\\"' => '"' + ); + + if($value == 'true') { + $value = true; + } elseif($value == 'false') { + $value = false; + } else { + // remove quotes from quoted strings & unescape escaped data + $value = preg_replace($removequotes_pattern, '$2', $value); + $value = strtr($value, $unescape_pairs); + } + return $value; + } + +} diff --git a/lib/plugins/config/core/Configuration.php b/lib/plugins/config/core/Configuration.php new file mode 100644 index 000000000..c58645c5b --- /dev/null +++ b/lib/plugins/config/core/Configuration.php @@ -0,0 +1,219 @@ +<?php + +namespace dokuwiki\plugin\config\core; + +use dokuwiki\plugin\config\core\Setting\Setting; +use dokuwiki\plugin\config\core\Setting\SettingNoClass; +use dokuwiki\plugin\config\core\Setting\SettingNoDefault; +use dokuwiki\plugin\config\core\Setting\SettingNoKnownClass; +use dokuwiki\plugin\config\core\Setting\SettingUndefined; + +/** + * Holds all the current settings and proxies the Loader and Writer + * + * @author Chris Smith <chris@jalakai.co.uk> + * @author Ben Coburn <btcoburn@silicodon.net> + * @author Andreas Gohr <andi@splitbrain.org> + */ +class Configuration { + + const KEYMARKER = '____'; + + /** @var Setting[] metadata as array of Settings objects */ + protected $settings = array(); + /** @var Setting[] undefined and problematic settings */ + protected $undefined = array(); + + /** @var array all metadata */ + protected $metadata; + /** @var array all default settings */ + protected $default; + /** @var array all local settings */ + protected $local; + /** @var array all protected settings */ + protected $protected; + + /** @var bool have the settings been changed since loading from disk? */ + protected $changed = false; + + /** @var Loader */ + protected $loader; + /** @var Writer */ + protected $writer; + + /** + * ConfigSettings constructor. + */ + public function __construct() { + $this->loader = new Loader(new ConfigParser()); + $this->writer = new Writer(); + + $this->metadata = $this->loader->loadMeta(); + $this->default = $this->loader->loadDefaults(); + $this->local = $this->loader->loadLocal(); + $this->protected = $this->loader->loadProtected(); + + $this->initSettings(); + } + + /** + * Get all settings + * + * @return Setting[] + */ + public function getSettings() { + return $this->settings; + } + + /** + * Get all unknown or problematic settings + * + * @return Setting[] + */ + public function getUndefined() { + return $this->undefined; + } + + /** + * Have the settings been changed since loading from disk? + * + * @return bool + */ + public function hasChanged() { + return $this->changed; + } + + /** + * Check if the config can be written + * + * @return bool + */ + public function isLocked() { + return $this->writer->isLocked(); + } + + /** + * Update the settings using the data provided + * + * @param array $input as posted + * @return bool true if all updates went through, false on errors + */ + public function updateSettings($input) { + $ok = true; + + foreach($this->settings as $key => $obj) { + $value = isset($input[$key]) ? $input[$key] : null; + if($obj->update($value)) { + $this->changed = true; + } + if($obj->hasError()) $ok = false; + } + + return $ok; + } + + /** + * Save the settings + * + * This save the current state as defined in this object, including the + * undefined settings + * + * @throws \Exception + */ + public function save() { + // only save the undefined settings that have not been handled in settings + $undefined = array_diff_key($this->undefined, $this->settings); + $this->writer->save(array_merge($this->settings, $undefined)); + } + + /** + * Touch the settings + * + * @throws \Exception + */ + public function touch() { + $this->writer->touch(); + } + + /** + * Load the extension language strings + * + * @return array + */ + public function getLangs() { + return $this->loader->loadLangs(); + } + + /** + * Initalizes the $settings and $undefined properties + */ + protected function initSettings() { + $keys = array_merge( + array_keys($this->metadata), + array_keys($this->default), + array_keys($this->local), + array_keys($this->protected) + ); + $keys = array_unique($keys); + + foreach($keys as $key) { + $obj = $this->instantiateClass($key); + + if($obj->shouldHaveDefault() && !isset($this->default[$key])) { + $this->undefined[$key] = new SettingNoDefault($key); + } + + $d = isset($this->default[$key]) ? $this->default[$key] : null; + $l = isset($this->local[$key]) ? $this->local[$key] : null; + $p = isset($this->protected[$key]) ? $this->protected[$key] : null; + + $obj->initialize($d, $l, $p); + } + } + + /** + * Instantiates the proper class for the given config key + * + * The class is added to the $settings or $undefined arrays and returned + * + * @param string $key + * @return Setting + */ + protected function instantiateClass($key) { + if(isset($this->metadata[$key])) { + $param = $this->metadata[$key]; + $class = $this->determineClassName(array_shift($param), $key); // first param is class + $obj = new $class($key, $param); + $this->settings[$key] = $obj; + } else { + $obj = new SettingUndefined($key); + $this->undefined[$key] = $obj; + } + return $obj; + } + + /** + * Return the class to load + * + * @param string $class the class name as given in the meta file + * @param string $key the settings key + * @return string + */ + protected function determineClassName($class, $key) { + // try namespaced class first + if(is_string($class)) { + $modern = str_replace('_', '', ucwords($class, '_')); + $modern = '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting' . $modern; + if($modern && class_exists($modern)) return $modern; + // try class as given + if(class_exists($class)) return $class; + // class wasn't found add to errors + $this->undefined[$key] = new SettingNoKnownClass($key); + } else { + // no class given, add to errors + $this->undefined[$key] = new SettingNoClass($key); + } + return '\\dokuwiki\\plugin\\config\\core\\Setting\\Setting'; + } + +} diff --git a/lib/plugins/config/core/Loader.php b/lib/plugins/config/core/Loader.php new file mode 100644 index 000000000..90ad0f50e --- /dev/null +++ b/lib/plugins/config/core/Loader.php @@ -0,0 +1,269 @@ +<?php + +namespace dokuwiki\plugin\config\core; + +use dokuwiki\Extension\Event; + +/** + * Configuration loader + * + * Loads configuration meta data and settings from the various files. Honors the + * configuration cascade and installed plugins. + */ +class Loader { + /** @var ConfigParser */ + protected $parser; + + /** @var string[] list of enabled plugins */ + protected $plugins; + /** @var string current template */ + protected $template; + + /** + * Loader constructor. + * @param ConfigParser $parser + * @triggers PLUGIN_CONFIG_PLUGINLIST + */ + public function __construct(ConfigParser $parser) { + global $conf; + $this->parser = $parser; + $this->plugins = plugin_list(); + $this->template = $conf['template']; + // allow plugins to remove configurable plugins + Event::createAndTrigger('PLUGIN_CONFIG_PLUGINLIST', $this->plugins); + } + + /** + * Read the settings meta data + * + * Reads the main file, plugins and template settings meta data + * + * @return array + */ + public function loadMeta() { + // load main file + $meta = array(); + include DOKU_PLUGIN . 'config/settings/config.metadata.php'; + + // plugins + foreach($this->plugins as $plugin) { + $meta = array_merge( + $meta, + $this->loadExtensionMeta( + DOKU_PLUGIN . $plugin . '/conf/metadata.php', + 'plugin', + $plugin + ) + ); + } + + // current template + $meta = array_merge( + $meta, + $this->loadExtensionMeta( + tpl_incdir() . '/conf/metadata.php', + 'tpl', + $this->template + ) + ); + + return $meta; + } + + /** + * Read the default values + * + * Reads the main file, plugins and template defaults + * + * @return array + */ + public function loadDefaults() { + // load main files + global $config_cascade; + $conf = $this->loadConfigs($config_cascade['main']['default']); + + // plugins + foreach($this->plugins as $plugin) { + $conf = array_merge( + $conf, + $this->loadExtensionConf( + DOKU_PLUGIN . $plugin . '/conf/default.php', + 'plugin', + $plugin + ) + ); + } + + // current template + $conf = array_merge( + $conf, + $this->loadExtensionConf( + tpl_incdir() . '/conf/default.php', + 'tpl', + $this->template + ) + ); + + return $conf; + } + + /** + * Reads the language strings + * + * Only reads extensions, main one is loaded the usual way + * + * @return array + */ + public function loadLangs() { + $lang = array(); + + // plugins + foreach($this->plugins as $plugin) { + $lang = array_merge( + $lang, + $this->loadExtensionLang( + DOKU_PLUGIN . $plugin . '/', + 'plugin', + $plugin + ) + ); + } + + // current template + $lang = array_merge( + $lang, + $this->loadExtensionLang( + tpl_incdir() . '/', + 'tpl', + $this->template + ) + ); + + return $lang; + } + + /** + * Read the local settings + * + * @return array + */ + public function loadLocal() { + global $config_cascade; + return $this->loadConfigs($config_cascade['main']['local']); + } + + /** + * Read the protected settings + * + * @return array + */ + public function loadProtected() { + global $config_cascade; + return $this->loadConfigs($config_cascade['main']['protected']); + } + + /** + * Read the config values from the given files + * + * @param string[] $files paths to config php's + * @return array + */ + protected function loadConfigs($files) { + $conf = array(); + foreach($files as $file) { + $conf = array_merge($conf, $this->parser->parse($file)); + } + return $conf; + } + + /** + * Read settings file from an extension + * + * This is used to read the settings.php files of plugins and templates + * + * @param string $file php file to read + * @param string $type should be 'plugin' or 'tpl' + * @param string $extname name of the extension + * @return array + */ + protected function loadExtensionMeta($file, $type, $extname) { + if(!file_exists($file)) return array(); + $prefix = $type . Configuration::KEYMARKER . $extname . Configuration::KEYMARKER; + + // include file + $meta = array(); + include $file; + if(empty($meta)) return array(); + + // read data + $data = array(); + $data[$prefix . $type . '_settings_name'] = ['fieldset']; + foreach($meta as $key => $value) { + if($value[0] == 'fieldset') continue; //plugins only get one fieldset + $data[$prefix . $key] = $value; + } + + return $data; + } + + /** + * Read a default file from an extension + * + * This is used to read the default.php files of plugins and templates + * + * @param string $file php file to read + * @param string $type should be 'plugin' or 'tpl' + * @param string $extname name of the extension + * @return array + */ + protected function loadExtensionConf($file, $type, $extname) { + if(!file_exists($file)) return array(); + $prefix = $type . Configuration::KEYMARKER . $extname . Configuration::KEYMARKER; + + // parse file + $conf = $this->parser->parse($file); + if(empty($conf)) return array(); + + // read data + $data = array(); + foreach($conf as $key => $value) { + $data[$prefix . $key] = $value; + } + + return $data; + } + + /** + * Read the language file of an extension + * + * @param string $dir directory of the extension + * @param string $type should be 'plugin' or 'tpl' + * @param string $extname name of the extension + * @return array + */ + protected function loadExtensionLang($dir, $type, $extname) { + global $conf; + $ll = $conf['lang']; + $prefix = $type . Configuration::KEYMARKER . $extname . Configuration::KEYMARKER; + + // include files + $lang = array(); + if(file_exists($dir . 'lang/en/settings.php')) { + include $dir . 'lang/en/settings.php'; + } + if($ll != 'en' && file_exists($dir . 'lang/' . $ll . '/settings.php')) { + include $dir . 'lang/' . $ll . '/settings.php'; + } + + // set up correct keys + $strings = array(); + foreach($lang as $key => $val) { + $strings[$prefix . $key] = $val; + } + + // add fieldset key + $strings[$prefix . $type . '_settings_name'] = ucwords(str_replace('_', ' ', $extname)); + + return $strings; + } +} diff --git a/lib/plugins/config/core/Setting/Setting.php b/lib/plugins/config/core/Setting/Setting.php new file mode 100644 index 000000000..d64f68417 --- /dev/null +++ b/lib/plugins/config/core/Setting/Setting.php @@ -0,0 +1,294 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +use dokuwiki\plugin\config\core\Configuration; + +/** + * Class Setting + */ +class Setting { + /** @var string unique identifier of this setting */ + protected $key = ''; + + /** @var mixed the default value of this setting */ + protected $default = null; + /** @var mixed the local value of this setting */ + protected $local = null; + /** @var mixed the protected value of this setting */ + protected $protected = null; + + /** @var array valid alerts, images matching the alerts are in the plugin's images directory */ + static protected $validCautions = array('warning', 'danger', 'security'); + + protected $pattern = ''; + protected $error = false; // only used by those classes which error check + protected $input = null; // only used by those classes which error check + protected $caution = null; // used by any setting to provide an alert along with the setting + + /** + * Constructor. + * + * The given parameters will be set up as class properties + * + * @see initialize() to set the actual value of the setting + * + * @param string $key + * @param array|null $params array with metadata of setting + */ + public function __construct($key, $params = null) { + $this->key = $key; + + if(is_array($params)) { + foreach($params as $property => $value) { + $property = trim($property, '_'); // we don't use underscores anymore + $this->$property = $value; + } + } + } + + /** + * Set the current values for the setting $key + * + * This is used to initialize the setting with the data read form the config files. + * + * @see update() to set a new value + * @param mixed $default default setting value + * @param mixed $local local setting value + * @param mixed $protected protected setting value + */ + public function initialize($default = null, $local = null, $protected = null) { + $this->default = $this->cleanValue($default); + $this->local = $this->cleanValue($local); + $this->protected = $this->cleanValue($protected); + } + + /** + * update changed setting with validated user provided value $input + * - if changed value fails validation check, save it to $this->input (to allow echoing later) + * - if changed value passes validation check, set $this->local to the new value + * + * @param mixed $input the new value + * @return boolean true if changed, false otherwise + */ + public function update($input) { + if(is_null($input)) return false; + if($this->isProtected()) return false; + $input = $this->cleanValue($input); + + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + + // validate new value + if($this->pattern && !preg_match($this->pattern, $input)) { + $this->error = true; + $this->input = $input; + return false; + } + + // update local copy of this setting with new value + $this->local = $input; + + // setting ready for update + return true; + } + + /** + * Clean a value read from a config before using it internally + * + * Default implementation returns $value as is. Subclasses can override. + * Note: null should always be returned as null! + * + * This is applied in initialize() and update() + * + * @param mixed $value + * @return mixed + */ + protected function cleanValue($value) { + return $value; + } + + /** + * Should this type of config have a default? + * + * @return bool + */ + public function shouldHaveDefault() { + return true; + } + + /** + * Get this setting's unique key + * + * @return string + */ + public function getKey() { + return $this->key; + } + + /** + * Get the key of this setting marked up human readable + * + * @param bool $url link to dokuwiki.org manual? + * @return string + */ + public function getPrettyKey($url = true) { + $out = str_replace(Configuration::KEYMARKER, "»", $this->key); + if($url && !strstr($out, '»')) {//provide no urls for plugins, etc. + if($out == 'start') { + // exception, because this config name is clashing with our actual start page + return '<a href="http://www.dokuwiki.org/config:startpage">' . $out . '</a>'; + } else { + return '<a href="http://www.dokuwiki.org/config:' . $out . '">' . $out . '</a>'; + } + } + return $out; + } + + /** + * Returns setting key as an array key separator + * + * This is used to create form output + * + * @return string key + */ + public function getArrayKey() { + return str_replace(Configuration::KEYMARKER, "']['", $this->key); + } + + /** + * What type of configuration is this + * + * Returns one of + * + * 'plugin' for plugin configuration + * 'template' for template configuration + * 'dokuwiki' for core configuration + * + * @return string + */ + public function getType() { + if(substr($this->getKey(), 0, 10) == 'plugin' . Configuration::KEYMARKER) { + return 'plugin'; + } else if(substr($this->getKey(), 0, 7) == 'tpl' . Configuration::KEYMARKER) { + return 'template'; + } else { + return 'dokuwiki'; + } + } + + /** + * Build html for label and input of setting + * + * @param \admin_plugin_config $plugin object of config plugin + * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting + * @return string[] with content array(string $label_html, string $input_html) + */ + public function html(\admin_plugin_config $plugin, $echo = false) { + $disable = ''; + + if($this->isProtected()) { + $value = $this->protected; + $disable = 'disabled="disabled"'; + } else { + if($echo && $this->error) { + $value = $this->input; + } else { + $value = is_null($this->local) ? $this->default : $this->local; + } + } + + $key = htmlspecialchars($this->key); + $value = formText($value); + + $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>'; + $input = '<textarea rows="3" cols="40" id="config___' . $key . + '" name="config[' . $key . ']" class="edit" ' . $disable . '>' . $value . '</textarea>'; + return array($label, $input); + } + + /** + * Should the current local value be saved? + * + * @see out() to run when this returns true + * @return bool + */ + public function shouldBeSaved() { + if($this->isProtected()) return false; + if($this->local === null) return false; + if($this->default == $this->local) return false; + return true; + } + + /** + * Generate string to save local setting value to file according to $fmt + * + * @see shouldBeSaved() to check if this should be called + * @param string $var name of variable + * @param string $fmt save format + * @return string + */ + public function out($var, $fmt = 'php') { + if($fmt != 'php') return ''; + + $tr = array("\\" => '\\\\', "'" => '\\\''); // escape the value + $out = '$' . $var . "['" . $this->getArrayKey() . "'] = '" . strtr(cleanText($this->local), $tr) . "';\n"; + + return $out; + } + + /** + * Returns the localized prompt + * + * @param \admin_plugin_config $plugin object of config plugin + * @return string text + */ + public function prompt(\admin_plugin_config $plugin) { + $prompt = $plugin->getLang($this->key); + if(!$prompt) $prompt = htmlspecialchars(str_replace(array('____', '_'), ' ', $this->key)); + return $prompt; + } + + /** + * Is setting protected + * + * @return bool + */ + public function isProtected() { + return !is_null($this->protected); + } + + /** + * Is setting the default? + * + * @return bool + */ + public function isDefault() { + return !$this->isProtected() && is_null($this->local); + } + + /** + * Has an error? + * + * @return bool + */ + public function hasError() { + return $this->error; + } + + /** + * Returns caution + * + * @return false|string caution string, otherwise false for invalid caution + */ + public function caution() { + if(empty($this->caution)) return false; + if(!in_array($this->caution, Setting::$validCautions)) { + throw new \RuntimeException( + 'Invalid caution string (' . $this->caution . ') in metadata for setting "' . $this->key . '"' + ); + } + return $this->caution; + } + +} diff --git a/lib/plugins/config/core/Setting/SettingArray.php b/lib/plugins/config/core/Setting/SettingArray.php new file mode 100644 index 000000000..c48dc760b --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingArray.php @@ -0,0 +1,105 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_array + */ +class SettingArray extends Setting { + + /** + * Create an array from a string + * + * @param string $string + * @return array + */ + protected function fromString($string) { + $array = explode(',', $string); + $array = array_map('trim', $array); + $array = array_filter($array); + $array = array_unique($array); + return $array; + } + + /** + * Create a string from an array + * + * @param array $array + * @return string + */ + protected function fromArray($array) { + return join(', ', (array) $array); + } + + /** + * update setting with user provided value $input + * if value fails error check, save it + * + * @param string $input + * @return bool true if changed, false otherwise (incl. on error) + */ + public function update($input) { + if(is_null($input)) return false; + if($this->isProtected()) return false; + + $input = $this->fromString($input); + + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + + foreach($input as $item) { + if($this->pattern && !preg_match($this->pattern, $item)) { + $this->error = true; + $this->input = $input; + return false; + } + } + + $this->local = $input; + return true; + } + + /** + * Escaping + * + * @param string $string + * @return string + */ + protected function escape($string) { + $tr = array("\\" => '\\\\', "'" => '\\\''); + return "'" . strtr(cleanText($string), $tr) . "'"; + } + + /** @inheritdoc */ + public function out($var, $fmt = 'php') { + if($fmt != 'php') return ''; + + $vals = array_map(array($this, 'escape'), $this->local); + $out = '$' . $var . "['" . $this->getArrayKey() . "'] = array(" . join(', ', $vals) . ");\n"; + return $out; + } + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + $disable = ''; + + if($this->isProtected()) { + $value = $this->protected; + $disable = 'disabled="disabled"'; + } else { + if($echo && $this->error) { + $value = $this->input; + } else { + $value = is_null($this->local) ? $this->default : $this->local; + } + } + + $key = htmlspecialchars($this->key); + $value = htmlspecialchars($this->fromArray($value)); + + $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>'; + $input = '<input id="config___' . $key . '" name="config[' . $key . + ']" type="text" class="edit" value="' . $value . '" ' . $disable . '/>'; + return array($label, $input); + } +} diff --git a/lib/plugins/config/core/Setting/SettingAuthtype.php b/lib/plugins/config/core/Setting/SettingAuthtype.php new file mode 100644 index 000000000..3a6df6fe5 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingAuthtype.php @@ -0,0 +1,60 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_authtype + */ +class SettingAuthtype extends SettingMultichoice { + + /** @inheritdoc */ + public function initialize($default = null, $local = null, $protected = null) { + /** @var $plugin_controller \dokuwiki\Extension\PluginController */ + global $plugin_controller; + + // retrieve auth types provided by plugins + foreach($plugin_controller->getList('auth') as $plugin) { + $this->choices[] = $plugin; + } + + parent::initialize($default, $local, $protected); + } + + /** @inheritdoc */ + public function update($input) { + /** @var $plugin_controller \dokuwiki\Extension\PluginController */ + global $plugin_controller; + + // is an update possible/requested? + $local = $this->local; // save this, parent::update() may change it + if(!parent::update($input)) return false; // nothing changed or an error caught by parent + $this->local = $local; // restore original, more error checking to come + + // attempt to load the plugin + $auth_plugin = $plugin_controller->load('auth', $input); + + // @TODO: throw an error in plugin controller instead of returning null + if(is_null($auth_plugin)) { + $this->error = true; + msg('Cannot load Auth Plugin "' . $input . '"', -1); + return false; + } + + // verify proper instantiation (is this really a plugin?) @TODO use instanceof? implement interface? + if(is_object($auth_plugin) && !method_exists($auth_plugin, 'getPluginName')) { + $this->error = true; + msg('Cannot create Auth Plugin "' . $input . '"', -1); + return false; + } + + // did we change the auth type? logout + global $conf; + if($conf['authtype'] != $input) { + msg('Authentication system changed. Please re-login.'); + auth_logoff(); + } + + $this->local = $input; + return true; + } +} diff --git a/lib/plugins/config/core/Setting/SettingCompression.php b/lib/plugins/config/core/Setting/SettingCompression.php new file mode 100644 index 000000000..f97d82801 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingCompression.php @@ -0,0 +1,21 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_compression + */ +class SettingCompression extends SettingMultichoice { + + protected $choices = array('0'); // 0 = no compression, always supported + + /** @inheritdoc */ + public function initialize($default = null, $local = null, $protected = null) { + + // populate _choices with the compression methods supported by this php installation + if(function_exists('gzopen')) $this->choices[] = 'gz'; + if(function_exists('bzopen')) $this->choices[] = 'bz2'; + + parent::initialize($default, $local, $protected); + } +} diff --git a/lib/plugins/config/core/Setting/SettingDirchoice.php b/lib/plugins/config/core/Setting/SettingDirchoice.php new file mode 100644 index 000000000..dfb27f5f4 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingDirchoice.php @@ -0,0 +1,33 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_dirchoice + */ +class SettingDirchoice extends SettingMultichoice { + + protected $dir = ''; + + /** @inheritdoc */ + public function initialize($default = null, $local = null, $protected = null) { + + // populate $this->_choices with a list of directories + $list = array(); + + if($dh = @opendir($this->dir)) { + while(false !== ($entry = readdir($dh))) { + if($entry == '.' || $entry == '..') continue; + if($this->pattern && !preg_match($this->pattern, $entry)) continue; + + $file = (is_link($this->dir . $entry)) ? readlink($this->dir . $entry) : $this->dir . $entry; + if(is_dir($file)) $list[] = $entry; + } + closedir($dh); + } + sort($list); + $this->choices = $list; + + parent::initialize($default, $local, $protected); + } +} diff --git a/lib/plugins/config/core/Setting/SettingDisableactions.php b/lib/plugins/config/core/Setting/SettingDisableactions.php new file mode 100644 index 000000000..2553175bd --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingDisableactions.php @@ -0,0 +1,23 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_disableactions + */ +class SettingDisableactions extends SettingMulticheckbox { + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + global $lang; + + // make some language adjustments (there must be a better way) + // transfer some DokuWiki language strings to the plugin + $plugin->addLang($this->key . '_revisions', $lang['btn_revs']); + foreach($this->choices as $choice) { + if(isset($lang['btn_' . $choice])) $plugin->addLang($this->key . '_' . $choice, $lang['btn_' . $choice]); + } + + return parent::html($plugin, $echo); + } +} diff --git a/lib/plugins/config/core/Setting/SettingEmail.php b/lib/plugins/config/core/Setting/SettingEmail.php new file mode 100644 index 000000000..25a0c0e75 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingEmail.php @@ -0,0 +1,58 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_email + */ +class SettingEmail extends SettingString { + protected $multiple = false; + protected $placeholders = false; + + /** @inheritdoc */ + public function update($input) { + if(is_null($input)) return false; + if($this->isProtected()) return false; + + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + if($input === '') { + $this->local = $input; + return true; + } + $mail = $input; + + if($this->placeholders) { + // replace variables with pseudo values + $mail = str_replace('@USER@', 'joe', $mail); + $mail = str_replace('@NAME@', 'Joe Schmoe', $mail); + $mail = str_replace('@MAIL@', 'joe@example.com', $mail); + } + + // multiple mail addresses? + if($this->multiple) { + $mails = array_filter(array_map('trim', explode(',', $mail))); + } else { + $mails = array($mail); + } + + // check them all + foreach($mails as $mail) { + // only check the address part + if(preg_match('#(.*?)<(.*?)>#', $mail, $matches)) { + $addr = $matches[2]; + } else { + $addr = $mail; + } + + if(!mail_isvalid($addr)) { + $this->error = true; + $this->input = $input; + return false; + } + } + + $this->local = $input; + return true; + } +} diff --git a/lib/plugins/config/core/Setting/SettingFieldset.php b/lib/plugins/config/core/Setting/SettingFieldset.php new file mode 100644 index 000000000..4e8618967 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingFieldset.php @@ -0,0 +1,17 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * A do-nothing class used to detect the 'fieldset' type. + * + * Used to start a new settings "display-group". + */ +class SettingFieldset extends Setting { + + /** @inheritdoc */ + public function shouldHaveDefault() { + return false; + } + +} diff --git a/lib/plugins/config/core/Setting/SettingHidden.php b/lib/plugins/config/core/Setting/SettingHidden.php new file mode 100644 index 000000000..ca8a03eb9 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingHidden.php @@ -0,0 +1,10 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_hidden + */ +class SettingHidden extends Setting { + // Used to explicitly ignore a setting in the configuration manager. +} diff --git a/lib/plugins/config/core/Setting/SettingImConvert.php b/lib/plugins/config/core/Setting/SettingImConvert.php new file mode 100644 index 000000000..8740d94c8 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingImConvert.php @@ -0,0 +1,28 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_im_convert + */ +class SettingImConvert extends SettingString { + + /** @inheritdoc */ + public function update($input) { + if($this->isProtected()) return false; + + $input = trim($input); + + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + + if($input && !file_exists($input)) { + $this->error = true; + $this->input = $input; + return false; + } + + $this->local = $input; + return true; + } +} diff --git a/lib/plugins/config/core/Setting/SettingLicense.php b/lib/plugins/config/core/Setting/SettingLicense.php new file mode 100644 index 000000000..8dacf8e25 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingLicense.php @@ -0,0 +1,23 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_license + */ +class SettingLicense extends SettingMultichoice { + + protected $choices = array(''); // none choosen + + /** @inheritdoc */ + public function initialize($default = null, $local = null, $protected = null) { + global $license; + + foreach($license as $key => $data) { + $this->choices[] = $key; + $this->lang[$this->key . '_o_' . $key] = $data['name']; // stored in setting + } + + parent::initialize($default, $local, $protected); + } +} diff --git a/lib/plugins/config/core/Setting/SettingMulticheckbox.php b/lib/plugins/config/core/Setting/SettingMulticheckbox.php new file mode 100644 index 000000000..df212cca0 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingMulticheckbox.php @@ -0,0 +1,163 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_multicheckbox + */ +class SettingMulticheckbox extends SettingString { + + protected $choices = array(); + protected $combine = array(); + protected $other = 'always'; + + /** @inheritdoc */ + public function update($input) { + if($this->isProtected()) return false; + + // split any combined values + convert from array to comma separated string + $input = ($input) ? $input : array(); + $input = $this->array2str($input); + + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + + if($this->pattern && !preg_match($this->pattern, $input)) { + $this->error = true; + $this->input = $input; + return false; + } + + $this->local = $input; + return true; + } + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + + $disable = ''; + + if($this->isProtected()) { + $value = $this->protected; + $disable = 'disabled="disabled"'; + } else { + if($echo && $this->error) { + $value = $this->input; + } else { + $value = is_null($this->local) ? $this->default : $this->local; + } + } + + $key = htmlspecialchars($this->key); + + // convert from comma separated list into array + combine complimentary actions + $value = $this->str2array($value); + $default = $this->str2array($this->default); + + $input = ''; + foreach($this->choices as $choice) { + $idx = array_search($choice, $value); + $idx_default = array_search($choice, $default); + + $checked = ($idx !== false) ? 'checked="checked"' : ''; + + // @todo ideally this would be handled using a second class of "default" + $class = (($idx !== false) == (false !== $idx_default)) ? " selectiondefault" : ""; + + $prompt = ($plugin->getLang($this->key . '_' . $choice) ? + $plugin->getLang($this->key . '_' . $choice) : htmlspecialchars($choice)); + + $input .= '<div class="selection' . $class . '">' . "\n"; + $input .= '<label for="config___' . $key . '_' . $choice . '">' . $prompt . "</label>\n"; + $input .= '<input id="config___' . $key . '_' . $choice . '" name="config[' . $key . + '][]" type="checkbox" class="checkbox" value="' . $choice . '" ' . $disable . ' ' . $checked . "/>\n"; + $input .= "</div>\n"; + + // remove this action from the disabledactions array + if($idx !== false) unset($value[$idx]); + if($idx_default !== false) unset($default[$idx_default]); + } + + // handle any remaining values + if($this->other != 'never') { + $other = join(',', $value); + // test equivalent to ($this->_other == 'always' || ($other && $this->_other == 'exists') + // use != 'exists' rather than == 'always' to ensure invalid values default to 'always' + if($this->other != 'exists' || $other) { + + $class = ( + (count($default) == count($value)) && + (count($value) == count(array_intersect($value, $default))) + ) ? + " selectiondefault" : ""; + + $input .= '<div class="other' . $class . '">' . "\n"; + $input .= '<label for="config___' . $key . '_other">' . + $plugin->getLang($key . '_other') . + "</label>\n"; + $input .= '<input id="config___' . $key . '_other" name="config[' . $key . + '][other]" type="text" class="edit" value="' . htmlspecialchars($other) . + '" ' . $disable . " />\n"; + $input .= "</div>\n"; + } + } + $label = '<label>' . $this->prompt($plugin) . '</label>'; + return array($label, $input); + } + + /** + * convert comma separated list to an array and combine any complimentary values + * + * @param string $str + * @return array + */ + protected function str2array($str) { + $array = explode(',', $str); + + if(!empty($this->combine)) { + foreach($this->combine as $key => $combinators) { + $idx = array(); + foreach($combinators as $val) { + if(($idx[] = array_search($val, $array)) === false) break; + } + + if(count($idx) && $idx[count($idx) - 1] !== false) { + foreach($idx as $i) unset($array[$i]); + $array[] = $key; + } + } + } + + return $array; + } + + /** + * convert array of values + other back to a comma separated list, incl. splitting any combined values + * + * @param array $input + * @return string + */ + protected function array2str($input) { + + // handle other + $other = trim($input['other']); + $other = !empty($other) ? explode(',', str_replace(' ', '', $input['other'])) : array(); + unset($input['other']); + + $array = array_unique(array_merge($input, $other)); + + // deconstruct any combinations + if(!empty($this->combine)) { + foreach($this->combine as $key => $combinators) { + + $idx = array_search($key, $array); + if($idx !== false) { + unset($array[$idx]); + $array = array_merge($array, $combinators); + } + } + } + + return join(',', array_unique($array)); + } +} diff --git a/lib/plugins/config/core/Setting/SettingMultichoice.php b/lib/plugins/config/core/Setting/SettingMultichoice.php new file mode 100644 index 000000000..3a50857e0 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingMultichoice.php @@ -0,0 +1,71 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_multichoice + */ +class SettingMultichoice extends SettingString { + protected $choices = array(); + public $lang; //some custom language strings are stored in setting + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + $disable = ''; + $nochoice = ''; + + if($this->isProtected()) { + $value = $this->protected; + $disable = ' disabled="disabled"'; + } else { + $value = is_null($this->local) ? $this->default : $this->local; + } + + // ensure current value is included + if(!in_array($value, $this->choices)) { + $this->choices[] = $value; + } + // disable if no other choices + if(!$this->isProtected() && count($this->choices) <= 1) { + $disable = ' disabled="disabled"'; + $nochoice = $plugin->getLang('nochoice'); + } + + $key = htmlspecialchars($this->key); + + $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>'; + + $input = "<div class=\"input\">\n"; + $input .= '<select class="edit" id="config___' . $key . '" name="config[' . $key . ']"' . $disable . '>' . "\n"; + foreach($this->choices as $choice) { + $selected = ($value == $choice) ? ' selected="selected"' : ''; + $option = $plugin->getLang($this->key . '_o_' . $choice); + if(!$option && isset($this->lang[$this->key . '_o_' . $choice])) { + $option = $this->lang[$this->key . '_o_' . $choice]; + } + if(!$option) $option = $choice; + + $choice = htmlspecialchars($choice); + $option = htmlspecialchars($option); + $input .= ' <option value="' . $choice . '"' . $selected . ' >' . $option . '</option>' . "\n"; + } + $input .= "</select> $nochoice \n"; + $input .= "</div>\n"; + + return array($label, $input); + } + + /** @inheritdoc */ + public function update($input) { + if(is_null($input)) return false; + if($this->isProtected()) return false; + + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + + if(!in_array($input, $this->choices)) return false; + + $this->local = $input; + return true; + } +} diff --git a/lib/plugins/config/core/Setting/SettingNoClass.php b/lib/plugins/config/core/Setting/SettingNoClass.php new file mode 100644 index 000000000..8efff216a --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingNoClass.php @@ -0,0 +1,12 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_no_class + * A do-nothing class used to detect settings with a missing setting class. + * Used internaly to hide undefined settings, and generate the undefined settings list. + */ +class SettingNoClass extends SettingUndefined { + protected $errorMessage = '_msg_setting_no_class'; +} diff --git a/lib/plugins/config/core/Setting/SettingNoDefault.php b/lib/plugins/config/core/Setting/SettingNoDefault.php new file mode 100644 index 000000000..07b8412dd --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingNoDefault.php @@ -0,0 +1,13 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_no_default + * + * A do-nothing class used to detect settings with no default value. + * Used internaly to hide undefined settings, and generate the undefined settings list. + */ +class SettingNoDefault extends SettingUndefined { + protected $errorMessage = '_msg_setting_no_default'; +} diff --git a/lib/plugins/config/core/Setting/SettingNoKnownClass.php b/lib/plugins/config/core/Setting/SettingNoKnownClass.php new file mode 100644 index 000000000..3c527e1ee --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingNoKnownClass.php @@ -0,0 +1,11 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * A do-nothing class used to detect settings with a missing setting class. + * Used internaly to hide undefined settings, and generate the undefined settings list. + */ +class SettingNoKnownClass extends SettingUndefined { + protected $errorMessage = '_msg_setting_no_known_class'; +} diff --git a/lib/plugins/config/core/Setting/SettingNumeric.php b/lib/plugins/config/core/Setting/SettingNumeric.php new file mode 100644 index 000000000..8a6b17956 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingNumeric.php @@ -0,0 +1,42 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_numeric + */ +class SettingNumeric extends SettingString { + // This allows for many PHP syntax errors... + // var $_pattern = '/^[-+\/*0-9 ]*$/'; + // much more restrictive, but should eliminate syntax errors. + protected $pattern = '/^[-+]? *[0-9]+ *(?:[-+*] *[0-9]+ *)*$/'; + protected $min = null; + protected $max = null; + + /** @inheritdoc */ + public function update($input) { + $local = $this->local; + $valid = parent::update($input); + if($valid && !(is_null($this->min) && is_null($this->max))) { + $numeric_local = (int) eval('return ' . $this->local . ';'); + if((!is_null($this->min) && $numeric_local < $this->min) || + (!is_null($this->max) && $numeric_local > $this->max)) { + $this->error = true; + $this->input = $input; + $this->local = $local; + $valid = false; + } + } + return $valid; + } + + /** @inheritdoc */ + public function out($var, $fmt = 'php') { + if($fmt != 'php') return ''; + + $local = $this->local === '' ? "''" : $this->local; + $out = '$' . $var . "['" . $this->getArrayKey() . "'] = " . $local . ";\n"; + + return $out; + } +} diff --git a/lib/plugins/config/core/Setting/SettingNumericopt.php b/lib/plugins/config/core/Setting/SettingNumericopt.php new file mode 100644 index 000000000..a486e187f --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingNumericopt.php @@ -0,0 +1,25 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_numericopt + */ +class SettingNumericopt extends SettingNumeric { + // just allow an empty config + protected $pattern = '/^(|[-]?[0-9]+(?:[-+*][0-9]+)*)$/'; + + /** + * @inheritdoc + * Empty string is valid for numericopt + */ + public function update($input) { + if($input === '') { + if($input == $this->local) return false; + $this->local = $input; + return true; + } + + return parent::update($input); + } +} diff --git a/lib/plugins/config/core/Setting/SettingOnoff.php b/lib/plugins/config/core/Setting/SettingOnoff.php new file mode 100644 index 000000000..780778b48 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingOnoff.php @@ -0,0 +1,57 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_onoff + */ +class SettingOnoff extends SettingNumeric { + + /** + * We treat the strings 'false' and 'off' as false + * @inheritdoc + */ + protected function cleanValue($value) { + if($value === null) return null; + + if(is_string($value)) { + if(strtolower($value) === 'false') return 0; + if(strtolower($value) === 'off') return 0; + if(trim($value) === '') return 0; + } + + return (int) (bool) $value; + } + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + $disable = ''; + + if($this->isProtected()) { + $value = $this->protected; + $disable = ' disabled="disabled"'; + } else { + $value = is_null($this->local) ? $this->default : $this->local; + } + + $key = htmlspecialchars($this->key); + $checked = ($value) ? ' checked="checked"' : ''; + + $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>'; + $input = '<div class="input"><input id="config___' . $key . '" name="config[' . $key . + ']" type="checkbox" class="checkbox" value="1"' . $checked . $disable . '/></div>'; + return array($label, $input); + } + + /** @inheritdoc */ + public function update($input) { + if($this->isProtected()) return false; + + $input = ($input) ? 1 : 0; + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + + $this->local = $input; + return true; + } +} diff --git a/lib/plugins/config/core/Setting/SettingPassword.php b/lib/plugins/config/core/Setting/SettingPassword.php new file mode 100644 index 000000000..9d9c53377 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingPassword.php @@ -0,0 +1,39 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_password + */ +class SettingPassword extends SettingString { + + protected $code = 'plain'; // mechanism to be used to obscure passwords + + /** @inheritdoc */ + public function update($input) { + if($this->isProtected()) return false; + if(!$input) return false; + + if($this->pattern && !preg_match($this->pattern, $input)) { + $this->error = true; + $this->input = $input; + return false; + } + + $this->local = conf_encodeString($input, $this->code); + return true; + } + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + + $disable = $this->isProtected() ? 'disabled="disabled"' : ''; + + $key = htmlspecialchars($this->key); + + $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>'; + $input = '<input id="config___' . $key . '" name="config[' . $key . + ']" autocomplete="off" type="password" class="edit" value="" ' . $disable . ' />'; + return array($label, $input); + } +} diff --git a/lib/plugins/config/core/Setting/SettingRegex.php b/lib/plugins/config/core/Setting/SettingRegex.php new file mode 100644 index 000000000..b38f0a560 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingRegex.php @@ -0,0 +1,34 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_regex + */ +class SettingRegex extends SettingString { + + protected $delimiter = '/'; // regex delimiter to be used in testing input + protected $pregflags = 'ui'; // regex pattern modifiers to be used in testing input + + /** @inheritdoc */ + public function update($input) { + + // let parent do basic checks, value, not changed, etc. + $local = $this->local; + if(!parent::update($input)) return false; + $this->local = $local; + + // see if the regex compiles and runs (we don't check for effectiveness) + $regex = $this->delimiter . $input . $this->delimiter . $this->pregflags; + $lastError = error_get_last(); + @preg_match($regex, 'testdata'); + if(preg_last_error() != PREG_NO_ERROR || error_get_last() != $lastError) { + $this->input = $input; + $this->error = true; + return false; + } + + $this->local = $input; + return true; + } +} diff --git a/lib/plugins/config/core/Setting/SettingRenderer.php b/lib/plugins/config/core/Setting/SettingRenderer.php new file mode 100644 index 000000000..37ba9c70a --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingRenderer.php @@ -0,0 +1,56 @@ +<?php +/** + * additional setting classes specific to these settings + * + * @author Chris Smith <chris@jalakai.co.uk> + */ + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_renderer + */ +class SettingRenderer extends SettingMultichoice { + protected $prompts = array(); + protected $format = null; + + /** @inheritdoc */ + public function initialize($default = null, $local = null, $protected = null) { + $format = $this->format; + + foreach(plugin_list('renderer') as $plugin) { + $renderer = plugin_load('renderer', $plugin); + if(method_exists($renderer, 'canRender') && $renderer->canRender($format)) { + $this->choices[] = $plugin; + + $info = $renderer->getInfo(); + $this->prompts[$plugin] = $info['name']; + } + } + + parent::initialize($default, $local, $protected); + } + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + + // make some language adjustments (there must be a better way) + // transfer some plugin names to the config plugin + foreach($this->choices as $choice) { + if(!$plugin->getLang($this->key . '_o_' . $choice)) { + if(!isset($this->prompts[$choice])) { + $plugin->addLang( + $this->key . '_o_' . $choice, + sprintf($plugin->getLang('renderer__core'), $choice) + ); + } else { + $plugin->addLang( + $this->key . '_o_' . $choice, + sprintf($plugin->getLang('renderer__plugin'), $this->prompts[$choice]) + ); + } + } + } + return parent::html($plugin, $echo); + } +} diff --git a/lib/plugins/config/core/Setting/SettingSavedir.php b/lib/plugins/config/core/Setting/SettingSavedir.php new file mode 100644 index 000000000..43e428dd3 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingSavedir.php @@ -0,0 +1,26 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_savedir + */ +class SettingSavedir extends SettingString { + + /** @inheritdoc */ + public function update($input) { + if($this->isProtected()) return false; + + $value = is_null($this->local) ? $this->default : $this->local; + if($value == $input) return false; + + if(!init_path($input)) { + $this->error = true; + $this->input = $input; + return false; + } + + $this->local = $input; + return true; + } +} diff --git a/lib/plugins/config/core/Setting/SettingSepchar.php b/lib/plugins/config/core/Setting/SettingSepchar.php new file mode 100644 index 000000000..2d64eb08b --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingSepchar.php @@ -0,0 +1,18 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_sepchar + */ +class SettingSepchar extends SettingMultichoice { + + /** @inheritdoc */ + public function __construct($key, $param = null) { + $str = '_-.'; + for($i = 0; $i < strlen($str); $i++) $this->choices[] = $str{$i}; + + // call foundation class constructor + parent::__construct($key, $param); + } +} diff --git a/lib/plugins/config/core/Setting/SettingString.php b/lib/plugins/config/core/Setting/SettingString.php new file mode 100644 index 000000000..b819407b7 --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingString.php @@ -0,0 +1,32 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +/** + * Class setting_string + */ +class SettingString extends Setting { + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + $disable = ''; + + if($this->isProtected()) { + $value = $this->protected; + $disable = 'disabled="disabled"'; + } else { + if($echo && $this->error) { + $value = $this->input; + } else { + $value = is_null($this->local) ? $this->default : $this->local; + } + } + + $key = htmlspecialchars($this->key); + $value = htmlspecialchars($value); + + $label = '<label for="config___' . $key . '">' . $this->prompt($plugin) . '</label>'; + $input = '<input id="config___' . $key . '" name="config[' . $key . + ']" type="text" class="edit" value="' . $value . '" ' . $disable . '/>'; + return array($label, $input); + } +} diff --git a/lib/plugins/config/core/Setting/SettingUndefined.php b/lib/plugins/config/core/Setting/SettingUndefined.php new file mode 100644 index 000000000..fa46a9f1d --- /dev/null +++ b/lib/plugins/config/core/Setting/SettingUndefined.php @@ -0,0 +1,40 @@ +<?php + +namespace dokuwiki\plugin\config\core\Setting; + +use dokuwiki\plugin\config\core\Configuration; + +/** + * A do-nothing class used to detect settings with no metadata entry. + * Used internaly to hide undefined settings, and generate the undefined settings list. + */ +class SettingUndefined extends SettingHidden { + + protected $errorMessage = '_msg_setting_undefined'; + + /** @inheritdoc */ + public function shouldHaveDefault() { + return false; + } + + /** @inheritdoc */ + public function html(\admin_plugin_config $plugin, $echo = false) { + // determine the name the meta key would be called + if(preg_match( + '/^(?:plugin|tpl)' . Configuration::KEYMARKER . '.*?' . Configuration::KEYMARKER . '(.*)$/', + $this->getKey(), + $undefined_setting_match + )) { + $undefined_setting_key = $undefined_setting_match[1]; + } else { + $undefined_setting_key = $this->getKey(); + } + + $label = '<span title="$meta[\'' . $undefined_setting_key . '\']">$' . + 'conf' . '[\'' . $this->getArrayKey() . '\']</span>'; + $input = $plugin->getLang($this->errorMessage); + + return array($label, $input); + } + +} diff --git a/lib/plugins/config/core/Writer.php b/lib/plugins/config/core/Writer.php new file mode 100644 index 000000000..6dee223ac --- /dev/null +++ b/lib/plugins/config/core/Writer.php @@ -0,0 +1,116 @@ +<?php + +namespace dokuwiki\plugin\config\core; +use dokuwiki\plugin\config\core\Setting\Setting; + +/** + * Writes the settings to the correct local file + */ +class Writer { + /** @var string header info */ + protected $header = 'Dokuwiki\'s Main Configuration File - Local Settings'; + + /** @var string the file where the config will be saved to */ + protected $savefile; + + /** + * Writer constructor. + */ + public function __construct() { + global $config_cascade; + $this->savefile = end($config_cascade['main']['local']); + } + + /** + * Save the given settings + * + * @param Setting[] $settings + * @throws \Exception + */ + public function save($settings) { + global $conf; + if($this->isLocked()) throw new \Exception('no save'); + + // backup current file (remove any existing backup) + if(file_exists($this->savefile)) { + if(file_exists($this->savefile . '.bak')) @unlink($this->savefile . '.bak'); + if(!io_rename($this->savefile, $this->savefile . '.bak')) throw new \Exception('no backup'); + } + + if(!$fh = @fopen($this->savefile, 'wb')) { + io_rename($this->savefile . '.bak', $this->savefile); // problem opening, restore the backup + throw new \Exception('no save'); + } + + $out = $this->getHeader(); + foreach($settings as $setting) { + if($setting->shouldBeSaved()) { + $out .= $setting->out('conf', 'php'); + } + } + + fwrite($fh, $out); + fclose($fh); + if($conf['fperm']) chmod($this->savefile, $conf['fperm']); + $this->opcacheUpdate($this->savefile); + } + + /** + * Update last modified time stamp of the config file + * + * Will invalidate all DokuWiki caches + * + * @throws \Exception when the config isn't writable + */ + public function touch() { + if($this->isLocked()) throw new \Exception('no save'); + @touch($this->savefile); + $this->opcacheUpdate($this->savefile); + } + + /** + * Invalidate the opcache of the given file + * + * @todo this should probably be moved to core + * @param string $file + */ + protected function opcacheUpdate($file) { + if(!function_exists('opcache_invalidate')) return; + opcache_invalidate($file); + } + + /** + * Configuration is considered locked if there is no local settings filename + * or the directory its in is not writable or the file exists and is not writable + * + * @return bool true: locked, false: writable + */ + public function isLocked() { + if(!$this->savefile) return true; + if(!is_writable(dirname($this->savefile))) return true; + if(file_exists($this->savefile) && !is_writable($this->savefile)) return true; + return false; + } + + /** + * Returns the PHP intro header for the config file + * + * @return string + */ + protected function getHeader() { + return join( + "\n", + array( + '<?php', + '/*', + ' * ' . $this->header, + ' * Auto-generated by config plugin', + ' * Run for user: ' . $_SERVER['REMOTE_USER'], + ' * Date: ' . date('r'), + ' */', + '', + '' + ) + ); + } +} diff --git a/lib/plugins/config/lang/en/lang.php b/lib/plugins/config/lang/en/lang.php index 63a49e36b..c48885c8d 100644 --- a/lib/plugins/config/lang/en/lang.php +++ b/lib/plugins/config/lang/en/lang.php @@ -46,6 +46,7 @@ $lang['_network'] = 'Network'; /* --- Undefined Setting Messages --- */ $lang['_msg_setting_undefined'] = 'No setting metadata.'; $lang['_msg_setting_no_class'] = 'No setting class.'; +$lang['_msg_setting_no_known_class'] = 'Setting class not available.'; $lang['_msg_setting_no_default'] = 'No default value.'; /* -------------------- Config Options --------------------------- */ diff --git a/lib/plugins/config/settings/config.class.php b/lib/plugins/config/settings/config.class.php deleted file mode 100644 index 09b9a2bec..000000000 --- a/lib/plugins/config/settings/config.class.php +++ /dev/null @@ -1,1431 +0,0 @@ -<?php -/** - * Configuration Class and generic setting classes - * - * @author Chris Smith <chris@jalakai.co.uk> - * @author Ben Coburn <btcoburn@silicodon.net> - */ - - -if(!defined('CM_KEYMARKER')) define('CM_KEYMARKER','____'); - -if (!class_exists('configuration')) { - /** - * Class configuration - */ - class configuration { - - var $_name = 'conf'; // name of the config variable found in the files (overridden by $config['varname']) - var $_format = 'php'; // format of the config file, supported formats - php (overridden by $config['format']) - var $_heading = ''; // heading string written at top of config file - don't include comment indicators - var $_loaded = false; // set to true after configuration files are loaded - var $_metadata = array(); // holds metadata describing the settings - /** @var setting[] */ - var $setting = array(); // array of setting objects - var $locked = false; // configuration is considered locked if it can't be updated - var $show_disabled_plugins = false; - - // configuration filenames - var $_default_files = array(); - var $_local_files = array(); // updated configuration is written to the first file - var $_protected_files = array(); - - var $_plugin_list = null; - - /** - * constructor - * - * @param string $datafile path to config metadata file - */ - public function __construct($datafile) { - global $conf, $config_cascade; - - if (!file_exists($datafile)) { - msg('No configuration metadata found at - '.htmlspecialchars($datafile),-1); - return; - } - $meta = array(); - include($datafile); - - if (isset($config['varname'])) $this->_name = $config['varname']; - if (isset($config['format'])) $this->_format = $config['format']; - if (isset($config['heading'])) $this->_heading = $config['heading']; - - $this->_default_files = $config_cascade['main']['default']; - $this->_local_files = $config_cascade['main']['local']; - $this->_protected_files = $config_cascade['main']['protected']; - - $this->locked = $this->_is_locked(); - $this->_metadata = array_merge($meta, $this->get_plugintpl_metadata($conf['template'])); - $this->retrieve_settings(); - } - - /** - * Retrieve and stores settings in setting[] attribute - */ - public function retrieve_settings() { - global $conf; - $no_default_check = array('setting_fieldset', 'setting_undefined', 'setting_no_class'); - - if (!$this->_loaded) { - $default = array_merge($this->get_plugintpl_default($conf['template']), $this->_read_config_group($this->_default_files)); - $local = $this->_read_config_group($this->_local_files); - $protected = $this->_read_config_group($this->_protected_files); - - $keys = array_merge(array_keys($this->_metadata),array_keys($default), array_keys($local), array_keys($protected)); - $keys = array_unique($keys); - - $param = null; - foreach ($keys as $key) { - if (isset($this->_metadata[$key])) { - $class = $this->_metadata[$key][0]; - - if($class && class_exists('setting_'.$class)){ - $class = 'setting_'.$class; - } else { - if($class != '') { - $this->setting[] = new setting_no_class($key,$param); - } - $class = 'setting'; - } - - $param = $this->_metadata[$key]; - array_shift($param); - } else { - $class = 'setting_undefined'; - $param = null; - } - - if (!in_array($class, $no_default_check) && !isset($default[$key])) { - $this->setting[] = new setting_no_default($key,$param); - } - - $this->setting[$key] = new $class($key,$param); - - $d = array_key_exists($key, $default) ? $default[$key] : null; - $l = array_key_exists($key, $local) ? $local[$key] : null; - $p = array_key_exists($key, $protected) ? $protected[$key] : null; - - $this->setting[$key]->initialize($d,$l,$p); - } - - $this->_loaded = true; - } - } - - /** - * Stores setting[] array to file - * - * @param string $id Name of plugin, which saves the settings - * @param string $header Text at the top of the rewritten settings file - * @param bool $backup backup current file? (remove any existing backup) - * @return bool succesful? - */ - public function save_settings($id, $header='', $backup=true) { - global $conf; - - if ($this->locked) return false; - - // write back to the last file in the local config cascade - $file = end($this->_local_files); - - // backup current file (remove any existing backup) - if (file_exists($file) && $backup) { - if (file_exists($file.'.bak')) @unlink($file.'.bak'); - if (!io_rename($file, $file.'.bak')) return false; - } - - if (!$fh = @fopen($file, 'wb')) { - io_rename($file.'.bak', $file); // problem opening, restore the backup - return false; - } - - if (empty($header)) $header = $this->_heading; - - $out = $this->_out_header($id,$header); - - foreach ($this->setting as $setting) { - $out .= $setting->out($this->_name, $this->_format); - } - - $out .= $this->_out_footer(); - - @fwrite($fh, $out); - fclose($fh); - if($conf['fperm']) chmod($file, $conf['fperm']); - return true; - } - - /** - * Update last modified time stamp of the config file - * - * @return bool - */ - public function touch_settings(){ - if ($this->locked) return false; - $file = end($this->_local_files); - return @touch($file); - } - - /** - * Read and merge given config files - * - * @param array $files file paths - * @return array config settings - */ - protected function _read_config_group($files) { - $config = array(); - foreach ($files as $file) { - $config = array_merge($config, $this->_read_config($file)); - } - - return $config; - } - - /** - * Return an array of config settings - * - * @param string $file file path - * @return array config settings - */ - function _read_config($file) { - - if (!$file) return array(); - - $config = array(); - - if ($this->_format == 'php') { - - if(file_exists($file)){ - $contents = @php_strip_whitespace($file); - }else{ - $contents = ''; - } - $pattern = '/\$'.$this->_name.'\[[\'"]([^=]+)[\'"]\] ?= ?(.*?);(?=[^;]*(?:\$'.$this->_name.'|$))/s'; - $matches=array(); - preg_match_all($pattern,$contents,$matches,PREG_SET_ORDER); - - for ($i=0; $i<count($matches); $i++) { - $value = $matches[$i][2]; - - // correct issues with the incoming data - // FIXME ... for now merge multi-dimensional array indices using ____ - $key = preg_replace('/.\]\[./',CM_KEYMARKER,$matches[$i][1]); - - // handle arrays - if(preg_match('/^array ?\((.*)\)/', $value, $match)){ - $arr = explode(',', $match[1]); - - // remove quotes from quoted strings & unescape escaped data - $len = count($arr); - for($j=0; $j<$len; $j++){ - $arr[$j] = trim($arr[$j]); - $arr[$j] = $this->_readValue($arr[$j]); - } - - $value = $arr; - }else{ - $value = $this->_readValue($value); - } - - $config[$key] = $value; - } - } - - return $config; - } - - /** - * Convert php string into value - * - * @param string $value - * @return bool|string - */ - protected function _readValue($value) { - $removequotes_pattern = '/^(\'|")(.*)(?<!\\\\)\1$/s'; - $unescape_pairs = array( - '\\\\' => '\\', - '\\\'' => '\'', - '\\"' => '"' - ); - - if($value == 'true') { - $value = true; - } elseif($value == 'false') { - $value = false; - } else { - // remove quotes from quoted strings & unescape escaped data - $value = preg_replace($removequotes_pattern,'$2',$value); - $value = strtr($value, $unescape_pairs); - } - return $value; - } - - /** - * Returns header of rewritten settings file - * - * @param string $id plugin name of which generated this output - * @param string $header additional text for at top of the file - * @return string text of header - */ - protected function _out_header($id, $header) { - $out = ''; - if ($this->_format == 'php') { - $out .= '<'.'?php'."\n". - "/*\n". - " * ".$header."\n". - " * Auto-generated by ".$id." plugin\n". - " * Run for user: ".$_SERVER['REMOTE_USER']."\n". - " * Date: ".date('r')."\n". - " */\n\n"; - } - - return $out; - } - - /** - * Returns footer of rewritten settings file - * - * @return string text of footer - */ - protected function _out_footer() { - $out = ''; - if ($this->_format == 'php') { - $out .= "\n// end auto-generated content\n"; - } - - return $out; - } - - /** - * Configuration is considered locked if there is no local settings filename - * or the directory its in is not writable or the file exists and is not writable - * - * @return bool true: locked, false: writable - */ - protected function _is_locked() { - if (!$this->_local_files) return true; - - $local = $this->_local_files[0]; - - if (!is_writable(dirname($local))) return true; - if (file_exists($local) && !is_writable($local)) return true; - - return false; - } - - /** - * not used ... conf's contents are an array! - * reduce any multidimensional settings to one dimension using CM_KEYMARKER - * - * @param $conf - * @param string $prefix - * @return array - */ - protected function _flatten($conf,$prefix='') { - - $out = array(); - - foreach($conf as $key => $value) { - if (!is_array($value)) { - $out[$prefix.$key] = $value; - continue; - } - - $tmp = $this->_flatten($value,$prefix.$key.CM_KEYMARKER); - $out = array_merge($out,$tmp); - } - - return $out; - } - - /** - * Returns array of plugin names - * - * @return array plugin names - * @triggers PLUGIN_CONFIG_PLUGINLIST event - */ - function get_plugin_list() { - if (is_null($this->_plugin_list)) { - $list = plugin_list('',$this->show_disabled_plugins); - - // remove this plugin from the list - $idx = array_search('config',$list); - unset($list[$idx]); - sort($list); // Sort plugin list alphabetically for display - - trigger_event('PLUGIN_CONFIG_PLUGINLIST',$list); - $this->_plugin_list = $list; - } - - return $this->_plugin_list; - } - - /** - * load metadata for plugin and template settings - * - * @param string $tpl name of active template - * @return array metadata of settings - */ - function get_plugintpl_metadata($tpl){ - $file = '/conf/metadata.php'; - $class = '/conf/settings.class.php'; - $metadata = array(); - - foreach ($this->get_plugin_list() as $plugin) { - $plugin_dir = plugin_directory($plugin); - if (file_exists(DOKU_PLUGIN.$plugin_dir.$file)){ - $meta = array(); - @include(DOKU_PLUGIN.$plugin_dir.$file); - @include(DOKU_PLUGIN.$plugin_dir.$class); - if (!empty($meta)) { - $metadata['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.'plugin_settings_name'] = array('fieldset'); - } - foreach ($meta as $key => $value){ - if ($value[0]=='fieldset') { continue; } //plugins only get one fieldset - $metadata['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.$key] = $value; - } - } - } - - // the same for the active template - if (file_exists(tpl_incdir().$file)){ - $meta = array(); - @include(tpl_incdir().$file); - @include(tpl_incdir().$class); - if (!empty($meta)) { - $metadata['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'] = array('fieldset'); - } - foreach ($meta as $key => $value){ - if ($value[0]=='fieldset') { continue; } //template only gets one fieldset - $metadata['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.$key] = $value; - } - } - - return $metadata; - } - - /** - * Load default settings for plugins and templates - * - * @param string $tpl name of active template - * @return array default settings - */ - function get_plugintpl_default($tpl){ - $file = '/conf/default.php'; - $default = array(); - - foreach ($this->get_plugin_list() as $plugin) { - $plugin_dir = plugin_directory($plugin); - if (file_exists(DOKU_PLUGIN.$plugin_dir.$file)){ - $conf = $this->_read_config(DOKU_PLUGIN.$plugin_dir.$file); - foreach ($conf as $key => $value){ - $default['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.$key] = $value; - } - } - } - - // the same for the active template - if (file_exists(tpl_incdir().$file)){ - $conf = $this->_read_config(tpl_incdir().$file); - foreach ($conf as $key => $value){ - $default['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.$key] = $value; - } - } - - return $default; - } - - } -} - -if (!class_exists('setting')) { - /** - * Class setting - */ - class setting { - - var $_key = ''; - var $_default = null; - var $_local = null; - var $_protected = null; - - var $_pattern = ''; - var $_error = false; // only used by those classes which error check - var $_input = null; // only used by those classes which error check - var $_caution = null; // used by any setting to provide an alert along with the setting - // valid alerts, 'warning', 'danger', 'security' - // images matching the alerts are in the plugin's images directory - - static protected $_validCautions = array('warning','danger','security'); - - /** - * @param string $key - * @param array|null $params array with metadata of setting - */ - public function __construct($key, $params=null) { - $this->_key = $key; - - if (is_array($params)) { - foreach($params as $property => $value) { - $this->$property = $value; - } - } - } - - /** - * Receives current values for the setting $key - * - * @param mixed $default default setting value - * @param mixed $local local setting value - * @param mixed $protected protected setting value - */ - public function initialize($default, $local, $protected) { - if (isset($default)) $this->_default = $default; - if (isset($local)) $this->_local = $local; - if (isset($protected)) $this->_protected = $protected; - } - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - public function update($input) { - if (is_null($input)) return false; - if ($this->is_protected()) return false; - - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - - if ($this->_pattern && !preg_match($this->_pattern,$input)) { - $this->_error = true; - $this->_input = $input; - return false; - } - - $this->_local = $input; - return true; - } - - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return string[] with content array(string $label_html, string $input_html) - */ - public function html(admin_plugin_config $plugin, $echo=false) { - $disable = ''; - - if ($this->is_protected()) { - $value = $this->_protected; - $disable = 'disabled="disabled"'; - } else { - if ($echo && $this->_error) { - $value = $this->_input; - } else { - $value = is_null($this->_local) ? $this->_default : $this->_local; - } - } - - $key = htmlspecialchars($this->_key); - $value = formText($value); - - $label = '<label for="config___'.$key.'">'.$this->prompt($plugin).'</label>'; - $input = '<textarea rows="3" cols="40" id="config___'.$key.'" name="config['.$key.']" class="edit" '.$disable.'>'.$value.'</textarea>'; - return array($label,$input); - } - - /** - * Generate string to save setting value to file according to $fmt - * - * @param string $var name of variable - * @param string $fmt save format - * @return string - */ - public function out($var, $fmt='php') { - - if ($this->is_protected()) return ''; - if (is_null($this->_local) || ($this->_default == $this->_local)) return ''; - - $out = ''; - - if ($fmt=='php') { - $tr = array("\\" => '\\\\', "'" => '\\\''); - - $out = '$'.$var."['".$this->_out_key()."'] = '".strtr( cleanText($this->_local), $tr)."';\n"; - } - - return $out; - } - - /** - * Returns the localized prompt - * - * @param admin_plugin_config $plugin object of config plugin - * @return string text - */ - public function prompt(admin_plugin_config $plugin) { - $prompt = $plugin->getLang($this->_key); - if (!$prompt) $prompt = htmlspecialchars(str_replace(array('____','_'),' ',$this->_key)); - return $prompt; - } - - /** - * Is setting protected - * - * @return bool - */ - public function is_protected() { return !is_null($this->_protected); } - - /** - * Is setting the default? - * - * @return bool - */ - public function is_default() { return !$this->is_protected() && is_null($this->_local); } - - /** - * Has an error? - * - * @return bool - */ - public function error() { return $this->_error; } - - /** - * Returns caution - * - * @return false|string caution string, otherwise false for invalid caution - */ - public function caution() { - if (!empty($this->_caution)) { - if (!in_array($this->_caution, setting::$_validCautions)) { - trigger_error('Invalid caution string ('.$this->_caution.') in metadata for setting "'.$this->_key.'"', E_USER_WARNING); - return false; - } - return $this->_caution; - } - // compatibility with previous cautionList - // TODO: check if any plugins use; remove - if (!empty($this->_cautionList[$this->_key])) { - $this->_caution = $this->_cautionList[$this->_key]; - unset($this->_cautionList); - - return $this->caution(); - } - return false; - } - - /** - * Returns setting key, eventually with referer to config: namespace at dokuwiki.org - * - * @param bool $pretty create nice key - * @param bool $url provide url to config: namespace - * @return string key - */ - public function _out_key($pretty=false,$url=false) { - if($pretty){ - $out = str_replace(CM_KEYMARKER,"»",$this->_key); - if ($url && !strstr($out,'»')) {//provide no urls for plugins, etc. - if ($out == 'start') //one exception - return '<a href="http://www.dokuwiki.org/config:startpage">'.$out.'</a>'; - else - return '<a href="http://www.dokuwiki.org/config:'.$out.'">'.$out.'</a>'; - } - return $out; - }else{ - return str_replace(CM_KEYMARKER,"']['",$this->_key); - } - } - } -} - - -if (!class_exists('setting_array')) { - /** - * Class setting_array - */ - class setting_array extends setting { - - /** - * Create an array from a string - * - * @param string $string - * @return array - */ - protected function _from_string($string){ - $array = explode(',', $string); - $array = array_map('trim', $array); - $array = array_filter($array); - $array = array_unique($array); - return $array; - } - - /** - * Create a string from an array - * - * @param array $array - * @return string - */ - protected function _from_array($array){ - return join(', ', (array) $array); - } - - /** - * update setting with user provided value $input - * if value fails error check, save it - * - * @param string $input - * @return bool true if changed, false otherwise (incl. on error) - */ - function update($input) { - if (is_null($input)) return false; - if ($this->is_protected()) return false; - - $input = $this->_from_string($input); - - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - - foreach($input as $item){ - if ($this->_pattern && !preg_match($this->_pattern,$item)) { - $this->_error = true; - $this->_input = $input; - return false; - } - } - - $this->_local = $input; - return true; - } - - /** - * Escaping - * - * @param string $string - * @return string - */ - protected function _escape($string) { - $tr = array("\\" => '\\\\', "'" => '\\\''); - return "'".strtr( cleanText($string), $tr)."'"; - } - - /** - * Generate string to save setting value to file according to $fmt - * - * @param string $var name of variable - * @param string $fmt save format - * @return string - */ - function out($var, $fmt='php') { - - if ($this->is_protected()) return ''; - if (is_null($this->_local) || ($this->_default == $this->_local)) return ''; - - $out = ''; - - if ($fmt=='php') { - $vals = array_map(array($this, '_escape'), $this->_local); - $out = '$'.$var."['".$this->_out_key()."'] = array(".join(', ',$vals).");\n"; - } - - return $out; - } - - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return string[] with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo=false) { - $disable = ''; - - if ($this->is_protected()) { - $value = $this->_protected; - $disable = 'disabled="disabled"'; - } else { - if ($echo && $this->_error) { - $value = $this->_input; - } else { - $value = is_null($this->_local) ? $this->_default : $this->_local; - } - } - - $key = htmlspecialchars($this->_key); - $value = htmlspecialchars($this->_from_array($value)); - - $label = '<label for="config___'.$key.'">'.$this->prompt($plugin).'</label>'; - $input = '<input id="config___'.$key.'" name="config['.$key.']" type="text" class="edit" value="'.$value.'" '.$disable.'/>'; - return array($label,$input); - } - } -} - -if (!class_exists('setting_string')) { - /** - * Class setting_string - */ - class setting_string extends setting { - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return string[] with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo=false) { - $disable = ''; - - if ($this->is_protected()) { - $value = $this->_protected; - $disable = 'disabled="disabled"'; - } else { - if ($echo && $this->_error) { - $value = $this->_input; - } else { - $value = is_null($this->_local) ? $this->_default : $this->_local; - } - } - - $key = htmlspecialchars($this->_key); - $value = htmlspecialchars($value); - - $label = '<label for="config___'.$key.'">'.$this->prompt($plugin).'</label>'; - $input = '<input id="config___'.$key.'" name="config['.$key.']" type="text" class="edit" value="'.$value.'" '.$disable.'/>'; - return array($label,$input); - } - } -} - -if (!class_exists('setting_password')) { - /** - * Class setting_password - */ - class setting_password extends setting_string { - - var $_code = 'plain'; // mechanism to be used to obscure passwords - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - if ($this->is_protected()) return false; - if (!$input) return false; - - if ($this->_pattern && !preg_match($this->_pattern,$input)) { - $this->_error = true; - $this->_input = $input; - return false; - } - - $this->_local = conf_encodeString($input,$this->_code); - return true; - } - - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return string[] with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo=false) { - - $disable = $this->is_protected() ? 'disabled="disabled"' : ''; - - $key = htmlspecialchars($this->_key); - - $label = '<label for="config___'.$key.'">'.$this->prompt($plugin).'</label>'; - $input = '<input id="config___'.$key.'" name="config['.$key.']" autocomplete="off" type="password" class="edit" value="" '.$disable.' />'; - return array($label,$input); - } - } -} - -if (!class_exists('setting_email')) { - /** - * Class setting_email - */ - class setting_email extends setting_string { - var $_multiple = false; - var $_placeholders = false; - - /** - * update setting with user provided value $input - * if value fails error check, save it - * - * @param mixed $input - * @return boolean true if changed, false otherwise (incl. on error) - */ - function update($input) { - if (is_null($input)) return false; - if ($this->is_protected()) return false; - - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - if($input === ''){ - $this->_local = $input; - return true; - } - $mail = $input; - - if($this->_placeholders){ - // replace variables with pseudo values - $mail = str_replace('@USER@','joe',$mail); - $mail = str_replace('@NAME@','Joe Schmoe',$mail); - $mail = str_replace('@MAIL@','joe@example.com',$mail); - } - - // multiple mail addresses? - if ($this->_multiple) { - $mails = array_filter(array_map('trim', explode(',', $mail))); - } else { - $mails = array($mail); - } - - // check them all - foreach ($mails as $mail) { - // only check the address part - if(preg_match('#(.*?)<(.*?)>#', $mail, $matches)){ - $addr = $matches[2]; - }else{ - $addr = $mail; - } - - if (!mail_isvalid($addr)) { - $this->_error = true; - $this->_input = $input; - return false; - } - } - - $this->_local = $input; - return true; - } - } -} - -if (!class_exists('setting_numeric')) { - /** - * Class setting_numeric - */ - class setting_numeric extends setting_string { - // This allows for many PHP syntax errors... - // var $_pattern = '/^[-+\/*0-9 ]*$/'; - // much more restrictive, but should eliminate syntax errors. - var $_pattern = '/^[-+]? *[0-9]+ *(?:[-+*] *[0-9]+ *)*$/'; - var $_min = null; - var $_max = null; - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - $local = $this->_local; - $valid = parent::update($input); - if ($valid && !(is_null($this->_min) && is_null($this->_max))) { - $numeric_local = (int) eval('return '.$this->_local.';'); - if ((!is_null($this->_min) && $numeric_local < $this->_min) || - (!is_null($this->_max) && $numeric_local > $this->_max)) { - $this->_error = true; - $this->_input = $input; - $this->_local = $local; - $valid = false; - } - } - return $valid; - } - - /** - * Generate string to save setting value to file according to $fmt - * - * @param string $var name of variable - * @param string $fmt save format - * @return string - */ - function out($var, $fmt='php') { - - if ($this->is_protected()) return ''; - if (is_null($this->_local) || ($this->_default == $this->_local)) return ''; - - $out = ''; - - if ($fmt=='php') { - $local = $this->_local === '' ? "''" : $this->_local; - $out .= '$'.$var."['".$this->_out_key()."'] = ".$local.";\n"; - } - - return $out; - } - } -} - -if (!class_exists('setting_numericopt')) { - /** - * Class setting_numericopt - */ - class setting_numericopt extends setting_numeric { - // just allow an empty config - var $_pattern = '/^(|[-]?[0-9]+(?:[-+*][0-9]+)*)$/'; - - - /** - * Empty string is valid for numericopt - * - * @param mixed $input - * - * @return bool - */ - function update($input) { - if ($input === '') { - return true; - } - - return parent::update($input); - } - } -} - -if (!class_exists('setting_onoff')) { - /** - * Class setting_onoff - */ - class setting_onoff extends setting_numeric { - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return string[] with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo = false) { - $disable = ''; - - if ($this->is_protected()) { - $value = $this->_protected; - $disable = ' disabled="disabled"'; - } else { - $value = is_null($this->_local) ? $this->_default : $this->_local; - } - - $key = htmlspecialchars($this->_key); - $checked = ($value) ? ' checked="checked"' : ''; - - $label = '<label for="config___'.$key.'">'.$this->prompt($plugin).'</label>'; - $input = '<div class="input"><input id="config___'.$key.'" name="config['.$key.']" type="checkbox" class="checkbox" value="1"'.$checked.$disable.'/></div>'; - return array($label,$input); - } - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - if ($this->is_protected()) return false; - - $input = ($input) ? 1 : 0; - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - - $this->_local = $input; - return true; - } - } -} - -if (!class_exists('setting_multichoice')) { - /** - * Class setting_multichoice - */ - class setting_multichoice extends setting_string { - var $_choices = array(); - var $lang; //some custom language strings are stored in setting - - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return string[] with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo = false) { - $disable = ''; - $nochoice = ''; - - if ($this->is_protected()) { - $value = $this->_protected; - $disable = ' disabled="disabled"'; - } else { - $value = is_null($this->_local) ? $this->_default : $this->_local; - } - - // ensure current value is included - if (!in_array($value, $this->_choices)) { - $this->_choices[] = $value; - } - // disable if no other choices - if (!$this->is_protected() && count($this->_choices) <= 1) { - $disable = ' disabled="disabled"'; - $nochoice = $plugin->getLang('nochoice'); - } - - $key = htmlspecialchars($this->_key); - - $label = '<label for="config___'.$key.'">'.$this->prompt($plugin).'</label>'; - - $input = "<div class=\"input\">\n"; - $input .= '<select class="edit" id="config___'.$key.'" name="config['.$key.']"'.$disable.'>'."\n"; - foreach ($this->_choices as $choice) { - $selected = ($value == $choice) ? ' selected="selected"' : ''; - $option = $plugin->getLang($this->_key.'_o_'.$choice); - if (!$option && isset($this->lang[$this->_key.'_o_'.$choice])) $option = $this->lang[$this->_key.'_o_'.$choice]; - if (!$option) $option = $choice; - - $choice = htmlspecialchars($choice); - $option = htmlspecialchars($option); - $input .= ' <option value="'.$choice.'"'.$selected.' >'.$option.'</option>'."\n"; - } - $input .= "</select> $nochoice \n"; - $input .= "</div>\n"; - - return array($label,$input); - } - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - if (is_null($input)) return false; - if ($this->is_protected()) return false; - - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - - if (!in_array($input, $this->_choices)) return false; - - $this->_local = $input; - return true; - } - } -} - - -if (!class_exists('setting_dirchoice')) { - /** - * Class setting_dirchoice - */ - class setting_dirchoice extends setting_multichoice { - - var $_dir = ''; - - /** - * Receives current values for the setting $key - * - * @param mixed $default default setting value - * @param mixed $local local setting value - * @param mixed $protected protected setting value - */ - function initialize($default,$local,$protected) { - - // populate $this->_choices with a list of directories - $list = array(); - - if ($dh = @opendir($this->_dir)) { - while (false !== ($entry = readdir($dh))) { - if ($entry == '.' || $entry == '..') continue; - if ($this->_pattern && !preg_match($this->_pattern,$entry)) continue; - - $file = (is_link($this->_dir.$entry)) ? readlink($this->_dir.$entry) : $this->_dir.$entry; - if (is_dir($file)) $list[] = $entry; - } - closedir($dh); - } - sort($list); - $this->_choices = $list; - - parent::initialize($default,$local,$protected); - } - } -} - - -if (!class_exists('setting_hidden')) { - /** - * Class setting_hidden - */ - class setting_hidden extends setting { - // Used to explicitly ignore a setting in the configuration manager. - } -} - -if (!class_exists('setting_fieldset')) { - /** - * Class setting_fieldset - */ - class setting_fieldset extends setting { - // A do-nothing class used to detect the 'fieldset' type. - // Used to start a new settings "display-group". - } -} - -if (!class_exists('setting_undefined')) { - /** - * Class setting_undefined - */ - class setting_undefined extends setting_hidden { - // A do-nothing class used to detect settings with no metadata entry. - // Used internaly to hide undefined settings, and generate the undefined settings list. - } -} - -if (!class_exists('setting_no_class')) { - /** - * Class setting_no_class - */ - class setting_no_class extends setting_undefined { - // A do-nothing class used to detect settings with a missing setting class. - // Used internaly to hide undefined settings, and generate the undefined settings list. - } -} - -if (!class_exists('setting_no_default')) { - /** - * Class setting_no_default - */ - class setting_no_default extends setting_undefined { - // A do-nothing class used to detect settings with no default value. - // Used internaly to hide undefined settings, and generate the undefined settings list. - } -} - -if (!class_exists('setting_multicheckbox')) { - /** - * Class setting_multicheckbox - */ - class setting_multicheckbox extends setting_string { - - var $_choices = array(); - var $_combine = array(); - var $_other = 'always'; - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - if ($this->is_protected()) return false; - - // split any combined values + convert from array to comma separated string - $input = ($input) ? $input : array(); - $input = $this->_array2str($input); - - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - - if ($this->_pattern && !preg_match($this->_pattern,$input)) { - $this->_error = true; - $this->_input = $input; - return false; - } - - $this->_local = $input; - return true; - } - - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show input value, when error occurred, otherwise the stored setting - * @return string[] with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo=false) { - - $disable = ''; - - if ($this->is_protected()) { - $value = $this->_protected; - $disable = 'disabled="disabled"'; - } else { - if ($echo && $this->_error) { - $value = $this->_input; - } else { - $value = is_null($this->_local) ? $this->_default : $this->_local; - } - } - - $key = htmlspecialchars($this->_key); - - // convert from comma separated list into array + combine complimentary actions - $value = $this->_str2array($value); - $default = $this->_str2array($this->_default); - - $input = ''; - foreach ($this->_choices as $choice) { - $idx = array_search($choice, $value); - $idx_default = array_search($choice,$default); - - $checked = ($idx !== false) ? 'checked="checked"' : ''; - - // @todo ideally this would be handled using a second class of "default" - $class = (($idx !== false) == (false !== $idx_default)) ? " selectiondefault" : ""; - - $prompt = ($plugin->getLang($this->_key.'_'.$choice) ? - $plugin->getLang($this->_key.'_'.$choice) : htmlspecialchars($choice)); - - $input .= '<div class="selection'.$class.'">'."\n"; - $input .= '<label for="config___'.$key.'_'.$choice.'">'.$prompt."</label>\n"; - $input .= '<input id="config___'.$key.'_'.$choice.'" name="config['.$key.'][]" type="checkbox" class="checkbox" value="'.$choice.'" '.$disable.' '.$checked."/>\n"; - $input .= "</div>\n"; - - // remove this action from the disabledactions array - if ($idx !== false) unset($value[$idx]); - if ($idx_default !== false) unset($default[$idx_default]); - } - - // handle any remaining values - if ($this->_other != 'never'){ - $other = join(',',$value); - // test equivalent to ($this->_other == 'always' || ($other && $this->_other == 'exists') - // use != 'exists' rather than == 'always' to ensure invalid values default to 'always' - if ($this->_other != 'exists' || $other) { - - $class = ((count($default) == count($value)) && (count($value) == count(array_intersect($value,$default)))) ? - " selectiondefault" : ""; - - $input .= '<div class="other'.$class.'">'."\n"; - $input .= '<label for="config___'.$key.'_other">'.$plugin->getLang($key.'_other')."</label>\n"; - $input .= '<input id="config___'.$key.'_other" name="config['.$key.'][other]" type="text" class="edit" value="'.htmlspecialchars($other).'" '.$disable." />\n"; - $input .= "</div>\n"; - } - } - $label = '<label>'.$this->prompt($plugin).'</label>'; - return array($label,$input); - } - - /** - * convert comma separated list to an array and combine any complimentary values - * - * @param string $str - * @return array - */ - function _str2array($str) { - $array = explode(',',$str); - - if (!empty($this->_combine)) { - foreach ($this->_combine as $key => $combinators) { - $idx = array(); - foreach ($combinators as $val) { - if (($idx[] = array_search($val, $array)) === false) break; - } - - if (count($idx) && $idx[count($idx)-1] !== false) { - foreach ($idx as $i) unset($array[$i]); - $array[] = $key; - } - } - } - - return $array; - } - - /** - * convert array of values + other back to a comma separated list, incl. splitting any combined values - * - * @param array $input - * @return string - */ - function _array2str($input) { - - // handle other - $other = trim($input['other']); - $other = !empty($other) ? explode(',',str_replace(' ','',$input['other'])) : array(); - unset($input['other']); - - $array = array_unique(array_merge($input, $other)); - - // deconstruct any combinations - if (!empty($this->_combine)) { - foreach ($this->_combine as $key => $combinators) { - - $idx = array_search($key,$array); - if ($idx !== false) { - unset($array[$idx]); - $array = array_merge($array, $combinators); - } - } - } - - return join(',',array_unique($array)); - } - } -} - -if (!class_exists('setting_regex')){ - /** - * Class setting_regex - */ - class setting_regex extends setting_string { - - var $_delimiter = '/'; // regex delimiter to be used in testing input - var $_pregflags = 'ui'; // regex pattern modifiers to be used in testing input - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (incl. on error) - */ - function update($input) { - - // let parent do basic checks, value, not changed, etc. - $local = $this->_local; - if (!parent::update($input)) return false; - $this->_local = $local; - - // see if the regex compiles and runs (we don't check for effectiveness) - $regex = $this->_delimiter . $input . $this->_delimiter . $this->_pregflags; - $lastError = error_get_last(); - @preg_match($regex,'testdata'); - if (preg_last_error() != PREG_NO_ERROR || error_get_last() != $lastError) { - $this->_input = $input; - $this->_error = true; - return false; - } - - $this->_local = $input; - return true; - } - } -} diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php index 1d7eea9a5..9a9b6d901 100644 --- a/lib/plugins/config/settings/config.metadata.php +++ b/lib/plugins/config/settings/config.metadata.php @@ -2,16 +2,15 @@ /** * Metadata for configuration manager plugin * - * Note: This file should be included within a function to ensure it - * doesn't clash with the settings it is describing. + * Note: This file is loaded in Loader::loadMeta(). * * Format: * $meta[<setting name>] = array(<handler class id>,<param name> => <param value>); * * <handler class id> is the handler class name without the "setting_" prefix * - * Defined classes: - * Generic (source: settings/config.class.php) + * Defined classes (see core/Setting/*): + * Generic * ------------------------------------------- * '' - default class ('setting'), textarea, minimal input validation, setting output in quotes * 'string' - single line text input, minimal input validation, setting output in quotes @@ -38,7 +37,7 @@ * to see if will compile & run as a regex. in addition to _pattern, also accepts _delimiter * (default '/') and _pregflags (default 'ui') * - * Single Setting (source: settings/extra.class.php) + * Single Setting * ------------------------------------------------- * 'savedir' - as 'setting', input tested against initpath() (inc/init.php) * 'sepchar' - as multichoice, selection constructed from string of valid values @@ -76,26 +75,10 @@ * 'never' as it will not discard unknown/other values. * optional for 'multicheckbox', ignored by others * + * The order of the settings influences the order in which they apppear in the config manager * * @author Chris Smith <chris@jalakai.co.uk> */ -// ---------------[ settings for settings ]------------------------------ -$config['format'] = 'php'; // format of setting files, supported formats: php -$config['varname'] = 'conf'; // name of the config variable, sans $ - -// this string is written at the top of the rewritten settings file, -// !! do not include any comment indicators !! -// this value can be overriden when calling save_settings() method -$config['heading'] = 'Dokuwiki\'s Main Configuration File - Local Settings'; - -// test value (FIXME, remove before publishing) -//$meta['test'] = array('multichoice','_choices' => array('')); - -// --------------[ setting metadata ]------------------------------------ -// - for description of format and fields see top of file -// - order the settings in the order you wish them to appear -// - any settings not mentioned will come after the last setting listed and -// will use the default class with no parameters $meta['_basic'] = array('fieldset'); $meta['title'] = array('string'); @@ -122,7 +105,10 @@ $meta['fullpath'] = array('onoff','_caution' => 'security'); $meta['typography'] = array('multichoice','_choices' => array(0,1,2)); $meta['dformat'] = array('string'); $meta['signature'] = array('string'); -$meta['showuseras'] = array('multichoice','_choices' => array('loginname','username','username_link','email','email_link')); +$meta['showuseras'] = array( + 'multichoice', + '_choices' => array('loginname', 'username', 'username_link', 'email', 'email_link') +); $meta['toptoclevel'] = array('multichoice','_choices' => array(1,2,3,4,5)); // 5 toc levels $meta['tocminheads'] = array('multichoice','_choices' => array(0,1,2,3,4,5,10,15,20)); $meta['maxtoclevel'] = array('multichoice','_choices' => array(0,1,2,3,4,5)); @@ -146,9 +132,29 @@ $meta['superuser'] = array('string','_caution' => 'danger'); $meta['manager'] = array('string'); $meta['profileconfirm'] = array('onoff'); $meta['rememberme'] = array('onoff'); -$meta['disableactions'] = array('disableactions', - '_choices' => array('backlink','index','recent','revisions','search','subscription','register','resendpwd','profile','profile_delete','edit','wikicode','check', 'rss'), - '_combine' => array('subscription' => array('subscribe','unsubscribe'), 'wikicode' => array('source','export_raw'))); +$meta['disableactions'] = array( + 'disableactions', + '_choices' => array( + 'backlink', + 'index', + 'recent', + 'revisions', + 'search', + 'subscription', + 'register', + 'resendpwd', + 'profile', + 'profile_delete', + 'edit', + 'wikicode', + 'check', + 'rss' + ), + '_combine' => array( + 'subscription' => array('subscribe', 'unsubscribe'), + 'wikicode' => array('source', 'export_raw') + ) +); $meta['auth_security_timeout'] = array('numeric'); $meta['securecookie'] = array('onoff'); $meta['remote'] = array('onoff','_caution' => 'security'); diff --git a/lib/plugins/config/settings/extra.class.php b/lib/plugins/config/settings/extra.class.php deleted file mode 100644 index 41af42247..000000000 --- a/lib/plugins/config/settings/extra.class.php +++ /dev/null @@ -1,309 +0,0 @@ -<?php -/** - * additional setting classes specific to these settings - * - * @author Chris Smith <chris@jalakai.co.uk> - */ - -if (!class_exists('setting_sepchar')) { - /** - * Class setting_sepchar - */ - class setting_sepchar extends setting_multichoice { - - /** - * @param string $key - * @param array|null $param array with metadata of setting - */ - function __construct($key,$param=null) { - $str = '_-.'; - for ($i=0;$i<strlen($str);$i++) $this->_choices[] = $str{$i}; - - // call foundation class constructor - parent::__construct($key,$param); - } - } -} - -if (!class_exists('setting_savedir')) { - /** - * Class setting_savedir - */ - class setting_savedir extends setting_string { - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - if ($this->is_protected()) return false; - - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - - if (!init_path($input)) { - $this->_error = true; - $this->_input = $input; - return false; - } - - $this->_local = $input; - return true; - } - } -} - -if (!class_exists('setting_authtype')) { - /** - * Class setting_authtype - */ - class setting_authtype extends setting_multichoice { - - /** - * Receives current values for the setting $key - * - * @param mixed $default default setting value - * @param mixed $local local setting value - * @param mixed $protected protected setting value - */ - function initialize($default,$local,$protected) { - /** @var $plugin_controller Doku_Plugin_Controller */ - global $plugin_controller; - - // retrieve auth types provided by plugins - foreach ($plugin_controller->getList('auth') as $plugin) { - $this->_choices[] = $plugin; - } - - parent::initialize($default,$local,$protected); - } - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - /** @var $plugin_controller Doku_Plugin_Controller */ - global $plugin_controller; - - // is an update possible/requested? - $local = $this->_local; // save this, parent::update() may change it - if (!parent::update($input)) return false; // nothing changed or an error caught by parent - $this->_local = $local; // restore original, more error checking to come - - // attempt to load the plugin - $auth_plugin = $plugin_controller->load('auth', $input); - - // @TODO: throw an error in plugin controller instead of returning null - if (is_null($auth_plugin)) { - $this->_error = true; - msg('Cannot load Auth Plugin "' . $input . '"', -1); - return false; - } - - // verify proper instantiation (is this really a plugin?) @TODO use instanceof? implement interface? - if (is_object($auth_plugin) && !method_exists($auth_plugin, 'getPluginName')) { - $this->_error = true; - msg('Cannot create Auth Plugin "' . $input . '"', -1); - return false; - } - - // did we change the auth type? logout - global $conf; - if($conf['authtype'] != $input) { - msg('Authentication system changed. Please re-login.'); - auth_logoff(); - } - - $this->_local = $input; - return true; - } - } -} - -if (!class_exists('setting_im_convert')) { - /** - * Class setting_im_convert - */ - class setting_im_convert extends setting_string { - - /** - * update changed setting with user provided value $input - * - if changed value fails error check, save it to $this->_input (to allow echoing later) - * - if changed value passes error check, set $this->_local to the new value - * - * @param mixed $input the new value - * @return boolean true if changed, false otherwise (also on error) - */ - function update($input) { - if ($this->is_protected()) return false; - - $input = trim($input); - - $value = is_null($this->_local) ? $this->_default : $this->_local; - if ($value == $input) return false; - - if ($input && !file_exists($input)) { - $this->_error = true; - $this->_input = $input; - return false; - } - - $this->_local = $input; - return true; - } - } -} - -if (!class_exists('setting_disableactions')) { - /** - * Class setting_disableactions - */ - class setting_disableactions extends setting_multicheckbox { - - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return array with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo=false) { - global $lang; - - // make some language adjustments (there must be a better way) - // transfer some DokuWiki language strings to the plugin - $plugin->addLang($this->_key.'_revisions', $lang['btn_revs']); - foreach ($this->_choices as $choice) { - if (isset($lang['btn_'.$choice])) $plugin->addLang($this->_key.'_'.$choice, $lang['btn_'.$choice]); - } - - return parent::html($plugin, $echo); - } - } -} - -if (!class_exists('setting_compression')) { - /** - * Class setting_compression - */ - class setting_compression extends setting_multichoice { - - var $_choices = array('0'); // 0 = no compression, always supported - - /** - * Receives current values for the setting $key - * - * @param mixed $default default setting value - * @param mixed $local local setting value - * @param mixed $protected protected setting value - */ - function initialize($default,$local,$protected) { - - // populate _choices with the compression methods supported by this php installation - if (function_exists('gzopen')) $this->_choices[] = 'gz'; - if (function_exists('bzopen')) $this->_choices[] = 'bz2'; - - parent::initialize($default,$local,$protected); - } - } -} - -if (!class_exists('setting_license')) { - /** - * Class setting_license - */ - class setting_license extends setting_multichoice { - - var $_choices = array(''); // none choosen - - /** - * Receives current values for the setting $key - * - * @param mixed $default default setting value - * @param mixed $local local setting value - * @param mixed $protected protected setting value - */ - function initialize($default,$local,$protected) { - global $license; - - foreach($license as $key => $data){ - $this->_choices[] = $key; - $this->lang[$this->_key.'_o_'.$key] = $data['name']; // stored in setting - } - - parent::initialize($default,$local,$protected); - } - } -} - - -if (!class_exists('setting_renderer')) { - /** - * Class setting_renderer - */ - class setting_renderer extends setting_multichoice { - var $_prompts = array(); - var $_format = null; - - /** - * Receives current values for the setting $key - * - * @param mixed $default default setting value - * @param mixed $local local setting value - * @param mixed $protected protected setting value - */ - function initialize($default,$local,$protected) { - $format = $this->_format; - - foreach (plugin_list('renderer') as $plugin) { - $renderer = plugin_load('renderer',$plugin); - if (method_exists($renderer,'canRender') && $renderer->canRender($format)) { - $this->_choices[] = $plugin; - - $info = $renderer->getInfo(); - $this->_prompts[$plugin] = $info['name']; - } - } - - parent::initialize($default,$local,$protected); - } - - /** - * Build html for label and input of setting - * - * @param admin_plugin_config $plugin object of config plugin - * @param bool $echo true: show inputted value, when error occurred, otherwise the stored setting - * @return array with content array(string $label_html, string $input_html) - */ - function html(admin_plugin_config $plugin, $echo=false) { - - // make some language adjustments (there must be a better way) - // transfer some plugin names to the config plugin - foreach($this->_choices as $choice) { - if(!$plugin->getLang($this->_key . '_o_' . $choice)) { - if(!isset($this->_prompts[$choice])) { - $plugin->addLang( - $this->_key . '_o_' . $choice, - sprintf($plugin->getLang('renderer__core'), $choice) - ); - } else { - $plugin->addLang( - $this->_key . '_o_' . $choice, - sprintf($plugin->getLang('renderer__plugin'), $this->_prompts[$choice]) - ); - } - } - } - return parent::html($plugin, $echo); - } - } -} diff --git a/lib/plugins/extension/_test/extension.test.php b/lib/plugins/extension/_test/extension.test.php index d4f13201d..1f8e2fca7 100644 --- a/lib/plugins/extension/_test/extension.test.php +++ b/lib/plugins/extension/_test/extension.test.php @@ -6,8 +6,8 @@ * makes protected methods accessible */ class mock_helper_plugin_extension_extension extends helper_plugin_extension_extension { - public function find_folders(&$result, $base, $default_type = 'plugin', $dir = '') { - return parent::find_folders($result, $base, $default_type, $dir); + public function findFolders(&$result, $base, $default_type = 'plugin', $dir = '') { + return parent::findFolders($result, $base, $default_type, $dir); } } @@ -78,7 +78,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $tdir = dirname(__FILE__).'/testdata'; $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/plugin1", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/plugin1", 'plugin'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -86,7 +86,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('plugin1', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/plugin2", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/plugin2", 'plugin'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('plugin', $result['new'][0]['type']); @@ -94,7 +94,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('plugin2', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/plgsub3", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/plgsub3", 'plugin'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -102,7 +102,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('plgsub3/plugin3', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/plgsub4", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/plgsub4", 'plugin'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('plugin', $result['new'][0]['type']); @@ -110,7 +110,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('plgsub4/plugin4', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/plgfoo5", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/plgfoo5", 'plugin'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('plugin', $result['new'][0]['type']); @@ -118,7 +118,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('plgfoo5', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/plgsub6/plgfoo6", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/plgsub6/plgfoo6", 'plugin'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('plugin', $result['new'][0]['type']); @@ -126,7 +126,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('plgsub6/plgfoo6', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/either1", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/either1", 'plugin'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -134,7 +134,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('either1', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/eithersub2/either2", 'plugin'); + $ok = $extension->findFolders($result, "$tdir/eithersub2/either2", 'plugin'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -147,7 +147,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $tdir = dirname(__FILE__).'/testdata'; $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/template1", 'template'); + $ok = $extension->findFolders($result, "$tdir/template1", 'template'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -155,7 +155,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('template1', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/template2", 'template'); + $ok = $extension->findFolders($result, "$tdir/template2", 'template'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -163,7 +163,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('template2', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplsub3", 'template'); + $ok = $extension->findFolders($result, "$tdir/tplsub3", 'template'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -171,7 +171,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplsub3/template3', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplsub4", 'template'); + $ok = $extension->findFolders($result, "$tdir/tplsub4", 'template'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -179,7 +179,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplsub4/template4', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplfoo5", 'template'); + $ok = $extension->findFolders($result, "$tdir/tplfoo5", 'template'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -187,7 +187,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplfoo5', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplsub6/tplfoo6", 'template'); + $ok = $extension->findFolders($result, "$tdir/tplsub6/tplfoo6", 'template'); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -195,7 +195,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplsub6/tplfoo6', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/either1", 'template'); + $ok = $extension->findFolders($result, "$tdir/either1", 'template'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -203,7 +203,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('either1', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/eithersub2/either2", 'template'); + $ok = $extension->findFolders($result, "$tdir/eithersub2/either2", 'template'); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -216,7 +216,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $tdir = dirname(__FILE__).'/testdata'; $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/template1"); + $ok = $extension->findFolders($result, "$tdir/template1"); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -224,7 +224,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('template1', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/template2"); + $ok = $extension->findFolders($result, "$tdir/template2"); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -232,7 +232,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('template2', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplsub3"); + $ok = $extension->findFolders($result, "$tdir/tplsub3"); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -240,7 +240,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplsub3/template3', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplsub4"); + $ok = $extension->findFolders($result, "$tdir/tplsub4"); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -248,7 +248,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplsub4/template4', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplfoo5"); + $ok = $extension->findFolders($result, "$tdir/tplfoo5"); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -256,7 +256,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplfoo5', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/tplsub6/tplfoo6"); + $ok = $extension->findFolders($result, "$tdir/tplsub6/tplfoo6"); $this->assertTrue($ok); $this->assertEquals(1, count($result['new'])); $this->assertEquals('template', $result['new'][0]['type']); @@ -264,7 +264,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('tplsub6/tplfoo6', $this->extdir($result['new'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/either1"); + $ok = $extension->findFolders($result, "$tdir/either1"); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -272,7 +272,7 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertEquals('either1', $this->extdir($result['old'][0]['tmp'])); $result = array('old' => array(), 'new' => array()); - $ok = $extension->find_folders($result, "$tdir/eithersub2/either2"); + $ok = $extension->findFolders($result, "$tdir/eithersub2/either2"); $this->assertTrue($ok); $this->assertEquals(0, count($result['new'])); $this->assertEquals(1, count($result['old'])); @@ -292,4 +292,4 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $dir = trim(substr($dir, $len), '/'); return $dir; } -}
\ No newline at end of file +} diff --git a/lib/plugins/extension/action.php b/lib/plugins/extension/action.php index 4af84f8df..3255f24b0 100644 --- a/lib/plugins/extension/action.php +++ b/lib/plugins/extension/action.php @@ -5,10 +5,8 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -class action_plugin_extension extends DokuWiki_Action_Plugin { +class action_plugin_extension extends DokuWiki_Action_Plugin +{ /** * Registers a callback function for a given event @@ -16,10 +14,10 @@ class action_plugin_extension extends DokuWiki_Action_Plugin { * @param Doku_Event_Handler $controller DokuWiki's event controller object * @return void */ - public function register(Doku_Event_Handler $controller) { + public function register(Doku_Event_Handler $controller) + { $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'info'); - } /** @@ -28,24 +26,25 @@ class action_plugin_extension extends DokuWiki_Action_Plugin { * @param Doku_Event $event * @param $param */ - public function info(Doku_Event &$event, $param) { + public function info(Doku_Event &$event, $param) + { global $USERINFO; global $INPUT; - if($event->data != 'plugin_extension') return; + if ($event->data != 'plugin_extension') return; $event->preventDefault(); $event->stopPropagation(); /** @var admin_plugin_extension $admin */ $admin = plugin_load('admin', 'extension'); - if(!$admin->isAccessibleByCurrentUser()) { + if (!$admin->isAccessibleByCurrentUser()) { http_status(403); echo 'Forbidden'; exit; } $ext = $INPUT->str('ext'); - if(!$ext) { + if (!$ext) { http_status(400); echo 'no extension given'; return; @@ -56,10 +55,9 @@ class action_plugin_extension extends DokuWiki_Action_Plugin { $extension->setExtension($ext); $act = $INPUT->str('act'); - switch($act) { + switch ($act) { case 'enable': case 'disable': - $json = new JSON(); $extension->$act(); //enables/disables $reverse = ($act == 'disable') ? 'enable' : 'disable'; @@ -71,7 +69,7 @@ class action_plugin_extension extends DokuWiki_Action_Plugin { ); header('Content-Type: application/json'); - echo $json->encode($return); + json_encode($return); break; case 'info': @@ -79,9 +77,7 @@ class action_plugin_extension extends DokuWiki_Action_Plugin { /** @var helper_plugin_extension_list $list */ $list = plugin_load('helper', 'extension_list'); header('Content-Type: text/html; charset=utf-8'); - echo $list->make_info($extension); + echo $list->makeInfo($extension); } } - } - diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 1f1d4b513..421b7138f 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -6,13 +6,11 @@ * @author Michael Hamann <michael@content-space.de> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - /** * Admin part of the extension manager */ -class admin_plugin_extension extends DokuWiki_Admin_Plugin { +class admin_plugin_extension extends DokuWiki_Admin_Plugin +{ protected $infoFor = null; /** @var helper_plugin_extension_gui */ protected $gui; @@ -22,28 +20,32 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { * * loads additional helpers */ - public function __construct() { + public function __construct() + { $this->gui = plugin_load('helper', 'extension_gui'); } /** * @return int sort number in admin menu */ - public function getMenuSort() { + public function getMenuSort() + { return 0; } /** * @return bool true if only access for superuser, false is for superusers and moderators */ - public function forAdminOnly() { + public function forAdminOnly() + { return true; } /** * Execute the requested action(s) and initialize the plugin repository */ - public function handle() { + public function handle() + { global $INPUT; // initialize the remote repository /* @var helper_plugin_extension_repository $repository */ @@ -54,7 +56,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { msg($this->getLang('repo_error').' [<a href="'.$url.'">'.$this->getLang('repo_retry').'</a>]', -1); } - if(!in_array('ssl', stream_get_transports())) { + if (!in_array('ssl', stream_get_transports())) { msg($this->getLang('nossl'), -1); } @@ -62,42 +64,60 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { $extension = $this->loadHelper('extension_extension'); try { - if($INPUT->post->has('fn') && checkSecurityToken()) { + if ($INPUT->post->has('fn') && checkSecurityToken()) { $actions = $INPUT->post->arr('fn'); - foreach($actions as $action => $extensions) { - foreach($extensions as $extname => $label) { - switch($action) { + foreach ($actions as $action => $extensions) { + foreach ($extensions as $extname => $label) { + switch ($action) { case 'install': case 'reinstall': case 'update': $extension->setExtension($extname); $installed = $extension->installOrUpdate(); - foreach($installed as $ext => $info) { - msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); + foreach ($installed as $ext => $info) { + msg( + sprintf( + $this->getLang('msg_' . $info['type'] . '_' . $info['action'] . '_success'), + $info['base'] + ), + 1 + ); } break; case 'uninstall': $extension->setExtension($extname); $status = $extension->uninstall(); - if($status) { - msg(sprintf($this->getLang('msg_delete_success'), hsc($extension->getDisplayName())), 1); + if ($status) { + msg( + sprintf( + $this->getLang('msg_delete_success'), + hsc($extension->getDisplayName()) + ), + 1 + ); } else { - msg(sprintf($this->getLang('msg_delete_failed'), hsc($extension->getDisplayName())), -1); + msg( + sprintf( + $this->getLang('msg_delete_failed'), + hsc($extension->getDisplayName()) + ), + -1 + ); } break; - case 'enable'; + case 'enable': $extension->setExtension($extname); $status = $extension->enable(); - if($status !== true) { + if ($status !== true) { msg($status, -1); } else { msg(sprintf($this->getLang('msg_enabled'), hsc($extension->getDisplayName())), 1); } break; - case 'disable'; + case 'disable': $extension->setExtension($extname); $status = $extension->disable(); - if($status !== true) { + if ($status !== true) { msg($status, -1); } else { msg(sprintf($this->getLang('msg_disabled'), hsc($extension->getDisplayName())), 1); @@ -107,37 +127,36 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { } } send_redirect($this->gui->tabURL('', array(), '&', true)); - } elseif($INPUT->post->str('installurl') && checkSecurityToken()) { + } elseif ($INPUT->post->str('installurl') && checkSecurityToken()) { $installed = $extension->installFromURL($INPUT->post->str('installurl')); - foreach($installed as $ext => $info) { + foreach ($installed as $ext => $info) { msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); } send_redirect($this->gui->tabURL('', array(), '&', true)); - } elseif(isset($_FILES['installfile']) && checkSecurityToken()) { + } elseif (isset($_FILES['installfile']) && checkSecurityToken()) { $installed = $extension->installFromUpload('installfile'); - foreach($installed as $ext => $info) { + foreach ($installed as $ext => $info) { msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); } send_redirect($this->gui->tabURL('', array(), '&', true)); } - - } catch(Exception $e) { + } catch (Exception $e) { msg($e->getMessage(), -1); send_redirect($this->gui->tabURL('', array(), '&', true)); } - } /** * Render HTML output */ - public function html() { + public function html() + { ptln('<h1>'.$this->getLang('menu').'</h1>'); ptln('<div id="extension__manager">'); $this->gui->tabNavigation(); - switch($this->gui->currentTab()) { + switch ($this->gui->currentTab()) { case 'search': $this->gui->tabSearch(); break; diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 7266ed8e6..0186620d0 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -6,14 +6,14 @@ * @author Michael Hamann <michael@content-space.de> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); -if(!defined('DOKU_TPLLIB')) define('DOKU_TPLLIB', DOKU_INC.'lib/tpl/'); +use dokuwiki\HTTP\DokuHTTPClient; +use dokuwiki\Extension\PluginController; /** * Class helper_plugin_extension_extension represents a single extension (plugin or template) */ -class helper_plugin_extension_extension extends DokuWiki_Plugin { +class helper_plugin_extension_extension extends DokuWiki_Plugin +{ private $id; private $base; private $is_template = false; @@ -26,13 +26,25 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** @var array list of temporary directories */ private $temporary = array(); + /** @var string where templates are installed to */ + private $tpllib = ''; + + /** + * helper_plugin_extension_extension constructor. + */ + public function __construct() + { + $this->tpllib = dirname(tpl_incdir()).'/'; + } + /** * Destructor * * deletes any dangling temporary directories */ - public function __destruct() { - foreach($this->temporary as $dir){ + public function __destruct() + { + foreach ($this->temporary as $dir) { io_rmdir($dir, true); } } @@ -40,7 +52,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * @return bool false, this component is not a singleton */ - public function isSingleton() { + public function isSingleton() + { return false; } @@ -50,12 +63,13 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @param string $id The id of the extension (prefixed with template: for templates) * @return bool If some (local or remote) data was found */ - public function setExtension($id) { + public function setExtension($id) + { $id = cleanID($id); $this->id = $id; $this->base = $id; - if(substr($id, 0 , 9) == 'template:'){ + if (substr($id, 0, 9) == 'template:') { $this->base = substr($id, 9); $this->is_template = true; } else { @@ -85,7 +99,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If the extension is installed locally */ - public function isInstalled() { + public function isInstalled() + { return is_dir($this->getInstallDir()); } @@ -94,8 +109,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool */ - public function isGitControlled() { - if(!$this->isInstalled()) return false; + public function isGitControlled() + { + if (!$this->isInstalled()) return false; return is_dir($this->getInstallDir().'/.git'); } @@ -104,12 +120,16 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If the extension is bundled */ - public function isBundled() { + public function isBundled() + { if (!empty($this->remoteInfo['bundled'])) return $this->remoteInfo['bundled']; - return in_array($this->id, - array( - 'authad', 'authldap', 'authmysql', 'authpdo', 'authpgsql', 'authplain', 'acl', 'info', 'extension', - 'revert', 'popularity', 'config', 'safefnrecode', 'styling', 'testing', 'template:dokuwiki' + return in_array( + $this->id, + array( + 'authad', 'authldap', 'authmysql', 'authpdo', + 'authpgsql', 'authplain', 'acl', 'info', 'extension', + 'revert', 'popularity', 'config', 'safefnrecode', 'styling', + 'testing', 'template:dokuwiki' ) ); } @@ -119,12 +139,13 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool if the extension is protected */ - public function isProtected() { + public function isProtected() + { // never allow deinstalling the current auth plugin: global $conf; if ($this->id == $conf['authtype']) return true; - /** @var Doku_Plugin_Controller $plugin_controller */ + /** @var PluginController $plugin_controller */ global $plugin_controller; $cascade = $plugin_controller->getCascade(); return (isset($cascade['protected'][$this->id]) && $cascade['protected'][$this->id]); @@ -135,7 +156,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If the extension is installed in the correct directory */ - public function isInWrongFolder() { + public function isInWrongFolder() + { return $this->base != $this->getBase(); } @@ -144,13 +166,14 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If the extension is enabled */ - public function isEnabled() { + public function isEnabled() + { global $conf; - if($this->isTemplate()){ + if ($this->isTemplate()) { return ($conf['template'] == $this->getBase()); } - /* @var Doku_Plugin_Controller $plugin_controller */ + /* @var PluginController $plugin_controller */ global $plugin_controller; return !$plugin_controller->isdisabled($this->base); } @@ -160,9 +183,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If an update is available */ - public function updateAvailable() { - if(!$this->isInstalled()) return false; - if($this->isBundled()) return false; + public function updateAvailable() + { + if (!$this->isInstalled()) return false; + if ($this->isBundled()) return false; $lastupdate = $this->getLastUpdate(); if ($lastupdate === false) return false; $installed = $this->getInstalledVersion(); @@ -175,7 +199,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If this extension is a template */ - public function isTemplate() { + public function isTemplate() + { return $this->is_template; } @@ -186,7 +211,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string */ - public function getID() { + public function getID() + { return $this->id; } @@ -195,7 +221,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string The name of the installation directory */ - public function getInstallName() { + public function getInstallName() + { return $this->base; } @@ -205,7 +232,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string The basename */ - public function getBase() { + public function getBase() + { if (!empty($this->localInfo['base'])) return $this->localInfo['base']; return $this->base; } @@ -215,7 +243,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string The display name */ - public function getDisplayName() { + public function getDisplayName() + { if (!empty($this->localInfo['name'])) return $this->localInfo['name']; if (!empty($this->remoteInfo['name'])) return $this->remoteInfo['name']; return $this->base; @@ -226,7 +255,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The name of the author or false if there is none */ - public function getAuthor() { + public function getAuthor() + { if (!empty($this->localInfo['author'])) return $this->localInfo['author']; if (!empty($this->remoteInfo['author'])) return $this->remoteInfo['author']; return false; @@ -237,7 +267,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The email address or false if there is none */ - public function getEmail() { + public function getEmail() + { // email is only in the local data if (!empty($this->localInfo['email'])) return $this->localInfo['email']; return false; @@ -248,7 +279,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The md5sum of the email if there is any, false otherwise */ - public function getEmailID() { + public function getEmailID() + { if (!empty($this->remoteInfo['emailid'])) return $this->remoteInfo['emailid']; if (!empty($this->localInfo['email'])) return md5($this->localInfo['email']); return false; @@ -259,7 +291,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string The description */ - public function getDescription() { + public function getDescription() + { if (!empty($this->localInfo['desc'])) return $this->localInfo['desc']; if (!empty($this->remoteInfo['description'])) return $this->remoteInfo['description']; return ''; @@ -270,7 +303,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string The URL */ - public function getURL() { + public function getURL() + { if (!empty($this->localInfo['url'])) return $this->localInfo['url']; return 'https://www.dokuwiki.org/'.($this->isTemplate() ? 'template' : 'plugin').':'.$this->getBase(); } @@ -280,7 +314,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The version, usually in the form yyyy-mm-dd if there is any */ - public function getInstalledVersion() { + public function getInstalledVersion() + { if (!empty($this->localInfo['date'])) return $this->localInfo['date']; if ($this->isInstalled()) return $this->getLang('unknownversion'); return false; @@ -291,7 +326,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The date of the last update or false if not available */ - public function getUpdateDate() { + public function getUpdateDate() + { if (!empty($this->managerData['updated'])) return $this->managerData['updated']; return $this->getInstallDate(); } @@ -301,7 +337,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The date of the installation or false if not available */ - public function getInstallDate() { + public function getInstallDate() + { if (!empty($this->managerData['installed'])) return $this->managerData['installed']; return false; } @@ -311,7 +348,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The base names of the dependencies */ - public function getDependencies() { + public function getDependencies() + { if (!empty($this->remoteInfo['dependencies'])) return $this->remoteInfo['dependencies']; return array(); } @@ -321,8 +359,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The base names of the missing dependencies */ - public function getMissingDependencies() { - /* @var Doku_Plugin_Controller $plugin_controller */ + public function getMissingDependencies() + { + /* @var PluginController $plugin_controller */ global $plugin_controller; $dependencies = $this->getDependencies(); $missing_dependencies = array(); @@ -339,7 +378,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The names of the conflicting extensions */ - public function getConflicts() { + public function getConflicts() + { if (!empty($this->remoteInfo['conflicts'])) return $this->remoteInfo['conflicts']; return array(); } @@ -349,7 +389,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The names of similar extensions */ - public function getSimilarExtensions() { + public function getSimilarExtensions() + { if (!empty($this->remoteInfo['similar'])) return $this->remoteInfo['similar']; return array(); } @@ -359,7 +400,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The names of the tags of the extension */ - public function getTags() { + public function getTags() + { if (!empty($this->remoteInfo['tags'])) return $this->remoteInfo['tags']; return array(); } @@ -369,7 +411,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return float|bool The popularity information or false if it isn't available */ - public function getPopularity() { + public function getPopularity() + { if (!empty($this->remoteInfo['popularity'])) return $this->remoteInfo['popularity']; return false; } @@ -380,7 +423,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The security warning if there is any, false otherwise */ - public function getSecurityWarning() { + public function getSecurityWarning() + { if (!empty($this->remoteInfo['securitywarning'])) return $this->remoteInfo['securitywarning']; return false; } @@ -390,7 +434,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The security issue if there is any, false otherwise */ - public function getSecurityIssue() { + public function getSecurityIssue() + { if (!empty($this->remoteInfo['securityissue'])) return $this->remoteInfo['securityissue']; return false; } @@ -400,7 +445,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The screenshot URL if there is any, false otherwise */ - public function getScreenshotURL() { + public function getScreenshotURL() + { if (!empty($this->remoteInfo['screenshoturl'])) return $this->remoteInfo['screenshoturl']; return false; } @@ -410,7 +456,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The thumbnail URL if there is any, false otherwise */ - public function getThumbnailURL() { + public function getThumbnailURL() + { if (!empty($this->remoteInfo['thumbnailurl'])) return $this->remoteInfo['thumbnailurl']; return false; } @@ -419,7 +466,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The previously used download URL, false if the extension has been installed manually */ - public function getLastDownloadURL() { + public function getLastDownloadURL() + { if (!empty($this->managerData['downloadurl'])) return $this->managerData['downloadurl']; return false; } @@ -429,7 +477,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The download URL if there is any, false otherwise */ - public function getDownloadURL() { + public function getDownloadURL() + { if (!empty($this->remoteInfo['downloadurl'])) return $this->remoteInfo['downloadurl']; return false; } @@ -439,7 +488,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If the download URL has changed */ - public function hasDownloadURLChanged() { + public function hasDownloadURLChanged() + { $lasturl = $this->getLastDownloadURL(); $currenturl = $this->getDownloadURL(); return ($lasturl && $currenturl && $lasturl != $currenturl); @@ -450,7 +500,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The bug tracker URL if there is any, false otherwise */ - public function getBugtrackerURL() { + public function getBugtrackerURL() + { if (!empty($this->remoteInfo['bugtracker'])) return $this->remoteInfo['bugtracker']; return false; } @@ -460,7 +511,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The URL of the source repository if there is any, false otherwise */ - public function getSourcerepoURL() { + public function getSourcerepoURL() + { if (!empty($this->remoteInfo['sourcerepo'])) return $this->remoteInfo['sourcerepo']; return false; } @@ -470,7 +522,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The donation URL if there is any, false otherwise */ - public function getDonationURL() { + public function getDonationURL() + { if (!empty($this->remoteInfo['donationurl'])) return $this->remoteInfo['donationurl']; return false; } @@ -480,7 +533,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The type(s) as array of strings */ - public function getTypes() { + public function getTypes() + { if (!empty($this->remoteInfo['types'])) return $this->remoteInfo['types']; if ($this->isTemplate()) return array(32 => 'template'); return array(); @@ -491,7 +545,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The versions in the form yyyy-mm-dd => ('label' => label, 'implicit' => implicit) */ - public function getCompatibleVersions() { + public function getCompatibleVersions() + { if (!empty($this->remoteInfo['compatible'])) return $this->remoteInfo['compatible']; return array(); } @@ -501,7 +556,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string|bool The last available update in the form yyyy-mm-dd if there is any, false otherwise */ - public function getLastUpdate() { + public function getLastUpdate() + { if (!empty($this->remoteInfo['lastupdate'])) return $this->remoteInfo['lastupdate']; return false; } @@ -511,9 +567,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string The base path of the extension */ - public function getInstallDir() { + public function getInstallDir() + { if ($this->isTemplate()) { - return DOKU_TPLLIB.$this->base; + return $this->tpllib.$this->base; } else { return DOKU_PLUGIN.$this->base; } @@ -524,7 +581,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string One of "none", "manual", "git" or "automatic" */ - public function getInstallType() { + public function getInstallType() + { if (!$this->isInstalled()) return 'none'; if (!empty($this->managerData)) return 'automatic'; if (is_dir($this->getInstallDir().'/.git')) return 'git'; @@ -536,17 +594,17 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool|string True or error string */ - public function canModify() { - if($this->isInstalled()) { - if(!is_writable($this->getInstallDir())) { + public function canModify() + { + if ($this->isInstalled()) { + if (!is_writable($this->getInstallDir())) { return 'noperms'; } } - if($this->isTemplate() && !is_writable(DOKU_TPLLIB)) { + if ($this->isTemplate() && !is_writable($this->tpllib)) { return 'notplperms'; - - } elseif(!is_writable(DOKU_PLUGIN)) { + } elseif (!is_writable(DOKU_PLUGIN)) { return 'nopluginperms'; } return true; @@ -559,20 +617,21 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @throws Exception when something goes wrong * @return array The list of installed extensions */ - public function installFromUpload($field){ - if($_FILES[$field]['error']){ + public function installFromUpload($field) + { + if ($_FILES[$field]['error']) { throw new Exception($this->getLang('msg_upload_failed').' ('.$_FILES[$field]['error'].')'); } $tmp = $this->mkTmpDir(); - if(!$tmp) throw new Exception($this->getLang('error_dircreate')); + if (!$tmp) throw new Exception($this->getLang('error_dircreate')); // filename may contain the plugin name for old style plugins... $basename = basename($_FILES[$field]['name']); $basename = preg_replace('/\.(tar\.gz|tar\.bz|tar\.bz2|tar|tgz|tbz|zip)$/', '', $basename); $basename = preg_replace('/[\W]+/', '', $basename); - if(!move_uploaded_file($_FILES[$field]['tmp_name'], "$tmp/upload.archive")){ + if (!move_uploaded_file($_FILES[$field]['tmp_name'], "$tmp/upload.archive")) { throw new Exception($this->getLang('msg_upload_failed')); } @@ -582,7 +641,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $this->removeDeletedfiles($installed); // purge cache $this->purgeCache(); - }catch (Exception $e){ + } catch (Exception $e) { throw $e; } return $installed; @@ -595,7 +654,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @throws Exception when something goes wrong * @return array The list of installed extensions */ - public function installFromURL($url){ + public function installFromURL($url) + { try { $path = $this->download($url); $installed = $this->installArchive($path, true); @@ -604,7 +664,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // purge cache $this->purgeCache(); - }catch (Exception $e){ + } catch (Exception $e) { throw $e; } return $installed; @@ -616,7 +676,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @throws \Exception when something goes wrong * @return array The list of installed extensions */ - public function installOrUpdate() { + public function installOrUpdate() + { $url = $this->getDownloadURL(); $path = $this->download($url); $installed = $this->installArchive($path, $this->isInstalled(), $this->getBase()); @@ -637,7 +698,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool If the plugin was sucessfully uninstalled */ - public function uninstall() { + public function uninstall() + { $this->purgeCache(); return io_rmdir($this->getInstallDir(), true); } @@ -647,12 +709,13 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool|string True or an error message */ - public function enable() { + public function enable() + { if ($this->isTemplate()) return $this->getLang('notimplemented'); if (!$this->isInstalled()) return $this->getLang('notinstalled'); if ($this->isEnabled()) return $this->getLang('alreadyenabled'); - /* @var Doku_Plugin_Controller $plugin_controller */ + /* @var PluginController $plugin_controller */ global $plugin_controller; if ($plugin_controller->enable($this->base)) { $this->purgeCache(); @@ -667,10 +730,11 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool|string True or an error message */ - public function disable() { + public function disable() + { if ($this->isTemplate()) return $this->getLang('notimplemented'); - /* @var Doku_Plugin_Controller $plugin_controller */ + /* @var PluginController $plugin_controller */ global $plugin_controller; if (!$this->isInstalled()) return $this->getLang('notinstalled'); if (!$this->isEnabled()) return $this->getLang('alreadydisabled'); @@ -685,7 +749,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * Purge the cache by touching the main configuration file */ - protected function purgeCache() { + protected function purgeCache() + { global $config_cascade; // expire dokuwiki caches @@ -696,7 +761,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * Read local extension data either from info.txt or getInfo() */ - protected function readLocalData() { + protected function readLocalData() + { if ($this->isTemplate()) { $infopath = $this->getInstallDir().'/template.info.txt'; } else { @@ -706,19 +772,18 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { if (is_readable($infopath)) { $this->localInfo = confToHash($infopath); } elseif (!$this->isTemplate() && $this->isEnabled()) { - global $plugin_types; $path = $this->getInstallDir().'/'; $plugin = null; - foreach($plugin_types as $type) { - if(file_exists($path.$type.'.php')) { + foreach (PluginController::PLUGIN_TYPES as $type) { + if (file_exists($path.$type.'.php')) { $plugin = plugin_load($type, $this->base); if ($plugin) break; } - if($dh = @opendir($path.$type.'/')) { - while(false !== ($cp = readdir($dh))) { - if($cp == '.' || $cp == '..' || strtolower(substr($cp, -4)) != '.php') continue; + if ($dh = @opendir($path.$type.'/')) { + while (false !== ($cp = readdir($dh))) { + if ($cp == '.' || $cp == '..' || strtolower(substr($cp, -4)) != '.php') continue; $plugin = plugin_load($type, $this->base.'_'.substr($cp, 0, -4)); if ($plugin) break; @@ -741,21 +806,22 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @param string $url Where the extension was downloaded from. (empty for manual installs via upload) * @param array $installed Optional list of installed plugins */ - protected function updateManagerData($url = '', $installed = null) { + protected function updateManagerData($url = '', $installed = null) + { $origID = $this->getID(); - if(is_null($installed)) { + if (is_null($installed)) { $installed = array($origID); } - foreach($installed as $ext => $info) { - if($this->getID() != $ext) $this->setExtension($ext); - if($url) { + foreach ($installed as $ext => $info) { + if ($this->getID() != $ext) $this->setExtension($ext); + if ($url) { $this->managerData['downloadurl'] = $url; - } elseif(isset($this->managerData['downloadurl'])) { + } elseif (isset($this->managerData['downloadurl'])) { unset($this->managerData['downloadurl']); } - if(isset($this->managerData['installed'])) { + if (isset($this->managerData['installed'])) { $this->managerData['updated'] = date('r'); } else { $this->managerData['installed'] = date('r'); @@ -763,23 +829,24 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $this->writeManagerData(); } - if($this->getID() != $origID) $this->setExtension($origID); + if ($this->getID() != $origID) $this->setExtension($origID); } /** * Read the manager.dat file */ - protected function readManagerData() { + protected function readManagerData() + { $managerpath = $this->getInstallDir().'/manager.dat'; if (is_readable($managerpath)) { $file = @file($managerpath); - if(!empty($file)) { - foreach($file as $line) { + if (!empty($file)) { + foreach ($file as $line) { list($key, $value) = explode('=', trim($line, DOKU_LF), 2); $key = trim($key); $value = trim($value); // backwards compatible with old plugin manager - if($key == 'url') $key = 'downloadurl'; + if ($key == 'url') $key = 'downloadurl'; $this->managerData[$key] = $value; } } @@ -789,7 +856,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * Write the manager.data file */ - protected function writeManagerData() { + protected function writeManagerData() + { $managerpath = $this->getInstallDir().'/manager.dat'; $data = ''; foreach ($this->managerData as $k => $v) { @@ -805,9 +873,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return false|string */ - protected function mkTmpDir(){ + protected function mkTmpDir() + { $dir = io_mktmpdir(); - if(!$dir) return false; + if (!$dir) return false; $this->temporary[] = $dir; return $dir; } @@ -844,7 +913,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { if (is_string($content_disposition) && preg_match('/attachment;\s*filename\s*=\s*"([^"]*)"/i', $content_disposition, $match)) { - $name = utf8_basename($match[1]); + $name = \dokuwiki\Utf8\PhpString::basename($match[1]); } } @@ -872,27 +941,28 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @throws Exception when something goes wrong * @return string The path where the archive was saved */ - public function download($url) { + public function download($url) + { // check the url - if(!preg_match('/https?:\/\//i', $url)){ + if (!preg_match('/https?:\/\//i', $url)) { throw new Exception($this->getLang('error_badurl')); } // try to get the file from the path (used as plugin name fallback) $file = parse_url($url, PHP_URL_PATH); - if(is_null($file)){ + if (is_null($file)) { $file = md5($url); - }else{ - $file = utf8_basename($file); + } else { + $file = \dokuwiki\Utf8\PhpString::basename($file); } // create tmp directory for download - if(!($tmp = $this->mkTmpDir())) { + if (!($tmp = $this->mkTmpDir())) { throw new Exception($this->getLang('error_dircreate')); } // download - if(!$file = $this->downloadToFile($url, $tmp.'/', $file)) { + if (!$file = $this->downloadToFile($url, $tmp.'/', $file)) { io_rmdir($tmp, true); throw new Exception(sprintf($this->getLang('error_download'), '<bdi>'.hsc($url).'</bdi>')); } @@ -907,16 +977,17 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @throws Exception when something went wrong * @return array list of installed extensions */ - public function installArchive($file, $overwrite=false, $base = '') { + public function installArchive($file, $overwrite = false, $base = '') + { $installed_extensions = array(); // create tmp directory for decompression - if(!($tmp = $this->mkTmpDir())) { + if (!($tmp = $this->mkTmpDir())) { throw new Exception($this->getLang('error_dircreate')); } // add default base folder if specified to handle case where zip doesn't contain this - if($base && !@mkdir($tmp.'/'.$base)) { + if ($base && !@mkdir($tmp.'/'.$base)) { throw new Exception($this->getLang('error_dircreate')); } @@ -927,33 +998,33 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // move the folder(s) to lib/.. $result = array('old'=>array(), 'new'=>array()); $default = ($this->isTemplate() ? 'template' : 'plugin'); - if(!$this->find_folders($result, $tmp.'/'.$base, $default)) { + if (!$this->findFolders($result, $tmp.'/'.$base, $default)) { throw new Exception($this->getLang('error_findfolder')); } // choose correct result array - if(count($result['new'])) { + if (count($result['new'])) { $install = $result['new']; - }else{ + } else { $install = $result['old']; } - if(!count($install)){ + if (!count($install)) { throw new Exception($this->getLang('error_findfolder')); } // now install all found items - foreach($install as $item) { + foreach ($install as $item) { // where to install? - if($item['type'] == 'template') { - $target_base_dir = DOKU_TPLLIB; - }else{ + if ($item['type'] == 'template') { + $target_base_dir = $this->tpllib; + } else { $target_base_dir = DOKU_PLUGIN; } - if(!empty($item['base'])) { + if (!empty($item['base'])) { // use base set in info.txt - } elseif($base && count($install) == 1) { + } elseif ($base && count($install) == 1) { $item['base'] = $base; } else { // default - use directory as found in zip @@ -964,7 +1035,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // check to make sure we aren't overwriting anything $target = $target_base_dir.$item['base']; - if(!$overwrite && file_exists($target)) { + if (!$overwrite && file_exists($target)) { // TODO remember our settings, ask the user to confirm overwrite continue; } @@ -972,10 +1043,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $action = file_exists($target) ? 'update' : 'install'; // copy action - if($this->dircopy($item['tmp'], $target)) { + if ($this->dircopy($item['tmp'], $target)) { // return info $id = $item['base']; - if($item['type'] == 'template') { + if ($item['type'] == 'template') { $id = 'template:'.$id; } $installed_extensions[$id] = array( @@ -989,7 +1060,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } // cleanup - if($tmp) io_rmdir($tmp, true); + if ($tmp) io_rmdir($tmp, true); return $installed_extensions; } @@ -1015,20 +1086,20 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @param string $subdir - a subdirectory. do not set. used by recursion * @return bool - false on error */ - protected function find_folders(&$result, $directory, $default_type='plugin', $subdir='') { + protected function findFolders(&$result, $directory, $default_type = 'plugin', $subdir = '') + { $this_dir = "$directory$subdir"; $dh = @opendir($this_dir); - if(!$dh) return false; + if (!$dh) return false; $found_dirs = array(); $found_files = 0; $found_template_parts = 0; while (false !== ($f = readdir($dh))) { - if($f == '.' || $f == '..') continue; + if ($f == '.' || $f == '..') continue; - if(is_dir("$this_dir/$f")) { + if (is_dir("$this_dir/$f")) { $found_dirs[] = "$subdir/$f"; - } else { // it's a file -> check for config $found_files++; @@ -1057,11 +1128,11 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { closedir($dh); // files where found but no info.txt - use old method - if($found_files){ + if ($found_files) { $info = array(); $info['tmp'] = $this_dir; // does this look like a template or should we use the default type? - if($found_template_parts >= 2) { + if ($found_template_parts >= 2) { $info['type'] = 'template'; } else { $info['type'] = $default_type; @@ -1073,7 +1144,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // we have no files yet -> recurse foreach ($found_dirs as $found_dir) { - $this->find_folders($result, $directory, $default_type, "$found_dir"); + $this->findFolders($result, $directory, $default_type, "$found_dir"); } return true; } @@ -1088,13 +1159,13 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @throws Exception * @return bool */ - private function decompress($file, $target) { + private function decompress($file, $target) + { // decompression library doesn't like target folders ending in "/" - if(substr($target, -1) == "/") $target = substr($target, 0, -1); - - $ext = $this->guess_archive($file); - if(in_array($ext, array('tar', 'bz', 'gz'))) { + if (substr($target, -1) == "/") $target = substr($target, 0, -1); + $ext = $this->guessArchiveType($file); + if (in_array($ext, array('tar', 'bz', 'gz'))) { try { $tar = new \splitbrain\PHPArchive\Tar(); $tar->open($file); @@ -1104,8 +1175,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } return true; - } elseif($ext == 'zip') { - + } elseif ($ext == 'zip') { try { $zip = new \splitbrain\PHPArchive\Zip(); $zip->open($file); @@ -1131,15 +1201,16 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @param string $file The file to analyze * @return string|false false if the file can't be read, otherwise an "extension" */ - private function guess_archive($file) { + private function guessArchiveType($file) + { $fh = fopen($file, 'rb'); - if(!$fh) return false; + if (!$fh) return false; $magic = fread($fh, 5); fclose($fh); - if(strpos($magic, "\x42\x5a") === 0) return 'bz'; - if(strpos($magic, "\x1f\x8b") === 0) return 'gz'; - if(strpos($magic, "\x50\x4b\x03\x04") === 0) return 'zip'; + if (strpos($magic, "\x42\x5a") === 0) return 'bz'; + if (strpos($magic, "\x1f\x8b") === 0) return 'gz'; + if (strpos($magic, "\x50\x4b\x03\x04") === 0) return 'zip'; return 'tar'; } @@ -1150,27 +1221,27 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @param string $dst filename path to file * @return bool|int|string */ - private function dircopy($src, $dst) { + private function dircopy($src, $dst) + { global $conf; - if(is_dir($src)) { - if(!$dh = @opendir($src)) return false; + if (is_dir($src)) { + if (!$dh = @opendir($src)) return false; - if($ok = io_mkdir_p($dst)) { + if ($ok = io_mkdir_p($dst)) { while ($ok && (false !== ($f = readdir($dh)))) { - if($f == '..' || $f == '.') continue; + if ($f == '..' || $f == '.') continue; $ok = $this->dircopy("$src/$f", "$dst/$f"); } } closedir($dh); return $ok; - } else { $exists = file_exists($dst); - if(!@copy($src, $dst)) return false; - if(!$exists && !empty($conf['fperm'])) chmod($dst, $conf['fperm']); + if (!@copy($src, $dst)) return false; + if (!$exists && !empty($conf['fperm'])) chmod($dst, $conf['fperm']); @touch($dst, filemtime($src)); } @@ -1182,29 +1253,30 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @param array $installed */ - private function removeDeletedfiles($installed) { - foreach($installed as $id => $extension) { + private function removeDeletedfiles($installed) + { + foreach ($installed as $id => $extension) { // only on update - if($extension['action'] == 'install') continue; + if ($extension['action'] == 'install') continue; // get definition file - if($extension['type'] == 'template') { - $extensiondir = DOKU_TPLLIB; - }else{ + if ($extension['type'] == 'template') { + $extensiondir = $this->tpllib; + } else { $extensiondir = DOKU_PLUGIN; } $extensiondir = $extensiondir . $extension['base'] .'/'; $definitionfile = $extensiondir . 'deleted.files'; - if(!file_exists($definitionfile)) continue; + if (!file_exists($definitionfile)) continue; // delete the old files $list = file($definitionfile); - foreach($list as $line) { + foreach ($list as $line) { $line = trim(preg_replace('/#.*$/', '', $line)); - if(!$line) continue; + if (!$line) continue; $file = $extensiondir . $line; - if(!file_exists($file)) continue; + if (!file_exists($file)) continue; io_rmdir($file, true); } diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 4ec6fec85..aa9e2ec45 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -6,13 +6,13 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); +use dokuwiki\Extension\PluginController; /** * Class helper_plugin_extension_list takes care of the overall GUI */ -class helper_plugin_extension_gui extends DokuWiki_Plugin { +class helper_plugin_extension_gui extends DokuWiki_Plugin +{ protected $tabs = array('plugins', 'templates', 'search', 'install'); @@ -24,7 +24,8 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * * initializes requested info window */ - public function __construct() { + public function __construct() + { global $INPUT; $this->infoFor = $INPUT->str('info'); } @@ -32,8 +33,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { /** * display the plugin tab */ - public function tabPlugins() { - /* @var Doku_Plugin_Controller $plugin_controller */ + public function tabPlugins() + { + /* @var PluginController $plugin_controller */ global $plugin_controller; echo '<div class="panelHeader">'; @@ -46,19 +48,20 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $extension = $this->loadHelper('extension_extension'); /* @var helper_plugin_extension_list $list */ $list = $this->loadHelper('extension_list'); - $list->start_form(); - foreach($pluginlist as $name) { + $list->startForm(); + foreach ($pluginlist as $name) { $extension->setExtension($name); - $list->add_row($extension, $extension->getID() == $this->infoFor); + $list->addRow($extension, $extension->getID() == $this->infoFor); } - $list->end_form(); + $list->endForm(); $list->render(); } /** * Display the template tab */ - public function tabTemplates() { + public function tabTemplates() + { echo '<div class="panelHeader">'; echo $this->locale_xhtml('intro_templates'); echo '</div>'; @@ -72,19 +75,20 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $extension = $this->loadHelper('extension_extension'); /* @var helper_plugin_extension_list $list */ $list = $this->loadHelper('extension_list'); - $list->start_form(); - foreach($tpllist as $name) { + $list->startForm(); + foreach ($tpllist as $name) { $extension->setExtension("template:$name"); - $list->add_row($extension, $extension->getID() == $this->infoFor); + $list->addRow($extension, $extension->getID() == $this->infoFor); } - $list->end_form(); + $list->endForm(); $list->render(); } /** * Display the search tab */ - public function tabSearch() { + public function tabSearch() + { global $INPUT; echo '<div class="panelHeader">'; echo $this->locale_xhtml('intro_search'); @@ -95,7 +99,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $form->addElement(form_makeButton('submit', '', $this->getLang('search'))); $form->printForm(); - if(!$INPUT->bool('q')) return; + if (!$INPUT->bool('q')) return; /* @var helper_plugin_extension_repository $repository FIXME should we use some gloabl instance? */ $repository = $this->loadHelper('extension_repository'); @@ -105,29 +109,35 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $extension = $this->loadHelper('extension_extension'); /* @var helper_plugin_extension_list $list */ $list = $this->loadHelper('extension_list'); - $list->start_form(); - if($result){ - foreach($result as $name) { + $list->startForm(); + if ($result) { + foreach ($result as $name) { $extension->setExtension($name); - $list->add_row($extension, $extension->getID() == $this->infoFor); + $list->addRow($extension, $extension->getID() == $this->infoFor); } } else { - $list->nothing_found(); + $list->nothingFound(); } - $list->end_form(); + $list->endForm(); $list->render(); - } /** * Display the template tab */ - public function tabInstall() { + public function tabInstall() + { echo '<div class="panelHeader">'; echo $this->locale_xhtml('intro_install'); echo '</div>'; - $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'), 'enctype' => 'multipart/form-data', 'class' => 'install')); + $form = new Doku_Form( + array( + 'action' => $this->tabURL('', array(), '&'), + 'enctype' => 'multipart/form-data', + 'class' => 'install' + ) + ); $form->addElement(form_makeTextField('installurl', '', $this->getLang('install_url'), '', 'block')); $form->addElement(form_makeFileField('installfile', $this->getLang('install_upload'), '', 'block')); $form->addElement(form_makeButton('submit', '', $this->getLang('btn_install'))); @@ -139,11 +149,12 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * * @fixme style active one */ - public function tabNavigation() { + public function tabNavigation() + { echo '<ul class="tabs">'; - foreach($this->tabs as $tab) { + foreach ($this->tabs as $tab) { $url = $this->tabURL($tab); - if($this->currentTab() == $tab) { + if ($this->currentTab() == $tab) { $class = ' active'; } else { $class = ''; @@ -158,11 +169,12 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * * @return string */ - public function currentTab() { + public function currentTab() + { global $INPUT; $tab = $INPUT->str('tab', 'plugins', true); - if(!in_array($tab, $this->tabs)) $tab = 'plugins'; + if (!in_array($tab, $this->tabs)) $tab = 'plugins'; return $tab; } @@ -175,19 +187,19 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * @param bool $absolute create absolute URLs? * @return string */ - public function tabURL($tab = '', $params = array(), $sep = '&', $absolute = false) { + public function tabURL($tab = '', $params = array(), $sep = '&', $absolute = false) + { global $ID; global $INPUT; - if(!$tab) $tab = $this->currentTab(); + if (!$tab) $tab = $this->currentTab(); $defaults = array( 'do' => 'admin', 'page' => 'extension', 'tab' => $tab, ); - if($tab == 'search') $defaults['q'] = $INPUT->str('q'); + if ($tab == 'search') $defaults['q'] = $INPUT->str('q'); return wl($ID, array_merge($defaults, $params), $absolute, $sep); } - } diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 656b4ea09..d895941cb 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -6,13 +6,11 @@ * @author Michael Hamann <michael@content-space.de> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - /** * Class helper_plugin_extension_list takes care of creating a HTML list of extensions */ -class helper_plugin_extension_list extends DokuWiki_Plugin { +class helper_plugin_extension_list extends DokuWiki_Plugin +{ protected $form = ''; /** @var helper_plugin_extension_gui */ protected $gui; @@ -22,30 +20,38 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * * loads additional helpers */ - public function __construct(){ + public function __construct() + { $this->gui = plugin_load('helper', 'extension_gui'); } - function start_form() { + /** + * Initialize the extension table form + */ + public function startForm() + { $this->form .= '<form id="extension__list" accept-charset="utf-8" method="post" action="">'; $hidden = array( 'do'=>'admin', 'page'=>'extension', 'sectok'=>getSecurityToken() ); - $this->add_hidden($hidden); + $this->addHidden($hidden); $this->form .= '<ul class="extensionList">'; } + /** * Build single row of extension table + * * @param helper_plugin_extension_extension $extension The extension that shall be added * @param bool $showinfo Show the info area */ - function add_row(helper_plugin_extension_extension $extension, $showinfo = false) { - $this->start_row($extension); - $this->populate_column('legend', $this->make_legend($extension, $showinfo)); - $this->populate_column('actions', $this->make_actions($extension)); - $this->end_row(); + public function addRow(helper_plugin_extension_extension $extension, $showinfo = false) + { + $this->startRow($extension); + $this->populateColumn('legend', $this->makeLegend($extension, $showinfo)); + $this->populateColumn('actions', $this->makeActions($extension)); + $this->endRow(); } /** @@ -55,7 +61,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param string $header The content of the header * @param int $level The level of the header */ - function add_header($id, $header, $level = 2) { + public function addHeader($id, $header, $level = 2) + { $this->form .='<h'.$level.' id="'.$id.'">'.hsc($header).'</h'.$level.'>'.DOKU_LF; } @@ -64,17 +71,20 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * * @param string $data The content */ - function add_p($data) { + public function addParagraph($data) + { $this->form .= '<p>'.hsc($data).'</p>'.DOKU_LF; } /** * Add hidden fields to the form with the given data - * @param array $array + * + * @param array $data key-value list of fields and their values to add */ - function add_hidden(array $array) { + public function addHidden(array $data) + { $this->form .= '<div class="no">'; - foreach ($array as $key => $value) { + foreach ($data as $key => $value) { $this->form .= '<input type="hidden" name="'.hsc($key).'" value="'.hsc($value).'" />'; } $this->form .= '</div>'.DOKU_LF; @@ -83,7 +93,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { /** * Add closing tags */ - function end_form() { + public function endForm() + { $this->form .= '</ul>'; $this->form .= '</form>'.DOKU_LF; } @@ -91,7 +102,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { /** * Show message when no results are found */ - function nothing_found() { + public function nothingFound() + { global $lang; $this->form .= '<li class="notfound">'.$lang['nothingfound'].'</li>'; } @@ -99,7 +111,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { /** * Print the form */ - function render() { + public function render() + { echo $this->form; } @@ -108,8 +121,10 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * * @param helper_plugin_extension_extension $extension The extension */ - private function start_row(helper_plugin_extension_extension $extension) { - $this->form .= '<li id="extensionplugin__'.hsc($extension->getID()).'" class="'.$this->make_class($extension).'">'; + private function startRow(helper_plugin_extension_extension $extension) + { + $this->form .= '<li id="extensionplugin__'.hsc($extension->getID()). + '" class="'.$this->makeClass($extension).'">'; } /** @@ -117,14 +132,16 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param string $class The class name * @param string $html The content */ - private function populate_column($class, $html) { + private function populateColumn($class, $html) + { $this->form .= '<div class="'.$class.' col">'.$html.'</div>'.DOKU_LF; } /** * End the row */ - private function end_row() { + private function endRow() + { $this->form .= '</li>'.DOKU_LF; } @@ -134,7 +151,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension * @return string The HTML code */ - function make_homepagelink(helper_plugin_extension_extension $extension) { + public function makeHomepageLink(helper_plugin_extension_extension $extension) + { $text = $this->getLang('homepage_link'); $url = hsc($extension->getURL()); return '<a href="'.$url.'" title="'.$url.'" class ="urlextern">'.$text.'</a> '; @@ -146,15 +164,16 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension object * @return string The class name */ - function make_class(helper_plugin_extension_extension $extension) { + public function makeClass(helper_plugin_extension_extension $extension) + { $class = ($extension->isTemplate()) ? 'template' : 'plugin'; - if($extension->isInstalled()) { + if ($extension->isInstalled()) { $class.=' installed'; $class.= ($extension->isEnabled()) ? ' enabled':' disabled'; - if($extension->updateAvailable()) $class .= ' updatable'; + if ($extension->updateAvailable()) $class .= ' updatable'; } - if(!$extension->canModify()) $class.= ' notselect'; - if($extension->isProtected()) $class.= ' protected'; + if (!$extension->canModify()) $class.= ' notselect'; + if ($extension->isProtected()) $class.= ' protected'; //if($this->showinfo) $class.= ' showinfo'; return $class; } @@ -165,17 +184,16 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension object * @return string The HTML code of the link */ - function make_author(helper_plugin_extension_extension $extension) { - global $ID; - - if($extension->getAuthor()) { - + public function makeAuthor(helper_plugin_extension_extension $extension) + { + if ($extension->getAuthor()) { $mailid = $extension->getEmailID(); - if($mailid){ + if ($mailid) { $url = $this->gui->tabURL('search', array('q' => 'authorid:'.$mailid)); - return '<bdi><a href="'.$url.'" class="author" title="'.$this->getLang('author_hint').'" ><img src="//www.gravatar.com/avatar/'.$mailid.'?s=20&d=mm" width="20" height="20" alt="" /> '.hsc($extension->getAuthor()).'</a></bdi>'; - - }else{ + return '<bdi><a href="'.$url.'" class="author" title="'.$this->getLang('author_hint').'" >'. + '<img src="//www.gravatar.com/avatar/'.$mailid.'?s=20&d=mm" width="20" height="20" alt="" /> '. + hsc($extension->getAuthor()).'</a></bdi>'; + } else { return '<bdi><span class="author">'.hsc($extension->getAuthor()).'</span></bdi>'; } } @@ -188,11 +206,12 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension object * @return string The HTML code */ - function make_screenshot(helper_plugin_extension_extension $extension) { + public function makeScreenshot(helper_plugin_extension_extension $extension) + { $screen = $extension->getScreenshotURL(); $thumb = $extension->getThumbnailURL(); - if($screen) { + if ($screen) { // use protocol independent URLs for images coming from us #595 $screen = str_replace('http://www.dokuwiki.org', '//www.dokuwiki.org', $screen); $thumb = str_replace('http://www.dokuwiki.org', '//www.dokuwiki.org', $thumb); @@ -201,11 +220,12 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $img = '<a href="'.hsc($screen).'" target="_blank" class="extension_screenshot">'. '<img alt="'.$title.'" width="120" height="70" src="'.hsc($thumb).'" />'. '</a>'; - } elseif($extension->isTemplate()) { - $img = '<img alt="" width="120" height="70" src="'.DOKU_BASE.'lib/plugins/extension/images/template.png" />'; - + } elseif ($extension->isTemplate()) { + $img = '<img alt="" width="120" height="70" src="'.DOKU_BASE. + 'lib/plugins/extension/images/template.png" />'; } else { - $img = '<img alt="" width="120" height="70" src="'.DOKU_BASE.'lib/plugins/extension/images/plugin.png" />'; + $img = '<img alt="" width="120" height="70" src="'.DOKU_BASE. + 'lib/plugins/extension/images/plugin.png" />'; } return '<div class="screenshot" >'.$img.'<span></span></div>'.DOKU_LF; } @@ -217,41 +237,51 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param bool $showinfo Show the info section * @return string The HTML code */ - function make_legend(helper_plugin_extension_extension $extension, $showinfo = false) { + public function makeLegend(helper_plugin_extension_extension $extension, $showinfo = false) + { $return = '<div>'; $return .= '<h2>'; - $return .= sprintf($this->getLang('extensionby'), '<bdi>'.hsc($extension->getDisplayName()).'</bdi>', $this->make_author($extension)); + $return .= sprintf( + $this->getLang('extensionby'), + '<bdi>'.hsc($extension->getDisplayName()).'</bdi>', + $this->makeAuthor($extension) + ); $return .= '</h2>'.DOKU_LF; - $return .= $this->make_screenshot($extension); + $return .= $this->makeScreenshot($extension); $popularity = $extension->getPopularity(); if ($popularity !== false && !$extension->isBundled()) { $popularityText = sprintf($this->getLang('popularity'), round($popularity*100, 2)); - $return .= '<div class="popularity" title="'.$popularityText.'"><div style="width: '.($popularity * 100).'%;"><span class="a11y">'.$popularityText.'</span></div></div>'.DOKU_LF; + $return .= '<div class="popularity" title="'.$popularityText.'">'. + '<div style="width: '.($popularity * 100).'%;">'. + '<span class="a11y">'.$popularityText.'</span>'. + '</div></div>'.DOKU_LF; } - if($extension->getDescription()) { + if ($extension->getDescription()) { $return .= '<p><bdi>'; $return .= hsc($extension->getDescription()).' '; $return .= '</bdi></p>'.DOKU_LF; } - $return .= $this->make_linkbar($extension); + $return .= $this->makeLinkbar($extension); - if($showinfo){ + if ($showinfo) { $url = $this->gui->tabURL(''); $class = 'close'; - }else{ + } else { $url = $this->gui->tabURL('', array('info' => $extension->getID())); $class = ''; } - $return .= ' <a href="'.$url.'#extensionplugin__'.$extension->getID().'" class="info '.$class.'" title="'.$this->getLang('btn_info').'" data-extid="'.$extension->getID().'">'.$this->getLang('btn_info').'</a>'; + $return .= ' <a href="'.$url.'#extensionplugin__'.$extension->getID(). + '" class="info '.$class.'" title="'.$this->getLang('btn_info'). + '" data-extid="'.$extension->getID().'">'.$this->getLang('btn_info').'</a>'; if ($showinfo) { - $return .= $this->make_info($extension); + $return .= $this->makeInfo($extension); } - $return .= $this->make_noticearea($extension); + $return .= $this->makeNoticeArea($extension); $return .= '</div>'.DOKU_LF; return $return; } @@ -262,17 +292,20 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension instance * @return string The HTML code */ - function make_linkbar(helper_plugin_extension_extension $extension) { + public function makeLinkbar(helper_plugin_extension_extension $extension) + { $return = '<div class="linkbar">'; - $return .= $this->make_homepagelink($extension); + $return .= $this->makeHomepageLink($extension); if ($extension->getBugtrackerURL()) { - $return .= ' <a href="'.hsc($extension->getBugtrackerURL()).'" title="'.hsc($extension->getBugtrackerURL()).'" class ="bugs">'.$this->getLang('bugs_features').'</a> '; + $return .= ' <a href="'.hsc($extension->getBugtrackerURL()). + '" title="'.hsc($extension->getBugtrackerURL()).'" class ="bugs">'. + $this->getLang('bugs_features').'</a> '; } - if ($extension->getTags()){ + if ($extension->getTags()) { $first = true; $return .= '<span class="tags">'.$this->getLang('tags').' '; foreach ($extension->getTags() as $tag) { - if (!$first){ + if (!$first) { $return .= ', '; } else { $first = false; @@ -292,37 +325,49 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension * @return string The HTML code */ - function make_noticearea(helper_plugin_extension_extension $extension) { + public function makeNoticeArea(helper_plugin_extension_extension $extension) + { $return = ''; $missing_dependencies = $extension->getMissingDependencies(); - if(!empty($missing_dependencies)) { - $return .= '<div class="msg error">'. - sprintf($this->getLang('missing_dependency'), '<bdi>'.implode(', ', /*array_map(array($this->helper, 'make_extensionsearchlink'),*/ $missing_dependencies).'</bdi>'). + if (!empty($missing_dependencies)) { + $return .= '<div class="msg error">' . + sprintf( + $this->getLang('missing_dependency'), + '<bdi>' . implode(', ', $missing_dependencies) . '</bdi>' + ) . '</div>'; } - if($extension->isInWrongFolder()) { - $return .= '<div class="msg error">'. - sprintf($this->getLang('wrong_folder'), '<bdi>'.hsc($extension->getInstallName()).'</bdi>', '<bdi>'.hsc($extension->getBase()).'</bdi>'). + if ($extension->isInWrongFolder()) { + $return .= '<div class="msg error">' . + sprintf( + $this->getLang('wrong_folder'), + '<bdi>' . hsc($extension->getInstallName()) . '</bdi>', + '<bdi>' . hsc($extension->getBase()) . '</bdi>' + ) . '</div>'; } - if(($securityissue = $extension->getSecurityIssue()) !== false) { + if (($securityissue = $extension->getSecurityIssue()) !== false) { $return .= '<div class="msg error">'. sprintf($this->getLang('security_issue'), '<bdi>'.hsc($securityissue).'</bdi>'). '</div>'; } - if(($securitywarning = $extension->getSecurityWarning()) !== false) { + if (($securitywarning = $extension->getSecurityWarning()) !== false) { $return .= '<div class="msg notify">'. sprintf($this->getLang('security_warning'), '<bdi>'.hsc($securitywarning).'</bdi>'). '</div>'; } - if($extension->updateAvailable()) { + if ($extension->updateAvailable()) { $return .= '<div class="msg notify">'. sprintf($this->getLang('update_available'), hsc($extension->getLastUpdate())). '</div>'; } - if($extension->hasDownloadURLChanged()) { - $return .= '<div class="msg notify">'. - sprintf($this->getLang('url_change'), '<bdi>'.hsc($extension->getDownloadURL()).'</bdi>', '<bdi>'.hsc($extension->getLastDownloadURL()).'</bdi>'). + if ($extension->hasDownloadURLChanged()) { + $return .= '<div class="msg notify">' . + sprintf( + $this->getLang('url_change'), + '<bdi>' . hsc($extension->getDownloadURL()) . '</bdi>', + '<bdi>' . hsc($extension->getLastDownloadURL()) . '</bdi>' + ) . '</div>'; } return $return.DOKU_LF; @@ -336,13 +381,14 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param string $url * @return string HTML link */ - function shortlink($url){ + public function shortlink($url) + { $link = parse_url($url); $base = $link['host']; - if(!empty($link['port'])) $base .= $base.':'.$link['port']; + if (!empty($link['port'])) $base .= $base.':'.$link['port']; $long = $link['path']; - if(!empty($link['query'])) $long .= $link['query']; + if (!empty($link['query'])) $long .= $link['query']; $name = shorten($base, $long, 55); @@ -355,17 +401,19 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension * @return string The HTML code */ - function make_info(helper_plugin_extension_extension $extension) { + public function makeInfo(helper_plugin_extension_extension $extension) + { $default = $this->getLang('unknown'); $return = '<dl class="details">'; $return .= '<dt>'.$this->getLang('status').'</dt>'; - $return .= '<dd>'.$this->make_status($extension).'</dd>'; + $return .= '<dd>'.$this->makeStatus($extension).'</dd>'; if ($extension->getDonationURL()) { $return .= '<dt>'.$this->getLang('donate').'</dt>'; $return .= '<dd>'; - $return .= '<a href="'.$extension->getDonationURL().'" class="donate">'.$this->getLang('donate_action').'</a>'; + $return .= '<a href="'.$extension->getDonationURL().'" class="donate">'. + $this->getLang('donate_action').'</a>'; $return .= '</dd>'; } @@ -407,7 +455,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return .= ($extension->getTypes() ? hsc(implode(', ', $extension->getTypes())) : $default); $return .= '</bdi></dd>'; - if(!$extension->isBundled() && $extension->getCompatibleVersions()) { + if (!$extension->isBundled() && $extension->getCompatibleVersions()) { $return .= '<dt>'.$this->getLang('compatible').'</dt>'; $return .= '<dd>'; foreach ($extension->getCompatibleVersions() as $date => $version) { @@ -416,24 +464,24 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return = rtrim($return, ', '); $return .= '</dd>'; } - if($extension->getDependencies()) { + if ($extension->getDependencies()) { $return .= '<dt>'.$this->getLang('depends').'</dt>'; $return .= '<dd>'; - $return .= $this->make_linklist($extension->getDependencies()); + $return .= $this->makeLinkList($extension->getDependencies()); $return .= '</dd>'; } - if($extension->getSimilarExtensions()) { + if ($extension->getSimilarExtensions()) { $return .= '<dt>'.$this->getLang('similar').'</dt>'; $return .= '<dd>'; - $return .= $this->make_linklist($extension->getSimilarExtensions()); + $return .= $this->makeLinkList($extension->getSimilarExtensions()); $return .= '</dd>'; } - if($extension->getConflicts()) { + if ($extension->getConflicts()) { $return .= '<dt>'.$this->getLang('conflicts').'</dt>'; $return .= '<dd>'; - $return .= $this->make_linklist($extension->getConflicts()); + $return .= $this->makeLinkList($extension->getConflicts()); $return .= '</dd>'; } $return .= '</dl>'.DOKU_LF; @@ -446,10 +494,12 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param array $ext The extensions * @return string The HTML code */ - function make_linklist($ext) { + public function makeLinkList($ext) + { $return = ''; foreach ($ext as $link) { - $return .= '<bdi><a href="'.$this->gui->tabURL('search', array('q'=>'ext:'.$link)).'">'.hsc($link).'</a></bdi>, '; + $return .= '<bdi><a href="'. + $this->gui->tabURL('search', array('q'=>'ext:'.$link)).'">'.hsc($link).'</a></bdi>, '; } return rtrim($return, ', '); } @@ -460,7 +510,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension * @return string The HTML code */ - function make_actions(helper_plugin_extension_extension $extension) { + public function makeActions(helper_plugin_extension_extension $extension) + { global $conf; $return = ''; $errors = ''; @@ -468,48 +519,52 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { if ($extension->isInstalled()) { if (($canmod = $extension->canModify()) === true) { if (!$extension->isProtected()) { - $return .= $this->make_action('uninstall', $extension); + $return .= $this->makeAction('uninstall', $extension); } if ($extension->getDownloadURL()) { if ($extension->updateAvailable()) { - $return .= $this->make_action('update', $extension); + $return .= $this->makeAction('update', $extension); } else { - $return .= $this->make_action('reinstall', $extension); + $return .= $this->makeAction('reinstall', $extension); } } - }else{ + } else { $errors .= '<p class="permerror">'.$this->getLang($canmod).'</p>'; } if (!$extension->isProtected() && !$extension->isTemplate()) { // no enable/disable for templates if ($extension->isEnabled()) { - $return .= $this->make_action('disable', $extension); + $return .= $this->makeAction('disable', $extension); } else { - $return .= $this->make_action('enable', $extension); + $return .= $this->makeAction('enable', $extension); } } - if ($extension->isGitControlled()){ + if ($extension->isGitControlled()) { $errors .= '<p class="permerror">'.$this->getLang('git').'</p>'; } - if ($extension->isEnabled() && in_array('Auth', $extension->getTypes()) && $conf['authtype'] != $extension->getID()) { + if ($extension->isEnabled() && + in_array('Auth', $extension->getTypes()) && + $conf['authtype'] != $extension->getID() + ) { $errors .= '<p class="permerror">'.$this->getLang('auth').'</p>'; } - - }else{ + } else { if (($canmod = $extension->canModify()) === true) { if ($extension->getDownloadURL()) { - $return .= $this->make_action('install', $extension); + $return .= $this->makeAction('install', $extension); } - }else{ + } else { $errors .= '<div class="permerror">'.$this->getLang($canmod).'</div>'; } } if (!$extension->isInstalled() && $extension->getDownloadURL()) { $return .= ' <span class="version">'.$this->getLang('available_version').' '; - $return .= ($extension->getLastUpdate() ? hsc($extension->getLastUpdate()) : $this->getLang('unknown')).'</span>'; + $return .= ($extension->getLastUpdate() + ? hsc($extension->getLastUpdate()) + : $this->getLang('unknown')).'</span>'; } return $return.' '.$errors.DOKU_LF; @@ -522,7 +577,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension * @return string The HTML code */ - function make_action($action, $extension) { + public function makeAction($action, $extension) + { $title = ''; switch ($action) { @@ -535,7 +591,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $classes = 'button '.$action; $name = 'fn['.$action.']['.hsc($extension->getID()).']'; - return '<button class="'.$classes.'" name="'.$name.'" type="submit" '.$title.'>'.$this->getLang('btn_'.$action).'</button> '; + return '<button class="'.$classes.'" name="'.$name.'" type="submit" '.$title.'>'. + $this->getLang('btn_'.$action).'</button> '; } /** @@ -544,7 +601,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension * @return string The description of all relevant statusses */ - function make_status(helper_plugin_extension_extension $extension) { + public function makeStatus(helper_plugin_extension_extension $extension) + { $status = array(); @@ -553,15 +611,16 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { if ($extension->isProtected()) { $status[] = $this->getLang('status_protected'); } else { - $status[] = $extension->isEnabled() ? $this->getLang('status_enabled') : $this->getLang('status_disabled'); + $status[] = $extension->isEnabled() + ? $this->getLang('status_enabled') + : $this->getLang('status_disabled'); } } else { $status[] = $this->getLang('status_not_installed'); } - if(!$extension->canModify()) $status[] = $this->getLang('status_unmodifiable'); - if($extension->isBundled()) $status[] = $this->getLang('status_bundled'); + if (!$extension->canModify()) $status[] = $this->getLang('status_unmodifiable'); + if ($extension->isBundled()) $status[] = $this->getLang('status_bundled'); $status[] = $extension->isTemplate() ? $this->getLang('status_template') : $this->getLang('status_plugin'); return join(', ', $status); } - } diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php index 99deb5b27..712baa05c 100644 --- a/lib/plugins/extension/helper/repository.php +++ b/lib/plugins/extension/helper/repository.php @@ -6,34 +6,39 @@ * @author Michael Hamann <michael@content-space.de> */ -#define('EXTENSION_REPOSITORY_API', 'http://localhost/dokuwiki/lib/plugins/pluginrepo/api.php'); - -if (!defined('EXTENSION_REPOSITORY_API_ENDPOINT')) - define('EXTENSION_REPOSITORY_API', 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php'); - -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); +use dokuwiki\Cache\Cache; +use dokuwiki\HTTP\DokuHTTPClient; +use dokuwiki\Extension\PluginController; /** * Class helper_plugin_extension_repository provides access to the extension repository on dokuwiki.org */ -class helper_plugin_extension_repository extends DokuWiki_Plugin { +class helper_plugin_extension_repository extends DokuWiki_Plugin +{ + + const EXTENSION_REPOSITORY_API = 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php'; + private $loaded_extensions = array(); private $has_access = null; + /** * Initialize the repository (cache), fetches data for all installed plugins */ - public function init() { - /* @var Doku_Plugin_Controller $plugin_controller */ + public function init() + { + /* @var PluginController $plugin_controller */ global $plugin_controller; if ($this->hasAccess()) { $list = $plugin_controller->getList('', true); $request_data = array('fmt' => 'php'); $request_needed = false; foreach ($list as $name) { - $cache = new cache('##extension_manager##'.$name, '.repo'); + $cache = new Cache('##extension_manager##'.$name, '.repo'); - if (!isset($this->loaded_extensions[$name]) && $this->hasAccess() && !$cache->useCache(array('age' => 3600 * 24))) { + if (!isset($this->loaded_extensions[$name]) && + $this->hasAccess() && + !$cache->useCache(array('age' => 3600 * 24)) + ) { $this->loaded_extensions[$name] = true; $request_data['ext'][] = $name; $request_needed = true; @@ -42,11 +47,11 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { if ($request_needed) { $httpclient = new DokuHTTPClient(); - $data = $httpclient->post(EXTENSION_REPOSITORY_API, $request_data); + $data = $httpclient->post(self::EXTENSION_REPOSITORY_API, $request_data); if ($data !== false) { $extensions = unserialize($data); foreach ($extensions as $extension) { - $cache = new cache('##extension_manager##'.$extension['plugin'], '.repo'); + $cache = new Cache('##extension_manager##'.$extension['plugin'], '.repo'); $cache->storeCache(serialize($extension)); } } else { @@ -64,12 +69,12 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { */ public function hasAccess($usecache = true) { if ($this->has_access === null) { - $cache = new cache('##extension_manager###hasAccess', '.repo'); + $cache = new Cache('##extension_manager###hasAccess', '.repo'); if (!$cache->useCache(array('age' => 60*10, 'purge' => !$usecache))) { $httpclient = new DokuHTTPClient(); $httpclient->timeout = 5; - $data = $httpclient->get(EXTENSION_REPOSITORY_API.'?cmd=ping'); + $data = $httpclient->get(self::EXTENSION_REPOSITORY_API.'?cmd=ping'); if ($data !== false) { $this->has_access = true; $cache->storeCache(1); @@ -90,13 +95,17 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { * @param string $name The plugin name to get the data for, template names need to be prefix by 'template:' * @return array The data or null if nothing was found (possibly no repository access) */ - public function getData($name) { - $cache = new cache('##extension_manager##'.$name, '.repo'); - - if (!isset($this->loaded_extensions[$name]) && $this->hasAccess() && !$cache->useCache(array('age' => 3600 * 24))) { + public function getData($name) + { + $cache = new Cache('##extension_manager##'.$name, '.repo'); + + if (!isset($this->loaded_extensions[$name]) && + $this->hasAccess() && + !$cache->useCache(array('age' => 3600 * 24)) + ) { $this->loaded_extensions[$name] = true; $httpclient = new DokuHTTPClient(); - $data = $httpclient->get(EXTENSION_REPOSITORY_API.'?fmt=php&ext[]='.urlencode($name)); + $data = $httpclient->get(self::EXTENSION_REPOSITORY_API.'?fmt=php&ext[]='.urlencode($name)); if ($data !== false) { $result = unserialize($data); $cache->storeCache(serialize($result[0])); @@ -117,21 +126,22 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { * @param string $q the query string * @return array a list of matching extensions */ - public function search($q){ - $query = $this->parse_query($q); + public function search($q) + { + $query = $this->parseQuery($q); $query['fmt'] = 'php'; $httpclient = new DokuHTTPClient(); - $data = $httpclient->post(EXTENSION_REPOSITORY_API, $query); + $data = $httpclient->post(self::EXTENSION_REPOSITORY_API, $query); if ($data === false) return array(); $result = unserialize($data); $ids = array(); // store cache info for each extension - foreach($result as $ext){ + foreach ($result as $ext) { $name = $ext['plugin']; - $cache = new cache('##extension_manager##'.$name, '.repo'); + $cache = new Cache('##extension_manager##'.$name, '.repo'); $cache->storeCache(serialize($ext)); $ids[] = $name; } @@ -145,7 +155,8 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { * @param string $q * @return array */ - protected function parse_query($q){ + protected function parseQuery($q) + { $parameters = array( 'tag' => array(), 'mail' => array(), @@ -154,29 +165,29 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { ); // extract tags - if(preg_match_all('/(^|\s)(tag:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ - foreach($matches as $m){ + if (preg_match_all('/(^|\s)(tag:([\S]+))/', $q, $matches, PREG_SET_ORDER)) { + foreach ($matches as $m) { $q = str_replace($m[2], '', $q); $parameters['tag'][] = $m[3]; } } // extract author ids - if(preg_match_all('/(^|\s)(authorid:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ - foreach($matches as $m){ + if (preg_match_all('/(^|\s)(authorid:([\S]+))/', $q, $matches, PREG_SET_ORDER)) { + foreach ($matches as $m) { $q = str_replace($m[2], '', $q); $parameters['mail'][] = $m[3]; } } // extract extensions - if(preg_match_all('/(^|\s)(ext:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ - foreach($matches as $m){ + if (preg_match_all('/(^|\s)(ext:([\S]+))/', $q, $matches, PREG_SET_ORDER)) { + foreach ($matches as $m) { $q = str_replace($m[2], '', $q); $parameters['ext'][] = $m[3]; } } // extract types - if(preg_match_all('/(^|\s)(type:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ - foreach($matches as $m){ + if (preg_match_all('/(^|\s)(type:([\S]+))/', $q, $matches, PREG_SET_ORDER)) { + foreach ($matches as $m) { $q = str_replace($m[2], '', $q); $parameters['type'][] = $m[3]; } diff --git a/lib/plugins/info/syntax.php b/lib/plugins/info/syntax.php index 773256faf..3fa35e733 100644 --- a/lib/plugins/info/syntax.php +++ b/lib/plugins/info/syntax.php @@ -6,33 +6,30 @@ * @author Andreas Gohr <andi@splitbrain.org> * @author Esther Brunner <wikidesign@gmail.com> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -/** - * All DokuWiki plugins to extend the parser/rendering mechanism - * need to inherit from this class - */ -class syntax_plugin_info extends DokuWiki_Syntax_Plugin { +class syntax_plugin_info extends DokuWiki_Syntax_Plugin +{ /** * What kind of syntax are we? */ - function getType(){ + public function getType() + { return 'substition'; } /** * What about paragraphs? */ - function getPType(){ + public function getPType() + { return 'block'; } /** * Where to sort in? */ - function getSort(){ + public function getSort() + { return 155; } @@ -40,8 +37,9 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { /** * Connect pattern to lexer */ - function connectTo($mode) { - $this->Lexer->addSpecialPattern('~~INFO:\w+~~',$mode,'plugin_info'); + public function connectTo($mode) + { + $this->Lexer->addSpecialPattern('~~INFO:\w+~~', $mode, 'plugin_info'); } /** @@ -53,8 +51,9 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * @param Doku_Handler $handler The Doku_Handler object * @return array Return an array with all data you want to use in render */ - function handle($match, $state, $pos, Doku_Handler $handler){ - $match = substr($match,7,-2); //strip ~~INFO: from start and ~~ from end + public function handle($match, $state, $pos, Doku_Handler $handler) + { + $match = substr($match, 7, -2); //strip ~~INFO: from start and ~~ from end return array(strtolower($match)); } @@ -66,40 +65,41 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * @param array $data data created by handler() * @return boolean rendered correctly? */ - function render($format, Doku_Renderer $renderer, $data) { - if($format == 'xhtml'){ + public function render($format, Doku_Renderer $renderer, $data) + { + if ($format == 'xhtml') { /** @var Doku_Renderer_xhtml $renderer */ //handle various info stuff - switch ($data[0]){ + switch ($data[0]) { case 'syntaxmodes': - $renderer->doc .= $this->_syntaxmodes_xhtml(); + $renderer->doc .= $this->renderSyntaxModes(); break; case 'syntaxtypes': - $renderer->doc .= $this->_syntaxtypes_xhtml(); + $renderer->doc .= $this->renderSyntaxTypes(); break; case 'syntaxplugins': - $this->_plugins_xhtml('syntax', $renderer); + $this->renderPlugins('syntax', $renderer); break; case 'adminplugins': - $this->_plugins_xhtml('admin', $renderer); + $this->renderPlugins('admin', $renderer); break; case 'actionplugins': - $this->_plugins_xhtml('action', $renderer); + $this->renderPlugins('action', $renderer); break; case 'rendererplugins': - $this->_plugins_xhtml('renderer', $renderer); + $this->renderPlugins('renderer', $renderer); break; case 'helperplugins': - $this->_plugins_xhtml('helper', $renderer); + $this->renderPlugins('helper', $renderer); break; case 'authplugins': - $this->_plugins_xhtml('auth', $renderer); + $this->renderPlugins('auth', $renderer); break; case 'remoteplugins': - $this->_plugins_xhtml('remote', $renderer); + $this->renderPlugins('remote', $renderer); break; case 'helpermethods': - $this->_helpermethods_xhtml($renderer); + $this->renderHelperMethods($renderer); break; default: $renderer->doc .= "no info about ".htmlspecialchars($data[0]); @@ -117,7 +117,8 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * @param string $type * @param Doku_Renderer_xhtml $renderer */ - function _plugins_xhtml($type, Doku_Renderer_xhtml $renderer){ + protected function renderPlugins($type, Doku_Renderer_xhtml $renderer) + { global $lang; $renderer->doc .= '<ul>'; @@ -125,24 +126,24 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { $plginfo = array(); // remove subparts - foreach($plugins as $p){ - if (!$po = plugin_load($type,$p)) continue; - list($name,/* $part */) = explode('_',$p,2); + foreach ($plugins as $p) { + if (!$po = plugin_load($type, $p)) continue; + list($name,/* $part */) = explode('_', $p, 2); $plginfo[$name] = $po->getInfo(); } // list them - foreach($plginfo as $info){ + foreach ($plginfo as $info) { $renderer->doc .= '<li><div class="li">'; - $renderer->externallink($info['url'],$info['name']); + $renderer->externallink($info['url'], $info['name']); $renderer->doc .= ' '; $renderer->doc .= '<em>'.$info['date'].'</em>'; $renderer->doc .= ' '; $renderer->doc .= $lang['by']; $renderer->doc .= ' '; - $renderer->emaillink($info['email'],$info['author']); + $renderer->emaillink($info['email'], $info['author']); $renderer->doc .= '<br />'; - $renderer->doc .= strtr(hsc($info['desc']),array("\n"=>"<br />")); + $renderer->doc .= strtr(hsc($info['desc']), array("\n"=>"<br />")); $renderer->doc .= '</div></li>'; unset($po); } @@ -157,39 +158,40 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * * @param Doku_Renderer_xhtml $renderer */ - function _helpermethods_xhtml(Doku_Renderer_xhtml $renderer){ + protected function renderHelperMethods(Doku_Renderer_xhtml $renderer) + { $plugins = plugin_list('helper'); - foreach($plugins as $p){ - if (!$po = plugin_load('helper',$p)) continue; + foreach ($plugins as $p) { + if (!$po = plugin_load('helper', $p)) continue; if (!method_exists($po, 'getMethods')) continue; $methods = $po->getMethods(); $info = $po->getInfo(); - $hid = $this->_addToTOC($info['name'], 2, $renderer); + $hid = $this->addToToc($info['name'], 2, $renderer); $doc = '<h2><a name="'.$hid.'" id="'.$hid.'">'.hsc($info['name']).'</a></h2>'; $doc .= '<div class="level2">'; $doc .= '<p>'.strtr(hsc($info['desc']), array("\n"=>"<br />")).'</p>'; $doc .= '<pre class="code">$'.$p." = plugin_load('helper', '".$p."');</pre>"; $doc .= '</div>'; - foreach ($methods as $method){ + foreach ($methods as $method) { $title = '$'.$p.'->'.$method['name'].'()'; - $hid = $this->_addToTOC($title, 3, $renderer); + $hid = $this->addToToc($title, 3, $renderer); $doc .= '<h3><a name="'.$hid.'" id="'.$hid.'">'.hsc($title).'</a></h3>'; $doc .= '<div class="level3">'; $doc .= '<div class="table"><table class="inline"><tbody>'; $doc .= '<tr><th>Description</th><td colspan="2">'.$method['desc']. '</td></tr>'; - if ($method['params']){ + if ($method['params']) { $c = count($method['params']); $doc .= '<tr><th rowspan="'.$c.'">Parameters</th><td>'; $params = array(); - foreach ($method['params'] as $desc => $type){ + foreach ($method['params'] as $desc => $type) { $params[] = hsc($desc).'</td><td>'.hsc($type); } $doc .= join($params, '</td></tr><tr><td>').'</td></tr>'; } - if ($method['return']){ + if ($method['return']) { $doc .= '<tr><th>Return value</th><td>'.hsc(key($method['return'])). '</td><td>'.hsc(current($method['return'])).'</td></tr>'; } @@ -207,18 +209,19 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * * @return string */ - function _syntaxtypes_xhtml(){ + protected function renderSyntaxTypes() + { global $PARSER_MODES; $doc = ''; $doc .= '<div class="table"><table class="inline"><tbody>'; - foreach($PARSER_MODES as $mode => $modes){ + foreach ($PARSER_MODES as $mode => $modes) { $doc .= '<tr>'; $doc .= '<td class="leftalign">'; $doc .= $mode; $doc .= '</td>'; $doc .= '<td class="leftalign">'; - $doc .= join(', ',$modes); + $doc .= join(', ', $modes); $doc .= '</td>'; $doc .= '</tr>'; } @@ -231,29 +234,30 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * * @return string */ - function _syntaxmodes_xhtml(){ + protected function renderSyntaxModes() + { $modes = p_get_parsermodes(); $compactmodes = array(); - foreach($modes as $mode){ + foreach ($modes as $mode) { $compactmodes[$mode['sort']][] = $mode['mode']; } $doc = ''; $doc .= '<div class="table"><table class="inline"><tbody>'; - foreach($compactmodes as $sort => $modes){ + foreach ($compactmodes as $sort => $modes) { $rowspan = ''; - if(count($modes) > 1) { + if (count($modes) > 1) { $rowspan = ' rowspan="'.count($modes).'"'; } - foreach($modes as $index => $mode) { + foreach ($modes as $index => $mode) { $doc .= '<tr>'; $doc .= '<td class="leftalign">'; $doc .= $mode; $doc .= '</td>'; - if($index === 0) { + if ($index === 0) { $doc .= '<td class="rightalign" '.$rowspan.'>'; $doc .= $sort; $doc .= '</td>'; @@ -274,11 +278,12 @@ class syntax_plugin_info extends DokuWiki_Syntax_Plugin { * @param Doku_Renderer_xhtml $renderer * @return string */ - protected function _addToTOC($text, $level, Doku_Renderer_xhtml $renderer){ + protected function addToToc($text, $level, Doku_Renderer_xhtml $renderer) + { global $conf; $hid = ''; - if (($level >= $conf['toptoclevel']) && ($level <= $conf['maxtoclevel'])){ + if (($level >= $conf['toptoclevel']) && ($level <= $conf['maxtoclevel'])) { $hid = $renderer->_headerToLink($text, true); $renderer->toc[] = array( 'hid' => $hid, diff --git a/lib/plugins/popularity/action.php b/lib/plugins/popularity/action.php index d5ec0f5c5..fac610735 100644 --- a/lib/plugins/popularity/action.php +++ b/lib/plugins/popularity/action.php @@ -5,44 +5,49 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ -require_once(DOKU_PLUGIN.'action.php'); -require_once(DOKU_PLUGIN.'popularity/admin.php'); - -class action_plugin_popularity extends Dokuwiki_Action_Plugin { +class action_plugin_popularity extends DokuWiki_Action_Plugin +{ /** * @var helper_plugin_popularity */ - var $helper; + protected $helper; - function __construct(){ + public function __construct() + { $this->helper = $this->loadHelper('popularity', false); } - /** - * Register its handlers with the dokuwiki's event controller - */ - function register(Doku_Event_Handler $controller) { - $controller->register_hook('INDEXER_TASKS_RUN', 'AFTER', $this, '_autosubmit', array()); + /** @inheritdoc */ + public function register(Doku_Event_Handler $controller) + { + $controller->register_hook('INDEXER_TASKS_RUN', 'AFTER', $this, 'autosubmit', array()); } - function _autosubmit(Doku_Event &$event, $param){ + /** + * Event handler + * + * @param Doku_Event $event + * @param $param + */ + public function autosubmit(Doku_Event &$event, $param) + { //Do we have to send the data now - if ( !$this->helper->isAutosubmitEnabled() || $this->_isTooEarlyToSubmit() ){ + if (!$this->helper->isAutosubmitEnabled() || $this->isTooEarlyToSubmit()) { return; } //Actually send it - $status = $this->helper->sendData( $this->helper->gatherAsString() ); + $status = $this->helper->sendData($this->helper->gatherAsString()); - if ( $status !== '' ){ + if ($status !== '') { //If an error occured, log it - io_saveFile( $this->helper->autosubmitErrorFile, $status ); + io_saveFile($this->helper->autosubmitErrorFile, $status); } else { //If the data has been sent successfully, previous log of errors are useless @unlink($this->helper->autosubmitErrorFile); //Update the last time we sent data - touch ( $this->helper->autosubmitFile ); + touch($this->helper->autosubmitFile); } $event->stopPropagation(); @@ -53,7 +58,8 @@ class action_plugin_popularity extends Dokuwiki_Action_Plugin { * Check if it's time to send autosubmit data * (we should have check if autosubmit is enabled first) */ - function _isTooEarlyToSubmit(){ + protected function isTooEarlyToSubmit() + { $lastSubmit = $this->helper->lastSentTime(); return $lastSubmit + 24*60*60*30 > time(); } diff --git a/lib/plugins/popularity/admin.php b/lib/plugins/popularity/admin.php index 0cf174e0d..61d8cc3bf 100644 --- a/lib/plugins/popularity/admin.php +++ b/lib/plugins/popularity/admin.php @@ -5,43 +5,44 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Andreas Gohr <andi@splitbrain.org> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); +class admin_plugin_popularity extends DokuWiki_Admin_Plugin +{ -/** - * All DokuWiki plugins to extend the admin function - * need to inherit from this class - */ -class admin_plugin_popularity extends DokuWiki_Admin_Plugin { + /** @var helper_plugin_popularity */ + protected $helper; + protected $sentStatus = null; /** - * @var helper_plugin_popularity + * admin_plugin_popularity constructor. */ - var $helper; - var $sentStatus = null; - - function __construct(){ + public function __construct() + { $this->helper = $this->loadHelper('popularity', false); } /** * return prompt for admin menu + * @param $language + * @return string */ - function getMenuText($language) { + public function getMenuText($language) + { return $this->getLang('name'); } /** * return sort order for position in admin menu */ - function getMenuSort() { + public function getMenuSort() + { return 2000; } /** * Accessible for managers */ - function forAdminOnly() { + public function forAdminOnly() + { return false; } @@ -49,18 +50,19 @@ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { /** * handle user request */ - function handle() { + public function handle() + { global $INPUT; //Send the data - if ( $INPUT->has('data') ){ - $this->sentStatus = $this->helper->sendData( $INPUT->str('data') ); - if ( $this->sentStatus === '' ){ + if ($INPUT->has('data')) { + $this->sentStatus = $this->helper->sendData($INPUT->str('data')); + if ($this->sentStatus === '') { //Update the last time we sent the data - touch ( $this->helper->popularityLastSubmitFile ); + touch($this->helper->popularityLastSubmitFile); } //Deal with the autosubmit option - $this->_enableAutosubmit( $INPUT->has('autosubmit') ); + $this->enableAutosubmit($INPUT->has('autosubmit')); } } @@ -68,9 +70,10 @@ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { * Enable or disable autosubmit * @param bool $enable If TRUE, it will enable autosubmit. Else, it will disable it. */ - function _enableAutosubmit( $enable ){ - if ( $enable ){ - io_saveFile( $this->helper->autosubmitFile, ' '); + protected function enableAutosubmit($enable) + { + if ($enable) { + io_saveFile($this->helper->autosubmitFile, ' '); } else { @unlink($this->helper->autosubmitFile); } @@ -79,17 +82,18 @@ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { /** * Output HTML form */ - function html() { + public function html() + { global $INPUT; - if ( ! $INPUT->has('data') ){ + if (! $INPUT->has('data')) { echo $this->locale_xhtml('intro'); //If there was an error the last time we tried to autosubmit, warn the user - if ( $this->helper->isAutoSubmitEnabled() ){ - if ( file_exists($this->helper->autosubmitErrorFile) ){ + if ($this->helper->isAutoSubmitEnabled()) { + if (file_exists($this->helper->autosubmitErrorFile)) { echo $this->getLang('autosubmitError'); - echo io_readFile( $this->helper->autosubmitErrorFile ); + echo io_readFile($this->helper->autosubmitErrorFile); } } @@ -98,12 +102,12 @@ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { //Print the last time the data was sent $lastSent = $this->helper->lastSentTime(); - if ( $lastSent !== 0 ){ + if ($lastSent !== 0) { echo $this->getLang('lastSent') . ' ' . datetime_h($lastSent); } } else { //If we just submitted the form - if ( $this->sentStatus === '' ){ + if ($this->sentStatus === '') { //If we successfully sent the data echo $this->locale_xhtml('submitted'); } else { @@ -122,9 +126,10 @@ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { * @param string $data The popularity data, if it has already been computed. NULL otherwise. * @return string The form, as an html string */ - function buildForm($submissionMode, $data = null){ + protected function buildForm($submissionMode, $data = null) + { $url = ($submissionMode === 'browser' ? $this->helper->submitUrl : script()); - if ( is_null($data) ){ + if (is_null($data)) { $data = $this->helper->gatherAsString(); } @@ -135,7 +140,7 @@ class admin_plugin_popularity extends DokuWiki_Admin_Plugin { .'</textarea><br />'; //If we submit via the server, we give the opportunity to suscribe to the autosubmission option - if ( $submissionMode !== 'browser' ){ + if ($submissionMode !== 'browser') { $form .= '<label for="autosubmit">' .'<input type="checkbox" name="autosubmit" id="autosubmit" ' .($this->helper->isAutosubmitEnabled() ? 'checked' : '' ) diff --git a/lib/plugins/popularity/helper.php b/lib/plugins/popularity/helper.php index b81ab7005..4537976ae 100644 --- a/lib/plugins/popularity/helper.php +++ b/lib/plugins/popularity/helper.php @@ -1,36 +1,43 @@ <?php + +use dokuwiki\HTTP\DokuHTTPClient; +use dokuwiki\Extension\Event; + /** * Popularity Feedback Plugin * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) */ - -class helper_plugin_popularity extends Dokuwiki_Plugin { +class helper_plugin_popularity extends Dokuwiki_Plugin +{ /** * The url where the data should be sent */ - var $submitUrl = 'http://update.dokuwiki.org/popularity.php'; + public $submitUrl = 'http://update.dokuwiki.org/popularity.php'; /** * Name of the file which determine if the the autosubmit is enabled, * and when it was submited for the last time */ - var $autosubmitFile; + public $autosubmitFile; /** * File where the last error which happened when we tried to autosubmit, will be log */ - var $autosubmitErrorFile; + public $autosubmitErrorFile; /** * Name of the file which determine when the popularity data was manually * submitted for the last time * (If this file doesn't exist, the data has never been sent) */ - var $popularityLastSubmitFile; + public $popularityLastSubmitFile; - - function __construct(){ + /** + * helper_plugin_popularity constructor. + */ + public function __construct() + { global $conf; $this->autosubmitFile = $conf['cachedir'].'/autosubmit.txt'; $this->autosubmitErrorFile = $conf['cachedir'].'/autosubmitError.txt'; @@ -38,46 +45,12 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { } /** - * Return methods of this helper - * - * @return array with methods description - */ - function getMethods(){ - $result = array(); - $result[] = array( - 'name' => 'isAutoSubmitEnabled', - 'desc' => 'Check if autosubmit is enabled', - 'params' => array(), - 'return' => array('result' => 'bool') - ); - $result[] = array( - 'name' => 'sendData', - 'desc' => 'Send the popularity data', - 'params' => array('data' => 'string'), - 'return' => array() - ); - $result[] = array( - 'name' => 'gatherAsString', - 'desc' => 'Gather the popularity data', - 'params' => array(), - 'return' => array('data' => 'string') - ); - $result[] = array( - 'name' => 'lastSentTime', - 'desc' => 'Compute the last time popularity data was sent', - 'params' => array(), - 'return' => array('data' => 'int') - ); - return $result; - - } - - /** * Check if autosubmit is enabled * * @return boolean TRUE if we should send data once a month, FALSE otherwise */ - function isAutoSubmitEnabled(){ + public function isAutoSubmitEnabled() + { return file_exists($this->autosubmitFile); } @@ -87,11 +60,12 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { * @param string $data The popularity data * @return string An empty string if everything worked fine, a string describing the error otherwise */ - function sendData($data){ + public function sendData($data) + { $error = ''; $httpClient = new DokuHTTPClient(); $status = $httpClient->sendRequest($this->submitUrl, array('data' => $data), 'POST'); - if ( ! $status ){ + if (! $status) { $error = $httpClient->error; } return $error; @@ -102,7 +76,8 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { * * @return int */ - function lastSentTime(){ + public function lastSentTime() + { $manualSubmission = @filemtime($this->popularityLastSubmitFile); $autoSubmission = @filemtime($this->autosubmitFile); @@ -114,13 +89,14 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { * * @return string The popularity data as a string */ - function gatherAsString(){ - $data = $this->_gather(); + public function gatherAsString() + { + $data = $this->gather(); $string = ''; - foreach($data as $key => $val){ - if(is_array($val)) foreach($val as $v){ + foreach ($data as $key => $val) { + if (is_array($val)) foreach ($val as $v) { $string .= hsc($key)."\t".hsc($v)."\n"; - }else{ + } else { $string .= hsc($key)."\t".hsc($val)."\n"; } } @@ -132,7 +108,8 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { * * @return array The popularity data as an array */ - function _gather(){ + protected function gather() + { global $conf; /** @var $auth DokuWiki_Auth_Plugin */ global $auth; @@ -156,81 +133,81 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { // number and size of pages $list = array(); - search($list,$conf['datadir'],array($this,'_search_count'),array('all'=>false),''); + search($list, $conf['datadir'], array($this, 'searchCountCallback'), array('all'=>false), ''); $data['page_count'] = $list['file_count']; $data['page_size'] = $list['file_size']; $data['page_biggest'] = $list['file_max']; $data['page_smallest'] = $list['file_min']; $data['page_nscount'] = $list['dir_count']; $data['page_nsnest'] = $list['dir_nest']; - if($list['file_count']) $data['page_avg'] = $list['file_size'] / $list['file_count']; + if ($list['file_count']) $data['page_avg'] = $list['file_size'] / $list['file_count']; $data['page_oldest'] = $list['file_oldest']; unset($list); // number and size of media $list = array(); - search($list,$conf['mediadir'],array($this,'_search_count'),array('all'=>true)); + search($list, $conf['mediadir'], array($this, 'searchCountCallback'), array('all'=>true)); $data['media_count'] = $list['file_count']; $data['media_size'] = $list['file_size']; $data['media_biggest'] = $list['file_max']; $data['media_smallest'] = $list['file_min']; $data['media_nscount'] = $list['dir_count']; $data['media_nsnest'] = $list['dir_nest']; - if($list['file_count']) $data['media_avg'] = $list['file_size'] / $list['file_count']; + if ($list['file_count']) $data['media_avg'] = $list['file_size'] / $list['file_count']; unset($list); // number and size of cache $list = array(); - search($list,$conf['cachedir'],array($this,'_search_count'),array('all'=>true)); + search($list, $conf['cachedir'], array($this, 'searchCountCallback'), array('all'=>true)); $data['cache_count'] = $list['file_count']; $data['cache_size'] = $list['file_size']; $data['cache_biggest'] = $list['file_max']; $data['cache_smallest'] = $list['file_min']; - if($list['file_count']) $data['cache_avg'] = $list['file_size'] / $list['file_count']; + if ($list['file_count']) $data['cache_avg'] = $list['file_size'] / $list['file_count']; unset($list); // number and size of index $list = array(); - search($list,$conf['indexdir'],array($this,'_search_count'),array('all'=>true)); + search($list, $conf['indexdir'], array($this, 'searchCountCallback'), array('all'=>true)); $data['index_count'] = $list['file_count']; $data['index_size'] = $list['file_size']; $data['index_biggest'] = $list['file_max']; $data['index_smallest'] = $list['file_min']; - if($list['file_count']) $data['index_avg'] = $list['file_size'] / $list['file_count']; + if ($list['file_count']) $data['index_avg'] = $list['file_size'] / $list['file_count']; unset($list); // number and size of meta $list = array(); - search($list,$conf['metadir'],array($this,'_search_count'),array('all'=>true)); + search($list, $conf['metadir'], array($this, 'searchCountCallback'), array('all'=>true)); $data['meta_count'] = $list['file_count']; $data['meta_size'] = $list['file_size']; $data['meta_biggest'] = $list['file_max']; $data['meta_smallest'] = $list['file_min']; - if($list['file_count']) $data['meta_avg'] = $list['file_size'] / $list['file_count']; + if ($list['file_count']) $data['meta_avg'] = $list['file_size'] / $list['file_count']; unset($list); // number and size of attic $list = array(); - search($list,$conf['olddir'],array($this,'_search_count'),array('all'=>true)); + search($list, $conf['olddir'], array($this, 'searchCountCallback'), array('all'=>true)); $data['attic_count'] = $list['file_count']; $data['attic_size'] = $list['file_size']; $data['attic_biggest'] = $list['file_max']; $data['attic_smallest'] = $list['file_min']; - if($list['file_count']) $data['attic_avg'] = $list['file_size'] / $list['file_count']; + if ($list['file_count']) $data['attic_avg'] = $list['file_size'] / $list['file_count']; $data['attic_oldest'] = $list['file_oldest']; unset($list); // user count - if($auth && $auth->canDo('getUserCount')){ + if ($auth && $auth->canDo('getUserCount')) { $data['user_count'] = $auth->getUserCount(); } // calculate edits per day $list = @file($conf['metadir'].'/_dokuwiki.changes'); $count = count($list); - if($count > 2){ - $first = (int) substr(array_shift($list),0,10); - $last = (int) substr(array_pop($list),0,10); + if ($count > 2) { + $first = (int) substr(array_shift($list), 0, 10); + $last = (int) substr(array_pop($list), 0, 10); $dur = ($last - $first)/(60*60*24); // number of days in the changelog $data['edits_per_day'] = $count/$dur; } @@ -240,7 +217,7 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { $data['plugin'] = plugin_list(); // pcre info - if(defined('PCRE_VERSION')) $data['pcre_version'] = PCRE_VERSION; + if (defined('PCRE_VERSION')) $data['pcre_version'] = PCRE_VERSION; $data['pcre_backtrack'] = ini_get('pcre.backtrack_limit'); $data['pcre_recursion'] = ini_get('pcre.recursion_limit'); @@ -249,27 +226,33 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { $data['webserver'] = $_SERVER['SERVER_SOFTWARE']; $data['php_version'] = phpversion(); $data['php_sapi'] = php_sapi_name(); - $data['php_memory'] = $this->_to_byte(ini_get('memory_limit')); + $data['php_memory'] = php_to_byte(ini_get('memory_limit')); $data['php_exectime'] = $phptime; $data['php_extension'] = get_loaded_extensions(); // plugin usage data - $this->_add_plugin_usage_data($data); + $this->addPluginUsageData($data); return $data; } - protected function _add_plugin_usage_data(&$data){ + /** + * Triggers event to let plugins add their own data + * + * @param $data + */ + protected function addPluginUsageData(&$data) + { $pluginsData = array(); - trigger_event('PLUGIN_POPULARITY_DATA_SETUP', $pluginsData); - foreach($pluginsData as $plugin => $d){ - if ( is_array($d) ) { - foreach($d as $key => $value){ - $data['plugin_' . $plugin . '_' . $key] = $value; - } - } else { - $data['plugin_' . $plugin] = $d; - } + Event::createAndTrigger('PLUGIN_POPULARITY_DATA_SETUP', $pluginsData); + foreach ($pluginsData as $plugin => $d) { + if (is_array($d)) { + foreach ($d as $key => $value) { + $data['plugin_' . $plugin . '_' . $key] = $value; + } + } else { + $data['plugin_' . $plugin] = $d; + } } } @@ -284,57 +267,26 @@ class helper_plugin_popularity extends Dokuwiki_Plugin { * @param array $opts option array as given to search() * @return bool */ - function _search_count(&$data,$base,$file,$type,$lvl,$opts){ + public function searchCountCallback(&$data, $base, $file, $type, $lvl, $opts) + { // traverse - if($type == 'd'){ - if($data['dir_nest'] < $lvl) $data['dir_nest'] = $lvl; + if ($type == 'd') { + if ($data['dir_nest'] < $lvl) $data['dir_nest'] = $lvl; $data['dir_count']++; return true; } //only search txt files if 'all' option not set - if($opts['all'] || substr($file,-4) == '.txt'){ + if ($opts['all'] || substr($file, -4) == '.txt') { $size = filesize($base.'/'.$file); $date = filemtime($base.'/'.$file); $data['file_count']++; $data['file_size'] += $size; - if(!isset($data['file_min']) || $data['file_min'] > $size) $data['file_min'] = $size; - if($data['file_max'] < $size) $data['file_max'] = $size; - if(!isset($data['file_oldest']) || $data['file_oldest'] > $date) $data['file_oldest'] = $date; + if (!isset($data['file_min']) || $data['file_min'] > $size) $data['file_min'] = $size; + if ($data['file_max'] < $size) $data['file_max'] = $size; + if (!isset($data['file_oldest']) || $data['file_oldest'] > $date) $data['file_oldest'] = $date; } return false; } - - /** - * Convert php.ini shorthands to byte - * - * @author <gilthans dot NO dot SPAM at gmail dot com> - * @link http://php.net/manual/en/ini.core.php#79564 - * - * @param string $v - * @return int|string - */ - function _to_byte($v){ - $l = substr($v, -1); - $ret = substr($v, 0, -1); - switch(strtoupper($l)){ - /** @noinspection PhpMissingBreakStatementInspection */ - case 'P': - $ret *= 1024; - /** @noinspection PhpMissingBreakStatementInspection */ - case 'T': - $ret *= 1024; - /** @noinspection PhpMissingBreakStatementInspection */ - case 'G': - $ret *= 1024; - /** @noinspection PhpMissingBreakStatementInspection */ - case 'M': - $ret *= 1024; - case 'K': - $ret *= 1024; - break; - } - return $ret; - } } diff --git a/lib/plugins/remote.php b/lib/plugins/remote.php index c2253dbd5..a3cbec722 100644 --- a/lib/plugins/remote.php +++ b/lib/plugins/remote.php @@ -1,104 +1,2 @@ <?php - -/** - * Class DokuWiki_Remote_Plugin - */ -abstract class DokuWiki_Remote_Plugin extends DokuWiki_Plugin { - - private $api; - - /** - * Constructor - */ - public function __construct() { - $this->api = new RemoteAPI(); - } - - /** - * Get all available methods with remote access. - * - * By default it exports all public methods of a remote plugin. Methods beginning - * with an underscore are skipped. - * - * @return array Information about all provided methods. {@see RemoteAPI}. - */ - public function _getMethods() { - $result = array(); - - $reflection = new \ReflectionClass($this); - foreach($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { - // skip parent methods, only methods further down are exported - $declaredin = $method->getDeclaringClass()->name; - if($declaredin == 'DokuWiki_Plugin' || $declaredin == 'DokuWiki_Remote_Plugin') continue; - $method_name = $method->name; - if(substr($method_name, 0, 1) == '_') continue; - - // strip asterisks - $doc = $method->getDocComment(); - $doc = preg_replace( - array('/^[ \t]*\/\*+[ \t]*/m', '/[ \t]*\*+[ \t]*/m', '/\*+\/\s*$/m','/\s*\/\s*$/m'), - array('', '', '', ''), - $doc - ); - - // prepare data - $data = array(); - $data['name'] = $method_name; - $data['public'] = 0; - $data['doc'] = $doc; - $data['args'] = array(); - - // get parameter type from doc block type hint - foreach($method->getParameters() as $parameter) { - $name = $parameter->name; - $type = 'string'; // we default to string - if(preg_match('/^@param[ \t]+([\w|\[\]]+)[ \t]\$'.$name.'/m', $doc, $m)){ - $type = $this->cleanTypeHint($m[1]); - } - $data['args'][] = $type; - } - - // get return type from doc block type hint - if(preg_match('/^@return[ \t]+([\w|\[\]]+)/m', $doc, $m)){ - $data['return'] = $this->cleanTypeHint($m[1]); - } else { - $data['return'] = 'string'; - } - - // add to result - $result[$method_name] = $data; - } - - return $result; - } - - /** - * Matches the given type hint against the valid options for the remote API - * - * @param string $hint - * @return string - */ - protected function cleanTypeHint($hint) { - $types = explode('|', $hint); - foreach($types as $t) { - if(substr($t, -2) == '[]') { - return 'array'; - } - if($t == 'boolean') { - return 'bool'; - } - if(in_array($t, array('array', 'string', 'int', 'double', 'bool', 'null', 'date', 'file'))) { - return $t; - } - } - return 'string'; - } - - /** - * @return RemoteAPI - */ - protected function getApi() { - return $this->api; - } - -} +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php index 1a0300585..2d11dc05a 100644 --- a/lib/plugins/revert/admin.php +++ b/lib/plugins/revert/admin.php @@ -1,66 +1,73 @@ <?php -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); + +use dokuwiki\ChangeLog\PageChangeLog; /** * All DokuWiki plugins to extend the admin function * need to inherit from this class */ -class admin_plugin_revert extends DokuWiki_Admin_Plugin { - var $cmd; +class admin_plugin_revert extends DokuWiki_Admin_Plugin +{ + protected $cmd; // some vars which might need tuning later - var $max_lines = 800; // lines to read from changelog - var $max_revs = 20; // numer of old revisions to check + protected $max_lines = 800; // lines to read from changelog + protected $max_revs = 20; // numer of old revisions to check /** * Constructor */ - function __construct(){ + public function __construct() + { $this->setupLocale(); } /** * access for managers */ - function forAdminOnly(){ + public function forAdminOnly() + { return false; } /** * return sort order for position in admin menu */ - function getMenuSort() { + public function getMenuSort() + { return 40; } /** * handle user request */ - function handle() { + public function handle() + { } /** * output appropriate html */ - function html() { + public function html() + { global $INPUT; echo $this->locale_xhtml('intro'); - $this->_searchform(); + $this->printSearchForm(); - if(is_array($INPUT->param('revert')) && checkSecurityToken()){ - $this->_revert($INPUT->arr('revert'),$INPUT->str('filter')); - }elseif($INPUT->has('filter')){ - $this->_list($INPUT->str('filter')); + if (is_array($INPUT->param('revert')) && checkSecurityToken()) { + $this->revertEdits($INPUT->arr('revert'), $INPUT->str('filter')); + } elseif ($INPUT->has('filter')) { + $this->listEdits($INPUT->str('filter')); } } /** * Display the form for searching spam pages */ - function _searchform(){ + protected function printSearchForm() + { global $lang, $INPUT; echo '<form action="" method="post"><div class="no">'; echo '<label>'.$this->getLang('filter').': </label>'; @@ -73,31 +80,32 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { /** * Start the reversion process */ - function _revert($revert,$filter){ + protected function revertEdits($revert, $filter) + { echo '<hr /><br />'; echo '<p>'.$this->getLang('revstart').'</p>'; echo '<ul>'; - foreach($revert as $id){ + foreach ($revert as $id) { global $REV; // find the last non-spammy revision $data = ''; $pagelog = new PageChangeLog($id); $old = $pagelog->getRevisions(0, $this->max_revs); - if(count($old)){ - foreach($old as $REV){ - $data = rawWiki($id,$REV); - if(strpos($data,$filter) === false) break; + if (count($old)) { + foreach ($old as $REV) { + $data = rawWiki($id, $REV); + if (strpos($data, $filter) === false) break; } } - if($data){ - saveWikiText($id,$data,'old revision restored',false); - printf('<li><div class="li">'.$this->getLang('reverted').'</div></li>',$id,$REV); - }else{ - saveWikiText($id,'','',false); - printf('<li><div class="li">'.$this->getLang('removed').'</div></li>',$id); + if ($data) { + saveWikiText($id, $data, 'old revision restored', false); + printf('<li><div class="li">'.$this->getLang('reverted').'</div></li>', $id, $REV); + } else { + saveWikiText($id, '', '', false); + printf('<li><div class="li">'.$this->getLang('removed').'</div></li>', $id); } @set_time_limit(10); flush(); @@ -110,7 +118,8 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { /** * List recent edits matching the given filter */ - function _list($filter){ + protected function listEdits($filter) + { global $conf; global $lang; echo '<hr /><br />'; @@ -118,13 +127,13 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { echo '<input type="hidden" name="filter" value="'.hsc($filter).'" />'; formSecurityToken(); - $recents = getRecents(0,$this->max_lines); + $recents = getRecents(0, $this->max_lines); echo '<ul>'; $cnt = 0; - foreach($recents as $recent){ - if($filter){ - if(strpos(rawWiki($recent['id']),$filter) === false) continue; + foreach ($recents as $recent) { + if ($filter) { + if (strpos(rawWiki($recent['id']), $filter) === false) continue; } $cnt++; @@ -132,10 +141,11 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { echo ($recent['type']===DOKU_CHANGE_TYPE_MINOR_EDIT) ? '<li class="minor">' : '<li>'; echo '<div class="li">'; - echo '<input type="checkbox" name="revert[]" value="'.hsc($recent['id']).'" checked="checked" id="revert__'.$cnt.'" />'; + echo '<input type="checkbox" name="revert[]" value="'.hsc($recent['id']). + '" checked="checked" id="revert__'.$cnt.'" />'; echo ' <label for="revert__'.$cnt.'">'.$date.'</label> '; - echo '<a href="'.wl($recent['id'],"do=diff").'">'; + echo '<a href="'.wl($recent['id'], "do=diff").'">'; $p = array(); $p['src'] = DOKU_BASE.'lib/images/diff.png'; $p['width'] = 15; @@ -146,7 +156,7 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { echo "<img $att />"; echo '</a> '; - echo '<a href="'.wl($recent['id'],"do=revisions").'">'; + echo '<a href="'.wl($recent['id'], "do=revisions").'">'; $p = array(); $p['src'] = DOKU_BASE.'lib/images/history.png'; $p['width'] = 12; @@ -157,7 +167,7 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { echo "<img $att />"; echo '</a> '; - echo html_wikilink(':'.$recent['id'],(useHeading('navigation'))?null:$recent['id']); + echo html_wikilink(':'.$recent['id'], (useHeading('navigation'))?null:$recent['id']); echo ' – '.htmlspecialchars($recent['sum']); echo ' <span class="user">'; @@ -174,11 +184,10 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { echo '<p>'; echo '<button type="submit">'.$this->getLang('revert').'</button> '; - printf($this->getLang('note2'),hsc($filter)); + printf($this->getLang('note2'), hsc($filter)); echo '</p>'; echo '</div></form>'; } - } //Setup VIM: ex: et ts=4 : diff --git a/lib/plugins/safefnrecode/action.php b/lib/plugins/safefnrecode/action.php index 9127f8df2..952d95c90 100644 --- a/lib/plugins/safefnrecode/action.php +++ b/lib/plugins/safefnrecode/action.php @@ -6,63 +6,63 @@ * @author Andreas Gohr <andi@splitbrain.org> */ -// must be run within Dokuwiki -if (!defined('DOKU_INC')) die(); - -require_once DOKU_PLUGIN.'action.php'; - -class action_plugin_safefnrecode extends DokuWiki_Action_Plugin { - - public function register(Doku_Event_Handler $controller) { - - $controller->register_hook('INDEXER_TASKS_RUN', 'BEFORE', $this, 'handle_indexer_tasks_run'); +class action_plugin_safefnrecode extends DokuWiki_Action_Plugin +{ + /** @inheritdoc */ + public function register(Doku_Event_Handler $controller) + { + $controller->register_hook('INDEXER_TASKS_RUN', 'BEFORE', $this, 'handleIndexerTasksRun'); } - public function handle_indexer_tasks_run(Doku_Event &$event, $param) { + /** + * Handle indexer event + * + * @param Doku_Event $event + * @param $param + */ + public function handleIndexerTasksRun(Doku_Event $event, $param) + { global $conf; - if($conf['fnencode'] != 'safe') return; + if ($conf['fnencode'] != 'safe') return; - if(!file_exists($conf['datadir'].'_safefn.recoded')){ + if (!file_exists($conf['datadir'].'_safefn.recoded')) { $this->recode($conf['datadir']); touch($conf['datadir'].'_safefn.recoded'); } - if(!file_exists($conf['olddir'].'_safefn.recoded')){ + if (!file_exists($conf['olddir'].'_safefn.recoded')) { $this->recode($conf['olddir']); touch($conf['olddir'].'_safefn.recoded'); } - if(!file_exists($conf['metadir'].'_safefn.recoded')){ + if (!file_exists($conf['metadir'].'_safefn.recoded')) { $this->recode($conf['metadir']); touch($conf['metadir'].'_safefn.recoded'); } - if(!file_exists($conf['mediadir'].'_safefn.recoded')){ + if (!file_exists($conf['mediadir'].'_safefn.recoded')) { $this->recode($conf['mediadir']); touch($conf['mediadir'].'_safefn.recoded'); } - } /** * Recursive function to rename all safe encoded files to use the new * square bracket post indicator */ - private function recode($dir){ + private function recode($dir) + { $dh = opendir($dir); - if(!$dh) return; + if (!$dh) return; while (($file = readdir($dh)) !== false) { - if($file == '.' || $file == '..') continue; # cur and upper dir - if(is_dir("$dir/$file")) $this->recode("$dir/$file"); #recurse - if(strpos($file,'%') === false) continue; # no encoding used - $new = preg_replace('/(%[^\]]*?)\./','\1]',$file); # new post indicator - if(preg_match('/%[^\]]+$/',$new)) $new .= ']'; # fix end FS#2122 - rename("$dir/$file","$dir/$new"); # rename it + if ($file == '.' || $file == '..') continue; # cur and upper dir + if (is_dir("$dir/$file")) $this->recode("$dir/$file"); #recurse + if (strpos($file, '%') === false) continue; # no encoding used + $new = preg_replace('/(%[^\]]*?)\./', '\1]', $file); # new post indicator + if (preg_match('/%[^\]]+$/', $new)) $new .= ']'; # fix end FS#2122 + rename("$dir/$file", "$dir/$new"); # rename it } closedir($dh); } - } - -// vim:ts=4:sw=4:et: diff --git a/lib/plugins/styling/action.php b/lib/plugins/styling/action.php index 2190fd61d..46245ca75 100644 --- a/lib/plugins/styling/action.php +++ b/lib/plugins/styling/action.php @@ -5,19 +5,8 @@ * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html * @author Andreas Gohr <andi@splitbrain.org> */ - -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -/** - * Class action_plugin_styling - * - * This handles all the save actions and loading the interface - * - * All this usually would be done within an admin plugin, but we want to have this available outside - * the admin interface using our floating dialog. - */ -class action_plugin_styling extends DokuWiki_Action_Plugin { +class action_plugin_styling extends DokuWiki_Action_Plugin +{ /** * Registers a callback functions @@ -25,8 +14,9 @@ class action_plugin_styling extends DokuWiki_Action_Plugin { * @param Doku_Event_Handler $controller DokuWiki's event controller object * @return void */ - public function register(Doku_Event_Handler $controller) { - $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handle_header'); + public function register(Doku_Event_Handler $controller) + { + $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handleHeader'); } /** @@ -37,26 +27,25 @@ class action_plugin_styling extends DokuWiki_Action_Plugin { * handler was registered] * @return void */ - public function handle_header(Doku_Event &$event, $param) { + public function handleHeader(Doku_Event &$event, $param) + { global $ACT; global $INPUT; - if($ACT != 'admin' || $INPUT->str('page') != 'styling') return; + if ($ACT != 'admin' || $INPUT->str('page') != 'styling') return; /** @var admin_plugin_styling $admin */ $admin = plugin_load('admin', 'styling'); - if(!$admin->isAccessibleByCurrentUser()) return; + if (!$admin->isAccessibleByCurrentUser()) return; // set preview $len = count($event->data['link']); - for($i = 0; $i < $len; $i++) { - if( - $event->data['link'][$i]['rel'] == 'stylesheet' && + for ($i = 0; $i < $len; $i++) { + if ($event->data['link'][$i]['rel'] == 'stylesheet' && strpos($event->data['link'][$i]['href'], 'lib/exe/css.php') !== false ) { $event->data['link'][$i]['href'] .= '&preview=1&tseed='.time(); } } } - } // vim:ts=4:sw=4:et: diff --git a/lib/plugins/styling/admin.php b/lib/plugins/styling/admin.php index e02f06604..41d7d1adf 100644 --- a/lib/plugins/styling/admin.php +++ b/lib/plugins/styling/admin.php @@ -5,45 +5,46 @@ * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html * @author Andreas Gohr <andi@splitbrain.org> */ - -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -class admin_plugin_styling extends DokuWiki_Admin_Plugin { +class admin_plugin_styling extends DokuWiki_Admin_Plugin +{ public $ispopup = false; /** * @return int sort number in admin menu */ - public function getMenuSort() { + public function getMenuSort() + { return 1000; } /** * @return bool true if only access for superuser, false is for superusers and moderators */ - public function forAdminOnly() { + public function forAdminOnly() + { return true; } /** * handle the different actions (also called from ajax) */ - public function handle() { + public function handle() + { global $INPUT; $run = $INPUT->extract('run')->str('run'); - if(!$run) return; - $run = "run_$run"; + if (!$run) return; + $run = 'run'.ucfirst($run); $this->$run(); } /** * Render HTML output, e.g. helpful text and a form */ - public function html() { + public function html() + { $class = 'nopopup'; - if($this->ispopup) $class = 'ispopup page'; + if ($this->ispopup) $class = 'ispopup page'; echo '<div id="plugin__styling" class="'.$class.'">'; ptln('<h1>'.$this->getLang('menu').'</h1>'); @@ -54,7 +55,8 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { /** * Create the actual editing form */ - public function form() { + public function form() + { global $conf; global $ID; @@ -62,13 +64,13 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { $styleini = $styleUtil->cssStyleini(); $replacements = $styleini['replacements']; - if($this->ispopup) { + if ($this->ispopup) { $target = DOKU_BASE.'lib/plugins/styling/popup.php'; } else { $target = wl($ID, array('do' => 'admin', 'page' => 'styling')); } - if(empty($replacements)) { + if (empty($replacements)) { echo '<p class="error">'.$this->getLang('error').'</p>'; } else { echo $this->locale_xhtml('intro'); @@ -76,21 +78,24 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { echo '<form class="styling" method="post" action="'.$target.'">'; echo '<table><tbody>'; - foreach($replacements as $key => $value) { + foreach ($replacements as $key => $value) { $name = tpl_getLang($key); - if(empty($name)) $name = $this->getLang($key); - if(empty($name)) $name = $key; + if (empty($name)) $name = $this->getLang($key); + if (empty($name)) $name = $key; echo '<tr>'; echo '<td><label for="tpl__'.hsc($key).'">'.$name.'</label></td>'; - echo '<td><input type="text" name="tpl['.hsc($key).']" id="tpl__'.hsc($key).'" value="'.hsc($value).'" '.$this->colorClass($key).' dir="ltr" /></td>'; + echo '<td><input type="text" name="tpl['.hsc($key).']" id="tpl__'.hsc($key).'" + value="'.hsc($value).'" '.$this->colorClass($key).' dir="ltr" /></td>'; echo '</tr>'; } echo '</tbody></table>'; echo '<p>'; - echo '<button type="submit" name="run[preview]" class="btn_preview primary">'.$this->getLang('btn_preview').'</button> '; - echo '<button type="submit" name="run[reset]">'.$this->getLang('btn_reset').'</button>'; #FIXME only if preview.ini exists + echo '<button type="submit" name="run[preview]" class="btn_preview primary">'. + $this->getLang('btn_preview').'</button> '; + #FIXME only if preview.ini exists: + echo '<button type="submit" name="run[reset]">'.$this->getLang('btn_reset').'</button>'; echo '</p>'; echo '<p>'; @@ -98,20 +103,21 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { echo '</p>'; echo '<p>'; - echo '<button type="submit" name="run[revert]">'.$this->getLang('btn_revert').'</button>'; #FIXME only if local.ini exists + #FIXME only if local.ini exists: + echo '<button type="submit" name="run[revert]">'.$this->getLang('btn_revert').'</button>'; echo '</p>'; echo '</form>'; echo tpl_locale_xhtml('style'); - } } /** * set the color class attribute */ - protected function colorClass($key) { + protected function colorClass($key) + { static $colors = array( 'text', 'background', @@ -127,7 +133,7 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { 'missing', ); - if(preg_match('/colou?r/', $key) || in_array(trim($key,'_'), $colors)) { + if (preg_match('/colou?r/', $key) || in_array(trim($key, '_'), $colors)) { return 'class="color"'; } else { return ''; @@ -137,7 +143,8 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { /** * saves the preview.ini (alos called from ajax directly) */ - public function run_preview() { + public function runPreview() + { global $conf; $ini = $conf['cachedir'].'/preview.ini'; io_saveFile($ini, $this->makeini()); @@ -146,7 +153,8 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { /** * deletes the preview.ini */ - protected function run_reset() { + protected function runReset() + { global $conf; $ini = $conf['cachedir'].'/preview.ini'; io_saveFile($ini, ''); @@ -155,17 +163,19 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { /** * deletes the local style.ini replacements */ - protected function run_revert() { - $this->replaceini(''); - $this->run_reset(); + protected function runRevert() + { + $this->replaceIni(''); + $this->runReset(); } /** * save the local style.ini replacements */ - protected function run_save() { - $this->replaceini($this->makeini()); - $this->run_reset(); + protected function runSave() + { + $this->replaceIni($this->makeini()); + $this->runReset(); } /** @@ -173,13 +183,14 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { * * @return string */ - protected function makeini() { + protected function makeini() + { global $INPUT; $ini = "[replacements]\n"; $ini .= ";These overwrites have been generated from the Template styling Admin interface\n"; $ini .= ";Any values in this section will be overwritten by that tool again\n"; - foreach($INPUT->arr('tpl') as $key => $val) { + foreach ($INPUT->arr('tpl') as $key => $val) { $ini .= $key.' = "'.addslashes($val).'"'."\n"; } @@ -191,10 +202,11 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { * * @param string $new the new ini contents */ - protected function replaceini($new) { + protected function replaceIni($new) + { global $conf; $ini = DOKU_CONF."tpl/".$conf['template']."/style.ini"; - if(file_exists($ini)) { + if (file_exists($ini)) { $old = io_readFile($ini); $old = preg_replace('/\[replacements\]\n.*?(\n\[.*]|$)/s', '\\1', $old); $old = trim($old); @@ -205,7 +217,6 @@ class admin_plugin_styling extends DokuWiki_Admin_Plugin { io_makeFileDir($ini); io_saveFile($ini, "$old\n\n$new"); } - } // vim:ts=4:sw=4:et: diff --git a/lib/plugins/styling/popup.php b/lib/plugins/styling/popup.php index 4a1735ccc..079062e43 100644 --- a/lib/plugins/styling/popup.php +++ b/lib/plugins/styling/popup.php @@ -1,5 +1,6 @@ <?php -if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__) . '/../../../'); +// phpcs:disable PSR1.Files.SideEffects +if (!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__) . '/../../../'); require_once(DOKU_INC . 'inc/init.php'); //close session session_write_close(); @@ -8,7 +9,7 @@ header('X-UA-Compatible: IE=edge,chrome=1'); /** @var admin_plugin_styling $plugin */ $plugin = plugin_load('admin', 'styling'); -if(!$plugin->isAccessibleByCurrentUser()) die('only admins allowed'); +if (!$plugin->isAccessibleByCurrentUser()) die('only admins allowed'); $plugin->ispopup = true; // handle posts diff --git a/lib/plugins/syntax.php b/lib/plugins/syntax.php index 9e2913d78..a3cbec722 100644 --- a/lib/plugins/syntax.php +++ b/lib/plugins/syntax.php @@ -1,134 +1,2 @@ <?php -/** - * Syntax Plugin Prototype - * - * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Andreas Gohr <andi@splitbrain.org> - */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -/** - * All DokuWiki plugins to extend the parser/rendering mechanism - * need to inherit from this class - */ -class DokuWiki_Syntax_Plugin extends Doku_Parser_Mode_Plugin { - - var $allowedModesSetup = false; - - /** - * Syntax Type - * - * Needs to return one of the mode types defined in $PARSER_MODES in parser.php - * - * @return string - */ - function getType(){ - trigger_error('getType() not implemented in '.get_class($this), E_USER_WARNING); - return ''; - } - - /** - * Allowed Mode Types - * - * Defines the mode types for other dokuwiki markup that maybe nested within the - * plugin's own markup. Needs to return an array of one or more of the mode types - * defined in $PARSER_MODES in parser.php - * - * @return array - */ - function getAllowedTypes() { - return array(); - } - - /** - * Paragraph Type - * - * Defines how this syntax is handled regarding paragraphs. This is important - * for correct XHTML nesting. Should return one of the following: - * - * 'normal' - The plugin can be used inside paragraphs - * 'block' - Open paragraphs need to be closed before plugin output - * 'stack' - Special case. Plugin wraps other paragraphs. - * - * @see Doku_Handler_Block - * - * @return string - */ - function getPType(){ - return 'normal'; - } - - /** - * Handler to prepare matched data for the rendering process - * - * This function can only pass data to render() via its return value - render() - * may be not be run during the object's current life. - * - * Usually you should only need the $match param. - * - * @param string $match The text matched by the patterns - * @param int $state The lexer state for the match - * @param int $pos The character position of the matched text - * @param Doku_Handler $handler The Doku_Handler object - * @return bool|array Return an array with all data you want to use in render, false don't add an instruction - */ - function handle($match, $state, $pos, Doku_Handler $handler){ - trigger_error('handle() not implemented in '.get_class($this), E_USER_WARNING); - } - - /** - * Handles the actual output creation. - * - * The function must not assume any other of the classes methods have been run - * during the object's current life. The only reliable data it receives are its - * parameters. - * - * The function should always check for the given output format and return false - * when a format isn't supported. - * - * $renderer contains a reference to the renderer object which is - * currently handling the rendering. You need to use it for writing - * the output. How this is done depends on the renderer used (specified - * by $format - * - * The contents of the $data array depends on what the handler() function above - * created - * - * @param string $format output format being rendered - * @param Doku_Renderer $renderer the current renderer object - * @param array $data data created by handler() - * @return boolean rendered correctly? (however, returned value is not used at the moment) - */ - function render($format, Doku_Renderer $renderer, $data) { - trigger_error('render() not implemented in '.get_class($this), E_USER_WARNING); - - } - - /** - * There should be no need to override this function - * - * @param string $mode - * @return bool - */ - function accepts($mode) { - - if (!$this->allowedModesSetup) { - global $PARSER_MODES; - - $allowedModeTypes = $this->getAllowedTypes(); - foreach($allowedModeTypes as $mt) { - $this->allowedModes = array_merge($this->allowedModes, $PARSER_MODES[$mt]); - } - - $idx = array_search(substr(get_class($this), 7), (array) $this->allowedModes); - if ($idx !== false) { - unset($this->allowedModes[$idx]); - } - $this->allowedModesSetup = true; - } - - return parent::accepts($mode); - } -} -//Setup VIM: ex: et ts=4 : +dbg_deprecated('Autoloading. Do not require() files yourself.'); diff --git a/lib/plugins/testing/action.php b/lib/plugins/testing/action.php index a242ab0b7..09b84262e 100644 --- a/lib/plugins/testing/action.php +++ b/lib/plugins/testing/action.php @@ -1,4 +1,7 @@ <?php + +use dokuwiki\Extension\Event; + /** * Plugin for testing the test system * @@ -8,13 +11,14 @@ */ class action_plugin_testing extends DokuWiki_Action_Plugin { - function register(Doku_Event_Handler $controller) { + /** @inheritdoc */ + public function register(Doku_Event_Handler $controller) { $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'dokuwikiStarted'); } - function dokuwikiStarted() { + public function dokuwikiStarted() { $param = array(); - trigger_event('TESTING_PLUGIN_INSTALLED', $param); + Event::createAndTrigger('TESTING_PLUGIN_INSTALLED', $param); msg('The testing plugin is enabled and should be disabled.',-1); } } diff --git a/lib/plugins/testing/conf/default.php b/lib/plugins/testing/conf/default.php new file mode 100644 index 000000000..392233dd8 --- /dev/null +++ b/lib/plugins/testing/conf/default.php @@ -0,0 +1,7 @@ +<?php +/** + * Default options + * + * They don't do anything and are just there for testing config reading + */ +$conf['schnibble'] = 0; diff --git a/lib/plugins/testing/conf/metadata.php b/lib/plugins/testing/conf/metadata.php new file mode 100644 index 000000000..377da63eb --- /dev/null +++ b/lib/plugins/testing/conf/metadata.php @@ -0,0 +1,7 @@ +<?php +/** + * Option Metadata + * + * They don't do anything and are just there for testing config reading + */ +$meta['schnibble'] = array('onoff'); diff --git a/lib/plugins/testing/lang/en/settings.php b/lib/plugins/testing/lang/en/settings.php new file mode 100644 index 000000000..e717c9021 --- /dev/null +++ b/lib/plugins/testing/lang/en/settings.php @@ -0,0 +1,5 @@ +<?php +/** + * Default options texts + */ +$lang['schnibble'] = 'Turns on the schnibble before the frobble is used'; diff --git a/lib/plugins/usermanager/_test/mocks.class.php b/lib/plugins/usermanager/_test/mocks.class.php index e524e451b..75ac51422 100644 --- a/lib/plugins/usermanager/_test/mocks.class.php +++ b/lib/plugins/usermanager/_test/mocks.class.php @@ -16,30 +16,30 @@ class admin_mock_usermanager extends admin_plugin_usermanager { public $lang; public function getImportFailures() { - return $this->_import_failures; + return $this->import_failures; } public function tryExport() { ob_start(); - $this->_export(); + $this->exportCSV(); return ob_get_clean(); } public function tryImport() { - return $this->_import(); + return $this->importCSV(); } // no need to send email notifications (mostly) - protected function _notifyUser($user, $password, $status_alert=true) { + protected function notifyUser($user, $password, $status_alert=true) { if ($this->mock_email_notifications) { $this->mock_email_notifications_sent++; return true; } else { - return parent::_notifyUser($user, $password, $status_alert); + return parent::notifyUser($user, $password, $status_alert); } } - protected function _isUploadedFile($file) { + protected function isUploadedFile($file) { return file_exists($file); } } diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index 3148971ce..423467133 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -10,52 +10,49 @@ * @author neolao <neolao@neolao.com> * @author Chris Smith <chris@jalakai.co.uk> */ -// must be run within Dokuwiki -if(!defined('DOKU_INC')) die(); - -if(!defined('DOKU_PLUGIN_IMAGES')) define('DOKU_PLUGIN_IMAGES',DOKU_BASE.'lib/plugins/usermanager/images/'); /** * All DokuWiki plugins to extend the admin function * need to inherit from this class */ -class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { - - protected $_auth = null; // auth object - protected $_user_total = 0; // number of registered users - protected $_filter = array(); // user selection filter(s) - protected $_start = 0; // index of first user to be displayed - protected $_last = 0; // index of the last user to be displayed - protected $_pagesize = 20; // number of users to list on one page - protected $_edit_user = ''; // set to user selected for editing - protected $_edit_userdata = array(); - protected $_disabled = ''; // if disabled set to explanatory string - protected $_import_failures = array(); - protected $_lastdisabled = false; // set to true if last user is unknown and last button is hence buggy +class admin_plugin_usermanager extends DokuWiki_Admin_Plugin +{ + const IMAGE_DIR = DOKU_BASE.'lib/plugins/usermanager/images/'; + + protected $auth = null; // auth object + protected $users_total = 0; // number of registered users + protected $filter = array(); // user selection filter(s) + protected $start = 0; // index of first user to be displayed + protected $last = 0; // index of the last user to be displayed + protected $pagesize = 20; // number of users to list on one page + protected $edit_user = ''; // set to user selected for editing + protected $edit_userdata = array(); + protected $disabled = ''; // if disabled set to explanatory string + protected $import_failures = array(); + protected $lastdisabled = false; // set to true if last user is unknown and last button is hence buggy /** * Constructor */ - public function __construct(){ + public function __construct() + { /** @var DokuWiki_Auth_Plugin $auth */ global $auth; $this->setupLocale(); if (!isset($auth)) { - $this->_disabled = $this->lang['noauth']; - } else if (!$auth->canDo('getUsers')) { - $this->_disabled = $this->lang['nosupport']; + $this->disabled = $this->lang['noauth']; + } elseif (!$auth->canDo('getUsers')) { + $this->disabled = $this->lang['nosupport']; } else { - // we're good to go - $this->_auth = & $auth; - + $this->auth = & $auth; } // attempt to retrieve any import failures from the session - if (!empty($_SESSION['import_failures'])){ - $this->_import_failures = $_SESSION['import_failures']; + if (!empty($_SESSION['import_failures'])) { + $this->import_failures = $_SESSION['import_failures']; } } @@ -65,12 +62,13 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param string $language * @return string */ - public function getMenuText($language) { + public function getMenuText($language) + { - if (!is_null($this->_auth)) + if (!is_null($this->auth)) return parent::getMenuText($language); - return $this->getLang('menu').' '.$this->_disabled; + return $this->getLang('menu').' '.$this->disabled; } /** @@ -78,29 +76,33 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return int */ - public function getMenuSort() { + public function getMenuSort() + { return 2; } /** * @return int current start value for pageination */ - public function getStart() { - return $this->_start; + public function getStart() + { + return $this->start; } /** * @return int number of users per page */ - public function getPagesize() { - return $this->_pagesize; + public function getPagesize() + { + return $this->pagesize; } /** * @param boolean $lastdisabled */ - public function setLastdisabled($lastdisabled) { - $this->_lastdisabled = $lastdisabled; + public function setLastdisabled($lastdisabled) + { + $this->lastdisabled = $lastdisabled; } /** @@ -108,9 +110,10 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return bool */ - public function handle() { + public function handle() + { global $INPUT; - if (is_null($this->_auth)) return false; + if (is_null($this->auth)) return false; // extract the command and any specific parameters // submit button name is of the form - fn[cmd][param(s)] @@ -125,33 +128,56 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { } if ($cmd != "search") { - $this->_start = $INPUT->int('start', 0); - $this->_filter = $this->_retrieveFilter(); + $this->start = $INPUT->int('start', 0); + $this->filter = $this->retrieveFilter(); } - switch($cmd){ - case "add" : $this->_addUser(); break; - case "delete" : $this->_deleteUser(); break; - case "modify" : $this->_modifyUser(); break; - case "edit" : $this->_editUser($param); break; - case "search" : $this->_setFilter($param); - $this->_start = 0; - break; - case "export" : $this->_export(); break; - case "import" : $this->_import(); break; - case "importfails" : $this->_downloadImportFailures(); break; + switch ($cmd) { + case "add": + $this->addUser(); + break; + case "delete": + $this->deleteUser(); + break; + case "modify": + $this->modifyUser(); + break; + case "edit": + $this->editUser($param); + break; + case "search": + $this->setFilter($param); + $this->start = 0; + break; + case "export": + $this->exportCSV(); + break; + case "import": + $this->importCSV(); + break; + case "importfails": + $this->downloadImportFailures(); + break; } - $this->_user_total = $this->_auth->canDo('getUserCount') ? $this->_auth->getUserCount($this->_filter) : -1; + $this->users_total = $this->auth->canDo('getUserCount') ? $this->auth->getUserCount($this->filter) : -1; // page handling - switch($cmd){ - case 'start' : $this->_start = 0; break; - case 'prev' : $this->_start -= $this->_pagesize; break; - case 'next' : $this->_start += $this->_pagesize; break; - case 'last' : $this->_start = $this->_user_total; break; + switch ($cmd) { + case 'start': + $this->start = 0; + break; + case 'prev': + $this->start -= $this->pagesize; + break; + case 'next': + $this->start += $this->pagesize; + break; + case 'last': + $this->start = $this->users_total; + break; } - $this->_validatePagination(); + $this->validatePagination(); return true; } @@ -160,21 +186,22 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return bool */ - public function html() { + public function html() + { global $ID; - if(is_null($this->_auth)) { + if (is_null($this->auth)) { print $this->lang['badauth']; return false; } - $user_list = $this->_auth->retrieveUsers($this->_start, $this->_pagesize, $this->_filter); + $user_list = $this->auth->retrieveUsers($this->start, $this->pagesize, $this->filter); - $page_buttons = $this->_pagination(); - $delete_disable = $this->_auth->canDo('delUser') ? '' : 'disabled="disabled"'; + $page_buttons = $this->pagination(); + $delete_disable = $this->auth->canDo('delUser') ? '' : 'disabled="disabled"'; - $editable = $this->_auth->canDo('UserMod'); - $export_label = empty($this->_filter) ? $this->lang['export_all'] : $this->lang['export_filtered']; + $editable = $this->auth->canDo('UserMod'); + $export_label = empty($this->filter) ? $this->lang['export_all'] : $this->lang['export_filtered']; print $this->locale_xhtml('intro'); print $this->locale_xhtml('list'); @@ -182,13 +209,21 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { ptln("<div id=\"user__manager\">"); ptln("<div class=\"level2\">"); - if ($this->_user_total > 0) { - ptln("<p>".sprintf($this->lang['summary'],$this->_start+1,$this->_last,$this->_user_total,$this->_auth->getUserCount())."</p>"); + if ($this->users_total > 0) { + ptln( + "<p>" . sprintf( + $this->lang['summary'], + $this->start + 1, + $this->last, + $this->users_total, + $this->auth->getUserCount() + ) . "</p>" + ); } else { - if($this->_user_total < 0) { + if ($this->users_total < 0) { $allUserTotal = 0; } else { - $allUserTotal = $this->_auth->getUserCount(); + $allUserTotal = $this->auth->getUserCount(); } ptln("<p>".sprintf($this->lang['nonefound'], $allUserTotal)."</p>"); } @@ -198,19 +233,29 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { ptln(" <table class=\"inline\">"); ptln(" <thead>"); ptln(" <tr>"); - ptln(" <th> </th><th>".$this->lang["user_id"]."</th><th>".$this->lang["user_name"]."</th><th>".$this->lang["user_mail"]."</th><th>".$this->lang["user_groups"]."</th>"); + ptln(" <th> </th> + <th>".$this->lang["user_id"]."</th> + <th>".$this->lang["user_name"]."</th> + <th>".$this->lang["user_mail"]."</th> + <th>".$this->lang["user_groups"]."</th>"); ptln(" </tr>"); ptln(" <tr>"); - ptln(" <td class=\"rightalign\"><input type=\"image\" src=\"".DOKU_PLUGIN_IMAGES."search.png\" name=\"fn[search][new]\" title=\"".$this->lang['search_prompt']."\" alt=\"".$this->lang['search']."\" class=\"button\" /></td>"); - ptln(" <td><input type=\"text\" name=\"userid\" class=\"edit\" value=\"".$this->_htmlFilter('user')."\" /></td>"); - ptln(" <td><input type=\"text\" name=\"username\" class=\"edit\" value=\"".$this->_htmlFilter('name')."\" /></td>"); - ptln(" <td><input type=\"text\" name=\"usermail\" class=\"edit\" value=\"".$this->_htmlFilter('mail')."\" /></td>"); - ptln(" <td><input type=\"text\" name=\"usergroups\" class=\"edit\" value=\"".$this->_htmlFilter('grps')."\" /></td>"); + ptln(" <td class=\"rightalign\"><input type=\"image\" src=\"". + self::IMAGE_DIR."search.png\" name=\"fn[search][new]\" title=\"". + $this->lang['search_prompt']."\" alt=\"".$this->lang['search']."\" class=\"button\" /></td>"); + ptln(" <td><input type=\"text\" name=\"userid\" class=\"edit\" value=\"". + $this->htmlFilter('user')."\" /></td>"); + ptln(" <td><input type=\"text\" name=\"username\" class=\"edit\" value=\"". + $this->htmlFilter('name')."\" /></td>"); + ptln(" <td><input type=\"text\" name=\"usermail\" class=\"edit\" value=\"". + $this->htmlFilter('mail')."\" /></td>"); + ptln(" <td><input type=\"text\" name=\"usergroups\" class=\"edit\" value=\"". + $this->htmlFilter('grps')."\" /></td>"); ptln(" </tr>"); ptln(" </thead>"); - if ($this->_user_total) { + if ($this->users_total) { ptln(" <tbody>"); foreach ($user_list as $user => $userinfo) { extract($userinfo); @@ -220,11 +265,12 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @var string $mail * @var array $grps */ - $groups = join(', ',$grps); + $groups = join(', ', $grps); ptln(" <tr class=\"user_info\">"); - ptln(" <td class=\"centeralign\"><input type=\"checkbox\" name=\"delete[".hsc($user)."]\" ".$delete_disable." /></td>"); + ptln(" <td class=\"centeralign\"><input type=\"checkbox\" name=\"delete[".hsc($user). + "]\" ".$delete_disable." /></td>"); if ($editable) { - ptln(" <td><a href=\"".wl($ID,array('fn[edit]['.$user.']' => 1, + ptln(" <td><a href=\"".wl($ID, array('fn[edit]['.$user.']' => 1, 'do' => 'admin', 'page' => 'usermanager', 'sectok' => getSecurityToken())). @@ -241,22 +287,27 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { ptln(" <tbody>"); ptln(" <tr><td colspan=\"5\" class=\"centeralign\">"); ptln(" <span class=\"medialeft\">"); - ptln(" <button type=\"submit\" name=\"fn[delete]\" id=\"usrmgr__del\" ".$delete_disable.">".$this->lang['delete_selected']."</button>"); + ptln(" <button type=\"submit\" name=\"fn[delete]\" id=\"usrmgr__del\" ".$delete_disable.">". + $this->lang['delete_selected']."</button>"); ptln(" </span>"); ptln(" <span class=\"mediaright\">"); - ptln(" <button type=\"submit\" name=\"fn[start]\" ".$page_buttons['start'].">".$this->lang['start']."</button>"); - ptln(" <button type=\"submit\" name=\"fn[prev]\" ".$page_buttons['prev'].">".$this->lang['prev']."</button>"); - ptln(" <button type=\"submit\" name=\"fn[next]\" ".$page_buttons['next'].">".$this->lang['next']."</button>"); - ptln(" <button type=\"submit\" name=\"fn[last]\" ".$page_buttons['last'].">".$this->lang['last']."</button>"); + ptln(" <button type=\"submit\" name=\"fn[start]\" ".$page_buttons['start'].">". + $this->lang['start']."</button>"); + ptln(" <button type=\"submit\" name=\"fn[prev]\" ".$page_buttons['prev'].">". + $this->lang['prev']."</button>"); + ptln(" <button type=\"submit\" name=\"fn[next]\" ".$page_buttons['next'].">". + $this->lang['next']."</button>"); + ptln(" <button type=\"submit\" name=\"fn[last]\" ".$page_buttons['last'].">". + $this->lang['last']."</button>"); ptln(" </span>"); - if (!empty($this->_filter)) { + if (!empty($this->filter)) { ptln(" <button type=\"submit\" name=\"fn[search][clear]\">".$this->lang['clear']."</button>"); } ptln(" <button type=\"submit\" name=\"fn[export]\">".$export_label."</button>"); ptln(" <input type=\"hidden\" name=\"do\" value=\"admin\" />"); ptln(" <input type=\"hidden\" name=\"page\" value=\"usermanager\" />"); - $this->_htmlFilterSettings(2); + $this->htmlFilterSettings(2); ptln(" </td></tr>"); ptln(" </tbody>"); @@ -266,32 +317,32 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { ptln("</form>"); ptln("</div>"); - $style = $this->_edit_user ? " class=\"edit_user\"" : ""; + $style = $this->edit_user ? " class=\"edit_user\"" : ""; - if ($this->_auth->canDo('addUser')) { + if ($this->auth->canDo('addUser')) { ptln("<div".$style.">"); print $this->locale_xhtml('add'); ptln(" <div class=\"level2\">"); - $this->_htmlUserForm('add',null,array(),4); + $this->htmlUserForm('add', null, array(), 4); ptln(" </div>"); ptln("</div>"); } - if($this->_edit_user && $this->_auth->canDo('UserMod')){ + if ($this->edit_user && $this->auth->canDo('UserMod')) { ptln("<div".$style." id=\"scroll__here\">"); print $this->locale_xhtml('edit'); ptln(" <div class=\"level2\">"); - $this->_htmlUserForm('modify',$this->_edit_user,$this->_edit_userdata,4); + $this->htmlUserForm('modify', $this->edit_user, $this->edit_userdata, 4); ptln(" </div>"); ptln("</div>"); } - if ($this->_auth->canDo('addUser')) { - $this->_htmlImportForm(); + if ($this->auth->canDo('addUser')) { + $this->htmlImportForm(); } ptln("</div>"); return true; @@ -323,7 +374,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param array $userdata array with name, mail, pass and grps * @param int $indent */ - protected function _htmlUserForm($cmd,$user='',$userdata=array(),$indent=0) { + protected function htmlUserForm($cmd, $user = '', $userdata = array(), $indent = 0) + { global $conf; global $ID; global $lang; @@ -333,28 +385,76 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { if ($user) { extract($userdata); - if (!empty($grps)) $groups = join(',',$grps); + if (!empty($grps)) $groups = join(',', $grps); } else { - $notes[] = sprintf($this->lang['note_group'],$conf['defaultgroup']); + $notes[] = sprintf($this->lang['note_group'], $conf['defaultgroup']); } - ptln("<form action=\"".wl($ID)."\" method=\"post\">",$indent); + ptln("<form action=\"".wl($ID)."\" method=\"post\">", $indent); formSecurityToken(); - ptln(" <div class=\"table\">",$indent); - ptln(" <table class=\"inline\">",$indent); - ptln(" <thead>",$indent); - ptln(" <tr><th>".$this->lang["field"]."</th><th>".$this->lang["value"]."</th></tr>",$indent); - ptln(" </thead>",$indent); - ptln(" <tbody>",$indent); - - $this->_htmlInputField($cmd."_userid", "userid", $this->lang["user_id"], $user, $this->_auth->canDo("modLogin"), true, $indent+6); - $this->_htmlInputField($cmd."_userpass", "userpass", $this->lang["user_pass"], "", $this->_auth->canDo("modPass"), false, $indent+6); - $this->_htmlInputField($cmd."_userpass2", "userpass2", $lang["passchk"], "", $this->_auth->canDo("modPass"), false, $indent+6); - $this->_htmlInputField($cmd."_username", "username", $this->lang["user_name"], $name, $this->_auth->canDo("modName"), true, $indent+6); - $this->_htmlInputField($cmd."_usermail", "usermail", $this->lang["user_mail"], $mail, $this->_auth->canDo("modMail"), true, $indent+6); - $this->_htmlInputField($cmd."_usergroups","usergroups",$this->lang["user_groups"],$groups,$this->_auth->canDo("modGroups"), false, $indent+6); - - if ($this->_auth->canDo("modPass")) { + ptln(" <div class=\"table\">", $indent); + ptln(" <table class=\"inline\">", $indent); + ptln(" <thead>", $indent); + ptln(" <tr><th>".$this->lang["field"]."</th><th>".$this->lang["value"]."</th></tr>", $indent); + ptln(" </thead>", $indent); + ptln(" <tbody>", $indent); + + $this->htmlInputField( + $cmd . "_userid", + "userid", + $this->lang["user_id"], + $user, + $this->auth->canDo("modLogin"), + true, + $indent + 6 + ); + $this->htmlInputField( + $cmd . "_userpass", + "userpass", + $this->lang["user_pass"], + "", + $this->auth->canDo("modPass"), + false, + $indent + 6 + ); + $this->htmlInputField( + $cmd . "_userpass2", + "userpass2", + $lang["passchk"], + "", + $this->auth->canDo("modPass"), + false, + $indent + 6 + ); + $this->htmlInputField( + $cmd . "_username", + "username", + $this->lang["user_name"], + $name, + $this->auth->canDo("modName"), + true, + $indent + 6 + ); + $this->htmlInputField( + $cmd . "_usermail", + "usermail", + $this->lang["user_mail"], + $mail, + $this->auth->canDo("modMail"), + true, + $indent + 6 + ); + $this->htmlInputField( + $cmd . "_usergroups", + "usergroups", + $this->lang["user_groups"], + $groups, + $this->auth->canDo("modGroups"), + false, + $indent + 6 + ); + + if ($this->auth->canDo("modPass")) { if ($cmd == 'add') { $notes[] = $this->lang['note_pass']; } @@ -362,37 +462,40 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { $notes[] = $this->lang['note_notify']; } - ptln("<tr><td><label for=\"".$cmd."_usernotify\" >".$this->lang["user_notify"].": </label></td><td><input type=\"checkbox\" id=\"".$cmd."_usernotify\" name=\"usernotify\" value=\"1\" /></td></tr>", $indent); + ptln("<tr><td><label for=\"".$cmd."_usernotify\" >". + $this->lang["user_notify"].": </label></td> + <td><input type=\"checkbox\" id=\"".$cmd."_usernotify\" name=\"usernotify\" value=\"1\" /> + </td></tr>", $indent); } - ptln(" </tbody>",$indent); - ptln(" <tbody>",$indent); - ptln(" <tr>",$indent); - ptln(" <td colspan=\"2\">",$indent); - ptln(" <input type=\"hidden\" name=\"do\" value=\"admin\" />",$indent); - ptln(" <input type=\"hidden\" name=\"page\" value=\"usermanager\" />",$indent); + ptln(" </tbody>", $indent); + ptln(" <tbody>", $indent); + ptln(" <tr>", $indent); + ptln(" <td colspan=\"2\">", $indent); + ptln(" <input type=\"hidden\" name=\"do\" value=\"admin\" />", $indent); + ptln(" <input type=\"hidden\" name=\"page\" value=\"usermanager\" />", $indent); // save current $user, we need this to access details if the name is changed if ($user) - ptln(" <input type=\"hidden\" name=\"userid_old\" value=\"".hsc($user)."\" />",$indent); + ptln(" <input type=\"hidden\" name=\"userid_old\" value=\"".hsc($user)."\" />", $indent); - $this->_htmlFilterSettings($indent+10); + $this->htmlFilterSettings($indent+10); - ptln(" <button type=\"submit\" name=\"fn[".$cmd."]\">".$this->lang[$cmd]."</button>",$indent); - ptln(" </td>",$indent); - ptln(" </tr>",$indent); - ptln(" </tbody>",$indent); - ptln(" </table>",$indent); + ptln(" <button type=\"submit\" name=\"fn[".$cmd."]\">".$this->lang[$cmd]."</button>", $indent); + ptln(" </td>", $indent); + ptln(" </tr>", $indent); + ptln(" </tbody>", $indent); + ptln(" </table>", $indent); if ($notes) { ptln(" <ul class=\"notes\">"); foreach ($notes as $note) { - ptln(" <li><span class=\"li\">".$note."</li>",$indent); + ptln(" <li><span class=\"li\">".$note."</li>", $indent); } ptln(" </ul>"); } - ptln(" </div>",$indent); - ptln("</form>",$indent); + ptln(" </div>", $indent); + ptln("</form>", $indent); } /** @@ -406,17 +509,18 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param bool $required is this field required? * @param int $indent */ - protected function _htmlInputField($id, $name, $label, $value, $cando, $required, $indent=0) { + protected function htmlInputField($id, $name, $label, $value, $cando, $required, $indent = 0) + { $class = $cando ? '' : ' class="disabled"'; - echo str_pad('',$indent); + echo str_pad('', $indent); - if($name == 'userpass' || $name == 'userpass2'){ + if ($name == 'userpass' || $name == 'userpass2') { $fieldtype = 'password'; $autocomp = 'autocomplete="off"'; - }elseif($name == 'usermail'){ + } elseif ($name == 'usermail') { $fieldtype = 'email'; $autocomp = ''; - }else{ + } else { $fieldtype = 'text'; $autocomp = ''; } @@ -425,13 +529,15 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { echo "<tr $class>"; echo "<td><label for=\"$id\" >$label: </label></td>"; echo "<td>"; - if($cando){ + if ($cando) { $req = ''; - if($required) $req = 'required="required"'; - echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\" value=\"$value\" class=\"edit\" $autocomp $req />"; - }else{ + if ($required) $req = 'required="required"'; + echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\" + value=\"$value\" class=\"edit\" $autocomp $req />"; + } else { echo "<input type=\"hidden\" name=\"$name\" value=\"$value\" />"; - echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\" value=\"$value\" class=\"edit disabled\" disabled=\"disabled\" />"; + echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\" + value=\"$value\" class=\"edit disabled\" disabled=\"disabled\" />"; } echo "</td>"; echo "</tr>"; @@ -443,9 +549,10 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param string $key name of search field * @return string html escaped value */ - protected function _htmlFilter($key) { - if (empty($this->_filter)) return ''; - return (isset($this->_filter[$key]) ? hsc($this->_filter[$key]) : ''); + protected function htmlFilter($key) + { + if (empty($this->filter)) return ''; + return (isset($this->filter[$key]) ? hsc($this->filter[$key]) : ''); } /** @@ -453,12 +560,13 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @param int $indent */ - protected function _htmlFilterSettings($indent=0) { + protected function htmlFilterSettings($indent = 0) + { - ptln("<input type=\"hidden\" name=\"start\" value=\"".$this->_start."\" />",$indent); + ptln("<input type=\"hidden\" name=\"start\" value=\"".$this->start."\" />", $indent); - foreach ($this->_filter as $key => $filter) { - ptln("<input type=\"hidden\" name=\"filter[".$key."]\" value=\"".hsc($filter)."\" />",$indent); + foreach ($this->filter as $key => $filter) { + ptln("<input type=\"hidden\" name=\"filter[".$key."]\" value=\"".hsc($filter)."\" />", $indent); } } @@ -467,57 +575,57 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @param int $indent */ - protected function _htmlImportForm($indent=0) { + protected function htmlImportForm($indent = 0) + { global $ID; - $failure_download_link = wl($ID,array('do'=>'admin','page'=>'usermanager','fn[importfails]'=>1)); + $failure_download_link = wl($ID, array('do'=>'admin','page'=>'usermanager','fn[importfails]'=>1)); - ptln('<div class="level2 import_users">',$indent); + ptln('<div class="level2 import_users">', $indent); print $this->locale_xhtml('import'); - ptln(' <form action="'.wl($ID).'" method="post" enctype="multipart/form-data">',$indent); + ptln(' <form action="'.wl($ID).'" method="post" enctype="multipart/form-data">', $indent); formSecurityToken(); - ptln(' <label>'.$this->lang['import_userlistcsv'].'<input type="file" name="import" /></label>',$indent); - ptln(' <button type="submit" name="fn[import]">'.$this->lang['import'].'</button>',$indent); - ptln(' <input type="hidden" name="do" value="admin" />',$indent); - ptln(' <input type="hidden" name="page" value="usermanager" />',$indent); + ptln(' <label>'.$this->lang['import_userlistcsv'].'<input type="file" name="import" /></label>', $indent); + ptln(' <button type="submit" name="fn[import]">'.$this->lang['import'].'</button>', $indent); + ptln(' <input type="hidden" name="do" value="admin" />', $indent); + ptln(' <input type="hidden" name="page" value="usermanager" />', $indent); - $this->_htmlFilterSettings($indent+4); - ptln(' </form>',$indent); + $this->htmlFilterSettings($indent+4); + ptln(' </form>', $indent); ptln('</div>'); // list failures from the previous import - if ($this->_import_failures) { - $digits = strlen(count($this->_import_failures)); - ptln('<div class="level3 import_failures">',$indent); + if ($this->import_failures) { + $digits = strlen(count($this->import_failures)); + ptln('<div class="level3 import_failures">', $indent); ptln(' <h3>'.$this->lang['import_header'].'</h3>'); - ptln(' <table class="import_failures">',$indent); - ptln(' <thead>',$indent); - ptln(' <tr>',$indent); - ptln(' <th class="line">'.$this->lang['line'].'</th>',$indent); - ptln(' <th class="error">'.$this->lang['error'].'</th>',$indent); - ptln(' <th class="userid">'.$this->lang['user_id'].'</th>',$indent); - ptln(' <th class="username">'.$this->lang['user_name'].'</th>',$indent); - ptln(' <th class="usermail">'.$this->lang['user_mail'].'</th>',$indent); - ptln(' <th class="usergroups">'.$this->lang['user_groups'].'</th>',$indent); - ptln(' </tr>',$indent); - ptln(' </thead>',$indent); - ptln(' <tbody>',$indent); - foreach ($this->_import_failures as $line => $failure) { - ptln(' <tr>',$indent); - ptln(' <td class="lineno"> '.sprintf('%0'.$digits.'d',$line).' </td>',$indent); + ptln(' <table class="import_failures">', $indent); + ptln(' <thead>', $indent); + ptln(' <tr>', $indent); + ptln(' <th class="line">'.$this->lang['line'].'</th>', $indent); + ptln(' <th class="error">'.$this->lang['error'].'</th>', $indent); + ptln(' <th class="userid">'.$this->lang['user_id'].'</th>', $indent); + ptln(' <th class="username">'.$this->lang['user_name'].'</th>', $indent); + ptln(' <th class="usermail">'.$this->lang['user_mail'].'</th>', $indent); + ptln(' <th class="usergroups">'.$this->lang['user_groups'].'</th>', $indent); + ptln(' </tr>', $indent); + ptln(' </thead>', $indent); + ptln(' <tbody>', $indent); + foreach ($this->import_failures as $line => $failure) { + ptln(' <tr>', $indent); + ptln(' <td class="lineno"> '.sprintf('%0'.$digits.'d', $line).' </td>', $indent); ptln(' <td class="error">' .$failure['error'].' </td>', $indent); - ptln(' <td class="field userid"> '.hsc($failure['user'][0]).' </td>',$indent); - ptln(' <td class="field username"> '.hsc($failure['user'][2]).' </td>',$indent); - ptln(' <td class="field usermail"> '.hsc($failure['user'][3]).' </td>',$indent); - ptln(' <td class="field usergroups"> '.hsc($failure['user'][4]).' </td>',$indent); - ptln(' </tr>',$indent); + ptln(' <td class="field userid"> '.hsc($failure['user'][0]).' </td>', $indent); + ptln(' <td class="field username"> '.hsc($failure['user'][2]).' </td>', $indent); + ptln(' <td class="field usermail"> '.hsc($failure['user'][3]).' </td>', $indent); + ptln(' <td class="field usergroups"> '.hsc($failure['user'][4]).' </td>', $indent); + ptln(' </tr>', $indent); } - ptln(' </tbody>',$indent); - ptln(' </table>',$indent); + ptln(' </tbody>', $indent); + ptln(' </table>', $indent); ptln(' <p><a href="'.$failure_download_link.'">'.$this->lang['import_downloadfailures'].'</a></p>'); ptln('</div>'); } - } /** @@ -525,17 +633,18 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return bool whether succesful */ - protected function _addUser(){ + protected function addUser() + { global $INPUT; if (!checkSecurityToken()) return false; - if (!$this->_auth->canDo('addUser')) return false; + if (!$this->auth->canDo('addUser')) return false; - list($user,$pass,$name,$mail,$grps,$passconfirm) = $this->_retrieveUser(); + list($user,$pass,$name,$mail,$grps,$passconfirm) = $this->retrieveUser(); if (empty($user)) return false; - if ($this->_auth->canDo('modPass')){ - if (empty($pass)){ - if($INPUT->has('usernotify')){ + if ($this->auth->canDo('modPass')) { + if (empty($pass)) { + if ($INPUT->has('usernotify')) { $pass = auth_pwgen($user); } else { msg($this->lang['add_fail'], -1); @@ -543,54 +652,53 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { return false; } } else { - if (!$this->_verifyPassword($pass,$passconfirm)) { + if (!$this->verifyPassword($pass, $passconfirm)) { msg($this->lang['add_fail'], -1); msg($this->lang['addUser_error_pass_not_identical'], -1); return false; } } } else { - if (!empty($pass)){ + if (!empty($pass)) { msg($this->lang['add_fail'], -1); msg($this->lang['addUser_error_modPass_disabled'], -1); return false; } } - if ($this->_auth->canDo('modName')){ - if (empty($name)){ + if ($this->auth->canDo('modName')) { + if (empty($name)) { msg($this->lang['add_fail'], -1); msg($this->lang['addUser_error_name_missing'], -1); return false; } } else { - if (!empty($name)){ + if (!empty($name)) { msg($this->lang['add_fail'], -1); msg($this->lang['addUser_error_modName_disabled'], -1); return false; } } - if ($this->_auth->canDo('modMail')){ - if (empty($mail)){ + if ($this->auth->canDo('modMail')) { + if (empty($mail)) { msg($this->lang['add_fail'], -1); msg($this->lang['addUser_error_mail_missing'], -1); return false; } } else { - if (!empty($mail)){ + if (!empty($mail)) { msg($this->lang['add_fail'], -1); msg($this->lang['addUser_error_modMail_disabled'], -1); return false; } } - if ($ok = $this->_auth->triggerUserMod('create', array($user,$pass,$name,$mail,$grps))) { - + if ($ok = $this->auth->triggerUserMod('create', array($user, $pass, $name, $mail, $grps))) { msg($this->lang['add_ok'], 1); if ($INPUT->has('usernotify') && $pass) { - $this->_notifyUser($user,$pass); + $this->notifyUser($user, $pass); } } else { msg($this->lang['add_fail'], -1); @@ -605,33 +713,34 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return bool whether succesful */ - protected function _deleteUser(){ + protected function deleteUser() + { global $conf, $INPUT; if (!checkSecurityToken()) return false; - if (!$this->_auth->canDo('delUser')) return false; + if (!$this->auth->canDo('delUser')) return false; $selected = $INPUT->arr('delete'); if (empty($selected)) return false; $selected = array_keys($selected); - if(in_array($_SERVER['REMOTE_USER'], $selected)) { + if (in_array($_SERVER['REMOTE_USER'], $selected)) { msg("You can't delete yourself!", -1); return false; } - $count = $this->_auth->triggerUserMod('delete', array($selected)); + $count = $this->auth->triggerUserMod('delete', array($selected)); if ($count == count($selected)) { $text = str_replace('%d', $count, $this->lang['delete_ok']); msg("$text.", 1); } else { $part1 = str_replace('%d', $count, $this->lang['delete_ok']); $part2 = str_replace('%d', (count($selected)-$count), $this->lang['delete_fail']); - msg("$part1, $part2",-1); + msg("$part1, $part2", -1); } // invalidate all sessions - io_saveFile($conf['cachedir'].'/sessionpurge',time()); + io_saveFile($conf['cachedir'].'/sessionpurge', time()); return true; } @@ -642,20 +751,21 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param string $param id of the user * @return bool whether succesful */ - protected function _editUser($param) { + protected function editUser($param) + { if (!checkSecurityToken()) return false; - if (!$this->_auth->canDo('UserMod')) return false; - $user = $this->_auth->cleanUser(preg_replace('/.*[:\/]/','',$param)); - $userdata = $this->_auth->getUserData($user); + if (!$this->auth->canDo('UserMod')) return false; + $user = $this->auth->cleanUser(preg_replace('/.*[:\/]/', '', $param)); + $userdata = $this->auth->getUserData($user); // no user found? if (!$userdata) { - msg($this->lang['edit_usermissing'],-1); + msg($this->lang['edit_usermissing'], -1); return false; } - $this->_edit_user = $user; - $this->_edit_userdata = $userdata; + $this->edit_user = $user; + $this->edit_userdata = $userdata; return true; } @@ -665,39 +775,39 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return bool whether succesful */ - protected function _modifyUser(){ + protected function modifyUser() + { global $conf, $INPUT; if (!checkSecurityToken()) return false; - if (!$this->_auth->canDo('UserMod')) return false; + if (!$this->auth->canDo('UserMod')) return false; // get currently valid user data - $olduser = $this->_auth->cleanUser(preg_replace('/.*[:\/]/','',$INPUT->str('userid_old'))); - $oldinfo = $this->_auth->getUserData($olduser); + $olduser = $this->auth->cleanUser(preg_replace('/.*[:\/]/', '', $INPUT->str('userid_old'))); + $oldinfo = $this->auth->getUserData($olduser); // get new user data subject to change - list($newuser,$newpass,$newname,$newmail,$newgrps,$passconfirm) = $this->_retrieveUser(); + list($newuser,$newpass,$newname,$newmail,$newgrps,$passconfirm) = $this->retrieveUser(); if (empty($newuser)) return false; $changes = array(); if ($newuser != $olduser) { - - if (!$this->_auth->canDo('modLogin')) { // sanity check, shouldn't be possible - msg($this->lang['update_fail'],-1); + if (!$this->auth->canDo('modLogin')) { // sanity check, shouldn't be possible + msg($this->lang['update_fail'], -1); return false; } // check if $newuser already exists - if ($this->_auth->getUserData($newuser)) { - msg(sprintf($this->lang['update_exists'],$newuser),-1); + if ($this->auth->getUserData($newuser)) { + msg(sprintf($this->lang['update_exists'], $newuser), -1); $re_edit = true; } else { $changes['user'] = $newuser; } } - if ($this->_auth->canDo('modPass')) { + if ($this->auth->canDo('modPass')) { if ($newpass || $passconfirm) { - if ($this->_verifyPassword($newpass,$passconfirm)) { + if ($this->verifyPassword($newpass, $passconfirm)) { $changes['pass'] = $newpass; } else { return false; @@ -710,33 +820,32 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { } } - if (!empty($newname) && $this->_auth->canDo('modName') && $newname != $oldinfo['name']) { + if (!empty($newname) && $this->auth->canDo('modName') && $newname != $oldinfo['name']) { $changes['name'] = $newname; } - if (!empty($newmail) && $this->_auth->canDo('modMail') && $newmail != $oldinfo['mail']) { + if (!empty($newmail) && $this->auth->canDo('modMail') && $newmail != $oldinfo['mail']) { $changes['mail'] = $newmail; } - if (!empty($newgrps) && $this->_auth->canDo('modGroups') && $newgrps != $oldinfo['grps']) { + if (!empty($newgrps) && $this->auth->canDo('modGroups') && $newgrps != $oldinfo['grps']) { $changes['grps'] = $newgrps; } - if ($ok = $this->_auth->triggerUserMod('modify', array($olduser, $changes))) { - msg($this->lang['update_ok'],1); + if ($ok = $this->auth->triggerUserMod('modify', array($olduser, $changes))) { + msg($this->lang['update_ok'], 1); if ($INPUT->has('usernotify') && !empty($changes['pass'])) { $notify = empty($changes['user']) ? $olduser : $newuser; - $this->_notifyUser($notify,$changes['pass']); + $this->notifyUser($notify, $changes['pass']); } // invalidate all sessions - io_saveFile($conf['cachedir'].'/sessionpurge',time()); - + io_saveFile($conf['cachedir'].'/sessionpurge', time()); } else { - msg($this->lang['update_fail'],-1); + msg($this->lang['update_fail'], -1); } if (!empty($re_edit)) { - $this->_editUser($olduser); + $this->editUser($olduser); } return $ok; @@ -750,9 +859,10 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param bool $status_alert whether status alert should be shown * @return bool whether succesful */ - protected function _notifyUser($user, $password, $status_alert=true) { + protected function notifyUser($user, $password, $status_alert = true) + { - if ($sent = auth_sendPassword($user,$password)) { + if ($sent = auth_sendPassword($user, $password)) { if ($status_alert) { msg($this->lang['notify_ok'], 1); } @@ -773,7 +883,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param string $confirm repeated password for confirmation * @return bool true if meets requirements, false otherwise */ - protected function _verifyPassword($password, $confirm) { + protected function verifyPassword($password, $confirm) + { global $lang; if (empty($password) && empty($confirm)) { @@ -797,7 +908,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param bool $clean whether the cleanUser method of the authentication backend is applied * @return array (user, password, full name, email, array(groups)) */ - protected function _retrieveUser($clean=true) { + protected function retrieveUser($clean = true) + { /** @var DokuWiki_Auth_Plugin $auth */ global $auth; global $INPUT; @@ -807,14 +919,14 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { $user[1] = $INPUT->str('userpass'); $user[2] = $INPUT->str('username'); $user[3] = $INPUT->str('usermail'); - $user[4] = explode(',',$INPUT->str('usergroups')); + $user[4] = explode(',', $INPUT->str('usergroups')); $user[5] = $INPUT->str('userpass2'); // repeated password for confirmation - $user[4] = array_map('trim',$user[4]); - if($clean) $user[4] = array_map(array($auth,'cleanGroup'),$user[4]); + $user[4] = array_map('trim', $user[4]); + if ($clean) $user[4] = array_map(array($auth,'cleanGroup'), $user[4]); $user[4] = array_filter($user[4]); $user[4] = array_unique($user[4]); - if(!count($user[4])) $user[4] = null; + if (!count($user[4])) $user[4] = null; return $user; } @@ -824,17 +936,18 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @param string $op 'new' or 'clear' */ - protected function _setFilter($op) { + protected function setFilter($op) + { - $this->_filter = array(); + $this->filter = array(); if ($op == 'new') { - list($user,/* $pass */,$name,$mail,$grps) = $this->_retrieveUser(false); + list($user,/* $pass */,$name,$mail,$grps) = $this->retrieveUser(false); - if (!empty($user)) $this->_filter['user'] = $user; - if (!empty($name)) $this->_filter['name'] = $name; - if (!empty($mail)) $this->_filter['mail'] = $mail; - if (!empty($grps)) $this->_filter['grps'] = join('|',$grps); + if (!empty($user)) $this->filter['user'] = $user; + if (!empty($name)) $this->filter['name'] = $name; + if (!empty($mail)) $this->filter['mail'] = $mail; + if (!empty($grps)) $this->filter['grps'] = join('|', $grps); } } @@ -843,7 +956,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return array */ - protected function _retrieveFilter() { + protected function retrieveFilter() + { global $INPUT; $t_filter = $INPUT->arr('filter'); @@ -862,14 +976,15 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { /** * Validate and improve the pagination values */ - protected function _validatePagination() { + protected function validatePagination() + { - if ($this->_start >= $this->_user_total) { - $this->_start = $this->_user_total - $this->_pagesize; + if ($this->start >= $this->users_total) { + $this->start = $this->users_total - $this->pagesize; } - if ($this->_start < 0) $this->_start = 0; + if ($this->start < 0) $this->start = 0; - $this->_last = min($this->_user_total, $this->_start + $this->_pagesize); + $this->last = min($this->users_total, $this->start + $this->pagesize); } /** @@ -877,21 +992,23 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return array with enable/disable attributes */ - protected function _pagination() { + protected function pagination() + { $disabled = 'disabled="disabled"'; $buttons = array(); - $buttons['start'] = $buttons['prev'] = ($this->_start == 0) ? $disabled : ''; + $buttons['start'] = $buttons['prev'] = ($this->start == 0) ? $disabled : ''; - if ($this->_user_total == -1) { + if ($this->users_total == -1) { $buttons['last'] = $disabled; $buttons['next'] = ''; } else { - $buttons['last'] = $buttons['next'] = (($this->_start + $this->_pagesize) >= $this->_user_total) ? $disabled : ''; + $buttons['last'] = $buttons['next'] = + (($this->start + $this->pagesize) >= $this->users_total) ? $disabled : ''; } - if ($this->_lastdisabled) { + if ($this->lastdisabled) { $buttons['last'] = $disabled; } @@ -901,9 +1018,10 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { /** * Export a list of users in csv format using the current filter criteria */ - protected function _export() { + protected function exportCSV() + { // list of users for export - based on current filter criteria - $user_list = $this->_auth->retrieveUsers(0, 0, $this->_filter); + $user_list = $this->auth->retrieveUsers(0, 0, $this->filter); $column_headings = array( $this->lang["user_id"], $this->lang["user_name"], @@ -920,14 +1038,16 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { # header('Content-type: text/plain;charset=utf-8'); // output the csv - $fd = fopen('php://output','w'); + $fd = fopen('php://output', 'w'); fputcsv($fd, $column_headings); foreach ($user_list as $user => $info) { - $line = array($user, $info['name'], $info['mail'], join(',',$info['grps'])); + $line = array($user, $info['name'], $info['mail'], join(',', $info['grps'])); fputcsv($fd, $line); } fclose($fd); - if (defined('DOKU_UNITTEST')){ return; } + if (defined('DOKU_UNITTEST')) { + return; + } die; } @@ -939,25 +1059,28 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @return bool whether successful */ - protected function _import() { + protected function importCSV() + { // check we are allowed to add users if (!checkSecurityToken()) return false; - if (!$this->_auth->canDo('addUser')) return false; + if (!$this->auth->canDo('addUser')) return false; // check file uploaded ok. - if (empty($_FILES['import']['size']) || !empty($_FILES['import']['error']) && $this->_isUploadedFile($_FILES['import']['tmp_name'])) { - msg($this->lang['import_error_upload'],-1); + if (empty($_FILES['import']['size']) || + !empty($_FILES['import']['error']) && $this->isUploadedFile($_FILES['import']['tmp_name']) + ) { + msg($this->lang['import_error_upload'], -1); return false; } // retrieve users from the file - $this->_import_failures = array(); + $this->import_failures = array(); $import_success_count = 0; $import_fail_count = 0; $line = 0; - $fd = fopen($_FILES['import']['tmp_name'],'r'); + $fd = fopen($_FILES['import']['tmp_name'], 'r'); if ($fd) { - while($csv = fgets($fd)){ - if (!utf8_check($csv)) { + while ($csv = fgets($fd)) { + if (!\dokuwiki\Utf8\Clean::isUtf8($csv)) { $csv = utf8_encode($csv); } $raw = str_getcsv($csv); @@ -969,35 +1092,42 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { if (count($raw) < 4) { // need at least four fields $import_fail_count++; $error = sprintf($this->lang['import_error_fields'], count($raw)); - $this->_import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv); + $this->import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv); continue; } - array_splice($raw,1,0,auth_pwgen()); // splice in a generated password - $clean = $this->_cleanImportUser($raw, $error); - if ($clean && $this->_addImportUser($clean, $error)) { - $sent = $this->_notifyUser($clean[0],$clean[1],false); - if (!$sent){ - msg(sprintf($this->lang['import_notify_fail'],$clean[0],$clean[3]),-1); + array_splice($raw, 1, 0, auth_pwgen()); // splice in a generated password + $clean = $this->cleanImportUser($raw, $error); + if ($clean && $this->importUser($clean, $error)) { + $sent = $this->notifyUser($clean[0], $clean[1], false); + if (!$sent) { + msg(sprintf($this->lang['import_notify_fail'], $clean[0], $clean[3]), -1); } $import_success_count++; } else { $import_fail_count++; array_splice($raw, 1, 1); // remove the spliced in password - $this->_import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv); + $this->import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv); } } - msg(sprintf($this->lang['import_success_count'], ($import_success_count+$import_fail_count), $import_success_count),($import_success_count ? 1 : -1)); + msg( + sprintf( + $this->lang['import_success_count'], + ($import_success_count + $import_fail_count), + $import_success_count + ), + ($import_success_count ? 1 : -1) + ); if ($import_fail_count) { - msg(sprintf($this->lang['import_failure_count'], $import_fail_count),-1); + msg(sprintf($this->lang['import_failure_count'], $import_fail_count), -1); } } else { - msg($this->lang['import_error_readfail'],-1); + msg($this->lang['import_error_readfail'], -1); } // save import failures into the session if (!headers_sent()) { session_start(); - $_SESSION['import_failures'] = $this->_import_failures; + $_SESSION['import_failures'] = $this->import_failures; session_write_close(); } return true; @@ -1010,17 +1140,18 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param string $error * @return array|false cleaned data or false */ - protected function _cleanImportUser($candidate, & $error){ + protected function cleanImportUser($candidate, & $error) + { global $INPUT; - // kludgy .... + // FIXME kludgy .... $INPUT->set('userid', $candidate[0]); $INPUT->set('userpass', $candidate[1]); $INPUT->set('username', $candidate[2]); $INPUT->set('usermail', $candidate[3]); $INPUT->set('usergroups', $candidate[4]); - $cleaned = $this->_retrieveUser(); + $cleaned = $this->retrieveUser(); list($user,/* $pass */,$name,$mail,/* $grps */) = $cleaned; if (empty($user)) { $error = $this->lang['import_error_baduserid']; @@ -1029,12 +1160,12 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { // no need to check password, handled elsewhere - if (!($this->_auth->canDo('modName') xor empty($name))){ + if (!($this->auth->canDo('modName') xor empty($name))) { $error = $this->lang['import_error_badname']; return false; } - if ($this->_auth->canDo('modMail')) { + if ($this->auth->canDo('modMail')) { if (empty($mail) || !mail_isvalid($mail)) { $error = $this->lang['import_error_badmail']; return false; @@ -1058,8 +1189,9 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param string &$error reference catched error message * @return bool whether successful */ - protected function _addImportUser($user, & $error){ - if (!$this->_auth->triggerUserMod('create', $user)) { + protected function importUser($user, &$error) + { + if (!$this->auth->triggerUserMod('create', $user)) { $error = $this->lang['import_error_create']; return false; } @@ -1070,7 +1202,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { /** * Downloads failures as csv file */ - protected function _downloadImportFailures(){ + protected function downloadImportFailures() + { // ============================================================================================== // GENERATE OUTPUT @@ -1081,8 +1214,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { # header('Content-type: text/plain;charset=utf-8'); // output the csv - $fd = fopen('php://output','w'); - foreach ($this->_import_failures as $fail) { + $fd = fopen('php://output', 'w'); + foreach ($this->import_failures as $fail) { fputs($fd, $fail['orig']); } fclose($fd); @@ -1095,7 +1228,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * @param string $file filename * @return bool */ - protected function _isUploadedFile($file) { + protected function isUploadedFile($file) + { return is_uploaded_file($file); } } diff --git a/lib/tpl/dokuwiki/images/pagetools-build.php b/lib/tpl/dokuwiki/images/pagetools-build.php index eaceeb257..e19d750c7 100644 --- a/lib/tpl/dokuwiki/images/pagetools-build.php +++ b/lib/tpl/dokuwiki/images/pagetools-build.php @@ -1,4 +1,5 @@ <?php +// phpcs:ignoreFile -- deprecated and will be removed /** * This script generates a sprite from the unprocessed pagetool icons by combining them * and overlaying a color layer for the active state. @@ -10,6 +11,7 @@ * The final sprite is optimized with optipng if available. * * @author Andreas Gohr <andi@splitbrain.org> + * @deprecated 2018-06-15 we no longer use PNG based icons * @todo Maybe add some more error checking */ $GAMMA = 0.8; diff --git a/lib/tpl/dokuwiki/tpl_footer.php b/lib/tpl/dokuwiki/tpl_footer.php index 34e8b90f6..c7a04e155 100644 --- a/lib/tpl/dokuwiki/tpl_footer.php +++ b/lib/tpl/dokuwiki/tpl_footer.php @@ -25,7 +25,8 @@ if (!defined('DOKU_INC')) die(); <a href="//jigsaw.w3.org/css-validator/check/referer?profile=css3" title="Valid CSS" <?php echo $target?>><img src="<?php echo tpl_basedir(); ?>images/button-css.png" width="80" height="15" alt="Valid CSS" /></a> <a href="https://dokuwiki.org/" title="Driven by DokuWiki" <?php echo $target?>><img - src="<?php echo tpl_basedir(); ?>images/button-dw.png" width="80" height="15" alt="Driven by DokuWiki" /></a> + src="<?php echo tpl_basedir(); ?>images/button-dw.png" width="80" height="15" + alt="Driven by DokuWiki" /></a> </div> </div></div><!-- /footer --> diff --git a/lib/tpl/index.php b/lib/tpl/index.php index 8b021511c..a3e9a8849 100644 --- a/lib/tpl/index.php +++ b/lib/tpl/index.php @@ -8,6 +8,7 @@ * @author Andreas Gohr <andi@splitbrain.org> * @author Anika Henke <anika@selfthinker.org> */ +// phpcs:disable PSR1.Files.SideEffects if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); if(!defined('NOSESSION')) define('NOSESSION',1); require_once(DOKU_INC.'inc/init.php'); @@ -44,8 +45,6 @@ require_once(DOKU_INC.'inc/init.php'); <body> <?php // get merged style.ini -define('SIMPLE_TEST', true); // hack to prevent css output and headers -require_once(DOKU_INC.'lib/exe/css.php'); $styleUtils = new \dokuwiki\StyleUtils($conf['template']); $ini = $styleUtils->cssStyleini(); |