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 ); 4542a27035SAndreas Gohr } 4642a27035SAndreas Gohr 4742a27035SAndreas Gohr /** 48*bd26d35bSAndreas Gohr * Check if the current mode should be handled by CAPTCHA 49*bd26d35bSAndreas Gohr * 50*bd26d35bSAndreas Gohr * @param string $act cleaned action mode 51*bd26d35bSAndreas Gohr * @return bool 52*bd26d35bSAndreas Gohr */ 53*bd26d35bSAndreas Gohr protected function is_protected($act) { 54*bd26d35bSAndreas Gohr global $INPUT; 55*bd26d35bSAndreas Gohr 56*bd26d35bSAndreas Gohr switch($act) { 57*bd26d35bSAndreas Gohr case 'save': 58*bd26d35bSAndreas Gohr return true; 59*bd26d35bSAndreas Gohr case 'register': 60*bd26d35bSAndreas Gohr return $INPUT->bool('save'); 61*bd26d35bSAndreas Gohr default: 62*bd26d35bSAndreas Gohr return false; 63*bd26d35bSAndreas Gohr } 64*bd26d35bSAndreas Gohr } 65*bd26d35bSAndreas Gohr 66*bd26d35bSAndreas Gohr /** 67*bd26d35bSAndreas Gohr * Aborts the given mode 68*bd26d35bSAndreas Gohr * 69*bd26d35bSAndreas Gohr * Aborting depends on the mode. It might unset certain input parameters or simply switch 70*bd26d35bSAndreas Gohr * the mode to something else (giving as return which needs to be passed back to the 71*bd26d35bSAndreas Gohr * ACTION_ACT_PREPROCESS event) 72*bd26d35bSAndreas Gohr * 73*bd26d35bSAndreas Gohr * @param string $act cleaned action mode 74*bd26d35bSAndreas Gohr * @return string the new mode to use 75*bd26d35bSAndreas Gohr */ 76*bd26d35bSAndreas Gohr protected function abort_action($act) { 77*bd26d35bSAndreas Gohr global $INPUT; 78*bd26d35bSAndreas Gohr 79*bd26d35bSAndreas Gohr switch($act) { 80*bd26d35bSAndreas Gohr case 'save': 81*bd26d35bSAndreas Gohr return 'preview'; 82*bd26d35bSAndreas Gohr case 'register': 83*bd26d35bSAndreas Gohr $INPUT->post->set('save', false); 84*bd26d35bSAndreas Gohr return 'register'; 85*bd26d35bSAndreas Gohr default: 86*bd26d35bSAndreas Gohr return $act; 87*bd26d35bSAndreas Gohr } 88*bd26d35bSAndreas Gohr } 89*bd26d35bSAndreas Gohr 90*bd26d35bSAndreas Gohr /** 9142a27035SAndreas Gohr * Will intercept the 'save' action and check for CAPTCHA first. 9242a27035SAndreas Gohr */ 937218f96cSAndreas Gohr public function handle_captcha_input(Doku_Event $event, $param) { 947218f96cSAndreas Gohr $act = act_clean($event->data); 95*bd26d35bSAndreas Gohr if(!$this->is_protected($act)) return; 9693f66506SAndreas Gohr 9742a27035SAndreas Gohr // do nothing if logged in user and no CAPTCHA required 9842a27035SAndreas Gohr if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 9942a27035SAndreas Gohr return; 10042a27035SAndreas Gohr } 10142a27035SAndreas Gohr 10277e00bf9SAndreas Gohr // check captcha 1037218f96cSAndreas Gohr /** @var helper_plugin_captcha $helper */ 10477e00bf9SAndreas Gohr $helper = plugin_load('helper', 'captcha'); 10577e00bf9SAndreas Gohr if(!$helper->check()) { 106*bd26d35bSAndreas Gohr $event->data = $this->abort_action($act); 10742a27035SAndreas Gohr } 10842a27035SAndreas Gohr } 10942a27035SAndreas Gohr 11042a27035SAndreas Gohr /** 1117218f96cSAndreas Gohr * Inject the CAPTCHA in a DokuForm 11242a27035SAndreas Gohr */ 1137218f96cSAndreas Gohr public function handle_form_output(Doku_Event $event, $param) { 11447afabe6SAndreas Gohr // get position of submit button 11547afabe6SAndreas Gohr $pos = $event->data->findElementByAttribute('type', 'submit'); 11647afabe6SAndreas Gohr if(!$pos) return; // no button -> source view mode 11747afabe6SAndreas Gohr 11842a27035SAndreas Gohr // do nothing if logged in user and no CAPTCHA required 11942a27035SAndreas Gohr if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 12042a27035SAndreas Gohr return; 12142a27035SAndreas Gohr } 12242a27035SAndreas Gohr 12377e00bf9SAndreas Gohr // get the CAPTCHA 1247218f96cSAndreas Gohr /** @var helper_plugin_captcha $helper */ 12577e00bf9SAndreas Gohr $helper = plugin_load('helper', 'captcha'); 12677e00bf9SAndreas Gohr $out = $helper->getHTML(); 12747afabe6SAndreas Gohr 1287218f96cSAndreas Gohr // new wiki - insert after the submit button 1297218f96cSAndreas Gohr $event->data->insertElement($pos + 1, $out); 13042a27035SAndreas Gohr } 13142a27035SAndreas Gohr 13242a27035SAndreas Gohr} 13342a27035SAndreas Gohr 134