|
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); |
|
|
|
/* |
|
* Core Member is a Mash-up of the old Freemember plugin and cp-login code, |
|
* to allow basic member functionality without the member module. |
|
* Supports login, logout, forgot password, reset password and change password. |
|
* |
|
* |
|
* FreeMember add-on for ExpressionEngine |
|
* Copyright (c) 2011 Crescendo Multimedia Ltd |
|
* |
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
* of this software and associated documentation files (the "Software"), to deal |
|
* in the Software without restriction, including without limitation the rights |
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
* copies of the Software, and to permit persons to whom the Software is |
|
* furnished to do so, subject to the following conditions: |
|
* |
|
* The above copyright notice and this permission notice shall be included in |
|
* all copies or substantial portions of the Software. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
* THE SOFTWARE. |
|
*/ |
|
|
|
$plugin_info = array( |
|
'pi_name' => 'core member plugin', |
|
'pi_version' => '1.0', |
|
'pi_author' => 'dev', |
|
'pi_author_url' => '', |
|
'pi_description' => 'Basic member login/logout and password functionality for EE-Core', |
|
); |
|
|
|
class Core_member |
|
{ |
|
public $return_data; |
|
|
|
public function __construct() |
|
{ |
|
// no default stuff |
|
} |
|
|
|
|
|
// ================================================================== |
|
public function login() |
|
{ |
|
$form_id = ee()->TMPL->fetch_param('form_id'); |
|
if (empty($form_id)) |
|
{ |
|
return 'Missing form_id parameter.'; |
|
} |
|
|
|
$tag_vars[0] = array( |
|
'username' => FALSE, |
|
'password' => FALSE, |
|
'auto_login' => FALSE, |
|
'error' => FALSE, |
|
); |
|
foreach ($tag_vars[0] as $field_name => $value) |
|
{ |
|
$tag_vars[0]['error:'.$field_name] = FALSE; |
|
} |
|
|
|
// handle form POST submission |
|
if (ee()->input->post('login_form') == $form_id) |
|
{ |
|
$tag_vars[0]['username'] = ee()->input->post('username'); |
|
$tag_vars[0]['auto_login'] = (bool) ee()->input->post('remember_me'); |
|
$tag_vars[0]['password'] = FALSE; // don't pre-load password field |
|
|
|
$result = $this->_member_login(); |
|
|
|
if ($result === true) |
|
{ |
|
$return_url = ee()->functions->create_url( ee()->input->post('return_url') ); |
|
ee()->functions->redirect($return_url); |
|
} |
|
else |
|
{ |
|
ee()->lang->loadfile('login'); |
|
$errors = array('error'=>''); |
|
|
|
foreach ($result as $error) { |
|
$errors['error'] .= lang($error) . ' '; |
|
} |
|
|
|
$tag_vars = $this->_display_errors($tag_vars, $errors); |
|
} |
|
} |
|
// auto_login_checked helper tag |
|
$tag_vars[0]['auto_login_checked'] = $tag_vars[0]['auto_login'] ? ' checked="checked" ' : FALSE; |
|
// start our form output |
|
$out = $this->_form_open(array( |
|
'hidden_fields' => array('login_form' => $form_id), |
|
)); |
|
// parse tagdata variables |
|
$out .= ee()->TMPL->parse_variables( ee()->TMPL->tagdata, $tag_vars); |
|
// end form output and return |
|
return $out.'</form>'; |
|
} |
|
|
|
|
|
// ================================================================== |
|
protected function _member_login() |
|
{ |
|
ee()->load->library('auth'); |
|
$errors = array(); |
|
|
|
/* --------------------------------- |
|
/* 'member_member_login_start' hook. |
|
/* - Take control of member login routine |
|
*/ |
|
$edata = ee()->extensions->call('member_member_login_start'); |
|
if (ee()->extensions->end_script === TRUE) return; |
|
/* |
|
/* ------------------------------- */ |
|
|
|
// Run through basic verifications: authenticate, username and |
|
// password both exist, not banned, IP checking is okay, run hook |
|
if ( ! ($verify_result = ee()->auth->verify())) |
|
{ |
|
// In the event it's a string, send it to return to login |
|
return ee()->auth->errors; |
|
} |
|
|
|
list($username, $password, $incoming) = $verify_result; |
|
$member_id = $incoming->member('member_id'); |
|
|
|
// Set cookies and start session |
|
// Kill existing flash cookie |
|
ee()->functions->set_cookie('flash'); |
|
|
|
if (isset($_POST['remember_me'])) |
|
{ |
|
$incoming->remember_me(); |
|
} |
|
|
|
if (is_numeric(ee()->input->post('site_id'))) |
|
{ |
|
ee()->functions->set_cookie('cp_last_site_id', ee()->input->post('site_id'), 0); |
|
} |
|
|
|
$incoming->start_session(FALSE); // not a CP session |
|
|
|
return true; |
|
} |
|
|
|
|
|
// ================================================================== |
|
public function logout() |
|
{ |
|
if (ee()->session->userdata('member_id') !== 0) |
|
{ |
|
|
|
ee()->db->where('ip_address', ee()->input->ip_address()); |
|
ee()->db->where('member_id', ee()->session->userdata('member_id')); |
|
ee()->db->delete('online_users'); |
|
|
|
ee()->session->destroy(); |
|
ee()->functions->set_cookie('read_topics'); |
|
|
|
/* ------------------------------------------- |
|
/* 'member_member_logout' hook. |
|
/* - Perform additional actions after logout |
|
/* - Added EE 1.6.1 |
|
*/ |
|
$edata = ee()->extensions->call('member_member_logout'); |
|
if (ee()->extensions->end_script === TRUE) return; |
|
/* |
|
/* -------------------------------------------*/ |
|
} |
|
|
|
if (($return = ee()->TMPL->fetch_param('return_url')) !== FALSE) |
|
{ |
|
ee()->functions->redirect(ee()->functions->create_url($return)); |
|
} |
|
else |
|
{ |
|
// return to most recent page |
|
ee()->functions->redirect(ee()->functions->form_backtrack(1)); |
|
} |
|
} |
|
|
|
|
|
// ================================================================== |
|
public function change_password() |
|
{ |
|
$form_id = ee()->TMPL->fetch_param('form_id'); |
|
|
|
if (empty($form_id)) |
|
{ |
|
return 'Missing form_id parameter.'; |
|
} |
|
|
|
$member_id = ee()->session->userdata('member_id'); |
|
|
|
if ($member_id == 0) |
|
{ |
|
show_error('change_password - You are not logged in'); |
|
} |
|
|
|
$tag_vars[0] = array( |
|
'password' => FALSE, |
|
'password_confirm' => FALSE, |
|
'current_password' => FALSE, |
|
'resetcode' => FALSE, |
|
'error' => FALSE, |
|
); |
|
|
|
foreach ($tag_vars[0] as $field_name => $value) |
|
{ |
|
$tag_vars[0]['error:'.$field_name] = FALSE; |
|
} |
|
|
|
// process form data |
|
if (ee()->input->post('login_form') == $form_id) |
|
{ |
|
ee()->load->library('form_validation'); |
|
ee()->lang->loadfile('myaccount'); |
|
|
|
// Put username into $_POST for valid_password validation |
|
$_POST['username'] = ee()->session->userdata('username'); |
|
|
|
ee()->form_validation->set_rules('current_password', 'lang:existing_password', 'required'); |
|
ee()->form_validation->set_rules('password', 'lang:new_password', 'valid_password|required'); |
|
ee()->form_validation->set_rules('password_confirm', 'lang:new_password_confirm', 'matches[password]|required'); |
|
|
|
if(ee()->form_validation->run() !== FALSE) |
|
{ |
|
// Validate current password |
|
ee()->load->library('auth'); |
|
|
|
$auth = ee()->auth->authenticate_id( |
|
$member_id, |
|
ee()->input->post('current_password') |
|
); |
|
|
|
if ($auth !== FALSE) |
|
{ |
|
// Update the member row with the new password. |
|
ee()->auth->update_password( |
|
$member_id, |
|
ee()->input->post('password') |
|
); |
|
|
|
$return_url = ee()->functions->create_url( ee()->input->post('return_url') ); |
|
ee()->functions->redirect($return_url); |
|
} |
|
else |
|
{ |
|
$errors = array('error'=> lang('invalid_password')); |
|
$tag_vars = $this->_display_errors($tag_vars, $errors); |
|
} |
|
} |
|
else |
|
{ |
|
$errors = array('error'=> ee()->form_validation->error_string()); |
|
$tag_vars = $this->_display_errors($tag_vars, $errors); |
|
} |
|
} |
|
|
|
// start our form output |
|
$out = $this->_form_open(array( |
|
'hidden_fields' => array('login_form' => $form_id), |
|
)); |
|
|
|
// parse tagdata variables |
|
$out .= ee()->TMPL->parse_variables( ee()->TMPL->tagdata, $tag_vars); |
|
|
|
// end form output and return |
|
return $out.'</form>'; |
|
|
|
} |
|
|
|
|
|
// ================================================================== |
|
public function forgot_password() |
|
{ |
|
$tag_vars = array(array( |
|
'email' => FALSE, |
|
'error:email' => FALSE, |
|
)); |
|
|
|
if ( ! $reset_url = ee()->TMPL->fetch_param('reset_url')) |
|
{ |
|
show_error('Missing reset_url parameter'); |
|
} |
|
|
|
// process form |
|
if (ee()->input->post('forgot_password')) |
|
{ |
|
|
|
$tag_vars[0]['email'] = ee()->input->post('email', TRUE); |
|
|
|
// generate reset code and URL |
|
$reset_code = ee()->functions->random('alnum', 10); |
|
|
|
$reset_url = ee()->functions->create_url($reset_url.'/'.$reset_code); |
|
|
|
// valide email address and send reset instructions |
|
$errors = $this->_member_forgot_password($reset_code, $reset_url); |
|
|
|
if (empty($errors)) |
|
{ |
|
$return_url = ee()->functions->create_url(ee()->input->post('return_url')); |
|
ee()->functions->redirect($return_url); |
|
} |
|
else |
|
{ |
|
$tag_vars = $this->_display_errors($tag_vars, $errors); |
|
} |
|
} |
|
|
|
// start our form output |
|
$out = $this->_form_open(array( |
|
'hidden_fields' => array('forgot_password' => 1), |
|
)); |
|
|
|
// parse tagdata variables |
|
$out .= ee()->TMPL->parse_variables(ee()->TMPL->tagdata, $tag_vars); |
|
|
|
// end form output and return |
|
return $out.'</form>'; |
|
} |
|
|
|
|
|
// ================================================================== |
|
private function _member_forgot_password($reset_code, $reset_url) |
|
{ |
|
ee()->lang->loadfile('myaccount'); |
|
|
|
// Error trapping |
|
if ( ! $address = ee()->input->post('email')) |
|
{ |
|
return array('email' => lang('invalid_email_address')); |
|
} |
|
|
|
ee()->load->helper('email'); |
|
|
|
if ( ! valid_email($address)) |
|
{ |
|
return array('email' => lang('invalid_email_address')); |
|
} |
|
|
|
$address = strip_tags($address); |
|
|
|
// Fetch user data |
|
ee()->db->select('member_id, username, screen_name'); |
|
ee()->db->where('email', $address); |
|
$query = ee()->db->get('members'); |
|
|
|
// Member not found, but show a generic action success message so spammers don't know if an email exists or not |
|
if ($query->num_rows() == 0) |
|
{ |
|
return array('email' => lang('forgotten_email_sent')); |
|
} |
|
|
|
$member_id = $query->row('member_id'); |
|
$name = ($query->row('screen_name') == '') ? $query->row('username') : $query->row('screen_name'); |
|
|
|
// Clean out any old reset codes. |
|
$a_day_ago = time() - (60*60*24); |
|
ee()->db->where('date <', $a_day_ago); |
|
ee()->db->or_where('member_id', $member_id); |
|
ee()->db->delete('reset_password'); |
|
|
|
// Create a new DB record with the temporary reset code |
|
$data = array('member_id' => $member_id, 'resetcode' => $reset_code, 'date' => time()); |
|
ee()->db->query(ee()->db->insert_string('exp_reset_password', $data)); |
|
|
|
// Buid the email message |
|
$swap = array( |
|
'name' => $name, |
|
'reset_url' => $reset_url, |
|
'site_name' => stripslashes(ee()->config->item('site_name')), |
|
'site_url' => ee()->config->item('site_url') |
|
); |
|
|
|
$template = ee()->functions->fetch_email_template('forgot_password_instructions'); |
|
$message_title = ee()->functions->var_swap($template['title'], $swap); |
|
$message = ee()->functions->var_swap($template['data'], $swap); |
|
|
|
// Instantiate the email class |
|
ee()->load->library('email'); |
|
ee()->email->wordwrap = true; |
|
ee()->email->from(ee()->config->item('webmaster_email'), ee()->config->item('webmaster_name')); |
|
ee()->email->to($address); |
|
ee()->email->subject($message_title); |
|
ee()->email->message($message); |
|
|
|
$vars['message_success'] = ''; |
|
$vars['message_error'] = ''; |
|
|
|
if ( ! ee()->email->send()) |
|
{ |
|
return array('email' => lang('error_sending_email')); |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
|
|
// ================================================================== |
|
public function reset_password() |
|
{ |
|
if (($reset_code = ee()->TMPL->fetch_param('code')) === FALSE) |
|
{ |
|
$reset_code = ee()->uri->segment(ee()->uri->total_segments()); |
|
} |
|
|
|
if (ee()->session->userdata('member_id') !== 0) |
|
{ |
|
show_error('Youre already logged in'); |
|
} |
|
|
|
if (ee()->session->userdata('is_banned') === TRUE) |
|
{ |
|
return show_error(lang('unauthorized_request')); |
|
} |
|
|
|
// Validate their reset code. Make sure it matches a valid member. |
|
$a_day_ago = time() - (60*60*24); |
|
$member_id_query = ee()->db->select('member_id') |
|
->where('resetcode', $reset_code) |
|
->where('date >', $a_day_ago) |
|
->get('reset_password'); |
|
|
|
// If we don't find a valid token, then they shouldn't be here. |
|
if ($member_id_query->num_rows() === 0) |
|
{ |
|
return ee()->TMPL->no_results(); |
|
} |
|
|
|
$member_id = $member_id_query->row('member_id'); |
|
|
|
$tag_vars = array(array( |
|
'password' => FALSE, |
|
'password_confirm' => FALSE, |
|
'error' => FALSE, |
|
)); |
|
|
|
foreach ($tag_vars[0] as $field_name => $value) |
|
{ |
|
$tag_vars[0]['error:'.$field_name] = FALSE; |
|
} |
|
|
|
// process form |
|
if (ee()->input->post('reset_password')) |
|
{ |
|
ee()->load->library('form_validation'); |
|
ee()->lang->loadfile('myaccount'); |
|
|
|
// Put username into $_POST for valid_password validation |
|
$_POST['username'] = ee()->db->select('username') |
|
->where('member_id', $member_id) |
|
->get('members') |
|
->row('username'); |
|
|
|
ee()->form_validation->set_rules('password', 'lang:new_password', 'valid_password|required'); |
|
ee()->form_validation->set_rules('password_confirm', 'lang:new_password_confirm', 'matches[password]|required'); |
|
|
|
if(ee()->form_validation->run() !== FALSE) |
|
{ |
|
// Update the member row with the new password. |
|
ee()->load->library('auth'); |
|
ee()->auth->update_password( |
|
$member_id, |
|
ee()->input->post('password') |
|
); |
|
|
|
// Invalidate the old token. While we're at it, may as well wipe out expired |
|
// tokens too, just to keep them from building up. |
|
ee()->db->where('date <', $a_day_ago) |
|
->or_where('member_id', $member_id) |
|
->delete('reset_password'); |
|
|
|
// Success, return to success template |
|
$return_url = ee()->functions->create_url(ee()->input->post('return_url')); |
|
ee()->functions->redirect($return_url); |
|
} |
|
else |
|
{ |
|
$errors = array('error'=> ee()->form_validation->error_string()); |
|
$tag_vars = $this->_display_errors($tag_vars, $errors); |
|
} |
|
|
|
} |
|
|
|
// start our form output |
|
$out = $this->_form_open(array( |
|
'hidden_fields' => array('reset_password' => 1), |
|
)); |
|
|
|
// parse tagdata variables |
|
$out .= ee()->TMPL->parse_variables(ee()->TMPL->tagdata, $tag_vars); |
|
|
|
// end form output and return |
|
return $out.'</form>'; |
|
} |
|
|
|
|
|
|
|
// ================================================================== |
|
/** |
|
* All our forms have common attributes |
|
*/ |
|
protected function _form_open($data) |
|
{ |
|
$data['action'] = ee()->functions->create_url(ee()->uri->uri_string); |
|
$data['id'] = ee()->TMPL->fetch_param('form_id'); |
|
$data['name'] = ee()->TMPL->fetch_param('form_name'); |
|
$data['class'] = ee()->TMPL->fetch_param('form_class'); |
|
|
|
if (empty($data['hidden_fields'])) |
|
{ |
|
$data['hidden_fields'] = array(); |
|
} |
|
|
|
$data['hidden_fields']['return_url'] = ee()->TMPL->fetch_param('return_url'); |
|
return ee()->functions->form_declaration($data); |
|
} |
|
|
|
|
|
// ================================================================== |
|
private function _display_errors($tag_vars, $errors) |
|
{ |
|
if ( ! is_array($errors)) |
|
{ |
|
// fatal error, display error message |
|
return ee()->output->show_user_error(FALSE, array($errors)); |
|
} |
|
|
|
if (ee()->TMPL->fetch_param('error_handling') != 'inline') |
|
{ |
|
// display standard error form |
|
ee()->output->show_user_error(FALSE, $errors); |
|
} |
|
|
|
// inline errors |
|
$delim = explode('|', ee()->TMPL->fetch_param('error_delimiters')); |
|
if (count($delim) != 2) |
|
{ |
|
$delim = array('', ''); |
|
} |
|
|
|
foreach ($errors as $field_name => $message) |
|
{ |
|
$tag_vars[0]['error:'.$field_name] = $delim[0].$message.$delim[1]; |
|
} |
|
|
|
return $tag_vars; |
|
} |
|
|
|
|
|
} |
|
|
|
/* End of file */ |
Great plugin!!! However I needed to add a pi. to the beginning of the filename to get it to work. Not sure if that was the right thing to do or not... but it worked.
thanks for the headsup, i changed the filename