xref: /plugin/captcha/action.php (revision bd26d35b7b32407ed0189c28198eae135056a68b)
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
47    /**
48     * Check if the current mode should be handled by CAPTCHA
49     *
50     * @param string $act cleaned action mode
51     * @return bool
52     */
53    protected function is_protected($act) {
54        global $INPUT;
55
56        switch($act) {
57            case 'save':
58                return true;
59            case 'register':
60                return $INPUT->bool('save');
61            default:
62                return false;
63        }
64    }
65
66    /**
67     * Aborts the given mode
68     *
69     * Aborting depends on the mode. It might unset certain input parameters or simply switch
70     * the mode to something else (giving as return which needs to be passed back to the
71     * ACTION_ACT_PREPROCESS event)
72     *
73     * @param string $act cleaned action mode
74     * @return string the new mode to use
75     */
76    protected function abort_action($act) {
77        global $INPUT;
78
79        switch($act) {
80            case 'save':
81                return 'preview';
82            case 'register':
83                $INPUT->post->set('save', false);
84                return 'register';
85            default:
86                return $act;
87        }
88    }
89
90    /**
91     * Will intercept the 'save' action and check for CAPTCHA first.
92     */
93    public function handle_captcha_input(Doku_Event $event, $param) {
94        $act = act_clean($event->data);
95        if(!$this->is_protected($act)) return;
96
97        // do nothing if logged in user and no CAPTCHA required
98        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
99            return;
100        }
101
102        // check captcha
103        /** @var helper_plugin_captcha $helper */
104        $helper = plugin_load('helper', 'captcha');
105        if(!$helper->check()) {
106            $event->data = $this->abort_action($act);
107        }
108    }
109
110    /**
111     * Inject the CAPTCHA in a DokuForm
112     */
113    public function handle_form_output(Doku_Event $event, $param) {
114        // get position of submit button
115        $pos = $event->data->findElementByAttribute('type', 'submit');
116        if(!$pos) return; // no button -> source view mode
117
118        // do nothing if logged in user and no CAPTCHA required
119        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
120            return;
121        }
122
123        // get the CAPTCHA
124        /** @var helper_plugin_captcha $helper */
125        $helper = plugin_load('helper', 'captcha');
126        $out = $helper->getHTML();
127
128        // new wiki - insert after the submit button
129        $event->data->insertElement($pos + 1, $out);
130    }
131
132}
133
134