1<?php 2/** 3 * registers users by means of a confirmation link 4 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 5 * @author Myron Turner<turnermm02@shaw.ca> 6 */ 7 8// must be run within Dokuwiki 9if(!defined('DOKU_INC')) die(); 10 11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 12require_once(DOKU_PLUGIN.'action.php'); 13require_once(DOKU_INC. 'inc/auth.php'); 14 15class action_plugin_preregister extends DokuWiki_Action_Plugin { 16 17 /** 18 * register the eventhandlers 19 */ 20 private $metaFn; 21 private $captcha; 22 23 function register(Doku_Event_Handler $controller){ 24 $controller->register_hook('FORM_REGISTER_OUTPUT', 'BEFORE', $this, 'update_register_form'); 25 $controller->register_hook('HTML_REGISTERFORM_OUTPUT', 'BEFORE', $this, 'update_register_form'); 26 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'allow_preregister_check'); 27 $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'process_preregister_check'); 28 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'AFTER', $this, 'metaheaders_after'); 29 } 30 31 function __construct() { 32 $metafile= 'preregister:db'; 33 $this->metaFn = metaFN($metafile,'.ser'); 34 $this->check_captcha_selection(); 35 } 36 function metaheaders_after (&$event, $param) { 37 global $ACT; 38 if($ACT !== 'register') return; 39 40 if($this->captcha == 'none' || $this->captcha == 'builtin') { 41 ptln( "\n<style type='text/css'>\n /*<![CDATA[*/"); 42 ptln("#plugin__captcha_wrapper{ display:none; }\n /*]]>*/\n</style>"); 43 } 44 45 } 46 47 48 function allow_preregister_check(&$event, $param) { 49 $act = $this->_act_clean($event->data); 50 if($act != 'preregistercheck') return; 51 $event->preventDefault(); 52 } 53 54 function process_preregister_check(&$event, $param) { 55 global $ACT, $INPUT; 56 57 if($ACT != 'preregistercheck') return; 58 if($_GET && $_GET['prereg']) { 59 $md5= $INPUT->str('prereg'); 60 if(!preg_match("/^(\w){32}$/",$md5,$matches)) return;; 61 echo $this->getLang('registering') . $md5; 62 $this->process_registration($md5); 63 $event->preventDefault(); 64 return; 65 } 66 67 $event->preventDefault(); 68 69 if(!$_POST['login']){ 70 msg('missing login: please fill out all fields'); 71 return; 72 } 73 else if(!$_POST['fullname']) { 74 msg('missing Real Name: please fill out all fields'); 75 return; 76 } 77 78 if($this->captcha =='captcha') { 79 $captcha = $this->loadHelper('captcha', true); 80 if(!$captcha->check()) { 81 return; 82 } 83 } 84 85 if($this->is_user($_REQUEST['login'])) return; // name already taken 86 if($this->captcha == 'builtin') { 87 $failed = false; 88 if(!isset($_REQUEST['card'])) { 89 echo '<h4>'. $this->getLang('cards_nomatch') . '</h4>'; 90 return; 91 } 92 foreach($_REQUEST['card'] as $card) { 93 if(strpos($_REQUEST['sel'],$card) === false) { 94 $failed = true; 95 break; 96 } 97 } 98 if($failed) { 99 echo '<h4>'. $this->getLang('cards_nomatch') . '</h4>'; 100 return; 101 } 102 } 103 $t = time(); 104 $salt = auth_cookiesalt(); 105 $index = md5(microtime() . $salt); 106 $url = DOKU_URL . 'doku.php?' . htmlentities($INPUT->str('id')). '&do=preregistercheck&prereg='. $index; 107 if($this->getConf('send_confirm')) { 108 $valid_email = true; 109 if($this->send_link($_REQUEST['email'], $url,$valid_email) ) { 110 echo $this->getLang('confirmation'); 111 } 112 else if($valid_email) { 113 echo $this->getLang('email_problem'); 114 } 115 } 116 else { 117 echo "<a href='$url'>$url</a><br /><br />\n"; 118 echo $this->getLang('screen_confirm'); 119 } 120 121 $data = unserialize(io_readFile($this->metaFn,false)); 122 if(!$data) $data = array(); 123 $data[$index] = $_POST; 124 $data[$index]['savetime'] = $t; 125 io_saveFile($this->metaFn,serialize($data)); 126 } 127 128 function update_register_form(&$event, $param) { 129 if($_SERVER['REMOTE_USER']){ 130 return; 131 } 132 $form = $event->data; 133 $form_update = false; 134 if(is_a($form,\dokuwiki\Form\Form::class)) { 135 $form_update = true; 136 $form->setHiddenField('save', 0); 137 $form->setHiddenField('do', 'preregistercheck'); 138 } 139 else { 140 $event->data->_hidden['save'] = 0; 141 $event->data->_hidden['do'] = 'preregistercheck'; 142 } 143 if(!$form_update) { 144 for($i=0; $i <count($event->data->_content); $i++) { 145 if(isset($event->data->_content[$i]['type']) && $event->data->_content[$i]['type'] == 'submit') 146 { 147 $event->data->_content[$i]['value'] = 'Submit'; 148 break; 149 } 150 } 151 } 152 153 else { 154 $pos = $form->findPositionByAttribute('type','submit'); 155 $form->removeElement($pos); 156 $button = $form->addButton('preregister','submit'); 157 $button->attrs(['type' => 'submit','value'=>'Submit']); 158 } 159 160 if($form_update) { 161 $pos = $form->findPositionByAttribute('type','submit'); 162 } 163 else $pos = $event->data->findElementByAttribute('type','submit'); 164 if(!$pos) return; // no button -> source view mode 165 if($this->captcha == 'builtin') { 166 $cards = $this-> get_cards(); 167 $sel =""; 168 $out = $this->format_cards($cards,$sel); 169 if($form_update) { 170 $form->setHiddenField('sel',implode("",$sel)); 171 $form->addHTML($out,$pos++); 172 } 173 else { 174 $event->data->_hidden['sel'] = implode("",$sel); 175 $event->data->insertElement($pos++,$out); 176 } 177 } 178 } 179 180 181 function process_registration($index) { 182 183 $data = unserialize(io_readFile($this->metaFn,false)); 184 if(!isset($data[$index])) { 185 msg($this->getLang('old_confirmation')); 186 return; 187 } 188 $post = $data[$index]; 189 $post['save'] = 1; 190 $_POST= array_merge($post, array()); 191 if(register()) { 192 unset($data[$index]); 193 io_saveFile($this->metaFn,serialize($data)); 194 } 195 196 } 197 198 199 function check_captcha_selection() { 200 $list = plugin_list(); 201 $this->captcha = $this->getConf('captcha'); 202 if(!in_array('captcha', $list)) { 203 if(preg_match("/captcha/", $this->captcha)) { 204 $this->captcha = 'builtin'; 205 } 206 return; 207 } 208 if($this->captcha == 'none' || $this->captcha == 'builtin') { 209 return; 210 } 211 if(plugin_isdisabled('captcha')) { 212 $this->captcha = 'builtin'; 213 return; 214 } 215 $this->captcha ='captcha'; 216 217 } 218 219 /** 220 * Pre-Sanitize the action command 221 * 222 * Similar to act_clean in action.php but simplified and without 223 * error messages 224 */ 225 function _act_clean($act){ 226 // check if the action was given as array key 227 if(is_array($act)){ 228 list($act) = array_keys($act); 229 } 230 231 //remove all bad chars 232 $act = strtolower($act); 233 $act = preg_replace('/[^a-z_]+/','',$act); 234 235 return $act; 236 } 237 238 function format_cards($cards,&$sel) { 239 $sel = array_slice($cards,0,3); 240 shuffle($cards); 241 $new_row = (int)(count($cards)/2); 242 $out = $sel[0] . ' ' . $sel[1] . ' ' . $sel[2] . '<br />'; 243 $out = str_replace(array('H','S','D','C'),array('♥','♠','♦','♣'),$out); 244 $out = $this->getLang('check_matching'). '<br />' . $out; 245 $out .= '<center><table cellspacing="2"><tr>'; 246 $i=0; 247 foreach($cards as $card) { 248 $i++; 249 $name = 'card[]'; 250 251 $out .= '<td>' . str_replace(array('H','S','D','C'),array('♥','♠','♦','♣'),$card) 252 . " <input type = 'checkbox' name = '$name' value = '$card' /></td>"; 253 if($i==$new_row) $out .='</tr><tr>'; 254 } 255 $out .= '</tr></table></center>'; 256 return $out; 257 } 258 259 function get_cards() { 260 for($i=1; $i<14; $i++) { 261 $c = $i; 262 if($i == 1) { 263 $c='A'; 264 } 265 if($i == 11) { 266 $c='J'; 267 } 268 if($c == 12) { 269 $c='Q'; 270 } 271 if($i == 13) { 272 $c='K'; 273 } 274 $hearts[] = $c . "H"; 275 $clubs[] = $c. "C"; 276 $diamonds[] = $c ."D"; 277 $spades[] = $c."S"; 278 } 279 $deck = array_merge($hearts,$clubs, $diamonds, $spades); 280 shuffle($deck); 281 return array_slice($deck,0,10); 282 } 283 284 285 function send_link($email, $url, &$valid_email) { 286 287 if(!mail_isvalid($email)) { 288 msg($this->getLang('bad_email') . $email); 289 $valid_email = false; 290 return false; 291 } 292 293 $text = $this->getLang('email_confirm') . "\n\n"; 294 $text .= "@URL@\n\n"; 295 $subject =$this->getLang('subject_confirm'); 296 297 $mail = new Mailer(); 298 $mail->to($email); 299 $mail->subject($subject); 300 $mail->setBody($text, array('url'=>$url)); 301 return $mail->send(); 302} 303 304function is_user($uname) { 305 global $config_cascade; 306 $authusers = $config_cascade['plainauth.users']['default']; 307 if(!is_readable($authusers)) return false; 308 309 $users = file($authusers); 310 $uname = utf8_strtolower($uname); 311 foreach($users as $line) { 312 $line = trim($line); 313 if($line{0} == '#') continue; 314 list($user,$rest) = preg_split('/:/',$line,2); 315 if(!trim($user)) continue; 316 if($uname == $user) { 317 msg($this->getLang('uid_inuse') . $user,-1); 318 return true; 319 } 320 } 321 return false; 322 } 323 324 function write_debug($what, $toscreen=true, $tofile=false) { 325 326 if(is_array($what)) { 327 $what = print_r($what,true); 328 } 329 if($toscreen) { 330 return "<pre>$what</pre>" ; 331 } 332 if(!$tofile) { 333 return ""; 334 } 335 336 337 $handle=fopen('preregister.txt','a'); 338 fwrite($handle, "$what\n"); 339 fclose($handle); 340 } 341} 342 343