1<?php 2 3namespace dokuwiki\Action; 4 5use dokuwiki\Ui\UserResendPwd; 6use dokuwiki\Action\Exception\ActionAbort; 7use dokuwiki\Action\Exception\ActionDisabledException; 8use dokuwiki\Extension\AuthPlugin; 9use dokuwiki\Ui; 10 11/** 12 * Class Resendpwd 13 * 14 * Handle password recovery 15 * 16 * @package dokuwiki\Action 17 */ 18class Resendpwd extends AbstractAclAction 19{ 20 /** @inheritdoc */ 21 public function minimumPermission() 22 { 23 return AUTH_NONE; 24 } 25 26 /** @inheritdoc */ 27 public function checkPreconditions() 28 { 29 parent::checkPreconditions(); 30 31 /** @var AuthPlugin $auth */ 32 global $auth; 33 global $conf; 34 if (isset($conf['resendpasswd']) && !$conf['resendpasswd']) 35 throw new ActionDisabledException(); //legacy option 36 if (!$auth->canDo('modPass')) throw new ActionDisabledException(); 37 } 38 39 /** @inheritdoc */ 40 public function preProcess() 41 { 42 if ($this->resendpwd()) { 43 throw new ActionAbort('login'); 44 } 45 } 46 47 /** @inheritdoc */ 48 public function tplContent() 49 { 50 (new UserResendPwd())->show(); 51 } 52 53 /** 54 * Send a new password 55 * 56 * This function handles both phases of the password reset: 57 * 58 * - handling the first request of password reset 59 * - validating the password reset auth token 60 * 61 * @author Benoit Chesneau <benoit@bchesneau.info> 62 * @author Chris Smith <chris@jalakai.co.uk> 63 * @author Andreas Gohr <andi@splitbrain.org> 64 * @fixme this should be split up into multiple methods 65 * @return bool true on success, false on any error 66 */ 67 protected function resendpwd() 68 { 69 global $lang; 70 global $conf; 71 /* @var AuthPlugin $auth */ 72 global $auth; 73 global $INPUT; 74 75 if (!actionOK('resendpwd')) { 76 msg($lang['resendna'], -1); 77 return false; 78 } 79 80 $token = preg_replace('/[^a-f0-9]+/', '', $INPUT->str('pwauth')); 81 82 if ($token) { 83 // we're in token phase - get user info from token 84 85 $tfile = $conf['cachedir'] . '/' . $token[0] . '/' . $token . '.pwauth'; 86 if (!file_exists($tfile)) { 87 msg($lang['resendpwdbadauth'], -1); 88 $INPUT->remove('pwauth'); 89 return false; 90 } 91 // token is only valid for 3 days 92 if ((time() - filemtime($tfile)) > (3 * 60 * 60 * 24)) { 93 msg($lang['resendpwdbadauth'], -1); 94 $INPUT->remove('pwauth'); 95 @unlink($tfile); 96 return false; 97 } 98 99 $user = io_readfile($tfile); 100 $userinfo = $auth->getUserData($user, $requireGroups = false); 101 if (empty($userinfo['mail'])) { 102 msg($lang['resendpwdnouser'], -1); 103 return false; 104 } 105 106 if (!$conf['autopasswd']) { // we let the user choose a password 107 $pass = $INPUT->str('pass'); 108 109 // password given correctly? 110 if (!$pass) return false; 111 if ($pass != $INPUT->str('passchk')) { 112 msg($lang['regbadpass'], -1); 113 return false; 114 } 115 116 // change it 117 if (!$auth->triggerUserMod('modify', [$user, ['pass' => $pass]])) { 118 msg($lang['proffail'], -1); 119 return false; 120 } 121 } else { // autogenerate the password and send by mail 122 $pass = auth_pwgen($user); 123 if (!$auth->triggerUserMod('modify', [$user, ['pass' => $pass]])) { 124 msg($lang['proffail'], -1); 125 return false; 126 } 127 128 if (auth_sendPassword($user, $pass)) { 129 msg($lang['resendpwdsuccess'], 1); 130 } else { 131 msg($lang['regmailfail'], -1); 132 } 133 } 134 135 @unlink($tfile); 136 return true; 137 } else { 138 // we're in request phase 139 140 if (!$INPUT->post->bool('save')) return false; 141 142 if (!$INPUT->post->str('login')) { 143 msg($lang['resendpwdmissing'], -1); 144 return false; 145 } else { 146 $user = trim($auth->cleanUser($INPUT->post->str('login'))); 147 } 148 149 $userinfo = $auth->getUserData($user, $requireGroups = false); 150 if (empty($userinfo['mail'])) { 151 msg($lang['resendpwdnouser'], -1); 152 return false; 153 } 154 155 // generate auth token 156 $token = md5(auth_randombytes(16)); // random secret 157 $tfile = $conf['cachedir'] . '/' . $token[0] . '/' . $token . '.pwauth'; 158 $url = wl('', ['do' => 'resendpwd', 'pwauth' => $token], true, '&'); 159 160 io_saveFile($tfile, $user); 161 162 $text = rawLocale('pwconfirm'); 163 $trep = [ 164 'FULLNAME' => $userinfo['name'], 165 'LOGIN' => $user, 166 'CONFIRM' => $url 167 ]; 168 169 $mail = new \Mailer(); 170 $mail->to($userinfo['name'] . ' <' . $userinfo['mail'] . '>'); 171 $mail->subject($lang['regpwmail']); 172 $mail->setBody($text, $trep); 173 if ($mail->send()) { 174 msg($lang['resendpwdconfirm'], 1); 175 } else { 176 msg($lang['regmailfail'], -1); 177 } 178 return true; 179 } 180 // never reached 181 } 182} 183