xref: /plugin/captcha/action.php (revision f74276b88372a902ec3afb17d672e19b09c5ea69)
142a27035SAndreas Gohr<?php
242a27035SAndreas Gohr/**
342a27035SAndreas Gohr * CAPTCHA antispam plugin
442a27035SAndreas Gohr *
542a27035SAndreas Gohr * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
642a27035SAndreas Gohr * @author     Andreas Gohr <gohr@cosmocode.de>
742a27035SAndreas Gohr */
842a27035SAndreas Gohr
942a27035SAndreas Gohr// must be run within Dokuwiki
1042a27035SAndreas Gohrif(!defined('DOKU_INC')) die();
1142a27035SAndreas Gohrif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
127218f96cSAndreas Gohr
1342a27035SAndreas Gohrclass action_plugin_captcha extends DokuWiki_Action_Plugin {
1442a27035SAndreas Gohr
1542a27035SAndreas Gohr    /**
1642a27035SAndreas Gohr     * register the eventhandlers
1742a27035SAndreas Gohr     */
187218f96cSAndreas Gohr    public function register(Doku_Event_Handler $controller) {
197218f96cSAndreas Gohr        // check CAPTCHA success
20c2695b40SAndreas Gohr        $controller->register_hook(
21c2695b40SAndreas Gohr            'ACTION_ACT_PREPROCESS',
2242a27035SAndreas Gohr            'BEFORE',
2342a27035SAndreas Gohr            $this,
247218f96cSAndreas Gohr            'handle_captcha_input',
25c2695b40SAndreas Gohr            array()
26c2695b40SAndreas Gohr        );
2742a27035SAndreas Gohr
287218f96cSAndreas Gohr        // inject in edit form
29c2695b40SAndreas Gohr        $controller->register_hook(
30c2695b40SAndreas Gohr            'HTML_EDITFORM_OUTPUT',
3147afabe6SAndreas Gohr            'BEFORE',
3247afabe6SAndreas Gohr            $this,
337218f96cSAndreas Gohr            'handle_form_output',
347218f96cSAndreas Gohr            array()
35c2695b40SAndreas Gohr        );
3642a27035SAndreas Gohr
377218f96cSAndreas Gohr        // inject in user registration
38c2695b40SAndreas Gohr        $controller->register_hook(
39c2695b40SAndreas Gohr            'HTML_REGISTERFORM_OUTPUT',
4047afabe6SAndreas Gohr            'BEFORE',
4147afabe6SAndreas Gohr            $this,
427218f96cSAndreas Gohr            'handle_form_output',
437218f96cSAndreas Gohr            array()
44c2695b40SAndreas Gohr        );
45*f74276b8SAndreas Gohr
46*f74276b8SAndreas Gohr        // inject in password reset
47*f74276b8SAndreas Gohr        $controller->register_hook(
48*f74276b8SAndreas Gohr            'HTML_RESENDPWDFORM_OUTPUT',
49*f74276b8SAndreas Gohr            'BEFORE',
50*f74276b8SAndreas Gohr            $this,
51*f74276b8SAndreas Gohr            'handle_form_output',
52*f74276b8SAndreas Gohr            array()
53*f74276b8SAndreas Gohr        );
5442a27035SAndreas Gohr    }
5542a27035SAndreas Gohr
5642a27035SAndreas Gohr    /**
57bd26d35bSAndreas Gohr     * Check if the current mode should be handled by CAPTCHA
58bd26d35bSAndreas Gohr     *
59*f74276b8SAndreas Gohr     * Note: checking needs to be done when a form has been submitted, not when the form
60*f74276b8SAndreas Gohr     * is shown for the first time. Except for the editing process this is not determined
61*f74276b8SAndreas Gohr     * by $act alone but needs to inspect other input variables.
62*f74276b8SAndreas Gohr     *
63bd26d35bSAndreas Gohr     * @param string $act cleaned action mode
64bd26d35bSAndreas Gohr     * @return bool
65bd26d35bSAndreas Gohr     */
66*f74276b8SAndreas Gohr    protected function needs_checking($act) {
67bd26d35bSAndreas Gohr        global $INPUT;
68bd26d35bSAndreas Gohr
69bd26d35bSAndreas Gohr        switch($act) {
70bd26d35bSAndreas Gohr            case 'save':
71bd26d35bSAndreas Gohr                return true;
72bd26d35bSAndreas Gohr            case 'register':
73*f74276b8SAndreas Gohr            case 'resendpwd':
74bd26d35bSAndreas Gohr                return $INPUT->bool('save');
75bd26d35bSAndreas Gohr            default:
76bd26d35bSAndreas Gohr                return false;
77bd26d35bSAndreas Gohr        }
78bd26d35bSAndreas Gohr    }
79bd26d35bSAndreas Gohr
80bd26d35bSAndreas Gohr    /**
81bd26d35bSAndreas Gohr     * Aborts the given mode
82bd26d35bSAndreas Gohr     *
83bd26d35bSAndreas Gohr     * Aborting depends on the mode. It might unset certain input parameters or simply switch
84bd26d35bSAndreas Gohr     * the mode to something else (giving as return which needs to be passed back to the
85bd26d35bSAndreas Gohr     * ACTION_ACT_PREPROCESS event)
86bd26d35bSAndreas Gohr     *
87bd26d35bSAndreas Gohr     * @param string $act cleaned action mode
88bd26d35bSAndreas Gohr     * @return string the new mode to use
89bd26d35bSAndreas Gohr     */
90bd26d35bSAndreas Gohr    protected function abort_action($act) {
91bd26d35bSAndreas Gohr        global $INPUT;
92bd26d35bSAndreas Gohr
93bd26d35bSAndreas Gohr        switch($act) {
94bd26d35bSAndreas Gohr            case 'save':
95bd26d35bSAndreas Gohr                return 'preview';
96bd26d35bSAndreas Gohr            case 'register':
97*f74276b8SAndreas Gohr            case 'resendpwd':
98bd26d35bSAndreas Gohr                $INPUT->post->set('save', false);
99*f74276b8SAndreas Gohr                return $act;
100bd26d35bSAndreas Gohr            default:
101bd26d35bSAndreas Gohr                return $act;
102bd26d35bSAndreas Gohr        }
103bd26d35bSAndreas Gohr    }
104bd26d35bSAndreas Gohr
105bd26d35bSAndreas Gohr    /**
10642a27035SAndreas Gohr     * Will intercept the 'save' action and check for CAPTCHA first.
10742a27035SAndreas Gohr     */
1087218f96cSAndreas Gohr    public function handle_captcha_input(Doku_Event $event, $param) {
1097218f96cSAndreas Gohr        $act = act_clean($event->data);
110*f74276b8SAndreas Gohr        if(!$this->needs_checking($act)) return;
11193f66506SAndreas Gohr
11242a27035SAndreas Gohr        // do nothing if logged in user and no CAPTCHA required
11342a27035SAndreas Gohr        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
11442a27035SAndreas Gohr            return;
11542a27035SAndreas Gohr        }
11642a27035SAndreas Gohr
11777e00bf9SAndreas Gohr        // check captcha
1187218f96cSAndreas Gohr        /** @var helper_plugin_captcha $helper */
11977e00bf9SAndreas Gohr        $helper = plugin_load('helper', 'captcha');
12077e00bf9SAndreas Gohr        if(!$helper->check()) {
121bd26d35bSAndreas Gohr            $event->data = $this->abort_action($act);
12242a27035SAndreas Gohr        }
12342a27035SAndreas Gohr    }
12442a27035SAndreas Gohr
12542a27035SAndreas Gohr    /**
1267218f96cSAndreas Gohr     * Inject the CAPTCHA in a DokuForm
12742a27035SAndreas Gohr     */
1287218f96cSAndreas Gohr    public function handle_form_output(Doku_Event $event, $param) {
12947afabe6SAndreas Gohr        // get position of submit button
13047afabe6SAndreas Gohr        $pos = $event->data->findElementByAttribute('type', 'submit');
13147afabe6SAndreas Gohr        if(!$pos) return; // no button -> source view mode
13247afabe6SAndreas Gohr
13342a27035SAndreas Gohr        // do nothing if logged in user and no CAPTCHA required
13442a27035SAndreas Gohr        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
13542a27035SAndreas Gohr            return;
13642a27035SAndreas Gohr        }
13742a27035SAndreas Gohr
13877e00bf9SAndreas Gohr        // get the CAPTCHA
1397218f96cSAndreas Gohr        /** @var helper_plugin_captcha $helper */
14077e00bf9SAndreas Gohr        $helper = plugin_load('helper', 'captcha');
14177e00bf9SAndreas Gohr        $out = $helper->getHTML();
14247afabe6SAndreas Gohr
1437218f96cSAndreas Gohr        // new wiki - insert after the submit button
1447218f96cSAndreas Gohr        $event->data->insertElement($pos + 1, $out);
14542a27035SAndreas Gohr    }
14642a27035SAndreas Gohr
14742a27035SAndreas Gohr}
14842a27035SAndreas Gohr
149