summaryrefslogtreecommitdiff
path: root/platform/www/inc/Action
diff options
context:
space:
mode:
Diffstat (limited to 'platform/www/inc/Action')
-rw-r--r--platform/www/inc/Action/AbstractAclAction.php25
-rw-r--r--platform/www/inc/Action/AbstractAction.php88
-rw-r--r--platform/www/inc/Action/AbstractAliasAction.php28
-rw-r--r--platform/www/inc/Action/AbstractUserAction.php25
-rw-r--r--platform/www/inc/Action/Admin.php45
-rw-r--r--platform/www/inc/Action/Backlink.php24
-rw-r--r--platform/www/inc/Action/Cancel.php25
-rw-r--r--platform/www/inc/Action/Check.php26
-rw-r--r--platform/www/inc/Action/Conflict.php34
-rw-r--r--platform/www/inc/Action/Denied.php23
-rw-r--r--platform/www/inc/Action/Diff.php35
-rw-r--r--platform/www/inc/Action/Draft.php39
-rw-r--r--platform/www/inc/Action/Draftdel.php38
-rw-r--r--platform/www/inc/Action/Edit.php91
-rw-r--r--platform/www/inc/Action/Exception/ActionAbort.php20
-rw-r--r--platform/www/inc/Action/Exception/ActionAclRequiredException.php17
-rw-r--r--platform/www/inc/Action/Exception/ActionDisabledException.php17
-rw-r--r--platform/www/inc/Action/Exception/ActionException.php66
-rw-r--r--platform/www/inc/Action/Exception/ActionUserRequiredException.php17
-rw-r--r--platform/www/inc/Action/Exception/FatalException.php26
-rw-r--r--platform/www/inc/Action/Exception/NoActionException.php15
-rw-r--r--platform/www/inc/Action/Export.php113
-rw-r--r--platform/www/inc/Action/Index.php25
-rw-r--r--platform/www/inc/Action/Locked.php25
-rw-r--r--platform/www/inc/Action/Login.php36
-rw-r--r--platform/www/inc/Action/Logout.php50
-rw-r--r--platform/www/inc/Action/Media.php24
-rw-r--r--platform/www/inc/Action/Plugin.php32
-rw-r--r--platform/www/inc/Action/Preview.php42
-rw-r--r--platform/www/inc/Action/Profile.php45
-rw-r--r--platform/www/inc/Action/ProfileDelete.php42
-rw-r--r--platform/www/inc/Action/Recent.php40
-rw-r--r--platform/www/inc/Action/Recover.php21
-rw-r--r--platform/www/inc/Action/Redirect.php65
-rw-r--r--platform/www/inc/Action/Register.php45
-rw-r--r--platform/www/inc/Action/Resendpwd.php177
-rw-r--r--platform/www/inc/Action/Revert.php60
-rw-r--r--platform/www/inc/Action/Revisions.php24
-rw-r--r--platform/www/inc/Action/Save.php60
-rw-r--r--platform/www/inc/Action/Search.php135
-rw-r--r--platform/www/inc/Action/Show.php36
-rw-r--r--platform/www/inc/Action/Sitemap.php66
-rw-r--r--platform/www/inc/Action/Source.php36
-rw-r--r--platform/www/inc/Action/Subscribe.php168
44 files changed, 2091 insertions, 0 deletions
diff --git a/platform/www/inc/Action/AbstractAclAction.php b/platform/www/inc/Action/AbstractAclAction.php
new file mode 100644
index 0000000..871edb0
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/AbstractAction.php b/platform/www/inc/Action/AbstractAction.php
new file mode 100644
index 0000000..ea86238
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/AbstractAliasAction.php b/platform/www/inc/Action/AbstractAliasAction.php
new file mode 100644
index 0000000..7240f5e
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/AbstractUserAction.php b/platform/www/inc/Action/AbstractUserAction.php
new file mode 100644
index 0000000..b4e3f1a
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Admin.php b/platform/www/inc/Action/Admin.php
new file mode 100644
index 0000000..1c9afd6
--- /dev/null
+++ b/platform/www/inc/Action/Admin.php
@@ -0,0 +1,45 @@
+<?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() {
+ return AUTH_READ; // let in check later
+ }
+
+ public function checkPreconditions() {
+ parent::checkPreconditions();
+ }
+
+ public function preProcess() {
+ global $INPUT;
+ global $INFO;
+
+ // retrieve admin plugin name from $_REQUEST['page']
+ if(($page = $INPUT->str('page', '', true)) != '') {
+ /** @var $plugin \dokuwiki\Extension\AdminPlugin */
+ if($plugin = plugin_getRequestAdminPlugin()) { // FIXME this method does also permission checking
+ if(!$plugin->isAccessibleByCurrentUser()) {
+ throw new ActionException('denied');
+ }
+ $plugin->handle();
+ }
+ }
+ }
+
+ public function tplContent() {
+ tpl_admin();
+ }
+
+}
diff --git a/platform/www/inc/Action/Backlink.php b/platform/www/inc/Action/Backlink.php
new file mode 100644
index 0000000..0337917
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Cancel.php b/platform/www/inc/Action/Cancel.php
new file mode 100644
index 0000000..d4d8277
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Check.php b/platform/www/inc/Action/Check.php
new file mode 100644
index 0000000..36ae8e8
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Conflict.php b/platform/www/inc/Action/Conflict.php
new file mode 100644
index 0000000..d880b5b
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Denied.php b/platform/www/inc/Action/Denied.php
new file mode 100644
index 0000000..c8e0192
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Diff.php b/platform/www/inc/Action/Diff.php
new file mode 100644
index 0000000..b14b1d0
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Draft.php b/platform/www/inc/Action/Draft.php
new file mode 100644
index 0000000..caf0870
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Draftdel.php b/platform/www/inc/Action/Draftdel.php
new file mode 100644
index 0000000..756c0e8
--- /dev/null
+++ b/platform/www/inc/Action/Draftdel.php
@@ -0,0 +1,38 @@
+<?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 for the current page and user if any
+ *
+ * Redirects to show, afterwards.
+ *
+ * @throws ActionAbort
+ */
+ public function preProcess() {
+ global $INFO, $ID;
+ $draft = new \dokuwiki\Draft($ID, $INFO['client']);
+ if ($draft->isDraftAvailable()) {
+ $draft->deleteDraft();
+ }
+
+ throw new ActionAbort('redirect');
+ }
+
+}
diff --git a/platform/www/inc/Action/Edit.php b/platform/www/inc/Action/Edit.php
new file mode 100644
index 0000000..061c9e2
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Exception/ActionAbort.php b/platform/www/inc/Action/Exception/ActionAbort.php
new file mode 100644
index 0000000..9c188bb
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Exception/ActionAclRequiredException.php b/platform/www/inc/Action/Exception/ActionAclRequiredException.php
new file mode 100644
index 0000000..64a2c61
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Exception/ActionDisabledException.php b/platform/www/inc/Action/Exception/ActionDisabledException.php
new file mode 100644
index 0000000..40a0c7d
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Exception/ActionException.php b/platform/www/inc/Action/Exception/ActionException.php
new file mode 100644
index 0000000..381584c
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Exception/ActionUserRequiredException.php b/platform/www/inc/Action/Exception/ActionUserRequiredException.php
new file mode 100644
index 0000000..aab06cc
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Exception/FatalException.php b/platform/www/inc/Action/Exception/FatalException.php
new file mode 100644
index 0000000..42e30cc
--- /dev/null
+++ b/platform/www/inc/Action/Exception/FatalException.php
@@ -0,0 +1,26 @@
+<?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 {
+ /**
+ * 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/platform/www/inc/Action/Exception/NoActionException.php b/platform/www/inc/Action/Exception/NoActionException.php
new file mode 100644
index 0000000..1c4e4d0
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Export.php b/platform/www/inc/Action/Export.php
new file mode 100644
index 0000000..6b46b27
--- /dev/null
+++ b/platform/www/inc/Action/Export.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace dokuwiki\Action;
+
+use dokuwiki\Action\Exception\ActionAbort;
+use dokuwiki\Extension\Event;
+
+/**
+ * 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;
+
+ Event::createAndTrigger('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/platform/www/inc/Action/Index.php b/platform/www/inc/Action/Index.php
new file mode 100644
index 0000000..c87a3f8
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Locked.php b/platform/www/inc/Action/Locked.php
new file mode 100644
index 0000000..41866e3
--- /dev/null
+++ b/platform/www/inc/Action/Locked.php
@@ -0,0 +1,25 @@
+<?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();
+ html_edit();
+ }
+
+}
diff --git a/platform/www/inc/Action/Login.php b/platform/www/inc/Action/Login.php
new file mode 100644
index 0000000..7f903ff
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Logout.php b/platform/www/inc/Action/Logout.php
new file mode 100644
index 0000000..28e8fee
--- /dev/null
+++ b/platform/www/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\Extension\AuthPlugin $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'), true, '&'));
+
+ // should never be reached
+ throw new ActionException('login');
+ }
+
+}
diff --git a/platform/www/inc/Action/Media.php b/platform/www/inc/Action/Media.php
new file mode 100644
index 0000000..77a2a6f
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Plugin.php b/platform/www/inc/Action/Plugin.php
new file mode 100644
index 0000000..43964cf
--- /dev/null
+++ b/platform/www/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 \dokuwiki\Extension\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/platform/www/inc/Action/Preview.php b/platform/www/inc/Action/Preview.php
new file mode 100644
index 0000000..7a5aa48
--- /dev/null
+++ b/platform/www/inc/Action/Preview.php
@@ -0,0 +1,42 @@
+<?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 $ID, $INFO;
+ $draft = new \dokuwiki\Draft($ID, $INFO['client']);
+ if (!$draft->saveDraft()) {
+ $errors = $draft->getErrors();
+ foreach ($errors as $error) {
+ msg(hsc($error), -1);
+ }
+ }
+ }
+
+}
diff --git a/platform/www/inc/Action/Profile.php b/platform/www/inc/Action/Profile.php
new file mode 100644
index 0000000..654a238
--- /dev/null
+++ b/platform/www/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\Extension\AuthPlugin $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/platform/www/inc/Action/ProfileDelete.php b/platform/www/inc/Action/ProfileDelete.php
new file mode 100644
index 0000000..89c58ed
--- /dev/null
+++ b/platform/www/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\Extension\AuthPlugin $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/platform/www/inc/Action/Recent.php b/platform/www/inc/Action/Recent.php
new file mode 100644
index 0000000..9273d52
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Recover.php b/platform/www/inc/Action/Recover.php
new file mode 100644
index 0000000..7966396
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Redirect.php b/platform/www/inc/Action/Redirect.php
new file mode 100644
index 0000000..dca911a
--- /dev/null
+++ b/platform/www/inc/Action/Redirect.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace dokuwiki\Action;
+
+use dokuwiki\Action\Exception\ActionAbort;
+use dokuwiki\Extension\Event;
+
+/**
+ * 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
+ Event::createAndTrigger('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/platform/www/inc/Action/Register.php b/platform/www/inc/Action/Register.php
new file mode 100644
index 0000000..7d21bff
--- /dev/null
+++ b/platform/www/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\Extension\AuthPlugin $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/platform/www/inc/Action/Resendpwd.php b/platform/www/inc/Action/Resendpwd.php
new file mode 100644
index 0000000..dfa4a99
--- /dev/null
+++ b/platform/www/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\Extension\AuthPlugin $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\Extension\AuthPlugin $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/platform/www/inc/Action/Revert.php b/platform/www/inc/Action/Revert.php
new file mode 100644
index 0000000..07c322c
--- /dev/null
+++ b/platform/www/inc/Action/Revert.php
@@ -0,0 +1,60 @@
+<?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() {
+ return AUTH_EDIT;
+ }
+
+ /**
+ *
+ * @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/platform/www/inc/Action/Revisions.php b/platform/www/inc/Action/Revisions.php
new file mode 100644
index 0000000..b8db531
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Save.php b/platform/www/inc/Action/Save.php
new file mode 100644
index 0000000..0b24729
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Search.php b/platform/www/inc/Action/Search.php
new file mode 100644
index 0000000..88bd0ba
--- /dev/null
+++ b/platform/www/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'];
+ unset($urlParts['id']);
+ $url = wl($ID, $urlParts, true, '&');
+ 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/platform/www/inc/Action/Show.php b/platform/www/inc/Action/Show.php
new file mode 100644
index 0000000..a5cb534
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Sitemap.php b/platform/www/inc/Action/Sitemap.php
new file mode 100644
index 0000000..370bcf0
--- /dev/null
+++ b/platform/www/inc/Action/Sitemap.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace dokuwiki\Action;
+
+use dokuwiki\Action\Exception\FatalException;
+use dokuwiki\Sitemap\Mapper;
+
+/**
+ * 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('Sitemap generation is disabled', 404);
+ }
+
+ $sitemap = Mapper::getFilePath();
+ if(Mapper::sitemapIsCompressed()) {
+ $mime = 'application/x-gzip';
+ } else {
+ $mime = 'application/xml; charset=utf-8';
+ }
+
+ // Check if sitemap file exists, otherwise create it
+ if(!is_readable($sitemap)) {
+ Mapper::generate();
+ }
+
+ if(is_readable($sitemap)) {
+ // Send headers
+ header('Content-Type: ' . $mime);
+ header('Content-Disposition: attachment; filename=' . \dokuwiki\Utf8\PhpString::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('Could not read the sitemap file - bad permissions?');
+ }
+
+}
diff --git a/platform/www/inc/Action/Source.php b/platform/www/inc/Action/Source.php
new file mode 100644
index 0000000..9b03fe9
--- /dev/null
+++ b/platform/www/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/platform/www/inc/Action/Subscribe.php b/platform/www/inc/Action/Subscribe.php
new file mode 100644
index 0000000..a129a86
--- /dev/null
+++ b/platform/www/inc/Action/Subscribe.php
@@ -0,0 +1,168 @@
+<?php
+
+namespace dokuwiki\Action;
+
+use dokuwiki\Action\Exception\ActionAbort;
+use dokuwiki\Action\Exception\ActionDisabledException;
+use dokuwiki\Subscriptions\SubscriberManager;
+use dokuwiki\Extension\Event;
+
+/**
+ * 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.
+ Event::createAndTrigger('ACTION_HANDLE_SUBSCRIBE', $params, array($this, 'handlePostData'));
+
+ $target = $params['target'];
+ $style = $params['style'];
+ $action = $params['action'];
+
+ // Perform action.
+ $subManager = new SubscriberManager();
+ if($action === 'unsubscribe') {
+ $ok = $subManager->remove($target, $INPUT->server->str('REMOTE_USER'), $style);
+ } else {
+ $ok = $subManager->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');
+ }
+
+ 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');
+ }
+
+}