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 Gohr 1242a27035SAndreas Gohrif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/'); 1342a27035SAndreas Gohrrequire_once(DOKU_PLUGIN.'action.php'); 1442a27035SAndreas Gohr 1542a27035SAndreas Gohrclass action_plugin_captcha extends DokuWiki_Action_Plugin { 1642a27035SAndreas Gohr 1742a27035SAndreas Gohr /** 1842a27035SAndreas Gohr * register the eventhandlers 1942a27035SAndreas Gohr */ 2042a27035SAndreas Gohr function register(&$controller) { 21*c2695b40SAndreas Gohr $controller->register_hook( 22*c2695b40SAndreas Gohr 'ACTION_ACT_PREPROCESS', 2342a27035SAndreas Gohr 'BEFORE', 2442a27035SAndreas Gohr $this, 2542a27035SAndreas Gohr 'handle_act_preprocess', 26*c2695b40SAndreas Gohr array() 27*c2695b40SAndreas Gohr ); 2842a27035SAndreas Gohr 2947afabe6SAndreas Gohr // old hook 30*c2695b40SAndreas Gohr $controller->register_hook( 31*c2695b40SAndreas Gohr 'HTML_EDITFORM_INJECTION', 3242a27035SAndreas Gohr 'BEFORE', 3342a27035SAndreas Gohr $this, 3447afabe6SAndreas Gohr 'handle_editform_output', 35*c2695b40SAndreas Gohr array('editform' => true, 'oldhook' => true) 36*c2695b40SAndreas Gohr ); 3747afabe6SAndreas Gohr 3847afabe6SAndreas Gohr // new hook 39*c2695b40SAndreas Gohr $controller->register_hook( 40*c2695b40SAndreas Gohr 'HTML_EDITFORM_OUTPUT', 4147afabe6SAndreas Gohr 'BEFORE', 4247afabe6SAndreas Gohr $this, 4347afabe6SAndreas Gohr 'handle_editform_output', 44*c2695b40SAndreas Gohr array('editform' => true, 'oldhook' => false) 45*c2695b40SAndreas Gohr ); 4642a27035SAndreas Gohr 4742a27035SAndreas Gohr if($this->getConf('regprotect')) { 4847afabe6SAndreas Gohr // old hook 49*c2695b40SAndreas Gohr $controller->register_hook( 50*c2695b40SAndreas Gohr 'HTML_REGISTERFORM_INJECTION', 5142a27035SAndreas Gohr 'BEFORE', 5242a27035SAndreas Gohr $this, 5347afabe6SAndreas Gohr 'handle_editform_output', 54*c2695b40SAndreas Gohr array('editform' => false, 'oldhook' => true) 55*c2695b40SAndreas Gohr ); 5647afabe6SAndreas Gohr 5747afabe6SAndreas Gohr // new hook 58*c2695b40SAndreas Gohr $controller->register_hook( 59*c2695b40SAndreas Gohr 'HTML_REGISTERFORM_OUTPUT', 6047afabe6SAndreas Gohr 'BEFORE', 6147afabe6SAndreas Gohr $this, 6247afabe6SAndreas Gohr 'handle_editform_output', 63*c2695b40SAndreas Gohr array('editform' => false, 'oldhook' => false) 64*c2695b40SAndreas Gohr ); 6542a27035SAndreas Gohr } 6642a27035SAndreas Gohr } 6742a27035SAndreas Gohr 6842a27035SAndreas Gohr /** 6942a27035SAndreas Gohr * Will intercept the 'save' action and check for CAPTCHA first. 7042a27035SAndreas Gohr */ 7142a27035SAndreas Gohr function handle_act_preprocess(&$event, $param) { 7293f66506SAndreas Gohr $act = $this->_act_clean($event->data); 7393f66506SAndreas Gohr if(!('save' == $act || ($this->getConf('regprotect') && 7493f66506SAndreas Gohr 'register' == $act && 75*c2695b40SAndreas Gohr $_POST['save'])) 76*c2695b40SAndreas Gohr ) { 7793f66506SAndreas Gohr return; // nothing to do for us 7893f66506SAndreas Gohr } 7993f66506SAndreas Gohr 8042a27035SAndreas Gohr // do nothing if logged in user and no CAPTCHA required 8142a27035SAndreas Gohr if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 8242a27035SAndreas Gohr return; 8342a27035SAndreas Gohr } 8442a27035SAndreas Gohr 8577e00bf9SAndreas Gohr // check captcha 8677e00bf9SAndreas Gohr $helper = plugin_load('helper', 'captcha'); 8777e00bf9SAndreas Gohr if(!$helper->check()) { 8893f66506SAndreas Gohr if($act == 'save') { 8993f66506SAndreas Gohr // stay in preview mode 9042a27035SAndreas Gohr $event->data = 'preview'; 9193f66506SAndreas Gohr } else { 9293f66506SAndreas Gohr // stay in register mode, but disable the save parameter 9393f66506SAndreas Gohr $_POST['save'] = false; 9442a27035SAndreas Gohr } 9542a27035SAndreas Gohr } 9642a27035SAndreas Gohr } 9742a27035SAndreas Gohr 9842a27035SAndreas Gohr /** 9942a27035SAndreas Gohr * Create the additional fields for the edit form 10042a27035SAndreas Gohr */ 10147afabe6SAndreas Gohr function handle_editform_output(&$event, $param) { 10247afabe6SAndreas Gohr // check if source view -> no captcha needed 10347afabe6SAndreas Gohr if(!$param['oldhook']) { 10447afabe6SAndreas Gohr // get position of submit button 10547afabe6SAndreas Gohr $pos = $event->data->findElementByAttribute('type', 'submit'); 10647afabe6SAndreas Gohr if(!$pos) return; // no button -> source view mode 10747afabe6SAndreas Gohr } elseif($param['editform'] && !$event->data['writable']) { 10842a27035SAndreas Gohr if($param['editform'] && !$event->data['writable']) return; 10947afabe6SAndreas Gohr } 11047afabe6SAndreas Gohr 11142a27035SAndreas Gohr // do nothing if logged in user and no CAPTCHA required 11242a27035SAndreas Gohr if(!$this->getConf('forusers') && $_SERVER['REMOTE_USER']) { 11342a27035SAndreas Gohr return; 11442a27035SAndreas Gohr } 11542a27035SAndreas Gohr 11677e00bf9SAndreas Gohr // get the CAPTCHA 11777e00bf9SAndreas Gohr $helper = plugin_load('helper', 'captcha'); 11877e00bf9SAndreas Gohr $out = $helper->getHTML(); 11947afabe6SAndreas Gohr 12047afabe6SAndreas Gohr if($param['oldhook']) { 12147afabe6SAndreas Gohr // old wiki - just print 12247afabe6SAndreas Gohr echo $out; 12347afabe6SAndreas Gohr } else { 12447afabe6SAndreas Gohr // new wiki - insert at correct position 12547afabe6SAndreas Gohr $event->data->insertElement($pos++, $out); 12647afabe6SAndreas Gohr } 12742a27035SAndreas Gohr } 12842a27035SAndreas Gohr 12942a27035SAndreas Gohr /** 13042a27035SAndreas Gohr * Pre-Sanitize the action command 13142a27035SAndreas Gohr * 13242a27035SAndreas Gohr * Similar to act_clean in action.php but simplified and without 13342a27035SAndreas Gohr * error messages 13442a27035SAndreas Gohr */ 13542a27035SAndreas Gohr function _act_clean($act) { 13642a27035SAndreas Gohr // check if the action was given as array key 13742a27035SAndreas Gohr if(is_array($act)) { 13842a27035SAndreas Gohr list($act) = array_keys($act); 13942a27035SAndreas Gohr } 14042a27035SAndreas Gohr 14142a27035SAndreas Gohr //remove all bad chars 14242a27035SAndreas Gohr $act = strtolower($act); 14342a27035SAndreas Gohr $act = preg_replace('/[^a-z_]+/', '', $act); 14442a27035SAndreas Gohr 14542a27035SAndreas Gohr return $act; 14642a27035SAndreas Gohr } 14742a27035SAndreas Gohr 14842a27035SAndreas Gohr} 14942a27035SAndreas Gohr 150