WordPress.org

Make WordPress Core

Ticket #15384: class-wp-login.php

File class-wp-login.php, 32.7 KB (added by norbertm, 4 years ago)
Line 
1<?php
2
3/**
4 * Class for handling user registration, login and related actions.
5 *
6 * Dispatch routes the request to the proper action.
7 *
8 * Process functions do the action processing and return errors if any.
9 * They call the Do functions which do the actual service level work.
10 *
11 * Finally the errors returned are passed to a Render function,
12 * which in turn calls one or many Output functions to output the HTML.
13 *
14 * @package WordPress
15 * @since 3.2.0
16 */
17class WP_Login {
18        /**
19         * Redirects to https if forced to use SSL.
20         */
21        function ensure_ssl_if_required() {
22                if ( force_ssl_admin() && !is_ssl() ) {
23                        if ( 0 === strpos($_SERVER['REQUEST_URI'], 'http') ) {
24                                wp_redirect(preg_replace('|^http://|', 'https://', $_SERVER['REQUEST_URI']));
25                                exit();
26                        } else {
27                                wp_redirect('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
28                                exit();
29                        }
30                }
31        }
32
33        /**
34         * Sets some cookies for render_login() to see if the browser supports them.
35         */
36        function send_test_cookies() {
37                //Set a cookie now to see if they are supported by the browser.
38                setcookie(TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN);
39                if ( SITECOOKIEPATH != COOKIEPATH )
40                        setcookie(TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN);
41        }
42
43        /**
44         * Checks for move flag.
45         */
46        function relocate_if_required() {
47                if ( defined('RELOCATE') ) { // Move flag is set
48                        if ( isset( $_SERVER['PATH_INFO'] ) && ($_SERVER['PATH_INFO'] != $_SERVER['PHP_SELF']) )
49                                $_SERVER['PHP_SELF'] = str_replace( $_SERVER['PATH_INFO'], '', $_SERVER['PHP_SELF'] );
50
51                        $schema = is_ssl() ? 'https://' : 'http://';
52                        if ( dirname($schema . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']) != get_option('siteurl') )
53                                update_option('siteurl', dirname($schema . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']) );
54                }
55        }
56
57        /**
58         * Dispatches to a controller based on the action requested.
59         */
60        function dispatch($action) {
61                if ( empty( $action ) ) {
62                        $action = 'login';
63                }
64
65                if ( isset($_GET['key']) )
66                        $action = 'resetpass';
67
68                // aliases for backwards compatibility
69                $aliases = array(
70                        'rp' => 'resetpass',
71                        'retrievepassword' => 'lostpassword'
72                );
73                if ( array_key_exists( $action, $aliases ) ) {
74                        $action = $aliases[$action];
75                }
76
77                // validate action so as to default to the login screen
78                if ( !in_array($action, array('logout', 'lostpassword', 'resetpass', 'register', 'login'), true) && false === has_filter('login_form_' . $action) )
79                        $action = 'login';
80
81                // allow plugins to override the default actions, and to add extra actions if they want
82                do_action('login_form_' . $action);
83
84                $errors = new WP_Error();
85               
86                $class_name = 'WP_Login_' . ucfirst($action);
87                if ( ! class_exists( $class_name )) {
88                        // This should never happen.
89                        echo "'Login class '" . $class_name . "' does not exist.";
90                        exit();
91                }
92               
93                $controller = new $class_name;
94
95                // if there is a separate method for processing, let's call that first
96                $method = 'process';
97                if ( method_exists( $controller, $method ) ) {
98                        $errors = call_user_func(array($controller, $method));
99                }
100
101                // render the output with any errors during processing
102                $method = 'render';
103                if ( ! method_exists( $controller, $method ) ) {
104                        // This should never happen.
105                        echo "'Action handler '" . $class_name . '::' . $method . "()' does not exist.";
106                        exit();
107                }
108               
109                call_user_func(array($controller, $method), $errors);
110                exit();
111        }
112}
113
114/**
115 * The base class for all login-related classes.
116 */
117class WP_Login_Base {
118        /**
119         * Redirects to the URL specified in the request.
120         * Defaults to the URL passed in the first parameter.
121         *
122         * @param string $url The URL to redirect to in case there was no URL specified in the request.
123         */
124        function _do_safe_redirect( $url ) {
125                $redirect_to = !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : $url;
126                wp_safe_redirect( $redirect_to );
127        }
128
129        /**
130         * Outputs the header for the login page.
131         *
132         * @uses do_action() Calls the 'login_head' for outputting HTML in the Log In
133         *              header.
134         * @uses apply_filters() Calls 'login_headerurl' for the top login link.
135         * @uses apply_filters() Calls 'login_headertitle' for the top login title.
136         * @uses apply_filters() Calls 'login_message' on the message to display in the
137         *              header.
138         * @uses $error The error global, which is checked for displaying errors.
139         *
140         * @param string $title Optional. WordPress Log In Page title to display in
141         *              <title/> element.
142         * @param string $message Optional. Message to display in header.
143         * @param WP_Error $wp_error Optional. WordPress Error Object
144         */
145        function _output_header($title = 'Log In', $message = '', $wp_error = '') {
146                global $error, $is_iphone, $interim_login, $current_site;
147
148                // Don't index any of these forms
149                add_filter( 'pre_option_blog_public', '__return_zero' );
150                add_action( 'login_head', 'noindex' );
151
152                if ( empty($wp_error) )
153                        $wp_error = new WP_Error();
154
155                // Shake it!
156                $shake_error_codes = array( 'empty_password', 'empty_email', 'invalid_email', 'invalidcombo', 'empty_username', 'invalid_username', 'incorrect_password' );
157                $shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );
158
159                if ( $shake_error_codes && $wp_error->get_error_code() && in_array( $wp_error->get_error_code(), $shake_error_codes ) )
160                        add_action( 'login_head', array('WP_Login_Base', '_output_page_shake_js'), 12 );
161?>
162<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
163<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
164<head>
165        <title><?php bloginfo('name'); ?> &rsaquo; <?php echo $title; ?></title>
166        <meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
167<?php
168        wp_admin_css( 'login', true );
169        wp_admin_css( 'colors-fresh', true );
170
171        if ( $is_iphone ) { ?>
172        <meta name="viewport" content="width=320; initial-scale=0.9; maximum-scale=1.0; user-scalable=0;" />
173        <style type="text/css" media="screen">
174        form { margin-left: 0px; }
175        #login { margin-top: 20px; }
176        </style>
177<?php
178        } elseif ( isset($interim_login) && $interim_login ) { ?>
179        <style type="text/css" media="all">
180        .login #login { margin: 20px auto; }
181        </style>
182<?php
183        }
184
185        do_action('login_head'); ?>
186</head>
187<body class="login">
188<?php   if ( !is_multisite() ) { ?>
189<div id="login"><h1><a href="<?php echo apply_filters('login_headerurl', 'http://wordpress.org/'); ?>" title="<?php echo apply_filters('login_headertitle', __('Powered by WordPress')); ?>"><?php bloginfo('name'); ?></a></h1>
190<?php   } else { ?>
191<div id="login"><h1><a href="<?php echo apply_filters('login_headerurl', network_home_url() ); ?>" title="<?php echo apply_filters('login_headertitle', $current_site->site_name ); ?>"><span class="hide"><?php bloginfo('name'); ?></span></a></h1>
192<?php   }
193
194                $message = apply_filters('login_message', $message);
195                if ( !empty( $message ) ) echo $message . "\n";
196
197                // Incase a plugin uses $error rather than the $errors object
198                if ( !empty( $error ) ) {
199                        $wp_error->add('error', $error);
200                        unset($error);
201                }
202
203                if ( $wp_error->get_error_code() ) {
204                        $errors = '';
205                        $messages = '';
206                        foreach ( $wp_error->get_error_codes() as $code ) {
207                                $severity = $wp_error->get_error_data($code);
208                                foreach ( $wp_error->get_error_messages($code) as $error ) {
209                                        if ( 'message' == $severity )
210                                                $messages .= '  ' . $error . "<br />\n";
211                                        else
212                                                $errors .= '    ' . $error . "<br />\n";
213                                }
214                        }
215                        if ( !empty($errors) )
216                                echo '<div id="login_error">' . apply_filters('login_errors', $errors) . "</div>\n";
217                        if ( !empty($messages) )
218                                echo '<p class="message">' . apply_filters('login_messages', $messages) . "</p>\n";
219                }
220        }
221       
222        /**
223         * Outputs the footer for the login page.
224         *
225         * @param string $input_id Which input to auto-focus
226         */
227        function _output_footer( $input_id = '' ) {
228                echo "</div>\n";
229
230                if ( !empty($input_id) ) {
231        ?>
232<script type="text/javascript">
233try{document.getElementById('<?php echo $input_id; ?>').focus();}catch(e){}
234if(typeof wpOnload=='function')wpOnload();
235</script>
236<?php
237        }
238?>
239<p id="backtoblog"><a href="<?php bloginfo('url'); ?>/" title="<?php _e('Are you lost?') ?>"><?php printf(__('&larr; Back to %s'), get_bloginfo('title', 'display' )); ?></a></p>
240<?php do_action('login_footer'); ?>
241</body>
242</html>
243        <?php
244        }
245
246        /**
247         * Shakes the entire page for the user to see there was an error.
248         */
249        function _output_page_shake_js() {
250                global $is_iphone;
251                if ( $is_iphone )
252                        return;
253        ?>
254<script type="text/javascript">
255addLoadEvent = function(func){if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
256function s(id,pos){g(id).left=pos+'px';}
257function g(id){return document.getElementById(id).style;}
258function shake(id,a,d){c=a.shift();s(id,c);if(a.length>0){setTimeout(function(){shake(id,a,d);},d);}else{try{g(id).position='static';wp_attempt_focus();}catch(e){}}}
259addLoadEvent(function(){ var p=new Array(15,30,15,0,-15,-30,-15,0);p=p.concat(p.concat(p));var i=document.forms[0].id;g(i).position='relative';shake(i,p,20);});
260</script>
261        <?php
262        }
263}
264
265class WP_Login_Logout extends WP_Login_Base {
266        /**
267         * Handles user logout.
268         */
269        function process() {
270                check_admin_referer('log-out');
271                wp_logout();
272
273                $this->_do_safe_redirect( 'wp-login.php?loggedout=true' );
274                exit();
275        }
276}
277
278class WP_Login_LostPassword extends WP_Login_Base {
279        /**
280         * Retrieves user password.
281         *
282         * @uses $wpdb WordPress Database object
283         *
284         * @return bool|WP_Error True: when finish. WP_Error on error
285         */
286        function _retrieve_password() {
287                global $wpdb, $current_site;
288
289                $errors = new WP_Error();
290
291                if ( empty( $_POST['user_login'] ) && empty( $_POST['user_email'] ) )
292                        $errors->add('empty_username', __('<strong>ERROR</strong>: Enter a username or e-mail address.'));
293
294                if ( strpos($_POST['user_login'], '@') ) {
295                        $user_data = get_user_by_email(trim($_POST['user_login']));
296                        if ( empty($user_data) )
297                                $errors->add('invalid_email', __('<strong>ERROR</strong>: There is no user registered with that email address.'));
298                } else {
299                        $login = trim($_POST['user_login']);
300                        $user_data = get_userdatabylogin($login);
301                }
302
303                do_action('lostpassword_post');
304
305                if ( $errors->get_error_code() )
306                        return $errors;
307
308                if ( !$user_data ) {
309                        $errors->add('invalidcombo', __('<strong>ERROR</strong>: Invalid username or e-mail.'));
310                        return $errors;
311                }
312
313                // redefining user_login ensures we return the right case in the email
314                $user_login = $user_data->user_login;
315                $user_email = $user_data->user_email;
316
317                do_action('retreive_password', $user_login);  // Misspelled and deprecated
318                do_action('retrieve_password', $user_login);
319
320                $allow = apply_filters('allow_password_reset', true, $user_data->ID);
321
322                if ( ! $allow )
323                        return new WP_Error('no_password_reset', __('Password reset is not allowed for this user'));
324
325                if ( is_wp_error($allow) )
326                        return $allow;
327
328                $key = $wpdb->get_var($wpdb->prepare("SELECT user_activation_key FROM $wpdb->users WHERE user_login = %s", $user_login));
329                if ( empty($key) ) {
330                        // Generate something random for a key...
331                        $key = wp_generate_password(20, false);
332                        do_action('retrieve_password_key', $user_login, $key);
333                        // Now insert the new md5 key into the db
334                        $wpdb->update($wpdb->users, array('user_activation_key' => $key), array('user_login' => $user_login));
335                }
336
337                $this->_retrieve_password_email( $user_login, $user_email, $key );
338
339                return true;
340        }
341
342        /**
343         * Sends out the requested password retrieval email.
344         *
345         * @param string $user_login The user login
346         * @param string $user_email Email address to send to
347         * @param string $key Hash to include within the link
348         */
349        function _retrieve_password_email( $user_login, $user_email, $key ) {
350                $message = __('Someone requested that the password be reset for the following account:') . "\r\n\r\n";
351                $message .= network_site_url() . "\r\n\r\n";
352                $message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n";
353                $message .= __('If this was a mistake, just ignore this email and nothing will happen.') . "\r\n\r\n";
354                $message .= __('To reset your password, visit the following address:') . "\r\n\r\n";
355                $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'login') . ">\r\n";
356
357                if ( is_multisite() )
358                        $blogname = $GLOBALS['current_site']->site_name;
359                else
360                        // The blogname option is escaped with esc_html on the way into the database in sanitize_option
361                        // we want to reverse this for the plain text arena of emails.
362                        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
363
364                $title = sprintf( __('[%s] Password Reset'), $blogname );
365
366                $title = apply_filters('retrieve_password_title', $title);
367                $message = apply_filters('retrieve_password_message', $message, $key);
368
369                if ( $message && !wp_mail($user_email, $title, $message) )
370                        wp_die( __('The e-mail could not be sent.') . "<br />\n" . __('Possible reason: your host may have disabled the mail() function...') );
371        }
372
373        /**
374         * Processes the password retrieval request.
375         *
376         * @return WP_Error
377         */
378        function process() {
379                $errors = new WP_Error();
380
381                if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
382                        $errors = $this->_retrieve_password();
383                        if ( !is_wp_error($errors) ) {
384                                $this->_do_safe_redirect( 'wp-login.php?checkemail=confirm' );
385                                exit();
386                        }
387                }
388
389                if ( isset($_GET['error']) && 'invalidkey' == $_GET['error'] ) $errors->add('invalidkey', __('Sorry, that key does not appear to be valid.'));
390
391                do_action('lost_password');
392
393                return $errors;
394        }
395
396        /**
397         * Renders the link retrieval form.
398         *
399         * @param WP_Error $errors
400         */
401        function render( $errors ) {
402                $redirect_to = apply_filters( 'lostpassword_redirect', !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '' );
403
404                $user_login = isset($_POST['user_login']) ? stripslashes($_POST['user_login']) : '';
405
406                $this->_output( $user_login, $errors, $redirect_to );
407        }
408       
409
410        /**
411         * Outputs the password retrieval form.
412         *
413         * @param string $user_login User name
414         * @param WP_Error $errors Errors, if any.
415         * @param $redirect_to URL to redirect to.
416         */
417        function _output( $user_login, $errors, $redirect_to ) {
418                $this->_output_header(__('Lost Password'), '<p class="message">' . __('Please enter your username or email address. You will receive a link to create a new password via email.') . '</p>', $errors);
419?>
420<form name="lostpasswordform" id="lostpasswordform" action="<?php echo site_url('wp-login.php?action=lostpassword', 'login_post') ?>" method="post">
421        <p>
422                <label><?php _e('Username or E-mail:') ?><br />
423                <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr($user_login); ?>" size="20" tabindex="10" /></label>
424        </p>
425<?php do_action('lostpassword_form'); ?>
426        <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
427        <p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button-primary" value="<?php esc_attr_e('Get New Password'); ?>" tabindex="100" /></p>
428</form>
429
430<p id="nav">
431<a href="<?php echo site_url('wp-login.php', 'login') ?>"><?php _e('Log in') ?></a>
432<?php if (get_option('users_can_register')) : ?>
433 | <a href="<?php echo site_url('wp-login.php?action=register', 'login') ?>"><?php _e('Register') ?></a>
434<?php endif; ?>
435</p>
436
437<?php
438                $this->_output_footer('user_login');
439        }
440}
441
442class WP_Login_Login extends WP_Login_Base {
443        var $_redirect_to = '';
444
445        /**
446         * Redirects the user after a successful login.
447         *
448         * @param WP_User $user
449         * @param string $redirect_to
450         */
451        function _redirect_after_login( $user, $redirect_to ) {
452                // If the user doesn't belong to a blog, send them to user admin. If the user can't edit posts, send them to their profile.
453                if ( is_multisite() && !get_active_blog_for_user($user->id) )
454                        $redirect_to = user_admin_url();
455                elseif ( !is_multisite() && !$user->has_cap('read') )
456                        $redirect_to = user_admin_url();
457                elseif ( !$user->has_cap('edit_posts') && ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' || $redirect_to == admin_url() ) )
458                        $redirect_to = admin_url('profile.php');
459
460                wp_safe_redirect($redirect_to);
461        }
462       
463        /**
464         * @return boolean
465         */
466        function _is_interim_login() {
467                return isset($_REQUEST['interim-login']);
468        }
469
470        /**
471         * Processes the login request.
472         *
473         * @return WP_Error
474         */
475        function process() {
476                $errors = new WP_Error();
477
478                $secure_cookie = '';
479                $interim_login = $this->_is_interim_login();
480
481                // If the user wants ssl but the session is not ssl, force a secure cookie.
482                if ( !empty($_POST['log']) && !force_ssl_admin() ) {
483                        $user_name = sanitize_user($_POST['log']);
484                        if ( $user = get_userdatabylogin($user_name) ) {
485                                if ( get_user_option('use_ssl', $user->ID) ) {
486                                        $secure_cookie = true;
487                                        force_ssl_admin(true);
488                                }
489                        }
490                }
491
492                if ( isset( $_REQUEST['redirect_to'] ) ) {
493                        $redirect_to = $_REQUEST['redirect_to'];
494                        // Redirect to https if user wants ssl
495                        if ( $secure_cookie && false !== strpos($redirect_to, 'wp-admin') )
496                                $redirect_to = preg_replace('|^http://|', 'https://', $redirect_to);
497                } else {
498                        $redirect_to = admin_url();
499                }
500
501                $reauth = empty($_REQUEST['reauth']) ? false : true;
502
503                // If the user was redirected to a secure login form from a non-secure admin page, and secure login is required but secure admin is not, then don't use a secure
504                // cookie and redirect back to the referring non-secure admin page.  This allows logins to always be POSTed over SSL while allowing the user to choose visiting
505                // the admin via http or https.
506                if ( !$secure_cookie && is_ssl() && force_ssl_login() && !force_ssl_admin() && ( 0 !== strpos($redirect_to, 'https') ) && ( 0 === strpos($redirect_to, 'http') ) )
507                        $secure_cookie = false;
508
509                $user = wp_signon('', $secure_cookie);
510
511                $redirect_to = apply_filters('login_redirect', $redirect_to, isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '', $user);
512
513                if ( !is_wp_error($user) && !$reauth ) {
514                        if ( $interim_login ) {
515                                $this->_output_interim();
516                                exit();
517                        }
518                       
519                        $this->_redirect_after_login( $user, $redirect_to );
520                        exit();
521                }
522
523                $errors = $user;
524                // Clear errors if loggedout is set.
525                if ( !empty($_GET['loggedout']) || $reauth )
526                        $errors = new WP_Error();
527
528                // If cookies are disabled we can't log in even with a valid user+pass
529                if ( isset($_POST['testcookie']) && empty($_COOKIE[TEST_COOKIE]) )
530                        $errors->add('test_cookie', __("<strong>ERROR</strong>: Cookies are blocked or not supported by your browser. You must <a href='http://www.google.com/cookies.html'>enable cookies</a> to use WordPress."));
531
532                // Some parts of this script use the main login form to display a message
533                if      ( isset($_GET['loggedout']) && TRUE == $_GET['loggedout'] )
534                        $errors->add('loggedout', __('You are now logged out.'), 'message');
535                elseif  ( isset($_GET['registration']) && 'disabled' == $_GET['registration'] )
536                        $errors->add('registerdisabled', __('User registration is currently not allowed.'));
537                elseif  ( isset($_GET['checkemail']) && 'confirm' == $_GET['checkemail'] )
538                        $errors->add('confirm', __('Check your e-mail for the confirmation link.'), 'message');
539                elseif  ( isset($_GET['checkemail']) && 'newpass' == $_GET['checkemail'] )
540                        $errors->add('newpass', __('Check your e-mail for your new password.'), 'message');
541                elseif  ( isset($_GET['checkemail']) && 'registered' == $_GET['checkemail'] )
542                        $errors->add('registered', __('Registration complete. Please check your e-mail.'), 'message');
543                elseif  ( $interim_login )
544                        $errors->add('expired', __('Your session has expired. Please log-in again.'), 'message');
545
546                // Clear any stale cookies.
547                if ( $reauth )
548                        wp_clear_auth_cookie();
549
550                // Store for use in render().
551                $this->_redirect_to = $redirect_to;
552
553                return $errors;
554        }
555
556        /**
557         * Renders the login form.
558         *
559         * @param WP_Error $errors
560         */
561        function render( $errors ) {
562                $user_login = '';
563               
564                if ( isset($_POST['log']) )
565                        $user_login = ( 'incorrect_password' == $errors->get_error_code() || 'empty_password' == $errors->get_error_code() ) ? esc_attr(stripslashes($_POST['log'])) : '';
566
567                $rememberme = ! empty( $_POST['rememberme'] );
568
569                $interim_login = $this->_is_interim_login();
570
571                $this->_output( $user_login, $rememberme, $interim_login, $this->_redirect_to, $errors);
572        }
573       
574        /**
575         *
576         */
577        function _output_interim() {
578                $message = '<p class="message">' . __('You have logged in successfully.') . '</p>';
579                $this->_output_header( '', $message ); ?>
580<script type="text/javascript">setTimeout( function(){window.close()}, 8000);</script>
581<p class="alignright">
582<input type="button" class="button-primary" value="<?php esc_attr_e('Close'); ?>" onclick="window.close()" /></p>
583</div></body></html>
584<?php
585        }
586       
587        /**
588         * Renders the login form.
589         *
590         * @param string $user_login User name
591         * @param $rememberme
592         * @param $interim_login
593         * @param string $redirect_to URL to redirect to.
594         * @param WP_Error $errors Errors, if any.
595         */
596        function _output( $user_login, $rememberme, $interim_login, $redirect_to, $errors ) {
597                $this->_output_header(__('Log In'), '', $errors);
598?>
599
600<form name="loginform" id="loginform" action="<?php echo site_url('wp-login.php', 'login_post') ?>" method="post">
601        <p>
602                <label><?php _e('Username') ?><br />
603                <input type="text" name="log" id="user_login" class="input" value="<?php echo esc_attr($user_login); ?>" size="20" tabindex="10" /></label>
604        </p>
605        <p>
606                <label><?php _e('Password') ?><br />
607                <input type="password" name="pwd" id="user_pass" class="input" value="" size="20" tabindex="20" /></label>
608        </p>
609<?php do_action('login_form'); ?>
610        <p class="forgetmenot"><label><input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="90"<?php checked( $rememberme ); ?> /> <?php esc_attr_e('Remember Me'); ?></label></p>
611        <p class="submit">
612                <input type="submit" name="wp-submit" id="wp-submit" class="button-primary" value="<?php esc_attr_e('Log In'); ?>" tabindex="100" />
613<?php   if ( $interim_login ) { ?>
614                <input type="hidden" name="interim-login" value="1" />
615<?php   } else { ?>
616                <input type="hidden" name="redirect_to" value="<?php echo esc_attr($redirect_to); ?>" />
617<?php   } ?>
618                <input type="hidden" name="testcookie" value="1" />
619        </p>
620</form>
621
622<?php if ( !$interim_login ) { ?>
623<p id="nav">
624<?php if ( isset($_GET['checkemail']) && in_array( $_GET['checkemail'], array('confirm', 'newpass') ) ) : ?>
625<?php elseif ( get_option('users_can_register') ) : ?>
626<a href="<?php echo site_url('wp-login.php?action=register', 'login') ?>"><?php _e('Register') ?></a> |
627<a href="<?php echo site_url('wp-login.php?action=lostpassword', 'login') ?>" title="<?php _e('Password Lost and Found') ?>"><?php _e('Lost your password?') ?></a>
628<?php else : ?>
629<a href="<?php echo site_url('wp-login.php?action=lostpassword', 'login') ?>" title="<?php _e('Password Lost and Found') ?>"><?php _e('Lost your password?') ?></a>
630<?php endif; ?>
631</p>
632</div>
633<p id="backtoblog"><a href="<?php bloginfo('url'); ?>/" title="<?php _e('Are you lost?') ?>"><?php printf(__('&larr; Back to %s'), get_bloginfo('title', 'display' )); ?></a></p>
634<?php } else { ?>
635</div>
636<?php } ?>
637
638<script type="text/javascript">
639function wp_attempt_focus(){
640setTimeout( function(){ try{
641<?php if ( $user_login || $interim_login ) { ?>
642d = document.getElementById('user_pass');
643d.value = '';
644<?php } else { ?>
645d = document.getElementById('user_login');
646<?php if ( 'invalid_username' == $errors->get_error_code() ) { ?>
647if( d.value != '' )
648d.value = '';
649<?php
650}
651}?>
652d.focus();
653d.select();
654} catch(e){}
655}, 200);
656}
657
658<?php if ( !$error ) { ?>
659wp_attempt_focus();
660<?php } ?>
661if(typeof wpOnload=='function')wpOnload();
662</script>
663<?php do_action( 'login_footer' ); ?>
664</body>
665</html>
666<?php
667        }
668}
669
670class WP_Login_Register extends WP_Login_Base {
671        /**
672         * Handles registering a new user.
673         *
674         * @param string $user_login User's username for logging in
675         * @param string $user_email User's email address to send password and add
676         * @return int|WP_Error Either user's ID or error on failure.
677         */
678        function _register_new_user( $user_login, $user_email ) {
679                $errors = new WP_Error();
680
681                $sanitized_user_login = sanitize_user( $user_login );
682                $user_email = apply_filters( 'user_registration_email', $user_email );
683
684                // Check the username
685                if ( $sanitized_user_login == '' ) {
686                        $errors->add( 'empty_username', __( '<strong>ERROR</strong>: Please enter a username.' ) );
687                } elseif ( ! validate_username( $user_login ) ) {
688                        $errors->add( 'invalid_username', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
689                        $sanitized_user_login = '';
690                } elseif ( username_exists( $sanitized_user_login ) ) {
691                        $errors->add( 'username_exists', __( '<strong>ERROR</strong>: This username is already registered, please choose another one.' ) );
692                }
693
694                // Check the e-mail address
695                if ( $user_email == '' ) {
696                        $errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please type your e-mail address.' ) );
697                } elseif ( ! is_email( $user_email ) ) {
698                        $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.' ) );
699                        $user_email = '';
700                } elseif ( email_exists( $user_email ) ) {
701                        $errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ) );
702                }
703
704                do_action( 'register_post', $sanitized_user_login, $user_email, $errors );
705
706                $errors = apply_filters( 'registration_errors', $errors, $sanitized_user_login, $user_email );
707
708                if ( $errors->get_error_code() )
709                        return $errors;
710
711                $user_pass = wp_generate_password( 12, false);
712                $user_id = wp_create_user( $sanitized_user_login, $user_pass, $user_email );
713                if ( ! $user_id ) {
714                        $errors->add( 'registerfail', sprintf( __( '<strong>ERROR</strong>: Couldn&#8217;t register you... please contact the <a href="mailto:%s">webmaster</a> !' ), get_option( 'admin_email' ) ) );
715                        return $errors;
716                }
717
718                update_user_option( $user_id, 'default_password_nag', true, true ); //Set up the Password change nag.
719
720                wp_new_user_notification( $user_id, $user_pass );
721
722                return $user_id;
723        }
724
725        /**
726         * Processes the user registration request.
727         *
728         * @return WP_Error
729         */
730        function process() {
731                if ( is_multisite() ) {
732                        // Multisite uses wp-signup.php
733                        wp_redirect( apply_filters( 'wp_signup_location', site_url('wp-signup.php') ) );
734                        exit;
735                }
736
737                if ( !get_option('users_can_register') ) {
738                        wp_redirect( site_url('wp-login.php?registration=disabled') );
739                        exit();
740                }
741
742                $errors = new WP_Error();
743
744                if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
745                        $user_login = $_POST['user_login'];
746                        $user_email = $_POST['user_email'];
747
748                        $errors = $this->_register_new_user( $user_login, $user_email );
749                        if ( !is_wp_error($errors) ) {
750                                $redirect_to = !empty( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : 'wp-login.php?checkemail=registered';
751                                wp_safe_redirect( $redirect_to );
752                                exit();
753                        }
754                }
755
756                return $errors;
757        }
758
759        /**
760         * Renders the registration form.
761         *
762         * @param WP_Error $errors
763         */
764        function render( $errors ) {
765                $user_login = '';
766                $user_email = '';
767
768                if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
769                        $user_login = $_POST['user_login'];
770                        $user_email = $_POST['user_email'];
771                }
772
773                $redirect_to = apply_filters( 'registration_redirect', !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '' );
774
775                $this->_output( $user_login, $user_email, $redirect_to, $errors );
776        }
777       
778
779        /**
780         * Outputs the registration form.
781         *
782         * @param string $user_login User name
783         * @param string $user_email User email
784         * @param string $redirect_to URL to redirect to after login.
785         * @param WP_Error $errors Errors, if any.
786         */
787        function _output( $user_login, $user_email, $redirect_to, $errors ) {
788                $this->_output_header(__('Registration Form'), '<p class="message register">' . __('Register For This Site') . '</p>', $errors);
789?>
790
791<form name="registerform" id="registerform" action="<?php echo site_url('wp-login.php?action=register', 'login_post') ?>" method="post">
792        <p>
793                <label><?php _e('Username') ?><br />
794                <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr(stripslashes($user_login)); ?>" size="20" tabindex="10" /></label>
795        </p>
796        <p>
797                <label><?php _e('E-mail') ?><br />
798                <input type="text" name="user_email" id="user_email" class="input" value="<?php echo esc_attr(stripslashes($user_email)); ?>" size="25" tabindex="20" /></label>
799        </p>
800<?php do_action('register_form'); ?>
801        <p id="reg_passmail"><?php _e('A password will be e-mailed to you.') ?></p>
802        <br class="clear" />
803        <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
804        <p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button-primary" value="<?php esc_attr_e('Register'); ?>" tabindex="100" /></p>
805</form>
806
807<p id="nav">
808<a href="<?php echo site_url('wp-login.php', 'login') ?>"><?php _e('Log in') ?></a> |
809<a href="<?php echo site_url('wp-login.php?action=lostpassword', 'login') ?>" title="<?php _e('Password Lost and Found') ?>"><?php _e('Lost your password?') ?></a>
810</p>
811
812<?php
813                $this->_output_footer('user_login');
814        }
815}
816
817class WP_Login_ResetPass extends WP_Login_Base {
818        /**
819         * Retrieves a user row based on password reset key and login
820         *
821         * @uses $wpdb WordPress Database object
822         *
823         * @param string $key Hash to validate sending user's password
824         * @param string $login The user login
825         *
826         * @return object|WP_Error
827         */
828        function _check_password_reset_key($key, $login) {
829                global $wpdb;
830
831                $key = preg_replace('/[^a-z0-9]/i', '', $key);
832
833                if ( empty( $key ) || !is_string( $key ) )
834                        return new WP_Error('invalid_key', __('Invalid key'));
835
836                if ( empty($login) || !is_string($login) )
837                        return new WP_Error('invalid_key', __('Invalid key'));
838
839                $user = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->users WHERE user_activation_key = %s AND user_login = %s", $key, $login));
840
841                if ( empty( $user ) )
842                        return new WP_Error('invalid_key', __('Invalid key'));
843
844                return $user;
845        }
846
847        /**
848         * Handles resetting the user's password.
849         *
850         * @uses $wpdb WordPress Database object
851         *
852         * @param string $key Hash to validate sending user's password
853         */
854        function _reset_password($user, $new_pass) {
855                do_action('password_reset', $user, $new_pass);
856
857                wp_set_password($new_pass, $user->ID);
858
859                wp_password_change_notification($user);
860        }
861
862        /**
863         * Processes the reset password request.
864         *
865         * @return WP_Error
866         */
867        function process() {
868                $user = $this->_check_password_reset_key($_GET['key'], $_GET['login']);
869                if ( is_wp_error($user) ) {
870                        wp_redirect( site_url('wp-login.php?action=lostpassword&error=invalidkey') );
871                        exit;
872                }
873
874                $errors = '';
875
876                if ( isset($_POST['pass1']) && $_POST['pass1'] != $_POST['pass2'] ) {
877                        $errors = new WP_Error('password_reset_mismatch', __('The passwords do not match.'));
878                } elseif ( isset($_POST['pass1']) && !empty($_POST['pass1']) ) {
879                        $this->_reset_password($user, $_POST['pass1']);
880                        $this->_output_completed();
881                        exit();
882                }
883
884                return $errors;
885        }
886
887        /**
888         * Renders the password change form.
889         *
890         * @param WP_Error $errors
891         */
892        function render( $errors ) {
893                wp_enqueue_script('utils');
894                wp_enqueue_script('user-profile');
895
896                $this->_output( $errors );
897        }
898       
899        /**
900         * Outputs the password change form.
901         *
902         * @param WP_Error $errors Errors, if any.
903         */
904        function _output( $errors ) {
905                $this->_output_header(__('Reset Password'), '<p class="message reset-pass">' . __('Enter your new password below.') . '</p>', $errors );
906?>
907<form name="resetpassform" id="resetpassform" action="<?php echo site_url('wp-login.php?action=resetpass&key=' . urlencode($_GET['key']) . '&login=' . urlencode($_GET['login']), 'login_post') ?>" method="post">
908        <input type="hidden" id="user_login" value="<?php echo esc_attr( $_GET['login'] ); ?>" autocomplete="off" />
909
910        <p>
911                <label><?php _e('New password') ?><br />
912                <input type="password" name="pass1" id="pass1" class="input" size="20" value="" autocomplete="off" /></label>
913        </p>
914        <p>
915                <label><?php _e('Confirm new password') ?><br />
916                <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" /></label>
917        </p>
918
919        <div id="pass-strength-result" class="hide-if-no-js"><?php _e('Strength indicator'); ?></div>
920        <p class="description indicator-hint"><?php _e('Hint: The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers and symbols like ! " ? $ % ^ &amp; ).'); ?></p>
921
922        <br class="clear" />
923        <p class="submit"><input type="submit" name="wp-submit" id="wp-submit" class="button-primary" value="<?php esc_attr_e('Reset Password'); ?>" tabindex="100" /></p>
924</form>
925
926<p id="nav">
927<a href="<?php echo site_url('wp-login.php', 'login') ?>"><?php _e('Log in') ?></a>
928<?php if (get_option('users_can_register')) : ?>
929 | <a href="<?php echo site_url('wp-login.php?action=register', 'login') ?>"><?php _e('Register') ?></a>
930<?php endif; ?>
931</p>
932
933<?php
934                $this->_output_footer('user_pass');
935        }
936
937        /**
938         * Outputs the password successfully changed message.
939         */
940        function _output_completed() {
941                $this->_output_header(__('Password Reset'), '<p class="message reset-pass">' . __('Your password has been reset.') . ' <a href="' . site_url('wp-login.php', 'login') . '">' . __('Log in') . '</a></p>');
942                $this->_output_footer();
943        }
944}
945?>