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(); 11 12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/'); 13require_once(DOKU_PLUGIN.'action.php'); 14 15class action_plugin_captcha extends DokuWiki_Action_Plugin { 16 17 /** 18 * register the eventhandlers 19 */ 20 function register(&$controller) { 21 $controller->register_hook( 22 'ACTION_ACT_PREPROCESS', 23 'BEFORE', 24 $this, 25 'handle_act_preprocess', 26 array() 27 ); 28 29 // old hook 30 $controller->register_hook( 31 'HTML_EDITFORM_INJECTION', 32 'BEFORE', 33 $this, 34 'handle_editform_output', 35 array('editform' => true, 'oldhook' => true) 36 ); 37 38 // new hook 39 $controller->register_hook( 40 'HTML_EDITFORM_OUTPUT', 41 'BEFORE', 42 $this, 43 'handle_editform_output', 44 array('editform' => true, 'oldhook' => false) 45 ); 46 47 if($this->getConf('regprotect')) { 48 // old hook 49 $controller->register_hook( 50 'HTML_REGISTERFORM_INJECTION', 51 'BEFORE', 52 $this, 53 'handle_editform_output', 54 array('editform' => false, 'oldhook' => true) 55 ); 56 57 // new hook 58 $controller->register_hook( 59 'HTML_REGISTERFORM_OUTPUT', 60 'BEFORE', 61 $this, 62 'handle_editform_output', 63 array('editform' => false, 'oldhook' => false) 64 ); 65 } 66 } 67 68 /** 69 * Will intercept the 'save' action and check for CAPTCHA first. 70 */ 71 function handle_act_preprocess(&$event, $param) { 72 $act = $this->_act_clean($event->data); 73 if(!('save' == $act || ($this->getConf('regprotect') && 74 'register' == $act && 75 $_POST['save'])) 76 ) { 77 return; // nothing to do for us 78 } 79 80 // do nothing if logged in user and no CAPTCHA required 81 if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 82 return; 83 } 84 85 // check captcha 86 $helper = plugin_load('helper', 'captcha'); 87 if(!$helper->check()) { 88 if($act == 'save') { 89 // stay in preview mode 90 $event->data = 'preview'; 91 } else { 92 // stay in register mode, but disable the save parameter 93 $_POST['save'] = false; 94 } 95 } 96 } 97 98 /** 99 * Create the additional fields for the edit form 100 */ 101 function handle_editform_output(&$event, $param) { 102 // check if source view -> no captcha needed 103 if(!$param['oldhook']) { 104 // get position of submit button 105 $pos = $event->data->findElementByAttribute('type', 'submit'); 106 if(!$pos) return; // no button -> source view mode 107 } elseif($param['editform'] && !$event->data['writable']) { 108 if($param['editform'] && !$event->data['writable']) return; 109 } 110 111 // do nothing if logged in user and no CAPTCHA required 112 if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 113 return; 114 } 115 116 // get the CAPTCHA 117 $helper = plugin_load('helper', 'captcha'); 118 $out = $helper->getHTML(); 119 120 if($param['oldhook']) { 121 // old wiki - just print 122 echo $out; 123 } else { 124 // new wiki - insert at correct position 125 $event->data->insertElement($pos++, $out); 126 } 127 } 128 129 /** 130 * Pre-Sanitize the action command 131 * 132 * Similar to act_clean in action.php but simplified and without 133 * error messages 134 */ 135 function _act_clean($act) { 136 // check if the action was given as array key 137 if(is_array($act)) { 138 list($act) = array_keys($act); 139 } 140 141 //remove all bad chars 142 $act = strtolower($act); 143 $act = preg_replace('/[^a-z_]+/', '', $act); 144 145 return $act; 146 } 147 148} 149 150