xref: /plugin/captcha/action.php (revision c2695b4064acf71a0be53fa2784565975ea97dd2)
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();
11
12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
13require_once(DOKU_PLUGIN.'action.php');
14
15class action_plugin_captcha extends DokuWiki_Action_Plugin {
16
17    /**
18     * register the eventhandlers
19     */
20    function register(&$controller) {
21        $controller->register_hook(
22            'ACTION_ACT_PREPROCESS',
23            'BEFORE',
24            $this,
25            'handle_act_preprocess',
26            array()
27        );
28
29        // old hook
30        $controller->register_hook(
31            'HTML_EDITFORM_INJECTION',
32            'BEFORE',
33            $this,
34            'handle_editform_output',
35            array('editform' => true, 'oldhook' => true)
36        );
37
38        // new hook
39        $controller->register_hook(
40            'HTML_EDITFORM_OUTPUT',
41            'BEFORE',
42            $this,
43            'handle_editform_output',
44            array('editform' => true, 'oldhook' => false)
45        );
46
47        if($this->getConf('regprotect')) {
48            // old hook
49            $controller->register_hook(
50                'HTML_REGISTERFORM_INJECTION',
51                'BEFORE',
52                $this,
53                'handle_editform_output',
54                array('editform' => false, 'oldhook' => true)
55            );
56
57            // new hook
58            $controller->register_hook(
59                'HTML_REGISTERFORM_OUTPUT',
60                'BEFORE',
61                $this,
62                'handle_editform_output',
63                array('editform' => false, 'oldhook' => false)
64            );
65        }
66    }
67
68    /**
69     * Will intercept the 'save' action and check for CAPTCHA first.
70     */
71    function handle_act_preprocess(&$event, $param) {
72        $act = $this->_act_clean($event->data);
73        if(!('save' == $act || ($this->getConf('regprotect') &&
74                'register' == $act &&
75                $_POST['save']))
76        ) {
77            return; // nothing to do for us
78        }
79
80        // do nothing if logged in user and no CAPTCHA required
81        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
82            return;
83        }
84
85        // check captcha
86        $helper = plugin_load('helper', 'captcha');
87        if(!$helper->check()) {
88            if($act == 'save') {
89                // stay in preview mode
90                $event->data = 'preview';
91            } else {
92                // stay in register mode, but disable the save parameter
93                $_POST['save'] = false;
94            }
95        }
96    }
97
98    /**
99     * Create the additional fields for the edit form
100     */
101    function handle_editform_output(&$event, $param) {
102        // check if source view -> no captcha needed
103        if(!$param['oldhook']) {
104            // get position of submit button
105            $pos = $event->data->findElementByAttribute('type', 'submit');
106            if(!$pos) return; // no button -> source view mode
107        } elseif($param['editform'] && !$event->data['writable']) {
108            if($param['editform'] && !$event->data['writable']) return;
109        }
110
111        // do nothing if logged in user and no CAPTCHA required
112        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) {
113            return;
114        }
115
116        // get the CAPTCHA
117        $helper = plugin_load('helper', 'captcha');
118        $out    = $helper->getHTML();
119
120        if($param['oldhook']) {
121            // old wiki - just print
122            echo $out;
123        } else {
124            // new wiki - insert at correct position
125            $event->data->insertElement($pos++, $out);
126        }
127    }
128
129    /**
130     * Pre-Sanitize the action command
131     *
132     * Similar to act_clean in action.php but simplified and without
133     * error messages
134     */
135    function _act_clean($act) {
136        // check if the action was given as array key
137        if(is_array($act)) {
138            list($act) = array_keys($act);
139        }
140
141        //remove all bad chars
142        $act = strtolower($act);
143        $act = preg_replace('/[^a-z_]+/', '', $act);
144
145        return $act;
146    }
147
148}
149
150