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