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