/** * Display login form * * @param array params */ function display_login_form($params) { global $Settings, $Plugins, $Session, $Blog, $blog, $dummy_fields; global $secure_htsrv_url, $admin_url, $baseurl, $ReqHost; $params = array_merge(array('form_action' => '', 'form_name' => 'login_form', 'form_layout' => '', 'form_class' => 'bComment', 'source' => 'inskin login form', 'inskin' => true, 'login_required' => true, 'validate_required' => NULL, 'redirect_to' => '', 'login' => '', 'action' => '', 'reqID' => '', 'sessID' => '', 'transmit_hashed_password' => false), $params); $inskin = $params['inskin']; $login = $params['login']; $redirect_to = $params['redirect_to']; $links = array(); if (empty($params['login_required']) && $params['action'] != 'req_validatemail' && strpos($redirect_to, $admin_url) !== 0 && strpos($ReqHost . $redirect_to, $admin_url) !== 0) { // No login required, allow to pass through // TODO: dh> validate redirect_to param?! // check if redirect_to url requires logged in user if (require_login($redirect_to, true)) { // logged in user require for redirect_to url if (!empty($blog)) { // blog is set if (empty($Blog)) { $BlogCache =& get_BlogCache(); $Blog = $BlogCache->get_by_ID($blog, false); } // set abort url to Blog url $abort_url = $Blog->gen_blogurl(); } else { // set abort login url to base url $abort_url = $baseurl; } } else { // logged in user isn't required for redirect_to url, set abort url to redirect_to $abort_url = $redirect_to; } $links[] = '<a href="' . htmlspecialchars(url_rel_to_same_host($abort_url, $ReqHost)) . '">' . T_('Abort login!') . '</a>'; } if (!$inskin && is_logged_in()) { // if we arrive here, but are logged in, provide an option to logout (e.g. during the email validation procedure) $links[] = get_user_logout_link(); } if (count($links)) { echo '<div style="float:right; margin: 0 1em">' . implode($links, ' · ') . '</div> <div class="clear"></div>'; } $Form = new Form($params['form_action'], $params['form_name'], 'post', $params['form_layout']); $Form->begin_form($params['form_class']); $Form->add_crumb('loginform'); $source = param('source', 'string', $params['source'] . ' login form'); $Form->hidden('source', $source); $Form->hidden('redirect_to', $redirect_to); if ($inskin) { // inskin login form $Form->hidden('inskin', true); $separator = '<br />'; } else { // standard login form $Form->hidden('validate_required', $params['validate_required']); if (isset($params['action'], $params['reqID'], $params['sessID']) && $params['action'] == 'validatemail') { // the user clicked the link from the "validate your account" email, but has not been logged in; pass on the relevant data: $Form->hidden('action', 'validatemail'); $Form->hidden('reqID', $params['reqID']); $Form->hidden('sessID', $params['sessID']); } $separator = ''; } // check if should transmit hashed password if ($params['transmit_hashed_password']) { // used by JS-password encryption/hashing: $pwd_salt = $Session->get('core.pwd_salt'); if (empty($pwd_salt)) { // Do not regenerate if already set because we want to reuse the previous salt on login screen reloads // fp> Question: the comment implies that the salt is reset even on failed login attemps. Why that? I would only have reset it on successful login. Do experts recommend it this way? // but if you kill the session you get a new salt anyway, so it's no big deal. // At that point, why not reset the salt at every reload? (it may be good to keep it, but I think the reason should be documented here) $pwd_salt = generate_random_key(64); $Session->set('core.pwd_salt', $pwd_salt, 86400); $Session->dbsave(); // save now, in case there's an error later, and not saving it would prevent the user from logging in. } $Form->hidden('pwd_salt', $pwd_salt); $Form->hidden('pwd_hashed', ''); // gets filled by JS } $Form->begin_field(); $Form->text_input($dummy_fields['login'], $params['login'], 18, T_('Login'), $separator . T_('Enter your username (or email address).'), array('maxlength' => 255, 'class' => 'input_text', 'required' => true)); $Form->end_field(); if ($inskin) { $lost_password_url = regenerate_url('disp', 'disp=lostpassword'); } else { $lost_password_url = $secure_htsrv_url . 'login.php?action=lostpassword&redirect_to=' . rawurlencode(url_rel_to_same_host($redirect_to, $secure_htsrv_url)); } if (!empty($login)) { $lost_password_url .= '&' . $dummy_fields['login'] . '=' . rawurlencode($login); } $pwd_note = $pwd_note = '<a href="' . $lost_password_url . '">' . T_('Lost password ?') . '</a>'; $Form->begin_field(); $Form->password_input($dummy_fields['pwd'], '', 18, T_('Password'), array('note' => $pwd_note, 'maxlength' => 70, 'class' => 'input_text', 'required' => true)); $Form->end_field(); // Allow a plugin to add fields/payload $Plugins->trigger_event('DisplayLoginFormFieldset', array('Form' => &$Form)); // Submit button(s): $submit_buttons = array(array('name' => 'login_action[login]', 'value' => T_('Log in!'), 'class' => 'search', 'style' => 'font-size: 120%')); if (!$inskin && strpos($redirect_to, $admin_url) !== 0 && strpos($ReqHost . $redirect_to, $admin_url) !== 0 && !is_admin_page()) { // provide button to log straight into backoffice, if we would not go there anyway $submit_buttons[] = array('name' => 'login_action[redirect_to_backoffice]', 'value' => T_('Log into backoffice!'), 'class' => 'search'); } $Form->buttons_input($submit_buttons); if ($inskin) { $before_register_link = '<strong>'; $after_register_link = '</strong>'; $register_link_style = 'text-align:right; margin: 1em 0 1ex'; } else { echo '<div class="center notes" style="margin: 1em 0">' . T_('You will have to accept cookies in order to log in.') . '</div>'; // Passthrough REQUEST data (when login is required after having POSTed something) // (Exclusion of 'login_action', 'login', and 'action' has been removed. This should get handled via detection in Form (included_input_field_names), // and "action" is protected via crumbs) $Form->hiddens_by_key(remove_magic_quotes($_REQUEST)); $before_register_link = ''; $after_register_link = ''; $register_link_style = 'text-align:right'; } echo '<div class="login_actions" style="' . $register_link_style . '">'; echo get_user_register_link($before_register_link, $after_register_link, T_('No account yet? Register here') . ' »', '#', true, $redirect_to, $source); echo '</div>'; $Form->end_form(); echo '<script type="text/javascript">'; // Autoselect login text input or pwd input, if there\'s a login already: echo 'var login = document.getElementById("' . $dummy_fields['login'] . '"); if( login.value.length > 0 ) { // Focus on the password field: document.getElementById("' . $dummy_fields['pwd'] . '").focus(); } else { // Focus on the login field: login.focus(); }'; if ($params['transmit_hashed_password']) { // Hash the password onsubmit and clear the original pwd field // TODO: dh> it would be nice to disable the clicked/used submit button. That's how it has been when the submit was attached to the submit button(s) echo 'addEvent( document.getElementById("login_form"), "submit", function(){' . 'var form = document.getElementById("login_form");' . 'if( form.pwd_hashed && form.' . $dummy_fields['pwd'] . ' && form.pwd_salt && typeof hex_sha1 != "undefined" && typeof hex_md5 != "undefined" ) {' . 'form.pwd_hashed.value = hex_sha1( hex_md5(form.' . $dummy_fields['pwd'] . '.value) + form.pwd_salt.value ); form.' . $dummy_fields['pwd'] . '.value = "padding_padding_padding_padding_padding_padding_hashed_' . $Session->ID . '";' . '} return true; }, false );'; } echo '</script>'; }
/** * Display the widget! * * @param array MUST contain at least the basic display params */ function display($params) { if (!is_logged_in()) { // Only logged in users can see this tools panel return false; } $this->init_display($params); // just in case it hasn't been done before $this->disp_params['item_start'] .= '<strong>'; $this->disp_params['item_end'] = '</strong>' . $this->disp_params['item_end']; $tools_links = ''; if ($this->get_param('user_postnew_link_show')) { // Write new post - disp=edit $tools_links .= get_item_new_link($this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_postnew_link']); } if ($this->get_param('user_messaging_link_show')) { // Messaging - disp=threads $tools_links .= get_user_messaging_link($this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_messaging_link'], $this->disp_params['user_messaging_link'], $this->disp_params['show_badge']); } if ($this->get_param('user_contacts_link_show')) { // Contacts - disp=contacts $tools_links .= get_user_contacts_link($this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_contacts_link'], $this->disp_params['user_contacts_link']); } if ($this->get_param('user_view_link_show')) { // See profile - disp=user $tools_links .= get_user_tab_link('user', $this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_view_link'], $this->disp_params['user_view_link']); } if ($this->get_param('user_profile_link_show')) { // Edit profile - disp=profile $tools_links .= get_user_profile_link($this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_profile_link'], $this->disp_params['user_profile_link']); } if ($this->get_param('user_picture_link_show')) { // Edit picture - disp=avatar $tools_links .= get_user_tab_link('avatar', $this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_picture_link'], $this->disp_params['user_picture_link']); } if ($this->get_param('user_password_link_show')) { // Edit password - disp=pwdchange $tools_links .= get_user_tab_link('pwdchange', $this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_password_link'], $this->disp_params['user_password_link']); } if ($this->get_param('user_preferences_link_show')) { // Edit preferences - disp=userprefs $tools_links .= get_user_tab_link('userprefs', $this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_preferences_link'], $this->disp_params['user_preferences_link']); } if ($this->get_param('user_subs_link_show')) { // Edit notifications - disp=subs $tools_links .= get_user_subs_link($this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_subs_link'], $this->disp_params['user_subs_link']); } if ($this->get_param('user_admin_link_show')) { // Admin $tools_links .= get_user_admin_link($this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_admin_link']); } if ($this->get_param('user_logout_link_show')) { // Logout $tools_links .= get_user_logout_link($this->disp_params['item_start'], $this->disp_params['item_end'], $this->disp_params['user_logout_link']); } if (empty($tools_links)) { // No available links to display return false; } // User tools: echo $this->disp_params['block_start']; if (!empty($this->disp_params['title'])) { // Display title echo $this->disp_params['block_title_start']; echo $this->disp_params['title']; echo $this->disp_params['block_title_end']; } echo $this->disp_params['list_start']; echo $tools_links; if (isset($this->BlockCache)) { // Do NOT cache because some of these links are using a redirect_to param, which makes it page dependent. // Note: also beware of the source param. // so this will be cached by the PageCache; there is no added benefit to cache it in the BlockCache // (which could have been shared between several pages): $this->BlockCache->abort_collect(); } echo $this->disp_params['list_end']; echo $this->disp_params['block_end']; }
return true; }, false ); <?php } ?> </script> <div class="login_actions" style="text-align:right"> <?php $links = array(); if ($link = get_user_register_link('', '', '', '#', true, $redirect_to)) { $links[] = $link; } if (empty($login_required) && $action != 'req_validatemail' && strpos($redirect_to, $admin_url) !== 0 && strpos($ReqHost . $redirect_to, $admin_url) !== 0) { // No login required, allow to pass through // TODO: dh> validate redirect_to param?! $links[] = '<a href="' . htmlspecialchars(url_rel_to_same_host($redirect_to, $ReqHost)) . '">' . T_('Abort login!') . '</a>'; } if (is_logged_in()) { // if we arrive here, but are logged in, provide an option to logout (e.g. during the email // validation procedure) $links[] = get_user_logout_link(); } echo implode(' · ', $links); ?> </div> <?php require dirname(__FILE__) . '/_html_footer.inc.php';
/** * Template tag: Output a link to logout */ function user_logout_link($before = '', $after = '', $link_text = '', $link_title = '#', $params = array()) { echo get_user_logout_link($before, $after, $link_text, $link_title, $params); }
/** * Display login form * * @param array params */ function display_login_form($params) { global $Settings, $Plugins, $Session, $Blog, $blog, $dummy_fields; global $secure_htsrv_url, $admin_url, $baseurl, $ReqHost, $redirect_to; $params = array_merge(array('form_before' => '', 'form_after' => '', 'form_action' => '', 'form_name' => 'login_form', 'form_title' => '', 'form_layout' => '', 'form_class' => 'bComment', 'source' => 'inskin login form', 'inskin' => true, 'inskin_urls' => true, 'login_required' => true, 'validate_required' => NULL, 'redirect_to' => '', 'return_to' => '', 'login' => '', 'action' => '', 'reqID' => '', 'sessID' => '', 'transmit_hashed_password' => false, 'display_abort_link' => true, 'abort_link_position' => 'above_form', 'abort_link_text' => T_('Abort login!'), 'display_reg_link' => false), $params); $inskin = $params['inskin']; $login = $params['login']; $redirect_to = $params['redirect_to']; $return_to = $params['return_to']; $links = array(); $form_links = array(); if ($params['display_abort_link'] && empty($params['login_required']) && $params['action'] != 'req_validatemail' && strpos($return_to, $admin_url) !== 0 && strpos($ReqHost . $return_to, $admin_url) !== 0) { // No login required, allow to pass through // TODO: dh> validate return_to param?! // check if return_to url requires logged in user if (empty($return_to) || require_login($return_to, true)) { // logged in user require for return_to url if (!empty($blog)) { // blog is set if (empty($Blog)) { $BlogCache =& get_BlogCache(); $Blog = $BlogCache->get_by_ID($blog, false); } // set abort url to Blog url $abort_url = $Blog->gen_blogurl(); } else { // set abort login url to base url $abort_url = $baseurl; } } else { // logged in user isn't required for return_to url, set abort url to return_to $abort_url = $return_to; } // Gets displayed as link to the location on the login form if no login is required $abort_link = '<a href="' . htmlspecialchars(url_rel_to_same_host($abort_url, $ReqHost)) . '">' . $params['abort_link_text'] . '</a>'; if ($params['abort_link_position'] == 'above_form') { // Display an abort link under login form $links[] = $abort_link; } elseif ($params['abort_link_position'] == 'form_title') { // Display an abort link in form title block $form_links[] = $abort_link; } } if (!$inskin && is_logged_in()) { // if we arrive here, but are logged in, provide an option to logout (e.g. during the email validation procedure) $links[] = get_user_logout_link(); } if (count($links)) { echo '<div class="evo_form__login_links">' . '<div class="floatright">' . implode($links, ' · ') . '</div>' . '<div class="clear"></div>' . '</div>'; } $form_links = count($form_links) ? '<span class="pull-right">' . implode(' ', $form_links) . '</span>' : ''; echo str_replace('$form_links$', $form_links, $params['form_before']); $Form = new Form($params['form_action'], $params['form_name'], 'post', $params['form_layout']); $Form->begin_form($params['form_class']); $Form->add_crumb('loginform'); $source = param('source', 'string', $params['source'] . ' login form'); $Form->hidden('source', $source); $Form->hidden('redirect_to', $redirect_to); $Form->hidden('return_to', $return_to); if ($inskin || $params['inskin_urls']) { // inskin login form $Form->hidden('inskin', true); $separator = '<br />'; } else { // standard login form if (!empty($params['form_title'])) { echo '<h4>' . $params['form_title'] . '</h4>'; } $Form->hidden('validate_required', $params['validate_required']); if (isset($params['action'], $params['reqID'], $params['sessID']) && $params['action'] == 'validatemail') { // the user clicked the link from the "validate your account" email, but has not been logged in; pass on the relevant data: $Form->hidden('action', 'validatemail'); $Form->hidden('reqID', $params['reqID']); $Form->hidden('sessID', $params['sessID']); } $separator = ''; } // check if should transmit hashed password if ($params['transmit_hashed_password']) { // used by JS-password encryption/hashing: $pwd_salt = $Session->get('core.pwd_salt'); if (empty($pwd_salt)) { // Do not regenerate if already set because we want to reuse the previous salt on login screen reloads // fp> Question: the comment implies that the salt is reset even on failed login attemps. Why that? I would only have reset it on successful login. Do experts recommend it this way? // but if you kill the session you get a new salt anyway, so it's no big deal. // At that point, why not reset the salt at every reload? (it may be good to keep it, but I think the reason should be documented here) $pwd_salt = generate_random_key(64); $Session->set('core.pwd_salt', $pwd_salt, 86400); $Session->dbsave(); // save now, in case there's an error later, and not saving it would prevent the user from logging in. } $Form->hidden('pwd_salt', $pwd_salt); // Add container for the hashed password hidden inputs echo '<div id="pwd_hashed_container"></div>'; // gets filled by JS } if ($inskin) { $Form->begin_field(); $Form->text_input($dummy_fields['login'], $params['login'], 18, T_('Login'), $separator . T_('Enter your username (or email address).'), array('maxlength' => 255, 'class' => 'input_text', 'required' => true)); $Form->end_field(); } else { $Form->text_input($dummy_fields['login'], $params['login'], 18, '', '', array('maxlength' => 255, 'class' => 'input_text', 'input_required' => 'required', 'placeholder' => T_('Username (or email address)'))); } $lost_password_url = get_lostpassword_url($redirect_to, '&', $return_to); if (!empty($login)) { $lost_password_url = url_add_param($lost_password_url, $dummy_fields['login'] . '=' . rawurlencode($login)); } $pwd_note = '<a href="' . $lost_password_url . '">' . T_('Lost your password?') . '</a>'; if ($inskin) { $Form->begin_field(); $Form->password_input($dummy_fields['pwd'], '', 18, T_('Password'), array('note' => $pwd_note, 'maxlength' => 70, 'class' => 'input_text', 'required' => true)); $Form->end_field(); } else { $Form->password_input($dummy_fields['pwd'], '', 18, '', array('placeholder' => T_('Password'), 'note' => $pwd_note, 'maxlength' => 70, 'class' => 'input_text', 'input_required' => 'required')); } // Allow a plugin to add fields/payload $Plugins->trigger_event('DisplayLoginFormFieldset', array('Form' => &$Form)); // Display registration link after login button $register_link = $params['display_reg_link'] ? get_user_register_link('', '', T_('Register') . ' »', '#', true, $redirect_to, $source, 'btn btn-primary btn-lg pull-right') : ''; // Submit button(s): $submit_buttons = array(array('name' => 'login_action[login]', 'value' => T_('Log in!'), 'class' => 'btn-success btn-lg', 'input_suffix' => $register_link)); $Form->buttons_input($submit_buttons); if ($inskin) { $before_register_link = '<div class="login_actions" style="text-align:right; margin: 1em 0 1ex"><strong>'; $after_register_link = '</strong></div>'; user_register_link($before_register_link, $after_register_link, T_('No account yet? Register here') . ' »', '#', true, $redirect_to, $source); } else { // Passthrough REQUEST data (when login is required after having POSTed something) // (Exclusion of 'login_action', 'login', and 'action' has been removed. This should get handled via detection in Form (included_input_field_names), // and "action" is protected via crumbs) $Form->hiddens_by_key(remove_magic_quotes($_REQUEST), array('pwd_hashed')); } $Form->end_form(); echo $params['form_after']; display_login_js_handler($params); }