Warning: Cannot modify header information - headers already sent by (output started at /var/www/jonas-eriksen.dk/pic/private/index.php:1) in /var/www/jonas-eriksen.dk/pic/private/index.php on line 215
PK!ñö/ôEE Event.phpnu„[µü¤name = $name; $this->data =& $data; } /** * @return string */ public function __toString() { return $this->name; } /** * advise all registered BEFORE handlers of this event * * if these methods are used by functions outside of this object, they must * properly handle correct processing of any default action and issue an * advise_after() signal. e.g. * $evt = new dokuwiki\Plugin\Doku_Event(name, data); * if ($evt->advise_before(canPreventDefault) { * // default action code block * } * $evt->advise_after(); * unset($evt); * * @param bool $enablePreventDefault * @return bool results of processing the event, usually $this->runDefault */ public function advise_before($enablePreventDefault = true) { global $EVENT_HANDLER; $this->canPreventDefault = $enablePreventDefault; if ($EVENT_HANDLER !== null) { $EVENT_HANDLER->process_event($this, 'BEFORE'); } else { dbglog($this->name . ':BEFORE event triggered before event system was initialized'); } return (!$enablePreventDefault || $this->runDefault); } /** * advise all registered AFTER handlers of this event * * @param bool $enablePreventDefault * @see advise_before() for details */ public function advise_after() { global $EVENT_HANDLER; $this->mayContinue = true; if ($EVENT_HANDLER !== null) { $EVENT_HANDLER->process_event($this, 'AFTER'); } else { dbglog($this->name . ':AFTER event triggered before event system was initialized'); } } /** * trigger * * - advise all registered (_BEFORE) handlers that this event is about to take place * - carry out the default action using $this->data based on $enablePrevent and * $this->_default, all of which may have been modified by the event handlers. * - advise all registered (_AFTER) handlers that the event has taken place * * @param null|callable $action * @param bool $enablePrevent * @return mixed $event->results * the value set by any _before or handlers if the default action is prevented * or the results of the default action (as modified by _after handlers) * or NULL no action took place and no handler modified the value */ public function trigger($action = null, $enablePrevent = true) { if (!is_callable($action)) { $enablePrevent = false; if ($action !== null) { trigger_error( 'The default action of ' . $this . ' is not null but also not callable. Maybe the method is not public?', E_USER_WARNING ); } } if ($this->advise_before($enablePrevent) && is_callable($action)) { $this->result = call_user_func_array($action, [&$this->data]); } $this->advise_after(); return $this->result; } /** * stopPropagation * * stop any further processing of the event by event handlers * this function does not prevent the default action taking place */ public function stopPropagation() { $this->mayContinue = false; } /** * may the event propagate to the next handler? * * @return bool */ public function mayPropagate() { return $this->mayContinue; } /** * preventDefault * * prevent the default action taking place */ public function preventDefault() { $this->runDefault = false; } /** * should the default action be executed? * * @return bool */ public function mayRunDefault() { return $this->runDefault; } /** * Convenience method to trigger an event * * Creates, triggers and destroys an event in one go * * @param string $name name for the event * @param mixed $data event data * @param callable $action (optional, default=NULL) default action, a php callback function * @param bool $canPreventDefault (optional, default=true) can hooks prevent the default action * * @return mixed the event results value after all event processing is complete * by default this is the return value of the default action however * it can be set or modified by event handler hooks */ static public function createAndTrigger($name, &$data, $action = null, $canPreventDefault = true) { $evt = new Event($name, $data); return $evt->trigger($action, $canPreventDefault); } } PK!s‰´×IISyntaxPlugin.phpnu„[µü¤ */ abstract class SyntaxPlugin extends \dokuwiki\Parsing\ParserMode\Plugin { use PluginTrait; protected $allowedModesSetup = false; /** * Syntax Type * * Needs to return one of the mode types defined in $PARSER_MODES in Parser.php * * @return string */ abstract public function getType(); /** * 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 */ public 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 */ public 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 */ abstract public function handle($match, $state, $pos, Doku_Handler $handler); /** * 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) */ abstract public function render($format, Doku_Renderer $renderer, $data); /** * There should be no need to override this function * * @param string $mode * @return bool */ public 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); } } PK!UÿòhÀÀ Plugin.phpnu„[µü¤ */ abstract class AdminPlugin extends 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() { // some plugins might not need this } /** * Output html of the admin page */ abstract public function html(); /** * 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 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(); } } PK!1}nÞÞActionPlugin.phpnu„[µü¤ */ abstract class ActionPlugin extends Plugin { /** * Registers a callback function for a given event * * @param \Doku_Event_Handler $controller */ abstract public function register(\Doku_Event_Handler $controller); } PK!L J..PluginTrait.phpnu„[µü¤getLang() protected $configloaded = false; // set to true by loadConfig() after loading plugin configuration variables protected $conf = array(); // array to hold plugin settings, best accessed via ->getConf() /** * @see PluginInterface::getInfo() */ public function getInfo() { $parts = explode('_', get_class($this)); $info = DOKU_PLUGIN . '/' . $parts[2] . '/plugin.info.txt'; if (file_exists($info)) return confToHash($info); msg( 'getInfo() not implemented in ' . get_class($this) . ' and ' . $info . ' not found.
' . 'Verify you\'re running the latest version of the plugin. If the problem persists, send a ' . 'bug report to the author of the ' . $parts[2] . ' plugin.', -1 ); return array( 'date' => '0000-00-00', 'name' => $parts[2] . ' plugin', ); } /** * @see PluginInterface::isSingleton() */ public function isSingleton() { return true; } /** * @see PluginInterface::loadHelper() */ public function loadHelper($name, $msg = true) { $obj = plugin_load('helper', $name); if (is_null($obj) && $msg) msg("Helper plugin $name is not available or invalid.", -1); return $obj; } // region introspection methods /** * @see PluginInterface::getPluginType() */ public function getPluginType() { list($t) = explode('_', get_class($this), 2); return $t; } /** * @see PluginInterface::getPluginName() */ public function getPluginName() { list(/* $t */, /* $p */, $n) = explode('_', get_class($this), 4); return $n; } /** * @see PluginInterface::getPluginComponent() */ public function getPluginComponent() { list(/* $t */, /* $p */, /* $n */, $c) = explode('_', get_class($this), 4); return (isset($c) ? $c : ''); } // endregion // region localization methods /** * @see PluginInterface::getLang() */ public function getLang($id) { if (!$this->localised) $this->setupLocale(); return (isset($this->lang[$id]) ? $this->lang[$id] : ''); } /** * @see PluginInterface::locale_xhtml() */ public function locale_xhtml($id) { return p_cached_output($this->localFN($id)); } /** * @see PluginInterface::localFN() */ public function localFN($id, $ext = 'txt') { global $conf; $plugin = $this->getPluginName(); $file = DOKU_CONF . 'plugin_lang/' . $plugin . '/' . $conf['lang'] . '/' . $id . '.' . $ext; if (!file_exists($file)) { $file = DOKU_PLUGIN . $plugin . '/lang/' . $conf['lang'] . '/' . $id . '.' . $ext; if (!file_exists($file)) { //fall back to english $file = DOKU_PLUGIN . $plugin . '/lang/en/' . $id . '.' . $ext; } } return $file; } /** * @see PluginInterface::setupLocale() */ public function setupLocale() { if ($this->localised) return; global $conf, $config_cascade; // definitely don't invoke "global $lang" $path = DOKU_PLUGIN . $this->getPluginName() . '/lang/'; $lang = array(); // don't include once, in case several plugin components require the same language file @include($path . 'en/lang.php'); foreach ($config_cascade['lang']['plugin'] as $config_file) { if (file_exists($config_file . $this->getPluginName() . '/en/lang.php')) { include($config_file . $this->getPluginName() . '/en/lang.php'); } } if ($conf['lang'] != 'en') { @include($path . $conf['lang'] . '/lang.php'); foreach ($config_cascade['lang']['plugin'] as $config_file) { if (file_exists($config_file . $this->getPluginName() . '/' . $conf['lang'] . '/lang.php')) { include($config_file . $this->getPluginName() . '/' . $conf['lang'] . '/lang.php'); } } } $this->lang = $lang; $this->localised = true; } // endregion // region configuration methods /** * @see PluginInterface::getConf() */ public function getConf($setting, $notset = false) { if (!$this->configloaded) { $this->loadConfig(); } if (isset($this->conf[$setting])) { return $this->conf[$setting]; } else { return $notset; } } /** * @see PluginInterface::loadConfig() */ public function loadConfig() { global $conf; $defaults = $this->readDefaultSettings(); $plugin = $this->getPluginName(); foreach ($defaults as $key => $value) { if (isset($conf['plugin'][$plugin][$key])) continue; $conf['plugin'][$plugin][$key] = $value; } $this->configloaded = true; $this->conf =& $conf['plugin'][$plugin]; } /** * read the plugin's default configuration settings from conf/default.php * this function is automatically called through getConf() * * @return array setting => value */ protected function readDefaultSettings() { $path = DOKU_PLUGIN . $this->getPluginName() . '/conf/'; $conf = array(); if (file_exists($path . 'default.php')) { include($path . 'default.php'); } return $conf; } // endregion // region output methods /** * @see PluginInterface::email() */ public function email($email, $name = '', $class = '', $more = '') { if (!$email) return $name; $email = obfuscate($email); if (!$name) $name = $email; $class = "class='" . ($class ? $class : 'mail') . "'"; return "$name"; } /** * @see PluginInterface::external_link() */ public function external_link($link, $title = '', $class = '', $target = '', $more = '') { global $conf; $link = htmlentities($link); if (!$title) $title = $link; if (!$target) $target = $conf['target']['extern']; if ($conf['relnofollow']) $more .= ' rel="nofollow"'; if ($class) $class = " class='$class'"; if ($target) $target = " target='$target'"; if ($more) $more = " " . trim($more); return "$title"; } /** * @see PluginInterface::render_text() */ public function render_text($text, $format = 'xhtml') { return p_render($format, p_get_instructions($text), $info); } // endregion } PK!)p}„V V RemotePlugin.phpnu„[µü¤api = new Api(); } /** * 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 dokuwiki\Remote\RemoteAPI}. * @throws ReflectionException */ 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\Extension\Plugin' || $declaredin === 'dokuwiki\Extension\RemotePlugin') { continue; } $method_name = $method->name; if (strpos($method_name, '_') === 0) { 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 Api */ protected function getApi() { return $this->api; } } PK!Ab”å<å<AuthPlugin.phpnu„[µü¤ * @author Jan Schumann */ abstract class AuthPlugin extends 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 */ 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 * @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 * @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 * @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 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 */ 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 (except this * function returns null, in which case, DokuWiki will * still run auth_login as a fallback, which may call * checkPass()). If this function is not returning null, * implementing checkPass() is not needed here 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 * * @param string $user Username * @param string $pass Cleartext Password * @param bool $sticky Cookie should not expire * @return bool true on successful auth, * null on unknown result (fallback to checkPass) */ 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 * @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 * @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 * @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 * @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 * @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 * @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 * @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 * @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 * @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 * @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 * @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 * @return bool */ public function useSessionCache($user) { global $conf; return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= @filemtime($conf['cachedir'] . '/sessionpurge')); } } PK!+~u¿4¿4PluginController.phpnu„[µü¤ */ class PluginController { /** @var array the types of plugins DokuWiki supports */ const PLUGIN_TYPES = ['auth', 'admin', 'syntax', 'action', 'renderer', 'helper', 'remote', 'cli']; protected $listByType = []; /** @var array all installed plugins and their enabled state [plugin=>enabled] */ protected $masterList = []; protected $pluginCascade = ['default' => [], 'local' => [], 'protected' => []]; protected $lastLocalConfigFile = ''; /** * Populates the master list of plugins */ public function __construct() { $this->loadConfig(); $this->populateMasterList(); } /** * Returns a list of available plugins of given type * * @param $type string, plugin_type name; * the type of plugin to return, * use empty string for all types * @param $all bool; * false to only return enabled plugins, * true to return both enabled and disabled plugins * * @return array of * - plugin names when $type = '' * - or plugin component names when a $type is given * * @author Andreas Gohr */ public function getList($type = '', $all = false) { // request the complete list if (!$type) { return $all ? array_keys($this->masterList) : array_keys(array_filter($this->masterList)); } if (!isset($this->listByType[$type]['enabled'])) { $this->listByType[$type]['enabled'] = $this->getListByType($type, true); } if ($all && !isset($this->listByType[$type]['disabled'])) { $this->listByType[$type]['disabled'] = $this->getListByType($type, false); } return $all ? array_merge($this->listByType[$type]['enabled'], $this->listByType[$type]['disabled']) : $this->listByType[$type]['enabled']; } /** * Loads the given plugin and creates an object of it * * @param $type string type of plugin to load * @param $name string name of the plugin to load * @param $new bool true to return a new instance of the plugin, false to use an already loaded instance * @param $disabled bool true to load even disabled plugins * @return PluginInterface|null the plugin object or null on failure * @author Andreas Gohr * */ public function load($type, $name, $new = false, $disabled = false) { //we keep all loaded plugins available in global scope for reuse global $DOKU_PLUGINS; list($plugin, /* $component */) = $this->splitName($name); // check if disabled if (!$disabled && !$this->isEnabled($plugin)) { return null; } $class = $type . '_plugin_' . $name; //plugin already loaded? if (!empty($DOKU_PLUGINS[$type][$name])) { if ($new || !$DOKU_PLUGINS[$type][$name]->isSingleton()) { return class_exists($class, true) ? new $class : null; } return $DOKU_PLUGINS[$type][$name]; } //construct class and instantiate if (!class_exists($class, true)) { # the plugin might be in the wrong directory $inf = confToHash(DOKU_PLUGIN . "$plugin/plugin.info.txt"); if ($inf['base'] && $inf['base'] != $plugin) { msg( sprintf( "Plugin installed incorrectly. Rename plugin directory '%s' to '%s'.", hsc($plugin), hsc( $inf['base'] ) ), -1 ); } elseif (preg_match('/^' . DOKU_PLUGIN_NAME_REGEX . '$/', $plugin) !== 1) { msg( sprintf( "Plugin name '%s' is not a valid plugin name, only the characters a-z and 0-9 are allowed. " . 'Maybe the plugin has been installed in the wrong directory?', hsc($plugin) ), -1 ); } return null; } $DOKU_PLUGINS[$type][$name] = new $class; return $DOKU_PLUGINS[$type][$name]; } /** * Whether plugin is disabled * * @param string $plugin name of plugin * @return bool true disabled, false enabled * @deprecated in favor of the more sensible isEnabled where the return value matches the enabled state */ public function isDisabled($plugin) { dbg_deprecated('isEnabled()'); return !$this->isEnabled($plugin); } /** * Check whether plugin is disabled * * @param string $plugin name of plugin * @return bool true enabled, false disabled */ public function isEnabled($plugin) { return !empty($this->masterList[$plugin]); } /** * Disable the plugin * * @param string $plugin name of plugin * @return bool true saving succeed, false saving failed */ public function disable($plugin) { if (array_key_exists($plugin, $this->pluginCascade['protected'])) return false; $this->masterList[$plugin] = 0; return $this->saveList(); } /** * Enable the plugin * * @param string $plugin name of plugin * @return bool true saving succeed, false saving failed */ public function enable($plugin) { if (array_key_exists($plugin, $this->pluginCascade['protected'])) return false; $this->masterList[$plugin] = 1; return $this->saveList(); } /** * Returns cascade of the config files * * @return array with arrays of plugin configs */ public function getCascade() { return $this->pluginCascade; } /** * Read all installed plugins and their current enabled state */ protected function populateMasterList() { if ($dh = @opendir(DOKU_PLUGIN)) { $all_plugins = array(); while (false !== ($plugin = readdir($dh))) { if ($plugin[0] === '.') continue; // skip hidden entries if (is_file(DOKU_PLUGIN . $plugin)) continue; // skip files, we're only interested in directories if (array_key_exists($plugin, $this->masterList) && $this->masterList[$plugin] == 0) { $all_plugins[$plugin] = 0; } elseif (array_key_exists($plugin, $this->masterList) && $this->masterList[$plugin] == 1) { $all_plugins[$plugin] = 1; } else { $all_plugins[$plugin] = 1; } } $this->masterList = $all_plugins; if (!file_exists($this->lastLocalConfigFile)) { $this->saveList(true); } } } /** * Includes the plugin config $files * and returns the entries of the $plugins array set in these files * * @param array $files list of files to include, latter overrides previous * @return array with entries of the $plugins arrays of the included files */ protected function checkRequire($files) { $plugins = array(); foreach ($files as $file) { if (file_exists($file)) { include_once($file); } } return $plugins; } /** * Save the current list of plugins * * @param bool $forceSave ; * false to save only when config changed * true to always save * @return bool true saving succeed, false saving failed */ protected function saveList($forceSave = false) { global $conf; if (empty($this->masterList)) return false; // Rebuild list of local settings $local_plugins = $this->rebuildLocal(); if ($local_plugins != $this->pluginCascade['local'] || $forceSave) { $file = $this->lastLocalConfigFile; $out = " $value) { $out .= "\$plugins['$plugin'] = $value;\n"; } // backup current file (remove any existing backup) if (file_exists($file)) { $backup = $file . '.bak'; if (file_exists($backup)) @unlink($backup); if (!@copy($file, $backup)) return false; if (!empty($conf['fperm'])) chmod($backup, $conf['fperm']); } //check if can open for writing, else restore return io_saveFile($file, $out); } return false; } /** * Rebuild the set of local plugins * * @return array array of plugins to be saved in end($config_cascade['plugins']['local']) */ protected function rebuildLocal() { //assign to local variable to avoid overwriting $backup = $this->masterList; //Can't do anything about protected one so rule them out completely $local_default = array_diff_key($backup, $this->pluginCascade['protected']); //Diff between local+default and default //gives us the ones we need to check and save $diffed_ones = array_diff_key($local_default, $this->pluginCascade['default']); //The ones which we are sure of (list of 0s not in default) $sure_plugins = array_filter($diffed_ones, array($this, 'negate')); //the ones in need of diff $conflicts = array_diff_key($local_default, $diffed_ones); //The final list return array_merge($sure_plugins, array_diff_assoc($conflicts, $this->pluginCascade['default'])); } /** * Build the list of plugins and cascade * */ protected function loadConfig() { global $config_cascade; foreach (array('default', 'protected') as $type) { if (array_key_exists($type, $config_cascade['plugins'])) { $this->pluginCascade[$type] = $this->checkRequire($config_cascade['plugins'][$type]); } } $local = $config_cascade['plugins']['local']; $this->lastLocalConfigFile = array_pop($local); $this->pluginCascade['local'] = $this->checkRequire(array($this->lastLocalConfigFile)); if (is_array($local)) { $this->pluginCascade['default'] = array_merge( $this->pluginCascade['default'], $this->checkRequire($local) ); } $this->masterList = array_merge( $this->pluginCascade['default'], $this->pluginCascade['local'], $this->pluginCascade['protected'] ); } /** * Returns a list of available plugin components of given type * * @param string $type plugin_type name; the type of plugin to return, * @param bool $enabled true to return enabled plugins, * false to return disabled plugins * @return array of plugin components of requested type */ protected function getListByType($type, $enabled) { $master_list = $enabled ? array_keys(array_filter($this->masterList)) : array_keys(array_filter($this->masterList, array($this, 'negate'))); $plugins = array(); foreach ($master_list as $plugin) { if (file_exists(DOKU_PLUGIN . "$plugin/$type.php")) { $plugins[] = $plugin; continue; } $typedir = DOKU_PLUGIN . "$plugin/$type/"; if (is_dir($typedir)) { if ($dp = opendir($typedir)) { while (false !== ($component = readdir($dp))) { if (strpos($component, '.') === 0 || strtolower(substr($component, -4)) !== '.php') continue; if (is_file($typedir . $component)) { $plugins[] = $plugin . '_' . substr($component, 0, -4); } } closedir($dp); } } }//foreach return $plugins; } /** * Split name in a plugin name and a component name * * @param string $name * @return array with * - plugin name * - and component name when available, otherwise empty string */ protected function splitName($name) { if (!isset($this->masterList[$name])) { return explode('_', $name, 2); } return array($name, ''); } /** * Returns inverse boolean value of the input * * @param mixed $input * @return bool inversed boolean value of input */ protected function negate($input) { return !(bool)$input; } } PK!Õ“ÓW¾ ¾ EventHandler.phpnu„[µü¤register($this); } } /** * register_hook * * register a hook for an event * * @param string $event string name used by the event, (incl '_before' or '_after' for triggers) * @param string $advise * @param object $obj object in whose scope method is to be executed, * if NULL, method is assumed to be a globally available function * @param string $method event handler function * @param mixed $param data passed to the event handler * @param int $seq sequence number for ordering hook execution (ascending) */ public function register_hook($event, $advise, $obj, $method, $param = null, $seq = 0) { $seq = (int)$seq; $doSort = !isset($this->hooks[$event . '_' . $advise][$seq]); $this->hooks[$event . '_' . $advise][$seq][] = array($obj, $method, $param); if ($doSort) { ksort($this->hooks[$event . '_' . $advise]); } } /** * process the before/after event * * @param Event $event * @param string $advise BEFORE or AFTER */ public function process_event($event, $advise = '') { $evt_name = $event->name . ($advise ? '_' . $advise : '_BEFORE'); if (!empty($this->hooks[$evt_name])) { foreach ($this->hooks[$evt_name] as $sequenced_hooks) { foreach ($sequenced_hooks as $hook) { list($obj, $method, $param) = $hook; if ($obj === null) { $method($event, $param); } else { $obj->$method($event, $param); } if (!$event->mayPropagate()) return; } } } } /** * Check if an event has any registered handlers * * When $advise is empty, both BEFORE and AFTER events will be considered, * otherwise only the given advisory is checked * * @param string $name Name of the event * @param string $advise BEFORE, AFTER or empty * @return bool */ public function hasHandlerForEvent($name, $advise = '') { if ($advise) { return isset($this->hooks[$name . '_' . $advise]); } return isset($this->hooks[$name . '_BEFORE']) || isset($this->hooks[$name . '_AFTER']); } } PK!}6ŽIññ CLIPlugin.phpnu„[µü¤ */ interface PluginInterface { /** * General Info * * Needs to return a associative array with the following values: * * base - the plugin's base name (eg. the directory it needs to be installed in) * author - Author of the plugin * email - Email address to contact the author * date - Last modified date of the plugin in YYYY-MM-DD format * name - Name of the plugin * desc - Short description of the plugin (Text only) * url - Website with more information on the plugin (eg. syntax description) */ public function getInfo(); /** * The type of the plugin inferred from the class name * * @return string plugin type */ public function getPluginType(); /** * The name of the plugin inferred from the class name * * @return string plugin name */ public function getPluginName(); /** * The component part of the plugin inferred from the class name * * @return string component name */ public function getPluginComponent(); /** * Access plugin language strings * * to try to minimise unnecessary loading of the strings when the plugin doesn't require them * e.g. when info plugin is querying plugins for information about themselves. * * @param string $id id of the string to be retrieved * @return string in appropriate language or english if not available */ public function getLang($id); /** * retrieve a language dependent file and pass to xhtml renderer for display * plugin equivalent of p_locale_xhtml() * * @param string $id id of language dependent wiki page * @return string parsed contents of the wiki page in xhtml format */ public function locale_xhtml($id); /** * Prepends appropriate path for a language dependent filename * plugin equivalent of localFN() * * @param string $id id of localization file * @param string $ext The file extension (usually txt) * @return string wiki text */ public function localFN($id, $ext = 'txt'); /** * Reads all the plugins language dependent strings into $this->lang * this function is automatically called by getLang() * * @todo this could be made protected and be moved to the trait only */ public function setupLocale(); /** * use this function to access plugin configuration variables * * @param string $setting the setting to access * @param mixed $notset what to return if the setting is not available * @return mixed */ public function getConf($setting, $notset = false); /** * merges the plugin's default settings with any local settings * this function is automatically called through getConf() * * @todo this could be made protected and be moved to the trait only */ public function loadConfig(); /** * Loads a given helper plugin (if enabled) * * @author Esther Brunner * * @param string $name name of plugin to load * @param bool $msg if a message should be displayed in case the plugin is not available * @return PluginInterface|null helper plugin object */ public function loadHelper($name, $msg = true); /** * email * standardised function to generate an email link according to obfuscation settings * * @param string $email * @param string $name * @param string $class * @param string $more * @return string html */ public function email($email, $name = '', $class = '', $more = ''); /** * external_link * standardised function to generate an external link according to conf settings * * @param string $link * @param string $title * @param string $class * @param string $target * @param string $more * @return string */ public function external_link($link, $title = '', $class = '', $target = '', $more = ''); /** * output text string through the parser, allows dokuwiki markup to be used * very ineffecient for small pieces of data - try not to use * * @param string $text wiki markup to parse * @param string $format output format * @return null|string */ public function render_text($text, $format = 'xhtml'); /** * Allow the plugin to prevent DokuWiki from reusing an instance * * @return bool false if the plugin has to be instantiated */ public function isSingleton(); } PK!ñö/ôEE Event.phpnu„[µü¤PK!s‰´×II~SyntaxPlugin.phpnu„[µü¤PK!UÿòhÀÀ )Plugin.phpnu„[µü¤PK!CƒÐ§Ó Ó *AdminPlugin.phpnu„[µü¤PK!1}nÞÞ6ActionPlugin.phpnu„[µü¤PK!L J..18PluginTrait.phpnu„[µü¤PK!)p}„V V žTRemotePlugin.phpnu„[µü¤PK!Ab”å<å<4bAuthPlugin.phpnu„[µü¤PK!+~u¿4¿4WŸPluginController.phpnu„[µü¤PK!Õ“ÓW¾ ¾ ZÔEventHandler.phpnu„[µü¤PK!}6ŽIññ XáCLIPlugin.phpnu„[µü¤PK!rïë^^†âPluginInterface.phpnu„[µü¤PK ³'ö