xref: /plugin/captcha/action.php (revision f74276b88372a902ec3afb17d672e19b09c5ea69)
1<?php
2/**
3 * CAPTCHA antispam plugin
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Andreas Gohr <gohr@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
12
13class action_plugin_captcha extends DokuWiki_Action_Plugin {
14
15    /**
16     * register the eventhandlers
17     */
18    public function register(Doku_Event_Handler $controller) {
19        // check CAPTCHA success
20        $controller->register_hook(
21            'ACTION_ACT_PREPROCESS',
22            'BEFORE',
23            $this,
24            'handle_captcha_input',
25            array()
26        );
27
28        // inject in edit form
29        $controller->register_hook(
30            'HTML_EDITFORM_OUTPUT',
31            'BEFORE',
32            $this,
33            'handle_form_output',
34            array()
35        );
36
37        // inject in user registration
38        $controller->register_hook(
39            'HTML_REGISTERFORM_OUTPUT',
40            'BEFORE',
41            $this,
42            'handle_form_output',
43            array()
44        );
45
46        // inject in password reset
47        $controller->register_hook(
48            'HTML_RESENDPWDFORM_OUTPUT',
49            'BEFORE',
50            $this,
51            'handle_form_output',
52            array()
53        );
54    }
55
56    /**
57     * Check if the current mode should be handled by CAPTCHA
58     *
59     * Note: checking needs to be done when a form has been submitted, not when the form
60     * is shown for the first time. Except for the editing process this is not determined
61     * by $act alone but needs to inspect other input variables.
62     *
63     * @param string $act cleaned action mode
64     * @return bool
65     */
66    protected function needs_checking($act) {
67        global $INPUT;
68
69        switch($act) {
70            case 'save':
71                return true;
72            case 'register':
73            case 'resendpwd':
74                return $INPUT->bool('save');
75            default:
76                return false;
77        }
78    }
79
80    /**
81     * Aborts the given mode
82     *
83     * Aborting depends on the mode. It might unset certain input parameters or simply switch
84     * the mode to something else (giving as return which needs to be passed back to the
85     * ACTION_ACT_PREPROCESS event)
86     *
87     * @param string $act cleaned action mode
88     * @return string the new mode to use
89     */
90    protected function abort_action($act) {
91        global $INPUT;
92
93        switch($act) {
94            case 'save':
95                return 'preview';
96            case 'register':
97            case 'resendpwd':
98                $INPUT->post->set('save', false);
99                return $act;
100            default:
101                return $act;
102        }
103    }
104
105    /**
106     * Will intercept the 'save' action and check for CAPTCHA first.
107     */
108    public function handle_captcha_input(Doku_Event $event, $param) {
109        $act = act_clean($event->data);
110        if(!$this->needs_checking($act)) return;
111
112        // do nothing if logged in user and no CAPTCHA required
113        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
114            return;
115        }
116
117        // check captcha
118        /** @var helper_plugin_captcha $helper */
119        $helper = plugin_load('helper', 'captcha');
120        if(!$helper->check()) {
121            $event->data = $this->abort_action($act);
122        }
123    }
124
125    /**
126     * Inject the CAPTCHA in a DokuForm
127     */
128    public function handle_form_output(Doku_Event $event, $param) {
129        // get position of submit button
130        $pos = $event->data->findElementByAttribute('type', 'submit');
131        if(!$pos) return; // no button -> source view mode
132
133        // do nothing if logged in user and no CAPTCHA required
134        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
135            return;
136        }
137
138        // get the CAPTCHA
139        /** @var helper_plugin_captcha $helper */
140        $helper = plugin_load('helper', 'captcha');
141        $out = $helper->getHTML();
142
143        // new wiki - insert after the submit button
144        $event->data->insertElement($pos + 1, $out);
145    }
146
147}
148
149