Source for file login.php
Documentation is available at login.php
* This is the login screen. It also handles actions related to loggin in and registering.
* This file is part of Quam Plures - {@link http://quamplures.net/}
* See also {@link https://launchpad.net/quam-plures}.
* @copyright (c) 2009 - 2011 by the Quam Plures developers - {@link http://quamplures.net/}
* @copyright (c)2003-2009 by Francois PLANQUE - {@link http://fplanque.net/}
* Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
* {@internal License choice
* - If you have received this file as part of a package, please find the license.txt file in
* the same folder or the closest folder above for complete license terms.
* - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
* then you must choose one of the following licenses before using the file:
* - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
* - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
* {@internal Open Source relicensing agreement:
* Daniel HAHLER grants Francois PLANQUE the right to license
* Daniel HAHLER's contributions to this file and the b2evolution project
* under any OSI approved OSS license (http://www.opensource.org/licenses/).
* Matt FOLLETT grants Francois PLANQUE the right to license
* Matt FOLLETT's contributions to this file and the b2evolution project
* under any OSI approved OSS license (http://www.opensource.org/licenses/).
* {@internal Below is a list of authors who have contributed to design/coding of this file: }}
* @author blueyed: Daniel HAHLER
* @author fplanque: Francois PLANQUE
* @author mfollett: Matt FOLLETT.
require_once dirname(__FILE__ ). '/../qp_config/_config.php';
require_once $inc_path. '_main.inc.php';
param( 'action', 'string', 'req_login' );
param( 'mode', 'string', '' );
param( 'login', 'string', '' );
// gets used by header_redirect();
// TODO: dh> problem here is that $ReqURI won't include the e.g. "ctrl" param in a POSTed form and therefor the user lands on the default admin page after logging in (again)
// fp> I think this will fix itself when we do another improvement: 303 redirect after each POST so that we never have an issue with people trying to reload a post
param( 'redirect_to', 'string', $ReqURI );
logout(); // logout $Session and set $current_User = NULL
// TODO: to give the user feedback through Messages, we would need to start a new $Session here and append $Messages to it.
case 'retrievepassword': // Send passwort change request by mail
$login_required = true; // Do not display "Without login.." link on the form
$ForgetfulUser = & $UserCache->get_by_login( $login );
// pretend that the email is sent for avoiding guessing user_login
$Messages->add( T_('If you correctly typed in your login, a link to change your password has been sent to your registered email address.' ), 'success' );
if( $demo_mode && ($ForgetfulUser->ID == 1
|| $ForgetfulUser->login == 'demouser'
|| $ForgetfulUser->login == 'demoblogger'
|| $ForgetfulUser->login == 'demospecial') )
$Messages->add( T_('You cannot reset this account in demo mode.'), 'error' );
if( empty( $ForgetfulUser->email ) )
$Messages->add( T_('You have no email address with your profile, therefore we cannot reset your password.')
. ' '. T_('Please try contacting the admin.'), 'error' );
$request_id = generate_random_key(22); // 22 to make it not too long for URL but unique/safe enough
$message = T_( 'Somebody (presumably you) has requested a password change for your account.' )
. T_('Login:'). " $login\n"
. T_('Link to change your password:')
. $srvc_url_sensitive. 'login.php?action=changepwd'
. '&sessID='. $Session->ID // used to detect cookie problems
. ' '. T_('For security reasons the link is only valid for your current session (by means of your session cookie).')
. T_('If it was not you that requested this password change, simply ignore this mail.');
if( ! send_mail( $ForgetfulUser->email, NULL, sprintf( T_('Password change request for %s'), $ForgetfulUser->login ), $message, $notify_from ) )
$Messages->add( T_('Sorry, the email with the link to reset your password could not be sent.')
. '<br />'. T_('Possible reason: the PHP mail() function may have been disabled on the server.'), 'error' );
$Session->set( 'core.changepwd.request_id', $request_id, 86400 * 2 ); // expires in two days (or when clicked)
$Session->dbsave(); // save immediately
$Messages->add( T_('If you correctly typed in your login, a link to change your password has been sent to your registered email address.' ), 'success' );
case 'changepwd': // Clicked "Change password request" link from a mail
param( 'reqID', 'string', '' );
param( 'sessID', 'integer', '' );
$ForgetfulUser = & $UserCache->get_by_login($login);
if( ! $ForgetfulUser || empty($reqID) )
{ // This was not requested
$Messages->add( T_('Invalid password change request! Please try again...'), 'error' );
$action = 'lostpassword';
$login_required = true; // Do not display "Without login.." link on the form
if( $sessID != $Session->ID )
{ // Another session ID than for requesting password change link used!
$Messages->add( T_('You have to use the same session (by means of your session cookie) as when you have requested the action. Please try again...'), 'error' );
$action = 'lostpassword';
$login_required = true; // Do not display "Without login.." link on the form
// Validate provided reqID against the one stored in the user's session
if( $Session->get( 'core.changepwd.request_id' ) != $reqID )
$Messages->add( T_('Invalid password change request! Please try again...'), 'error' );
$action = 'lostpassword';
$login_required = true; // Do not display "Without login.." link on the form
$Session->set_user_ID( $ForgetfulUser->ID );
// Add Message to change the password:
$Messages->add( T_( 'Please change your password to something you remember now.' ), 'success' );
// Note: the 'core.changepwd.request_id' Session setting gets removed in b2users.php
// Redirect to the user's profile in the "users" controller:
// TODO: This will probably fail if the user has no admin-access permission! Redirect to profile page in blog instead!?
// redirect Will save $Messages into Session:
case 'validatemail': // Clicked "Validate email" link from a mail
param( 'reqID', 'string', '' );
param( 'sessID', 'integer', '' );
{ // Already validated, e.g. clicked on an obsolete email link:
$Messages->add( T_('Your account has already been validated.'), 'note' );
// no break: cleanup & redirect below
{ // This was not requested
$Messages->add( T_('Invalid email address validation request!'), 'error' );
$action = 'req_validatemail';
// Check valid session (format only, meant as help for the user):
if( $sessID != $Session->ID )
{ // Another session ID than for requesting account validation link used!
$Messages->add( T_('You have to use the same session (by means of your session cookie) as when you have requested the action. Please try again...'), 'error' );
$action = 'req_validatemail';
// Validate provided reqID against the one stored in the user's session
$request_ids = $Session->get( 'core.validatemail.request_ids' );
&& ! ( isset ($current_User) && $current_User->group_ID == 1 && $reqID == 1 /* admin users can validate themselves by a button click */ ) )
$Messages->add( T_('Invalid email address validation request!'), 'error' );
$action = 'req_validatemail';
$login_required = true; // Do not display "Without login.." link on the form
{ // this can happen, if a new user registers and clicks on the "validate by email" link, without logging in first
// Note: we reuse $reqID and $sessID in the form to come back here.
$Messages->add( T_('Please login to validate your account.'), 'error' );
$current_User->set( 'validated', 1 );
$current_User->dbupdate();
$Messages->add( T_( 'Your email address has been validated.' ), 'success' );
$redirect_to = $Session->get( 'core.validatemail.redirect_to' );
if( empty($redirect_to) && $current_User->check_perm('admin') )
{ // User can access backoffice
$redirect_to = $admin_url;
$Session->delete('core.validatemail.request_ids');
$Session->delete('core.validatemail.redirect_to');
// redirect Will save $Messages into Session:
} // switch( $action ) (1st)
/* For actions that other delegate to from the switch above: */
case 'req_validatemail': // Send email validation link by mail (initial form and action)
$Messages->add( T_('You have to be logged in to request an account validation link.'), 'error' );
if( $current_User->validated || ! $Settings->get('newusers_mustvalidate') )
{ // validating emails is not activated/necessary (check this after login, so it gets not "announced")
param( 'req_validatemail_submit', 'integer', 0 ); // has the form been submitted
param( 'email', 'string', $current_User->email ); // the email address is editable
if( $req_validatemail_submit )
{ // Form has been submitted
// Call plugin event to allow catching input in general and validating own things from DisplayRegisterFormFieldset event
$Plugins->trigger_event( 'ValidateAccountFormSent' );
if( $Messages->count('error') )
$current_User->set_email( $email );
if( $current_User->dbupdate() )
$Messages->add( T_('Your profile has been updated.'), 'note' );
if( $current_User->send_validate_email($redirect_to) )
$Messages->add( sprintf( /* TRANS: %s gets replaced by the user's email address */ T_('An email has been sent to your email address (%s). Please click on the link therein to validate your account.'), $current_User->dget('email') ), 'success' );
$Messages->add( T_('Sorry, the email with the link to validate and activate your password could not be sent.')
. '<br />'. T_('Possible reason: the PHP mail() function may have been disabled on the server.'), 'error' );
{ // Form not yet submitted:
// Add a note, if we have already sent validation links:
$request_ids = $Session->get( 'core.validatemail.request_ids' );
$Messages->add( sprintf( T_('We have already sent you %d email(s) with a validation link.'), count($request_ids) ), 'note' );
if( empty($current_User->email) )
{ // add (error) note to be displayed in the form
$Messages->add( T_('You have no email address with your profile, therefore we cannot validate it. Please give your email address below.'), 'error' );
{ // Do not check this if the form was included inside of _main.inc
if( $ReqHost. $ReqPath != $srvc_url_sensitive. 'login.php' )
$Messages->add( sprintf( T_('WARNING: you are trying to log in on <strong>%s</strong> but we expect you to log in on <strong>%s</strong>. If this is due to an automatic redirect, this will prevent you from successfully loging in. You must either fix your webserver configuration, or your %s configuration in order for these two URLs to match.'), $ReqHost. $ReqPath, $srvc_url_sensitive. 'login.php', $app_name ), 'error' );
// Test if cookie_domain matches the URL where we want to redirect to:
// Make it relative to the form's target, in case it has been set absolute (and can be made relative).
// Just in case it gets sent absolute. This should not trigger this warning then..!
$cookie_domain_match = false;
if( $redirect_to[0] == '/' )
$cookie_domain_match = true;
$parsed_redirect_to = @parse_url($redirect_to);
if( isset ($parsed_redirect_to['host']) )
if( $cookie_domain == $parsed_redirect_to['host'] )
$cookie_domain_match = true;
elseif( $cookie_domain[0] == '.'
&& substr($cookie_domain,1) == substr($parsed_redirect_to['host'], 1- strlen($cookie_domain)) )
{ // cookie domain includes subdomains and matches the last part of where we want to redirect to
$cookie_domain_match = true;
$cookie_domain_match = preg_match( '#^https?://[a-z\-.]*'. str_replace( '.', '\.', $cookie_domain ). '#i', $redirect_to );
if( ! $cookie_domain_match )
$Messages->add( sprintf( T_('WARNING: you are trying to log in to <strong>%s</strong> but your cookie domain is <strong>%s</strong>. You will not be able to successfully log in to the requested domain until you fix your cookie domain in your %s configuration.'), $redirect_to, $cookie_domain, $app_name ), 'error' );
if( preg_match( '#/login.php([&?].*)?$#', $redirect_to ) )
{ // avoid "endless loops"
$redirect_to = $admin_url;
// Remove login and pwd parameters from URL, so that they do not trigger the login screen again:
$redirect_to = preg_replace( '~(?<=\?|&) (login|pwd) = [^&]+ ~x', '', $redirect_to );
$Debuglog->add( 'redirect_to: '. $redirect_to );
// Display retrieval form:
require $admintemplates_path. 'login/_lostpass_form.main.php';
// Send email validation link by mail (initial form and action)
// Display validation form:
require $admintemplates_path. 'login/_validate_form.main.php';
require $admintemplates_path. 'login/_login_form.main.php';
|