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