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