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 // inject in password reset 47 $controller->register_hook( 48 'HTML_RESENDPWDFORM_OUTPUT', 49 'BEFORE', 50 $this, 51 'handle_form_output', 52 array() 53 ); 54 } 55 56 /** 57 * Check if the current mode should be handled by CAPTCHA 58 * 59 * Note: checking needs to be done when a form has been submitted, not when the form 60 * is shown for the first time. Except for the editing process this is not determined 61 * by $act alone but needs to inspect other input variables. 62 * 63 * @param string $act cleaned action mode 64 * @return bool 65 */ 66 protected function needs_checking($act) { 67 global $INPUT; 68 69 switch($act) { 70 case 'save': 71 return true; 72 case 'register': 73 case 'resendpwd': 74 return $INPUT->bool('save'); 75 default: 76 return false; 77 } 78 } 79 80 /** 81 * Aborts the given mode 82 * 83 * Aborting depends on the mode. It might unset certain input parameters or simply switch 84 * the mode to something else (giving as return which needs to be passed back to the 85 * ACTION_ACT_PREPROCESS event) 86 * 87 * @param string $act cleaned action mode 88 * @return string the new mode to use 89 */ 90 protected function abort_action($act) { 91 global $INPUT; 92 93 switch($act) { 94 case 'save': 95 return 'preview'; 96 case 'register': 97 case 'resendpwd': 98 $INPUT->post->set('save', false); 99 return $act; 100 default: 101 return $act; 102 } 103 } 104 105 /** 106 * Will intercept the 'save' action and check for CAPTCHA first. 107 */ 108 public function handle_captcha_input(Doku_Event $event, $param) { 109 $act = act_clean($event->data); 110 if(!$this->needs_checking($act)) return; 111 112 // do nothing if logged in user and no CAPTCHA required 113 if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 114 return; 115 } 116 117 // check captcha 118 /** @var helper_plugin_captcha $helper */ 119 $helper = plugin_load('helper', 'captcha'); 120 if(!$helper->check()) { 121 $event->data = $this->abort_action($act); 122 } 123 } 124 125 /** 126 * Inject the CAPTCHA in a DokuForm 127 */ 128 public function handle_form_output(Doku_Event $event, $param) { 129 // get position of submit button 130 $pos = $event->data->findElementByAttribute('type', 'submit'); 131 if(!$pos) return; // no button -> source view mode 132 133 // do nothing if logged in user and no CAPTCHA required 134 if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 135 return; 136 } 137 138 // get the CAPTCHA 139 /** @var helper_plugin_captcha $helper */ 140 $helper = plugin_load('helper', 'captcha'); 141 $out = $helper->getHTML(); 142 143 // new wiki - insert after the submit button 144 $event->data->insertElement($pos + 1, $out); 145 } 146 147} 148 149