1<?php
2if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../../').'/');
3if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
4require_once(DOKU_PLUGIN.'action.php');
5
6/**
7 * @license    GPL 2 (http://www.gnu.org/licenses/gpl2.html)
8 * @author     Adrian Schlegel <adrian.schlegel@liip.ch>
9 * @author     Robert Bronsdon <reashlin@gmail.com>
10 * @author     Martin Gross <martin@pc-coholic.de>
11 */
12
13class action_plugin_recaptcha2 extends DokuWiki_Action_Plugin {
14
15    /**
16     * register an event hook
17     *
18     */
19    function register(Doku_Event_Handler $controller)
20    {
21        // only register the hooks if the necessary config paramters exist
22        if($this->getConf('publickey') && $this->getConf('privatekey')) {
23            if($this->getConf('regprotect') || $this->getConf('editprotect')){
24                    $controller->register_hook('ACTION_ACT_PREPROCESS',
25                                               'BEFORE',
26                                               $this,
27                                               'preprocess',
28                                               array());
29            }
30            if($this->getConf('regprotect')){
31                // new hook
32                $controller->register_hook('HTML_REGISTERFORM_OUTPUT',
33                                           'BEFORE',
34                                           $this,
35                                           'insert',
36                                           array('oldhook' => false));
37                // old hook
38                $controller->register_hook('HTML_REGISTERFORM_INJECTION',
39                                           'BEFORE',
40                                           $this,
41                                           'insert',
42                                           array('oldhook' => true));
43            }
44            if($this->getConf('editprotect')){
45                // old hook
46                $controller->register_hook('HTML_EDITFORM_INJECTION',
47                                           'BEFORE',
48                                           $this,
49                                           'editform_output',
50                                           array('editform' => true, 'oldhook' => true));
51                // new hook
52                $controller->register_hook('HTML_EDITFORM_OUTPUT',
53                                           'BEFORE',
54                                           $this,
55                                           'editform_output',
56                                           array('editform' => true, 'oldhook' => false));
57            }
58        }
59    }
60
61    /**
62     * Add reCAPTCHA to edit fields
63     *
64     * @param obj $event
65     * @param array $param
66     */
67    function editform_output(&$event, $param){
68        // check if source view -> no captcha needed
69        if(!$param['oldhook']){
70            // get position of submit button
71            $pos = $event->data->findElementByAttribute('type','submit');
72            if(!$pos){
73                return; // no button -> source view mode
74            }
75        } elseif($param['editform'] && !$event->data['writable']){
76            if($param['editform'] && !$event->data['writable']){
77                return;
78            }
79        }
80
81        // If users don't need to fill in captcha then end this here.
82        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']){
83            return;
84        }
85
86        $this->insert($event, $param);
87    }
88
89    /**
90     * insert html code for recaptcha into the form
91     *
92     * @param obj $event
93     * @param array $param
94     */
95    function insert(&$event, $param) {
96        global $conf;
97        $helper = plugin_load('helper','recaptcha2');
98        $recaptcha = $helper->getHTML($param['editform']);
99
100        if($param['oldhook']) {
101            echo $recaptcha;
102        } else {
103            $pos = $event->data->findElementByAttribute('type','submit');
104            $event->data->insertElement($pos++, $recaptcha);
105        }
106    }
107
108
109    /**
110     * process the answer to the captcha
111     *
112     * @param obj $event
113     * @param array $param
114     *
115     */
116    function preprocess(&$event, $param) {
117        // get and clean the action
118        $act = $this->_act_clean($event->data);
119        // If users don't need to fill in captcha then end this here.
120        if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']){
121            return;
122        }
123        // Check we are either registering or saving a html page
124        if(
125            ($act == 'register' && $this->getConf('regprotect') && $_POST['save'] ) ||
126            ($act == 'save' && $this->getConf('editprotect'))
127          ){
128
129            // Check the recaptcha answer and only submit if correct
130            $helper = plugin_load('helper', 'recaptcha2');
131            $resp = $helper->check();
132
133            if (!$resp->isSuccess()) {
134                if($act == 'save'){
135                    // stay in preview mode
136                    msg($this->getLang('testfailed'),-1);
137                    $event->data = 'preview';
138                }else{
139                    // stay in register mode, but disable the save parameter
140                    msg($this->getLang('testfailed'),-1);
141                    $_POST['save']  = false;
142                }
143            }
144        }
145    }
146
147    /**
148     * Pre-Sanitize the action command
149     *
150     * Similar to act_clean in action.php but simplified and without
151     * error messages
152     * (taken from Andreas Gohrs captcha plugin)
153     */
154    function _act_clean($act){
155         // check if the action was given as array key
156         if(is_array($act)){
157           list($act) = array_keys($act);
158         }
159
160         //remove all bad chars
161         $act = strtolower($act);
162         $act = preg_replace('/[^a-z_]+/','',$act);
163
164         return $act;
165     }
166} //end of action class
167