diff options
author | ahriman <ahriman@falte.red> | 2018-12-03 19:22:25 -0500 |
---|---|---|
committer | ahriman <ahriman@falte.red> | 2018-12-03 19:22:25 -0500 |
commit | 0ae8cbf5c0b1a198b963490985b7738392ebcb97 (patch) | |
tree | b2c77ae72c6b717e2b97492065196ac5ffb2d9e2 /wiki/inc/Action | |
parent | f57f6cc5a2d159f90168d292437dc4bd8cd7f934 (diff) | |
download | site-0ae8cbf5c0b1a198b963490985b7738392ebcb97.tar.gz |
installed dokuwiki, added to navbar, updated news
Diffstat (limited to 'wiki/inc/Action')
44 files changed, 2118 insertions, 0 deletions
diff --git a/wiki/inc/Action/AbstractAclAction.php b/wiki/inc/Action/AbstractAclAction.php new file mode 100644 index 0000000..871edb0 --- /dev/null +++ b/wiki/inc/Action/AbstractAclAction.php @@ -0,0 +1,25 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAclRequiredException; + +/** + * Class AbstractAclAction + * + * An action that requires the ACL subsystem to be enabled (eg. useacl=1) + * + * @package dokuwiki\Action + */ +abstract class AbstractAclAction extends AbstractAction { + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + global $conf; + global $auth; + if(!$conf['useacl']) throw new ActionAclRequiredException(); + if(!$auth) throw new ActionAclRequiredException(); + } + +} diff --git a/wiki/inc/Action/AbstractAction.php b/wiki/inc/Action/AbstractAction.php new file mode 100644 index 0000000..ea86238 --- /dev/null +++ b/wiki/inc/Action/AbstractAction.php @@ -0,0 +1,88 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionDisabledException; +use dokuwiki\Action\Exception\ActionException; +use dokuwiki\Action\Exception\FatalException; + +/** + * Class AbstractAction + * + * Base class for all actions + * + * @package dokuwiki\Action + */ +abstract class AbstractAction { + + /** @var string holds the name of the action (lowercase class name, no namespace) */ + protected $actionname; + + /** + * AbstractAction constructor. + * + * @param string $actionname the name of this action (see getActionName() for caveats) + */ + public function __construct($actionname = '') { + if($actionname !== '') { + $this->actionname = $actionname; + } else { + // http://stackoverflow.com/a/27457689/172068 + $this->actionname = strtolower(substr(strrchr(get_class($this), '\\'), 1)); + } + } + + /** + * Return the minimum permission needed + * + * This needs to return one of the AUTH_* constants. It will be checked against + * the current user and page after checkPermissions() ran through. If it fails, + * the user will be shown the Denied action. + * + * @return int + */ + abstract public function minimumPermission(); + + /** + * Check conditions are met to run this action + * + * @throws ActionException + * @return void + */ + public function checkPreconditions() { + } + + /** + * Process data + * + * This runs before any output is sent to the browser. + * + * Throw an Exception if a different action should be run after this step. + * + * @throws ActionException + * @return void + */ + public function preProcess() { + } + + /** + * Output whatever content is wanted within tpl_content(); + * + * @fixme we may want to return a Ui class here + */ + public function tplContent() { + throw new FatalException('No content for Action ' . $this->actionname); + } + + /** + * Returns the name of this action + * + * This is usually the lowercased class name, but may differ for some actions. + * eg. the export_ modes or for the Plugin action. + * + * @return string + */ + public function getActionName() { + return $this->actionname; + } +} diff --git a/wiki/inc/Action/AbstractAliasAction.php b/wiki/inc/Action/AbstractAliasAction.php new file mode 100644 index 0000000..7240f5e --- /dev/null +++ b/wiki/inc/Action/AbstractAliasAction.php @@ -0,0 +1,28 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\FatalException; + +/** + * Class AbstractAliasAction + * + * An action that is an alias for another action. Skips the minimumPermission check + * + * Be sure to implement preProcess() and throw an ActionAbort exception + * with the proper action. + * + * @package dokuwiki\Action + */ +abstract class AbstractAliasAction extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + public function preProcess() { + throw new FatalException('Alias Actions need to implement preProcess to load the aliased action'); + } + +} diff --git a/wiki/inc/Action/AbstractUserAction.php b/wiki/inc/Action/AbstractUserAction.php new file mode 100644 index 0000000..b4e3f1a --- /dev/null +++ b/wiki/inc/Action/AbstractUserAction.php @@ -0,0 +1,25 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionUserRequiredException; + +/** + * Class AbstractUserAction + * + * An action that requires a logged in user + * + * @package dokuwiki\Action + */ +abstract class AbstractUserAction extends AbstractAclAction { + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + global $INPUT; + if(!$INPUT->server->str('REMOTE_USER')) { + throw new ActionUserRequiredException(); + } + } + +} diff --git a/wiki/inc/Action/Admin.php b/wiki/inc/Action/Admin.php new file mode 100644 index 0000000..8d43057 --- /dev/null +++ b/wiki/inc/Action/Admin.php @@ -0,0 +1,56 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionException; + +/** + * Class Admin + * + * Action to show the admin interface or admin plugins + * + * @package dokuwiki\Action + */ +class Admin extends AbstractUserAction { + + /** @inheritdoc */ + public function minimumPermission() { + global $INFO; + + if($INFO['ismanager']) { + return AUTH_READ; // let in check later + } else { + return AUTH_ADMIN; + } + } + + public function checkPreconditions() { + parent::checkPreconditions(); + + global $INFO; + if(!$INFO['ismanager']) { + throw new ActionException('denied'); + } + } + + public function preProcess() { + global $INPUT; + global $INFO; + + // retrieve admin plugin name from $_REQUEST['page'] + if(($page = $INPUT->str('page', '', true)) != '') { + /** @var $plugin \DokuWiki_Admin_Plugin */ + if($plugin = plugin_getRequestAdminPlugin()) { // FIXME this method does also permission checking + if($plugin->forAdminOnly() && !$INFO['isadmin']) { + throw new ActionException('denied'); + } + $plugin->handle(); + } + } + } + + public function tplContent() { + tpl_admin(); + } + +} diff --git a/wiki/inc/Action/Backlink.php b/wiki/inc/Action/Backlink.php new file mode 100644 index 0000000..0337917 --- /dev/null +++ b/wiki/inc/Action/Backlink.php @@ -0,0 +1,24 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Backlink + * + * Shows which pages link to the current page + * + * @package dokuwiki\Action + */ +class Backlink extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function tplContent() { + html_backlinks(); + } + +} diff --git a/wiki/inc/Action/Cancel.php b/wiki/inc/Action/Cancel.php new file mode 100644 index 0000000..d4d8277 --- /dev/null +++ b/wiki/inc/Action/Cancel.php @@ -0,0 +1,25 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Cancel + * + * Alias for show. Aborts editing + * + * @package dokuwiki\Action + */ +class Cancel extends AbstractAliasAction { + + /** @inheritdoc */ + public function preProcess() { + global $ID; + unlock($ID); + + // continue with draftdel -> redirect -> show + throw new ActionAbort('draftdel'); + } + +} diff --git a/wiki/inc/Action/Check.php b/wiki/inc/Action/Check.php new file mode 100644 index 0000000..36ae8e8 --- /dev/null +++ b/wiki/inc/Action/Check.php @@ -0,0 +1,26 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Check + * + * Adds some debugging info before aborting to show + * + * @package dokuwiki\Action + */ +class Check extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + public function preProcess() { + check(); + throw new ActionAbort(); + } + +} diff --git a/wiki/inc/Action/Conflict.php b/wiki/inc/Action/Conflict.php new file mode 100644 index 0000000..d880b5b --- /dev/null +++ b/wiki/inc/Action/Conflict.php @@ -0,0 +1,34 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Conflict + * + * Show the conflict resolution screen + * + * @package dokuwiki\Action + */ +class Conflict extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + global $INFO; + if($INFO['exists']) { + return AUTH_EDIT; + } else { + return AUTH_CREATE; + } + } + + public function tplContent() { + global $PRE; + global $TEXT; + global $SUF; + global $SUM; + + html_conflict(con($PRE, $TEXT, $SUF), $SUM); + html_diff(con($PRE, $TEXT, $SUF), false); + } + +} diff --git a/wiki/inc/Action/Denied.php b/wiki/inc/Action/Denied.php new file mode 100644 index 0000000..c8e0192 --- /dev/null +++ b/wiki/inc/Action/Denied.php @@ -0,0 +1,23 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Denied + * + * Show the access denied screen + * + * @package dokuwiki\Action + */ +class Denied extends AbstractAclAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + public function tplContent() { + html_denied(); + } + +} diff --git a/wiki/inc/Action/Diff.php b/wiki/inc/Action/Diff.php new file mode 100644 index 0000000..b14b1d0 --- /dev/null +++ b/wiki/inc/Action/Diff.php @@ -0,0 +1,35 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Diff + * + * Show the differences between two revisions + * + * @package dokuwiki\Action + */ +class Diff extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** @inheritdoc */ + public function preProcess() { + global $INPUT; + + // store the selected diff type in cookie + $difftype = $INPUT->str('difftype'); + if(!empty($difftype)) { + set_doku_pref('difftype', $difftype); + } + } + + /** @inheritdoc */ + public function tplContent() { + html_diff(); + } + +} diff --git a/wiki/inc/Action/Draft.php b/wiki/inc/Action/Draft.php new file mode 100644 index 0000000..caf0870 --- /dev/null +++ b/wiki/inc/Action/Draft.php @@ -0,0 +1,39 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionException; + +/** + * Class Draft + * + * Screen to see and recover a draft + * + * @package dokuwiki\Action + * @fixme combine with Recover? + */ +class Draft extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + global $INFO; + if($INFO['exists']) { + return AUTH_EDIT; + } else { + return AUTH_CREATE; + } + } + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + global $INFO; + if(!file_exists($INFO['draft'])) throw new ActionException('edit'); + } + + /** @inheritdoc */ + public function tplContent() { + html_draft(); + } + +} diff --git a/wiki/inc/Action/Draftdel.php b/wiki/inc/Action/Draftdel.php new file mode 100644 index 0000000..77378f7 --- /dev/null +++ b/wiki/inc/Action/Draftdel.php @@ -0,0 +1,36 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Draftdel + * + * Delete a draft + * + * @package dokuwiki\Action + */ +class Draftdel extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_EDIT; + } + + /** + * Delete an existing draft if any + * + * Reads draft information from $INFO. Redirects to show, afterwards. + * + * @throws ActionAbort + */ + public function preProcess() { + global $INFO; + @unlink($INFO['draft']); + $INFO['draft'] = null; + + throw new ActionAbort('redirect'); + } + +} diff --git a/wiki/inc/Action/Edit.php b/wiki/inc/Action/Edit.php new file mode 100644 index 0000000..061c9e2 --- /dev/null +++ b/wiki/inc/Action/Edit.php @@ -0,0 +1,91 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Edit + * + * Handle editing + * + * @package dokuwiki\Action + */ +class Edit extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + global $INFO; + if($INFO['exists']) { + return AUTH_READ; // we check again below + } else { + return AUTH_CREATE; + } + } + + /** + * @inheritdoc falls back to 'source' if page not writable + */ + public function checkPreconditions() { + parent::checkPreconditions(); + global $INFO; + + // no edit permission? view source + if($INFO['exists'] && !$INFO['writable']) { + throw new ActionAbort('source'); + } + } + + /** @inheritdoc */ + public function preProcess() { + global $ID; + global $INFO; + + global $TEXT; + global $RANGE; + global $PRE; + global $SUF; + global $REV; + global $SUM; + global $lang; + global $DATE; + + if(!isset($TEXT)) { + if($INFO['exists']) { + if($RANGE) { + list($PRE, $TEXT, $SUF) = rawWikiSlices($RANGE, $ID, $REV); + } else { + $TEXT = rawWiki($ID, $REV); + } + } else { + $TEXT = pageTemplate($ID); + } + } + + //set summary default + if(!$SUM) { + if($REV) { + $SUM = sprintf($lang['restored'], dformat($REV)); + } elseif(!$INFO['exists']) { + $SUM = $lang['created']; + } + } + + // Use the date of the newest revision, not of the revision we edit + // This is used for conflict detection + if(!$DATE) $DATE = @filemtime(wikiFN($ID)); + + //check if locked by anyone - if not lock for my self + $lockedby = checklock($ID); + if($lockedby) { + throw new ActionAbort('locked'); + }; + lock($ID); + } + + /** @inheritdoc */ + public function tplContent() { + html_edit(); + } + +} diff --git a/wiki/inc/Action/Exception/ActionAbort.php b/wiki/inc/Action/Exception/ActionAbort.php new file mode 100644 index 0000000..9c188bb --- /dev/null +++ b/wiki/inc/Action/Exception/ActionAbort.php @@ -0,0 +1,20 @@ +<?php + +namespace dokuwiki\Action\Exception; + +/** + * Class ActionAbort + * + * Strictly speaking not an Exception but an expected execution path. Used to + * signal when one action is done and another should take over. + * + * If you want to signal the same but under some error condition use ActionException + * or one of it's decendants. + * + * The message will NOT be shown to the enduser + * + * @package dokuwiki\Action\Exception + */ +class ActionAbort extends ActionException { + +} diff --git a/wiki/inc/Action/Exception/ActionAclRequiredException.php b/wiki/inc/Action/Exception/ActionAclRequiredException.php new file mode 100644 index 0000000..64a2c61 --- /dev/null +++ b/wiki/inc/Action/Exception/ActionAclRequiredException.php @@ -0,0 +1,17 @@ +<?php + +namespace dokuwiki\Action\Exception; + +/** + * Class ActionAclRequiredException + * + * Thrown by AbstractACLAction when an action requires that the ACL subsystem is + * enabled but it isn't. You should not use it + * + * The message will NOT be shown to the enduser + * + * @package dokuwiki\Action\Exception + */ +class ActionAclRequiredException extends ActionException { + +} diff --git a/wiki/inc/Action/Exception/ActionDisabledException.php b/wiki/inc/Action/Exception/ActionDisabledException.php new file mode 100644 index 0000000..40a0c7d --- /dev/null +++ b/wiki/inc/Action/Exception/ActionDisabledException.php @@ -0,0 +1,17 @@ +<?php + +namespace dokuwiki\Action\Exception; + +/** + * Class ActionDisabledException + * + * Thrown when the requested action has been disabled. Eg. through the 'disableactions' + * config setting. You should probably not use it. + * + * The message will NOT be shown to the enduser, but a generic information will be shown. + * + * @package dokuwiki\Action\Exception + */ +class ActionDisabledException extends ActionException { + +} diff --git a/wiki/inc/Action/Exception/ActionException.php b/wiki/inc/Action/Exception/ActionException.php new file mode 100644 index 0000000..381584c --- /dev/null +++ b/wiki/inc/Action/Exception/ActionException.php @@ -0,0 +1,66 @@ +<?php + +namespace dokuwiki\Action\Exception; + +/** + * Class ActionException + * + * This exception and its subclasses signal that the current action should be + * aborted and a different action should be used instead. The new action can + * be given as parameter in the constructor. Defaults to 'show' + * + * The message will NOT be shown to the enduser + * + * @package dokuwiki\Action\Exception + */ +class ActionException extends \Exception { + + /** @var string the new action */ + protected $newaction; + + /** @var bool should the exception's message be shown to the user? */ + protected $displayToUser = false; + + /** + * ActionException constructor. + * + * When no new action is given 'show' is assumed. For requests that originated in a POST, + * a 'redirect' is used which will cause a redirect to the 'show' action. + * + * @param string|null $newaction the action that should be used next + * @param string $message optional message, will not be shown except for some dub classes + */ + public function __construct($newaction = null, $message = '') { + global $INPUT; + parent::__construct($message); + if(is_null($newaction)) { + if(strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post') { + $newaction = 'redirect'; + } else { + $newaction = 'show'; + } + } + + $this->newaction = $newaction; + } + + /** + * Returns the action to use next + * + * @return string + */ + public function getNewAction() { + return $this->newaction; + } + + /** + * Should this Exception's message be shown to the user? + * + * @param null|bool $set when null is given, the current setting is not changed + * @return bool + */ + public function displayToUser($set = null) { + if(!is_null($set)) $this->displayToUser = $set; + return $set; + } +} diff --git a/wiki/inc/Action/Exception/ActionUserRequiredException.php b/wiki/inc/Action/Exception/ActionUserRequiredException.php new file mode 100644 index 0000000..aab06cc --- /dev/null +++ b/wiki/inc/Action/Exception/ActionUserRequiredException.php @@ -0,0 +1,17 @@ +<?php + +namespace dokuwiki\Action\Exception; + +/** + * Class ActionUserRequiredException + * + * Thrown by AbstractUserAction when an action requires that a user is logged + * in but it isn't. You should not use it. + * + * The message will NOT be shown to the enduser + * + * @package dokuwiki\Action\Exception + */ +class ActionUserRequiredException extends ActionException { + +} diff --git a/wiki/inc/Action/Exception/FatalException.php b/wiki/inc/Action/Exception/FatalException.php new file mode 100644 index 0000000..5f2516f --- /dev/null +++ b/wiki/inc/Action/Exception/FatalException.php @@ -0,0 +1,29 @@ +<?php + +namespace dokuwiki\Action\Exception; + +/** + * Class FatalException + * + * A fatal exception during handling the action + * + * Will abort all handling and display some info to the user. The HTTP status code + * can be defined. + * + * @package dokuwiki\Action\Exception + */ +class FatalException extends \Exception { + + protected $status; + + /** + * FatalException constructor. + * + * @param string $message the message to send + * @param int $status the HTTP status to send + * @param null|\Exception $previous previous exception + */ + public function __construct($message = 'A fatal error occured', $status = 500, $previous = null) { + parent::__construct($message, $status, $previous); + } +} diff --git a/wiki/inc/Action/Exception/NoActionException.php b/wiki/inc/Action/Exception/NoActionException.php new file mode 100644 index 0000000..1c4e4d0 --- /dev/null +++ b/wiki/inc/Action/Exception/NoActionException.php @@ -0,0 +1,15 @@ +<?php + +namespace dokuwiki\Action\Exception; + +/** + * Class NoActionException + * + * Thrown in the ActionRouter when a wanted action can not be found. Triggers + * the unknown action event + * + * @package dokuwiki\Action\Exception + */ +class NoActionException extends \Exception { + +} diff --git a/wiki/inc/Action/Export.php b/wiki/inc/Action/Export.php new file mode 100644 index 0000000..1eec27e --- /dev/null +++ b/wiki/inc/Action/Export.php @@ -0,0 +1,112 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Export + * + * Handle exporting by calling the appropriate renderer + * + * @package dokuwiki\Action + */ +class Export extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** + * Export a wiki page for various formats + * + * Triggers ACTION_EXPORT_POSTPROCESS + * + * Event data: + * data['id'] -- page id + * data['mode'] -- requested export mode + * data['headers'] -- export headers + * data['output'] -- export output + * + * @author Andreas Gohr <andi@splitbrain.org> + * @author Michael Klier <chi@chimeric.de> + * @inheritdoc + */ + public function preProcess() { + global $ID; + global $REV; + global $conf; + global $lang; + + $pre = ''; + $post = ''; + $headers = array(); + + // search engines: never cache exported docs! (Google only currently) + $headers['X-Robots-Tag'] = 'noindex'; + + $mode = substr($this->actionname, 7); + switch($mode) { + case 'raw': + $headers['Content-Type'] = 'text/plain; charset=utf-8'; + $headers['Content-Disposition'] = 'attachment; filename=' . noNS($ID) . '.txt'; + $output = rawWiki($ID, $REV); + break; + case 'xhtml': + $pre .= '<!DOCTYPE html>' . DOKU_LF; + $pre .= '<html lang="' . $conf['lang'] . '" dir="' . $lang['direction'] . '">' . DOKU_LF; + $pre .= '<head>' . DOKU_LF; + $pre .= ' <meta charset="utf-8" />' . DOKU_LF; // FIXME improve wrapper + $pre .= ' <title>' . $ID . '</title>' . DOKU_LF; + + // get metaheaders + ob_start(); + tpl_metaheaders(); + $pre .= ob_get_clean(); + + $pre .= '</head>' . DOKU_LF; + $pre .= '<body>' . DOKU_LF; + $pre .= '<div class="dokuwiki export">' . DOKU_LF; + + // get toc + $pre .= tpl_toc(true); + + $headers['Content-Type'] = 'text/html; charset=utf-8'; + $output = p_wiki_xhtml($ID, $REV, false); + + $post .= '</div>' . DOKU_LF; + $post .= '</body>' . DOKU_LF; + $post .= '</html>' . DOKU_LF; + break; + case 'xhtmlbody': + $headers['Content-Type'] = 'text/html; charset=utf-8'; + $output = p_wiki_xhtml($ID, $REV, false); + break; + default: + $output = p_cached_output(wikiFN($ID, $REV), $mode, $ID); + $headers = p_get_metadata($ID, "format $mode"); + break; + } + + // prepare event data + $data = array(); + $data['id'] = $ID; + $data['mode'] = $mode; + $data['headers'] = $headers; + $data['output'] =& $output; + + trigger_event('ACTION_EXPORT_POSTPROCESS', $data); + + if(!empty($data['output'])) { + if(is_array($data['headers'])) foreach($data['headers'] as $key => $val) { + header("$key: $val"); + } + print $pre . $data['output'] . $post; + exit; + } + + throw new ActionAbort(); + } + +} diff --git a/wiki/inc/Action/Index.php b/wiki/inc/Action/Index.php new file mode 100644 index 0000000..c87a3f8 --- /dev/null +++ b/wiki/inc/Action/Index.php @@ -0,0 +1,25 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Index + * + * Show the human readable sitemap. Do not confuse with Sitemap + * + * @package dokuwiki\Action + */ +class Index extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function tplContent() { + global $IDX; + html_index($IDX); + } + +} diff --git a/wiki/inc/Action/Locked.php b/wiki/inc/Action/Locked.php new file mode 100644 index 0000000..3ff2c5b --- /dev/null +++ b/wiki/inc/Action/Locked.php @@ -0,0 +1,24 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Locked + * + * Show a locked screen when a page is locked + * + * @package dokuwiki\Action + */ +class Locked extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** @inheritdoc */ + public function tplContent() { + html_locked(); + } + +} diff --git a/wiki/inc/Action/Login.php b/wiki/inc/Action/Login.php new file mode 100644 index 0000000..7f903ff --- /dev/null +++ b/wiki/inc/Action/Login.php @@ -0,0 +1,36 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionException; + +/** + * Class Login + * + * The login form. Actual logins are handled in inc/auth.php + * + * @package dokuwiki\Action + */ +class Login extends AbstractAclAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function checkPreconditions() { + global $INPUT; + parent::checkPreconditions(); + if($INPUT->server->has('REMOTE_USER')) { + // nothing to do + throw new ActionException(); + } + } + + /** @inheritdoc */ + public function tplContent() { + html_login(); + } + +} diff --git a/wiki/inc/Action/Logout.php b/wiki/inc/Action/Logout.php new file mode 100644 index 0000000..1590904 --- /dev/null +++ b/wiki/inc/Action/Logout.php @@ -0,0 +1,50 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionDisabledException; +use dokuwiki\Action\Exception\ActionException; + +/** + * Class Logout + * + * Log out a user + * + * @package dokuwiki\Action + */ +class Logout extends AbstractUserAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + + /** @var \DokuWiki_Auth_Plugin $auth */ + global $auth; + if(!$auth->canDo('logout')) throw new ActionDisabledException(); + } + + /** @inheritdoc */ + public function preProcess() { + global $ID; + global $INPUT; + + // when logging out during an edit session, unlock the page + $lockedby = checklock($ID); + if($lockedby == $INPUT->server->str('REMOTE_USER')) { + unlock($ID); + } + + // do the logout stuff and redirect to login + auth_logoff(); + send_redirect(wl($ID, array('do' => 'login'))); + + // should never be reached + throw new ActionException('login'); + } + +} diff --git a/wiki/inc/Action/Media.php b/wiki/inc/Action/Media.php new file mode 100644 index 0000000..77a2a6f --- /dev/null +++ b/wiki/inc/Action/Media.php @@ -0,0 +1,24 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Media + * + * The full screen media manager + * + * @package dokuwiki\Action + */ +class Media extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** @inheritdoc */ + public function tplContent() { + tpl_media(); + } + +} diff --git a/wiki/inc/Action/Plugin.php b/wiki/inc/Action/Plugin.php new file mode 100644 index 0000000..c3e16bf --- /dev/null +++ b/wiki/inc/Action/Plugin.php @@ -0,0 +1,32 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Plugin + * + * Used to run action plugins + * + * @package dokuwiki\Action + */ +class Plugin extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** + * Outputs nothing but a warning unless an action plugin overwrites it + * + * @inheritdoc + * @triggers TPL_ACT_UNKNOWN + */ + public function tplContent() { + $evt = new \Doku_Event('TPL_ACT_UNKNOWN', $this->actionname); + if($evt->advise_before()) { + msg('Failed to handle action: ' . hsc($this->actionname), -1); + } + $evt->advise_after(); + } +} diff --git a/wiki/inc/Action/Preview.php b/wiki/inc/Action/Preview.php new file mode 100644 index 0000000..850b204 --- /dev/null +++ b/wiki/inc/Action/Preview.php @@ -0,0 +1,58 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Preview + * + * preview during editing + * + * @package dokuwiki\Action + */ +class Preview extends Edit { + + /** @inheritdoc */ + public function preProcess() { + header('X-XSS-Protection: 0'); + $this->savedraft(); + parent::preProcess(); + } + + /** @inheritdoc */ + public function tplContent() { + global $TEXT; + html_edit(); + html_show($TEXT); + } + + /** + * Saves a draft on preview + */ + protected function savedraft() { + global $INFO; + global $ID; + global $INPUT; + global $conf; + + if(!$conf['usedraft']) return; + if(!$INPUT->post->has('wikitext')) return; + + // ensure environment (safeguard when used via AJAX) + assert(isset($INFO['client']), 'INFO.client should have been set'); + assert(isset($ID), 'ID should have been set'); + + $draft = array( + 'id' => $ID, + 'prefix' => substr($INPUT->post->str('prefix'), 0, -1), + 'text' => $INPUT->post->str('wikitext'), + 'suffix' => $INPUT->post->str('suffix'), + 'date' => $INPUT->post->int('date'), + 'client' => $INFO['client'], + ); + $cname = getCacheName($draft['client'] . $ID, '.draft'); + if(io_saveFile($cname, serialize($draft))) { + $INFO['draft'] = $cname; + } + } + +} diff --git a/wiki/inc/Action/Profile.php b/wiki/inc/Action/Profile.php new file mode 100644 index 0000000..53d8d2f --- /dev/null +++ b/wiki/inc/Action/Profile.php @@ -0,0 +1,45 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; +use dokuwiki\Action\Exception\ActionDisabledException; + +/** + * Class Profile + * + * Handle the profile form + * + * @package dokuwiki\Action + */ +class Profile extends AbstractUserAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + + /** @var \DokuWiki_Auth_Plugin $auth */ + global $auth; + if(!$auth->canDo('Profile')) throw new ActionDisabledException(); + } + + /** @inheritdoc */ + public function preProcess() { + global $lang; + if(updateprofile()) { + msg($lang['profchanged'], 1); + throw new ActionAbort('show'); + } + } + + /** @inheritdoc */ + public function tplContent() { + html_updateprofile(); + } + +} diff --git a/wiki/inc/Action/ProfileDelete.php b/wiki/inc/Action/ProfileDelete.php new file mode 100644 index 0000000..995f813 --- /dev/null +++ b/wiki/inc/Action/ProfileDelete.php @@ -0,0 +1,42 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; +use dokuwiki\Action\Exception\ActionDisabledException; + +/** + * Class ProfileDelete + * + * Delete a user account + * + * @package dokuwiki\Action + */ +class ProfileDelete extends AbstractUserAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + + /** @var \DokuWiki_Auth_Plugin $auth */ + global $auth; + if(!$auth->canDo('delUser')) throw new ActionDisabledException(); + } + + /** @inheritdoc */ + public function preProcess() { + global $lang; + if(auth_deleteprofile()) { + msg($lang['profdeleted'], 1); + throw new ActionAbort('show'); + } else { + throw new ActionAbort('profile'); + } + } + +} diff --git a/wiki/inc/Action/Recent.php b/wiki/inc/Action/Recent.php new file mode 100644 index 0000000..9273d52 --- /dev/null +++ b/wiki/inc/Action/Recent.php @@ -0,0 +1,40 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Recent + * + * The recent changes view + * + * @package dokuwiki\Action + */ +class Recent extends AbstractAction { + + /** @var string what type of changes to show */ + protected $showType = 'both'; + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function preProcess() { + global $INPUT; + $show_changes = $INPUT->str('show_changes'); + if(!empty($show_changes)) { + set_doku_pref('show_changes', $show_changes); + $this->showType = $show_changes; + } else { + $this->showType = get_doku_pref('show_changes', 'both'); + } + } + + /** @inheritdoc */ + public function tplContent() { + global $INPUT; + html_recent((int) $INPUT->extract('first')->int('first'), $this->showType); + } + +} diff --git a/wiki/inc/Action/Recover.php b/wiki/inc/Action/Recover.php new file mode 100644 index 0000000..7966396 --- /dev/null +++ b/wiki/inc/Action/Recover.php @@ -0,0 +1,21 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Recover + * + * Recover a draft + * + * @package dokuwiki\Action + */ +class Recover extends AbstractAliasAction { + + /** @inheritdoc */ + public function preProcess() { + throw new ActionAbort('edit'); + } + +} diff --git a/wiki/inc/Action/Redirect.php b/wiki/inc/Action/Redirect.php new file mode 100644 index 0000000..2e28f45 --- /dev/null +++ b/wiki/inc/Action/Redirect.php @@ -0,0 +1,64 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Redirect + * + * Used to redirect to the current page with the last edited section as a target if found + * + * @package dokuwiki\Action + */ +class Redirect extends AbstractAliasAction { + + /** + * Redirect to the show action, trying to jump to the previously edited section + * + * @triggers ACTION_SHOW_REDIRECT + * @throws ActionAbort + */ + public function preProcess() { + global $PRE; + global $TEXT; + global $INPUT; + global $ID; + global $ACT; + + $opts = array( + 'id' => $ID, + 'preact' => $ACT + ); + //get section name when coming from section edit + if($INPUT->has('hid')) { + // Use explicitly transmitted header id + $opts['fragment'] = $INPUT->str('hid'); + } else if($PRE && preg_match('/^\s*==+([^=\n]+)/', $TEXT, $match)) { + // Fallback to old mechanism + $check = false; //Byref + $opts['fragment'] = sectionID($match[0], $check); + } + + // execute the redirect + trigger_event('ACTION_SHOW_REDIRECT', $opts, array($this, 'redirect')); + + // should never be reached + throw new ActionAbort('show'); + } + + /** + * Execute the redirect + * + * Default action for ACTION_SHOW_REDIRECT + * + * @param array $opts id and fragment for the redirect and the preact + */ + public function redirect($opts) { + $go = wl($opts['id'], '', true); + if(isset($opts['fragment'])) $go .= '#' . $opts['fragment']; + + //show it + send_redirect($go); + } +} diff --git a/wiki/inc/Action/Register.php b/wiki/inc/Action/Register.php new file mode 100644 index 0000000..0d54158 --- /dev/null +++ b/wiki/inc/Action/Register.php @@ -0,0 +1,45 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; +use dokuwiki\Action\Exception\ActionDisabledException; + +/** + * Class Register + * + * Self registering a new user + * + * @package dokuwiki\Action + */ +class Register extends AbstractAclAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + + /** @var \DokuWiki_Auth_Plugin $auth */ + global $auth; + global $conf; + if(isset($conf['openregister']) && !$conf['openregister']) throw new ActionDisabledException(); + if(!$auth->canDo('addUser')) throw new ActionDisabledException(); + } + + /** @inheritdoc */ + public function preProcess() { + if(register()) { // FIXME could be moved from auth to here + throw new ActionAbort('login'); + } + } + + /** @inheritdoc */ + public function tplContent() { + html_register(); + } + +} diff --git a/wiki/inc/Action/Resendpwd.php b/wiki/inc/Action/Resendpwd.php new file mode 100644 index 0000000..5b5e381 --- /dev/null +++ b/wiki/inc/Action/Resendpwd.php @@ -0,0 +1,177 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; +use dokuwiki\Action\Exception\ActionDisabledException; + +/** + * Class Resendpwd + * + * Handle password recovery + * + * @package dokuwiki\Action + */ +class Resendpwd extends AbstractAclAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + + /** @var \DokuWiki_Auth_Plugin $auth */ + global $auth; + global $conf; + if(isset($conf['resendpasswd']) && !$conf['resendpasswd']) throw new ActionDisabledException(); //legacy option + if(!$auth->canDo('modPass')) throw new ActionDisabledException(); + } + + /** @inheritdoc */ + public function preProcess() { + if($this->resendpwd()) { + throw new ActionAbort('login'); + } + } + + /** @inheritdoc */ + public function tplContent() { + html_resendpwd(); + } + + /** + * Send a new password + * + * This function handles both phases of the password reset: + * + * - handling the first request of password reset + * - validating the password reset auth token + * + * @author Benoit Chesneau <benoit@bchesneau.info> + * @author Chris Smith <chris@jalakai.co.uk> + * @author Andreas Gohr <andi@splitbrain.org> + * @fixme this should be split up into multiple methods + * @return bool true on success, false on any error + */ + protected function resendpwd() { + global $lang; + global $conf; + /* @var \DokuWiki_Auth_Plugin $auth */ + global $auth; + global $INPUT; + + if(!actionOK('resendpwd')) { + msg($lang['resendna'], -1); + return false; + } + + $token = preg_replace('/[^a-f0-9]+/', '', $INPUT->str('pwauth')); + + if($token) { + // we're in token phase - get user info from token + + $tfile = $conf['cachedir'] . '/' . $token{0} . '/' . $token . '.pwauth'; + if(!file_exists($tfile)) { + msg($lang['resendpwdbadauth'], -1); + $INPUT->remove('pwauth'); + return false; + } + // token is only valid for 3 days + if((time() - filemtime($tfile)) > (3 * 60 * 60 * 24)) { + msg($lang['resendpwdbadauth'], -1); + $INPUT->remove('pwauth'); + @unlink($tfile); + return false; + } + + $user = io_readfile($tfile); + $userinfo = $auth->getUserData($user, $requireGroups = false); + if(!$userinfo['mail']) { + msg($lang['resendpwdnouser'], -1); + return false; + } + + if(!$conf['autopasswd']) { // we let the user choose a password + $pass = $INPUT->str('pass'); + + // password given correctly? + if(!$pass) return false; + if($pass != $INPUT->str('passchk')) { + msg($lang['regbadpass'], -1); + return false; + } + + // change it + if(!$auth->triggerUserMod('modify', array($user, array('pass' => $pass)))) { + msg($lang['proffail'], -1); + return false; + } + + } else { // autogenerate the password and send by mail + + $pass = auth_pwgen($user); + if(!$auth->triggerUserMod('modify', array($user, array('pass' => $pass)))) { + msg($lang['proffail'], -1); + return false; + } + + if(auth_sendPassword($user, $pass)) { + msg($lang['resendpwdsuccess'], 1); + } else { + msg($lang['regmailfail'], -1); + } + } + + @unlink($tfile); + return true; + + } else { + // we're in request phase + + if(!$INPUT->post->bool('save')) return false; + + if(!$INPUT->post->str('login')) { + msg($lang['resendpwdmissing'], -1); + return false; + } else { + $user = trim($auth->cleanUser($INPUT->post->str('login'))); + } + + $userinfo = $auth->getUserData($user, $requireGroups = false); + if(!$userinfo['mail']) { + msg($lang['resendpwdnouser'], -1); + return false; + } + + // generate auth token + $token = md5(auth_randombytes(16)); // random secret + $tfile = $conf['cachedir'] . '/' . $token{0} . '/' . $token . '.pwauth'; + $url = wl('', array('do' => 'resendpwd', 'pwauth' => $token), true, '&'); + + io_saveFile($tfile, $user); + + $text = rawLocale('pwconfirm'); + $trep = array( + 'FULLNAME' => $userinfo['name'], + 'LOGIN' => $user, + 'CONFIRM' => $url + ); + + $mail = new \Mailer(); + $mail->to($userinfo['name'] . ' <' . $userinfo['mail'] . '>'); + $mail->subject($lang['regpwmail']); + $mail->setBody($text, $trep); + if($mail->send()) { + msg($lang['resendpwdconfirm'], 1); + } else { + msg($lang['regmailfail'], -1); + } + return true; + } + // never reached + } + +} diff --git a/wiki/inc/Action/Revert.php b/wiki/inc/Action/Revert.php new file mode 100644 index 0000000..ca35374 --- /dev/null +++ b/wiki/inc/Action/Revert.php @@ -0,0 +1,65 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; +use dokuwiki\Action\Exception\ActionException; + +/** + * Class Revert + * + * Quick revert to an old revision + * + * @package dokuwiki\Action + */ +class Revert extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + global $INFO; + if($INFO['ismanager']) { + return AUTH_EDIT; + } else { + return AUTH_ADMIN; + } + } + + /** + * + * @inheritdoc + * @throws ActionAbort + * @throws ActionException + * @todo check for writability of the current page ($INFO might do it wrong and check the attic version) + */ + public function preProcess() { + if(!checkSecurityToken()) throw new ActionException(); + + global $ID; + global $REV; + global $lang; + + // when no revision is given, delete current one + // FIXME this feature is not exposed in the GUI currently + $text = ''; + $sum = $lang['deleted']; + if($REV) { + $text = rawWiki($ID, $REV); + if(!$text) throw new ActionException(); //something went wrong + $sum = sprintf($lang['restored'], dformat($REV)); + } + + // spam check + if(checkwordblock($text)) { + msg($lang['wordblock'], -1); + throw new ActionException('edit'); + } + + saveWikiText($ID, $text, $sum, false); + msg($sum, 1); + $REV = ''; + + // continue with draftdel -> redirect -> show + throw new ActionAbort('draftdel'); + } + +} diff --git a/wiki/inc/Action/Revisions.php b/wiki/inc/Action/Revisions.php new file mode 100644 index 0000000..b8db531 --- /dev/null +++ b/wiki/inc/Action/Revisions.php @@ -0,0 +1,24 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Revisions + * + * Show the list of old revisions of the current page + * + * @package dokuwiki\Action + */ +class Revisions extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** @inheritdoc */ + public function tplContent() { + global $INPUT; + html_revisions($INPUT->int('first')); + } +} diff --git a/wiki/inc/Action/Save.php b/wiki/inc/Action/Save.php new file mode 100644 index 0000000..0b24729 --- /dev/null +++ b/wiki/inc/Action/Save.php @@ -0,0 +1,60 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; +use dokuwiki\Action\Exception\ActionException; + +/** + * Class Save + * + * Save at the end of an edit session + * + * @package dokuwiki\Action + */ +class Save extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + global $INFO; + if($INFO['exists']) { + return AUTH_EDIT; + } else { + return AUTH_CREATE; + } + } + + /** @inheritdoc */ + public function preProcess() { + if(!checkSecurityToken()) throw new ActionException('preview'); + + global $ID; + global $DATE; + global $PRE; + global $TEXT; + global $SUF; + global $SUM; + global $lang; + global $INFO; + global $INPUT; + + //spam check + if(checkwordblock()) { + msg($lang['wordblock'], -1); + throw new ActionException('edit'); + } + //conflict check + if($DATE != 0 && $INFO['meta']['date']['modified'] > $DATE) { + throw new ActionException('conflict'); + } + + //save it + saveWikiText($ID, con($PRE, $TEXT, $SUF, true), $SUM, $INPUT->bool('minor')); //use pretty mode for con + //unlock it + unlock($ID); + + // continue with draftdel -> redirect -> show + throw new ActionAbort('draftdel'); + } + +} diff --git a/wiki/inc/Action/Search.php b/wiki/inc/Action/Search.php new file mode 100644 index 0000000..382fc47 --- /dev/null +++ b/wiki/inc/Action/Search.php @@ -0,0 +1,135 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Search + * + * Search for pages and content + * + * @package dokuwiki\Action + */ +class Search extends AbstractAction { + + protected $pageLookupResults = array(); + protected $fullTextResults = array(); + protected $highlight = array(); + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** + * we only search if a search word was given + * + * @inheritdoc + */ + public function checkPreconditions() { + parent::checkPreconditions(); + } + + public function preProcess() + { + global $QUERY, $ID, $conf, $INPUT; + $s = cleanID($QUERY); + + if ($ID !== $conf['start'] && !$INPUT->has('q')) { + parse_str($INPUT->server->str('QUERY_STRING'), $urlParts); + $urlParts['q'] = $urlParts['id']; + $urlParts['id'] = $conf['start']; + $url = DOKU_URL . DOKU_SCRIPT . '?' . http_build_query($urlParts, null, '&'); + send_redirect($url); + } + + if ($s === '') throw new ActionAbort(); + $this->adjustGlobalQuery(); + } + + /** @inheritdoc */ + public function tplContent() + { + $this->execute(); + + $search = new \dokuwiki\Ui\Search($this->pageLookupResults, $this->fullTextResults, $this->highlight); + $search->show(); + } + + + /** + * run the search + */ + protected function execute() + { + global $INPUT, $QUERY; + $after = $INPUT->str('min'); + $before = $INPUT->str('max'); + $this->pageLookupResults = ft_pageLookup($QUERY, true, useHeading('navigation'), $after, $before); + $this->fullTextResults = ft_pageSearch($QUERY, $highlight, $INPUT->str('srt'), $after, $before); + $this->highlight = $highlight; + } + + /** + * Adjust the global query accordingly to the config search_nslimit and search_fragment + * + * This will only do something if the search didn't originate from the form on the searchpage itself + */ + protected function adjustGlobalQuery() + { + global $conf, $INPUT, $QUERY, $ID; + + if ($INPUT->bool('sf')) { + return; + } + + $Indexer = idx_get_indexer(); + $parsedQuery = ft_queryParser($Indexer, $QUERY); + + if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) { + if ($conf['search_nslimit'] > 0) { + if (getNS($ID) !== false) { + $nsParts = explode(':', getNS($ID)); + $ns = implode(':', array_slice($nsParts, 0, $conf['search_nslimit'])); + $QUERY .= " @$ns"; + } + } + } + + if ($conf['search_fragment'] !== 'exact') { + if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) { + if (strpos($QUERY, '*') === false) { + $queryParts = explode(' ', $QUERY); + $queryParts = array_map(function ($part) { + if (strpos($part, '@') === 0) { + return $part; + } + if (strpos($part, 'ns:') === 0) { + return $part; + } + if (strpos($part, '^') === 0) { + return $part; + } + if (strpos($part, '-ns:') === 0) { + return $part; + } + + global $conf; + + if ($conf['search_fragment'] === 'starts_with') { + return $part . '*'; + } + if ($conf['search_fragment'] === 'ends_with') { + return '*' . $part; + } + + return '*' . $part . '*'; + + }, $queryParts); + $QUERY = implode(' ', $queryParts); + } + } + } + } +} diff --git a/wiki/inc/Action/Show.php b/wiki/inc/Action/Show.php new file mode 100644 index 0000000..a5cb534 --- /dev/null +++ b/wiki/inc/Action/Show.php @@ -0,0 +1,36 @@ +<?php +/** + * Created by IntelliJ IDEA. + * User: andi + * Date: 2/10/17 + * Time: 4:32 PM + */ + +namespace dokuwiki\Action; + +/** + * Class Show + * + * The default action of showing a page + * + * @package dokuwiki\Action + */ +class Show extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** @inheritdoc */ + public function preProcess() { + global $ID; + unlock($ID); + } + + /** @inheritdoc */ + public function tplContent() { + html_show(); + } + +} diff --git a/wiki/inc/Action/Sitemap.php b/wiki/inc/Action/Sitemap.php new file mode 100644 index 0000000..025c515 --- /dev/null +++ b/wiki/inc/Action/Sitemap.php @@ -0,0 +1,65 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\FatalException; + +/** + * Class Sitemap + * + * Generate an XML sitemap for search engines. Do not confuse with Index + * + * @package dokuwiki\Action + */ +class Sitemap extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_NONE; + } + + /** + * Handle sitemap delivery + * + * @author Michael Hamann <michael@content-space.de> + * @throws FatalException + * @inheritdoc + */ + public function preProcess() { + global $conf; + + if($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) { + throw new FatalException(404, 'Sitemap generation is disabled'); + } + + $sitemap = \Sitemapper::getFilePath(); + if(\Sitemapper::sitemapIsCompressed()) { + $mime = 'application/x-gzip'; + } else { + $mime = 'application/xml; charset=utf-8'; + } + + // Check if sitemap file exists, otherwise create it + if(!is_readable($sitemap)) { + \Sitemapper::generate(); + } + + if(is_readable($sitemap)) { + // Send headers + header('Content-Type: ' . $mime); + header('Content-Disposition: attachment; filename=' . utf8_basename($sitemap)); + + http_conditionalRequest(filemtime($sitemap)); + + // Send file + //use x-sendfile header to pass the delivery to compatible webservers + http_sendfile($sitemap); + + readfile($sitemap); + exit; + } + + throw new FatalException(500, 'Could not read the sitemap file - bad permissions?'); + } + +} diff --git a/wiki/inc/Action/Source.php b/wiki/inc/Action/Source.php new file mode 100644 index 0000000..9b03fe9 --- /dev/null +++ b/wiki/inc/Action/Source.php @@ -0,0 +1,36 @@ +<?php + +namespace dokuwiki\Action; + +/** + * Class Source + * + * Show the source of a page + * + * @package dokuwiki\Action + */ +class Source extends AbstractAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** @inheritdoc */ + public function preProcess() { + global $TEXT; + global $INFO; + global $ID; + global $REV; + + if($INFO['exists']) { + $TEXT = rawWiki($ID, $REV); + } + } + + /** @inheritdoc */ + public function tplContent() { + html_edit(); + } + +} diff --git a/wiki/inc/Action/Subscribe.php b/wiki/inc/Action/Subscribe.php new file mode 100644 index 0000000..c165710 --- /dev/null +++ b/wiki/inc/Action/Subscribe.php @@ -0,0 +1,166 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; +use dokuwiki\Action\Exception\ActionDisabledException; + +/** + * Class Subscribe + * + * E-Mail subscription handling + * + * @package dokuwiki\Action + */ +class Subscribe extends AbstractUserAction { + + /** @inheritdoc */ + public function minimumPermission() { + return AUTH_READ; + } + + /** @inheritdoc */ + public function checkPreconditions() { + parent::checkPreconditions(); + + global $conf; + if(isset($conf['subscribers']) && !$conf['subscribers']) throw new ActionDisabledException(); + } + + /** @inheritdoc */ + public function preProcess() { + try { + $this->handleSubscribeData(); + } catch(ActionAbort $e) { + throw $e; + } catch(\Exception $e) { + msg($e->getMessage(), -1); + } + } + + /** @inheritdoc */ + public function tplContent() { + tpl_subscribe(); + } + + /** + * Handle page 'subscribe' + * + * @author Adrian Lang <lang@cosmocode.de> + * @throws \Exception if (un)subscribing fails + * @throws ActionAbort when (un)subscribing worked + */ + protected function handleSubscribeData() { + global $lang; + global $INFO; + global $INPUT; + + // get and preprocess data. + $params = array(); + foreach(array('target', 'style', 'action') as $param) { + if($INPUT->has("sub_$param")) { + $params[$param] = $INPUT->str("sub_$param"); + } + } + + // any action given? if not just return and show the subscription page + if(empty($params['action']) || !checkSecurityToken()) return; + + // Handle POST data, may throw exception. + trigger_event('ACTION_HANDLE_SUBSCRIBE', $params, array($this, 'handlePostData')); + + $target = $params['target']; + $style = $params['style']; + $action = $params['action']; + + // Perform action. + $sub = new \Subscription(); + if($action == 'unsubscribe') { + $ok = $sub->remove($target, $INPUT->server->str('REMOTE_USER'), $style); + } else { + $ok = $sub->add($target, $INPUT->server->str('REMOTE_USER'), $style); + } + + if($ok) { + msg( + sprintf( + $lang["subscr_{$action}_success"], hsc($INFO['userinfo']['name']), + prettyprint_id($target) + ), 1 + ); + throw new ActionAbort('redirect'); + } else { + throw new \Exception( + sprintf( + $lang["subscr_{$action}_error"], + hsc($INFO['userinfo']['name']), + prettyprint_id($target) + ) + ); + } + } + + /** + * Validate POST data + * + * Validates POST data for a subscribe or unsubscribe request. This is the + * default action for the event ACTION_HANDLE_SUBSCRIBE. + * + * @author Adrian Lang <lang@cosmocode.de> + * + * @param array &$params the parameters: target, style and action + * @throws \Exception + */ + public function handlePostData(&$params) { + global $INFO; + global $lang; + global $INPUT; + + // Get and validate parameters. + if(!isset($params['target'])) { + throw new \Exception('no subscription target given'); + } + $target = $params['target']; + $valid_styles = array('every', 'digest'); + if(substr($target, -1, 1) === ':') { + // Allow “list” subscribe style since the target is a namespace. + $valid_styles[] = 'list'; + } + $style = valid_input_set( + 'style', $valid_styles, $params, + 'invalid subscription style given' + ); + $action = valid_input_set( + 'action', array('subscribe', 'unsubscribe'), + $params, 'invalid subscription action given' + ); + + // Check other conditions. + if($action === 'subscribe') { + if($INFO['userinfo']['mail'] === '') { + throw new \Exception($lang['subscr_subscribe_noaddress']); + } + } elseif($action === 'unsubscribe') { + $is = false; + foreach($INFO['subscribed'] as $subscr) { + if($subscr['target'] === $target) { + $is = true; + } + } + if($is === false) { + throw new \Exception( + sprintf( + $lang['subscr_not_subscribed'], + $INPUT->server->str('REMOTE_USER'), + prettyprint_id($target) + ) + ); + } + // subscription_set deletes a subscription if style = null. + $style = null; + } + + $params = compact('target', 'style', 'action'); + } + +} |