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