1*eb872c2aStomLin1998567<?php 2*eb872c2aStomLin1998567if (!defined('DOKU_INC')) die(); 3*eb872c2aStomLin1998567 4*eb872c2aStomLin1998567/** 5*eb872c2aStomLin1998567 * PASSWD Plugin: Handles AJAX captcha refresh and password verification. 6*eb872c2aStomLin1998567 * 7*eb872c2aStomLin1998567 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 8*eb872c2aStomLin1998567 * @author tomLin1998567 9*eb872c2aStomLin1998567 */ 10*eb872c2aStomLin1998567class action_plugin_passwd extends DokuWiki_Action_Plugin 11*eb872c2aStomLin1998567{ 12*eb872c2aStomLin1998567 public function register(Doku_Event_Handler $controller) 13*eb872c2aStomLin1998567 { 14*eb872c2aStomLin1998567 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax'); 15*eb872c2aStomLin1998567 } 16*eb872c2aStomLin1998567 17*eb872c2aStomLin1998567 public function handleAjax(&$event, $param) 18*eb872c2aStomLin1998567 { 19*eb872c2aStomLin1998567 if ($event->data == 'passwd_refresh_captcha') { 20*eb872c2aStomLin1998567 $event->preventDefault(); 21*eb872c2aStomLin1998567 $this->sendCaptcha(); 22*eb872c2aStomLin1998567 return; 23*eb872c2aStomLin1998567 } 24*eb872c2aStomLin1998567 25*eb872c2aStomLin1998567 if ($event->data != 'passwd_check') return; 26*eb872c2aStomLin1998567 $event->preventDefault(); 27*eb872c2aStomLin1998567 28*eb872c2aStomLin1998567 global $INPUT, $ID; 29*eb872c2aStomLin1998567 $block = (int) $INPUT->str('block'); 30*eb872c2aStomLin1998567 $passwd = $INPUT->str('passwd'); 31*eb872c2aStomLin1998567 $id = $INPUT->str('id', $ID); 32*eb872c2aStomLin1998567 33*eb872c2aStomLin1998567 $captcha = $this->loadHelper('captcha', false); 34*eb872c2aStomLin1998567 if ($this->isCaptchaRequired($captcha) && !$this->verifyCaptcha($captcha)) { 35*eb872c2aStomLin1998567 return; 36*eb872c2aStomLin1998567 } 37*eb872c2aStomLin1998567 38*eb872c2aStomLin1998567 $blockText = $this->findPasswdBlock($id, $block); 39*eb872c2aStomLin1998567 if ($blockText === false) return; 40*eb872c2aStomLin1998567 41*eb872c2aStomLin1998567 $expected = $this->extractPassword($blockText); 42*eb872c2aStomLin1998567 if ($expected === false) return; 43*eb872c2aStomLin1998567 44*eb872c2aStomLin1998567 if ($passwd !== $expected) { 45*eb872c2aStomLin1998567 $newCaptcha = $this->isCaptchaRequired($captcha) ? $captcha->getHTML() : ''; 46*eb872c2aStomLin1998567 echo 'WRONG_PASSWORD|' . $newCaptcha; 47*eb872c2aStomLin1998567 return; 48*eb872c2aStomLin1998567 } 49*eb872c2aStomLin1998567 50*eb872c2aStomLin1998567 $this->renderContent($blockText); 51*eb872c2aStomLin1998567 } 52*eb872c2aStomLin1998567 53*eb872c2aStomLin1998567 /** 54*eb872c2aStomLin1998567 * Check whether captcha verification is enabled and available. 55*eb872c2aStomLin1998567 */ 56*eb872c2aStomLin1998567 protected function isCaptchaRequired($captcha) 57*eb872c2aStomLin1998567 { 58*eb872c2aStomLin1998567 return $this->getConf('require_captcha') && $captcha && $captcha->isEnabled(); 59*eb872c2aStomLin1998567 } 60*eb872c2aStomLin1998567 61*eb872c2aStomLin1998567 /** 62*eb872c2aStomLin1998567 * Verify the captcha. On failure output error with a fresh captcha. 63*eb872c2aStomLin1998567 * 64*eb872c2aStomLin1998567 * @return bool true if captcha passes (or not required) 65*eb872c2aStomLin1998567 */ 66*eb872c2aStomLin1998567 protected function verifyCaptcha($captcha) 67*eb872c2aStomLin1998567 { 68*eb872c2aStomLin1998567 if (!$captcha->check()) { 69*eb872c2aStomLin1998567 echo 'CAPTCHA_FAILED|' . $captcha->getHTML(); 70*eb872c2aStomLin1998567 return false; 71*eb872c2aStomLin1998567 } 72*eb872c2aStomLin1998567 return true; 73*eb872c2aStomLin1998567 } 74*eb872c2aStomLin1998567 75*eb872c2aStomLin1998567 /** 76*eb872c2aStomLin1998567 * Read a wiki page and locate the Nth PASSWD block. 77*eb872c2aStomLin1998567 * 78*eb872c2aStomLin1998567 * @param string $id Page ID 79*eb872c2aStomLin1998567 * @param int $block Zero-based block index 80*eb872c2aStomLin1998567 * @return string|false The raw block text, or false on failure 81*eb872c2aStomLin1998567 */ 82*eb872c2aStomLin1998567 protected function findPasswdBlock($id, $block) 83*eb872c2aStomLin1998567 { 84*eb872c2aStomLin1998567 preg_match_all( 85*eb872c2aStomLin1998567 '/<passwd\b[^>]*?>[\s\S]*?<\/passwd>/', 86*eb872c2aStomLin1998567 rawWiki($id), $matches, PREG_SET_ORDER 87*eb872c2aStomLin1998567 ); 88*eb872c2aStomLin1998567 89*eb872c2aStomLin1998567 if (!isset($matches[$block])) { 90*eb872c2aStomLin1998567 echo 'BLOCK_NOT_FOUND'; 91*eb872c2aStomLin1998567 return false; 92*eb872c2aStomLin1998567 } 93*eb872c2aStomLin1998567 return $matches[$block][0]; 94*eb872c2aStomLin1998567 } 95*eb872c2aStomLin1998567 96*eb872c2aStomLin1998567 /** 97*eb872c2aStomLin1998567 * Extract the password attribute from a PASSWD block. 98*eb872c2aStomLin1998567 * 99*eb872c2aStomLin1998567 * @param string $blockText Raw block text 100*eb872c2aStomLin1998567 * @return string|false The password, or false if missing 101*eb872c2aStomLin1998567 */ 102*eb872c2aStomLin1998567 protected function extractPassword($blockText) 103*eb872c2aStomLin1998567 { 104*eb872c2aStomLin1998567 if (!preg_match('/password="([^"]+)"/i', $blockText, $p)) { 105*eb872c2aStomLin1998567 echo 'PASSWORD_NOT_FOUND'; 106*eb872c2aStomLin1998567 return false; 107*eb872c2aStomLin1998567 } 108*eb872c2aStomLin1998567 return $p[1]; 109*eb872c2aStomLin1998567 } 110*eb872c2aStomLin1998567 111*eb872c2aStomLin1998567 /** 112*eb872c2aStomLin1998567 * Parse and render the inner wikitext of a PASSWD block as XHTML. 113*eb872c2aStomLin1998567 */ 114*eb872c2aStomLin1998567 protected function renderContent($blockText) 115*eb872c2aStomLin1998567 { 116*eb872c2aStomLin1998567 preg_match('/^<passwd\b[^>]*?>([\s\S]*?)<\/passwd>$/s', $blockText, $m); 117*eb872c2aStomLin1998567 $instructions = p_get_instructions($m[1]); 118*eb872c2aStomLin1998567 echo p_render('xhtml', $instructions, $info); 119*eb872c2aStomLin1998567 } 120*eb872c2aStomLin1998567 121*eb872c2aStomLin1998567 /** 122*eb872c2aStomLin1998567 * Generate and return a fresh captcha HTML snippet. 123*eb872c2aStomLin1998567 */ 124*eb872c2aStomLin1998567 protected function sendCaptcha() 125*eb872c2aStomLin1998567 { 126*eb872c2aStomLin1998567 $captcha = $this->loadHelper('captcha', false); 127*eb872c2aStomLin1998567 if ($captcha && $captcha->isEnabled()) { 128*eb872c2aStomLin1998567 echo $captcha->getHTML(); 129*eb872c2aStomLin1998567 } 130*eb872c2aStomLin1998567 } 131*eb872c2aStomLin1998567} 132