} if (version_compare($existing_version, '2.0.8RC1', '<')) { $frontend->Database->query('ALTER TABLE `tbl_fields_date` DROP `calendar`'); } if (version_compare($existing_version, '2.0.8RC3', '<=')) { ## Add -Indexes to .htaccess $htaccess = @file_get_contents(DOCROOT . '/.htaccess'); if ($htaccess !== false && !preg_match('/-Indexes/', $htaccess)) { $htaccess = str_replace('Options +FollowSymlinks', 'Options +FollowSymlinks -Indexes', $htaccess); @file_put_contents(DOCROOT . '/.htaccess', $htaccess); } ## 2.1 uses SHA1 instead of MD5 // Change the author table to allow 40 character values $frontend->Database->query("ALTER TABLE `tbl_authors` CHANGE `password` `password` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL"); // Generate a new password for the primary author account $new_password = General::generatePassword(); $username = $frontend->Database->fetchVar('username', 0, "SELECT `username` FROM `tbl_authors` WHERE `primary` = 'yes' LIMIT 1"); $frontend->Database->query(sprintf("UPDATE `tbl_authors` SET `password` = SHA1('%s') WHERE `primary` = 'yes' LIMIT 1", $new_password)); // Purge all sessions, forcing everyone to update their passwords $frontend->Database->query("TRUNCATE TABLE `tbl_sessions`"); // Update Upload field $upload_entry_tables = $frontend->Database->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_upload`"); if (is_array($upload_entry_tables) && !empty($upload_entry_tables)) { foreach ($upload_entry_tables as $field) { $frontend->Database->query(sprintf("ALTER TABLE `tbl_entries_data_%d` CHANGE `size` `size` INT(11) UNSIGNED NULL DEFAULT NULL", $field)); } } } if (version_compare($existing_version, '2.1.0', '<=')) { $frontend->Database->query('ALTER TABLE `tbl_fields_input` CHANGE `validator` `validator` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL;'); $frontend->Database->query('ALTER TABLE `tbl_fields_upload` CHANGE `validator` `validator` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL;');
private function __buildDrawerHTML($filter) { $form = new XMLElement('form', NULL, array('action' => '', 'method' => 'get')); $range = ElasticSearchLogs::getDateRange(); $label = new XMLElement('div', NULL, array('data-dateMin' => date('Y-m-d', strtotime($range->min)), 'data-dateMax' => date('Y-m-d', strtotime($range->max)), 'class' => 'label date-range')); $label->appendChild(new XMLElement('span', _('Date range'))); $label->appendChild(new XMLElement('input', NULL, array('type' => 'text', 'placeholder' => __('From'), 'name' => 'filter[date_from]', 'value' => $filter->date_from, 'autocomplete' => 'off'))); $label->appendChild(new XMLElement('span', __('to'), array('class' => 'conjunctive'))); $label->appendChild(new XMLElement('input', NULL, array('type' => 'text', 'placeholder' => __('To'), 'name' => 'filter[date_to]', 'value' => $filter->date_to, 'autocomplete' => 'off'))); $form->appendChild($label); // generate a random noun $password = General::generatePassword(); $password = preg_replace('/[0-9]/', '', $password); // remove numbers preg_match('/([A-Z][a-z]+){1,}/', $password, $nouns); // split into separate words based on capitals $noun = strtolower(end($nouns)); $label = new XMLElement('label', '<span>' . __('Query') . '</span>', array('class' => 'keywords')); $label->appendChild(new XMLElement('input', NULL, array('type' => 'text', 'placeholder' => __('e.g. %s', array($noun)), 'name' => 'filter[keywords]', 'value' => $filter->keywords))); $form->appendChild($label); $label = new XMLElement('div', __('Query returned an average of'), array('class' => 'label performance')); $span = new XMLElement('span'); $span->appendChild(Widget::Select('filter[average_results][compare]', array(array('=', preg_match('/^\\=/', $filter->average_results), 'exactly'), array('<', preg_match('/^\\</', $filter->average_results), 'less than'), array('>', preg_match('/^\\>/', $filter->average_results), 'more than')))); $span->appendChild(new XMLElement('input', NULL, array('type' => 'text', 'name' => 'filter[average_results][value]', 'value' => trim($filter->average_results, '=<>'), 'autocomplete' => 'off', 'placeholder' => __('all')))); $span->appendChild(new XMLElement('span', ' ' . __('result(s)'))); $label->appendChild($span); $form->appendChild($label); $label = new XMLElement('div', __('Users visited depth of'), array('class' => 'label performance')); $span = new XMLElement('span'); $span->appendChild(Widget::Select('filter[average_depth][compare]', array(array('=', preg_match('/^\\=/', $filter->average_depth), 'exactly'), array('<', preg_match('/^\\</', $filter->average_depth), 'less than'), array('>', preg_match('/^\\>/', $filter->average_depth), 'more than')))); $span->appendChild(new XMLElement('input', NULL, array('type' => 'text', 'name' => 'filter[average_depth][value]', 'value' => trim($filter->average_depth, '=<>'), 'autocomplete' => 'off', 'placeholder' => __('all')))); $span->appendChild(new XMLElement('span', ' ' . __('page(s)'))); $label->appendChild($span); $form->appendChild($label); $form->appendChild(new XMLElement('input', NULL, array('type' => 'submit', 'value' => __('Apply Filters'), 'class' => 'button create'))); $form->appendChild(new XMLElement('input', NULL, array('type' => 'button', 'value' => __('Clear'), 'class' => 'button clear'))); return $form; }
function action() { if (isset($_POST['action'])) { $actionParts = array_keys($_POST['action']); $action = end($actionParts); ##Login Attempted if ($action == 'login') { if (!isset($_POST['username']) || strlen(trim($_POST['username'])) == 0) { $this->invalid_credentials = true; $this->missing_username = true; } if (!isset($_POST['password']) || strlen(trim($_POST['password'])) == 0) { $this->invalid_credentials = true; $this->missing_password = true; } elseif (!Administration::instance()->login($_POST['username'], $_POST['password'])) { ## FIXME: Fix this delegate ### # Delegate: LoginFailure # Description: Failed login attempt. Username is provided. //Extension::notify('LoginFailure', getCurrentPage(), array('username' => $_POST['username'])); //$this->Body->appendChild(new XMLElement('p', 'Login invalid. <a href="'.ADMIN_URL . '/?forgot">Forgot your password?</a>')); //$this->_alert = 'Login invalid. <a href="'.ADMIN_URL . '/?forgot">Forgot your password?</a>'; $this->invalid_credentials = true; } else { ## FIXME: Fix this delegate ### # Delegate: LoginSuccess # Description: Successful login attempt. Username is provided. //Extension::notify('LoginSuccess', getCurrentPage(), array('username' => $_POST['username'])); if (isset($_POST['redirect'])) { redirect(URL . str_replace(parse_url(URL, PHP_URL_PATH), NULL, $_POST['redirect'])); } redirect(ADMIN_URL . '/'); } ##Reset of password requested } elseif ($action == 'reset') { $user = Symphony::Database()->query("SELECT id, email, first_name FROM `tbl_users` WHERE `email` = '%s'", array($_POST['email'])); if ($user->valid()) { $user = $user->current(); Symphony::Database()->delete('tbl_forgotpass', array(DateTimeObj::getGMT('c')), " `expiry` < '%s'"); $token = Symphony::Database()->query("\n\t\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\t\ttoken\n\t\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\t`tbl_forgotpass`\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\texpiry > '%s'\n\t\t\t\t\t\t\tAND\n\t\t\t\t\t\t\t\tuser_id = %d\n\t\t\t\t\t\t\t", DateTimeObj::getGMT('c'), $user->id); if ($token->valid()) { $token = substr(md5(time() . rand(0, 200)), 0, 6); Symphony::Database()->insert('tbl_forgotpass', array('user_id' => $user->id, 'token' => $token, 'expiry' => DateTimeObj::getGMT('c', time() + 120 * 60))); } $this->_email_sent = General::sendEmail($user['email'], 'noreply@' . HTTP_HOST, __('Symphony Concierge'), __('New Symphony Account Password'), __('Hi %s,', array($user->first_name)) . PHP_EOL . __('A new password has been requested for your account. Login using the following link, and change your password via the Users area:') . PHP_EOL . PHP_EOL . ' ' . ADMIN_URL . "/login/{$token}/" . PHP_EOL . PHP_EOL . __('It will expire in 2 hours. If you did not ask for a new password, please disregard this email.') . PHP_EOL . PHP_EOL . __('Best Regards,') . PHP_EOL . __('The Symphony Team')); ## FIXME: Fix this delegate ### # Delegate: PasswordResetSuccess # Description: A successful password reset has taken place. User ID is provided //Extension::notify('PasswordResetSuccess', getCurrentPage(), array('user_id' => $user['id'])); } else { ## FIXME: Fix this delegate ### # Delegate: PasswordResetFailure # Description: A failed password reset has taken place. User ID is provided //Extension::notify('PasswordResetFailure', getCurrentPage(), array('user_id' => $user['id'])); $this->_email_sent = false; } ##Change of password requested } elseif ($action == 'change' && Administration::instance()->isLoggedIn()) { if (empty($_POST['password']) || empty($_POST['password-confirmation']) || $_POST['password'] != $_POST['password-confirmation']) { $this->_mismatchedPassword = true; } else { $user_id = Administration::instance()->User->id; $user = User::load($user_id); $user->set('password', md5(Symphony::Database()->escape($_POST['password']))); if (!User::save($user) || !Administration::instance()->login($user->username, $_POST['password'])) { redirect(URL . "symphony/system/users/edit/{$user_id}/error/"); } ## FIXME: Fix this delegate ### # Delegate: PasswordChanged # Description: After editing an User. ID of the User is provided. //Extension::notify('PasswordChanged', getCurrentPage(), array('user_id' => $user_id)); redirect(ADMIN_URL . '/'); } } } elseif ($_REQUEST['action'] == 'resetpass' && isset($_REQUEST['token'])) { $user = Symphony::Database()->query("\n\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\tu.id, u.email, u.first_name\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t`tbl_users` as u, `tbl_forgotpass` as t2\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tt2.`token` = '%s'\n\t\t\t\t\t\tAND\n\t\t\t\t\t\t\tu.`id` = t2.`user_id`\n\t\t\t\t\t\tLIMIT 1\n\t\t\t\t\t", $_REQUEST['token']); if ($user->valid()) { $user = $user->current(); $newpass = General::generatePassword(); General::sendEmail($user->email, 'noreply@' . HTTP_HOST, 'Symphony Concierge', 'RE: New Symphony Account Password', 'Hi ' . $user['first_name'] . ',' . PHP_EOL . "As requested, here is your new Symphony User Password for '" . URL . "'" . PHP_EOL . "\t{$newpass}" . PHP_EOL . PHP_EOL . 'Best Regards,' . PHP_EOL . 'The Symphony Team'); Symphony::Database()->update('tbl_users', array('password' => md5($newpass)), array($user->id), "`id` = '%d'"); Symphony::Database()->delete('tbl_forgotpass', array($user->id), " `user_id` = '%d'"); ## FIXME: Fix this delegate ### # Delegate: PasswordResetRequest # Description: User has requested a password reset. User ID is provided. //Extension::notify('PasswordResetRequest', getCurrentPage(), array('user_id' => $user['id'])); $this->_alert = 'Password reset. Check your email'; } } }
### # Delegate: PasswordResetSuccess # Description: A successful password reset has taken place. Author ID is provided $CampfireManager->notifyMembers('PasswordResetSuccess', CURRENTPAGE, array('author_id' => $author['id'])); $_f = "newpass"; $error = "You have been sent an email with instructions."; } else { ### # Delegate: PasswordResetFailure # Description: A failed password reset has taken place. Author ID is provided $CampfireManager->notifyMembers('PasswordResetFailure', CURRENTPAGE, array('author_id' => $author['id'])); $error = "Symphony could not locate your account."; $_f = "forgot"; } } } if ($_REQUEST['action'] == "resetpass" && isset($_REQUEST['_t'])) { $sql = "SELECT t1.`id`, t1.`email`, t1.`firstname` " . "FROM `tbl_authors` as t1, `tbl_forgotpass` as t2 " . "WHERE t2.`token` = '" . $_REQUEST['_t'] . "' AND t1.`id` = t2.`author_id` " . "LIMIT 1"; $author = $DB->fetchRow(0, $sql); if (!empty($author)) { $newpass = General::generatePassword(); General::sendEmail($author['email'], "*****@*****.**", "Symphony Concierge", "RE: New Symphony Account Password", "Hi " . $author['firstname'] . ",\nAs requested, here is your new Symphony Author Password for '" . URL . "' \n\n\t{$newpass}\n\n" . "\n\nBest Regards,\nThe Symphony Team"); $DB->update(array("password" => md5($newpass)), "tbl_authors", "WHERE `id` = '" . $author['id'] . "' LIMIT 1"); $DB->delete("tbl_forgotpass", "WHERE `author_id` = '" . $author['id'] . "'"); ### # Delegate: PasswordResetRequest # Description: User has requested a password reset. Author ID is provided. $CampfireManager->notifyMembers('PasswordResetRequest', CURRENTPAGE, array('author_id' => $author['id'])); $error = "Password reset. Check your email"; } }
function action() { if (isset($_POST['action'])) { $actionParts = array_keys($_POST['action']); $action = end($actionParts); ##Login Attempted if ($action == 'login') { if (empty($_POST['username']) || empty($_POST['password']) || !$this->_Parent->login($_POST['username'], $_POST['password'])) { ## TODO: Fix Me ### # Delegate: LoginFailure # Description: Failed login attempt. Username is provided. //$ExtensionManager->notifyMembers('LoginFailure', getCurrentPage(), array('username' => $_POST['username'])); //$this->Body->appendChild(new XMLElement('p', 'Login invalid. <a href="'.URL.'/symphony/?forgot">Forgot your password?</a>')); //$this->_alert = 'Login invalid. <a href="'.URL.'/symphony/?forgot">Forgot your password?</a>'; $this->_invalidPassword = true; } else { ## TODO: Fix Me ### # Delegate: LoginSuccess # Description: Successful login attempt. Username is provided. //$ExtensionManager->notifyMembers('LoginSuccess', getCurrentPage(), array('username' => $_POST['username'])); if (isset($_POST['redirect'])) { redirect(URL . str_replace(parse_url(URL, PHP_URL_PATH), '', $_POST['redirect'])); } redirect(URL . '/symphony/'); } ##Reset of password requested } elseif ($action == 'reset') { $author = $this->_Parent->Database->fetchRow(0, "SELECT `id`, `email`, `first_name` FROM `tbl_authors` WHERE `email` = '" . $_POST['email'] . "'"); if (!empty($author)) { $this->_Parent->Database->delete('tbl_forgotpass', " `expiry` < '" . DateTimeObj::getGMT('c') . "' "); if (!($token = $this->_Parent->Database->fetchVar('token', 0, "SELECT `token` FROM `tbl_forgotpass` WHERE `expiry` > '" . DateTimeObj::getGMT('c') . "' AND `author_id` = " . $author['id']))) { $token = substr(md5(time() . rand(0, 200)), 0, 6); $this->_Parent->Database->insert(array('author_id' => $author['id'], 'token' => $token, 'expiry' => DateTimeObj::getGMT('c', time() + 120 * 60)), 'tbl_forgotpass'); } $this->_email_sent = General::sendEmail($author['email'], $this->_Parent->Database->fetchVar('email', 0, "SELECT `email` FROM `tbl_authors` ORDER BY `id` ASC LIMIT 1"), __('Symphony Concierge'), __('New Symphony Account Password'), __('Hi %s,', array($author['first_name'])) . self::CRLF . __('A new password has been requested for your account. Login using the following link, and change your password via the Authors area:') . self::CRLF . self::CRLF . ' ' . URL . "/symphony/login/{$token}/" . self::CRLF . self::CRLF . __('It will expire in 2 hours. If you did not ask for a new password, please disregard this email.') . self::CRLF . self::CRLF . __('Best Regards,') . self::CRLF . __('The Symphony Team')); ## TODO: Fix Me ### # Delegate: PasswordResetSuccess # Description: A successful password reset has taken place. Author ID is provided //$ExtensionManager->notifyMembers('PasswordResetSuccess', getCurrentPage(), array('author_id' => $author['id'])); } else { ## TODO: Fix Me ### # Delegate: PasswordResetFailure # Description: A failed password reset has taken place. Author ID is provided //$ExtensionManager->notifyMembers('PasswordResetFailure', getCurrentPage(), array('author_id' => $author['id'])); $this->_email_sent = false; } ##Change of password requested } elseif ($action == 'change' && $this->_Parent->isLoggedIn()) { if (empty($_POST['password']) || empty($_POST['password-confirmation']) || $_POST['password'] != $_POST['password-confirmation']) { $this->_mismatchedPassword = true; } else { $author_id = $this->_Parent->Author->get('id'); require_once TOOLKIT . '/class.authormanager.php'; $authorManager = new AuthorManager($this->_Parent); $author = $authorManager->fetchByID($author_id); $author->set('password', md5($this->_Parent->Database->cleanValue($_POST['password']))); if (!$author->commit() || !$this->_Parent->login($author->get('username'), $_POST['password'])) { redirect(URL . "symphony/system/authors/edit/{$author_id}/error/"); } ## TODO: Fix me ### # Delegate: PasswordChanged # Description: After editing an author. ID of the author is provided. //$ExtensionManager->notifyMembers('PasswordChanged', getCurrentPage(), array('author_id' => $author_id)); redirect(URL . '/symphony/'); } } } elseif ($_REQUEST['action'] == 'resetpass' && isset($_REQUEST['token'])) { $sql = "SELECT t1.`id`, t1.`email`, t1.`first_name` \n\t\t\t\t\t FROM `tbl_authors` as t1, `tbl_forgotpass` as t2\n\t\t\t\t\t \tWHERE t2.`token` = '" . $_REQUEST['token'] . "' AND t1.`id` = t2.`author_id`\n\t\t\t\t\t \tLIMIT 1"; $author = $this->_Parent->Database->fetchRow(0, $sql); if (!empty($author)) { $newpass = General::generatePassword(); General::sendEmail($author['email'], '*****@*****.**', 'Symphony Concierge', 'RE: New Symphony Account Password', 'Hi ' . $author['first_name'] . ',' . self::CRLF . "As requested, here is your new Symphony Author Password for '" . URL . "'" . self::CRLF . "\t{$newpass}" . self::CRLF . self::CRLF . 'Best Regards,' . self::CRLF . 'The Symphony Team'); $this->_Parent->Database->update(array('password' => md5($newpass)), 'tbl_authors', " `id` = '" . $author['id'] . "' LIMIT 1"); $this->_Parent->Database->delete('tbl_forgotpass', " `author_id` = '" . $author['id'] . "'"); ## TODO: Fix Me ### # Delegate: PasswordResetRequest # Description: User has requested a password reset. Author ID is provided. //$ExtensionManager->notifyMembers('PasswordResetRequest', getCurrentPage(), array('author_id' => $author['id'])); $this->_alert = 'Password reset. Check your email'; } } }
public function sendNewPasswordEmail($member_id) { $entry = $this->fetchMemberFromID($member_id); if (!$entry instanceof Entry) { throw new Exception('Invalid member ID specified'); } if (!($role = $this->fetchRole($entry->getData($this->roleField(), true)->role_id))) { return; } $new_password = General::generatePassword(); // Attempt to update the password Symphony::Database()->query(sprintf("UPDATE `tbl_entries_data_%d` SET `password` = '%s' WHERE `entry_id` = %d LIMIT 1", $this->usernameAndPasswordField(), md5($new_password), $member_id)); $email_template = EmailTemplate::find('new-password', $role->id()); $member_field_handle = $this->usernameAndPasswordFieldHandle(); return $email_template->send($entry->get('id'), array('root' => URL, "{$member_field_handle}::username" => $entry->getData($this->usernameAndPasswordField(), true)->username, 'new-password' => $new_password, 'site-name' => Symphony::Configuration()->get('sitename', 'general'))); }
protected function __trigger() { $success = true; $result = new XMLElement('forgot-password'); $Members = $this->_Parent->ExtensionManager->create('members'); $username = $email = $code = NULL; if (isset($_POST['fields']['code']) && strlen(trim($_POST['fields']['code'])) > 0) { $code = $_POST['fields']['code']; $new_password = General::generatePassword(); self::__init(); $db = ASDCLoader::instance(); // Make sure we dont accidently use an expired token extension_Members::purgeTokens(); $token_row = $db->query(sprintf("SELECT * FROM `tbl_members_login_tokens` WHERE `token` = '%s' LIMIT 1", $db->escape($code)))->current(); // No code, you are a spy! if ($token_row === false) { redirect(URL . '/members/reset-pass/failed/'); } // Attempt to update the password $db->query(sprintf("UPDATE `tbl_entries_data_%d` SET `password` = '%s' WHERE `entry_id` = %d LIMIT 1", $Members->usernameAndPasswordField(), md5($new_password), $token_row->member_id)); extension_Members::purgeTokens($token_row->member_id); // SEND THE EMAIL!! $entry = $Members->initialiseMemberObject($token_row->member_id); $email_address = $entry->getData(self::findFieldID('email-address', 'members')); $name = $entry->getData(self::findFieldID('name', 'members')); $subject = 'Your new password'; $body = 'Dear {$name}, Just now, you have asked the Symphony brain trust to bestow you with a new password. Well, here it is: {$new-password} There\'s a good chance that you won\'t like this new password and want to change it - don\'t worry, we\'re not offended. You can do that once you\'ve logged in by going here: {$root}/members/change-pass/ If you have any trouble, please email us at support@symphony-cms.com and we\'ll do our best to help. Regards, Symphony Team'; $body = str_replace(array('{$name}', '{$root}', '{$new-password}'), array($name['value'], URL, $new_password), $body); $sender_email = 'noreply@' . parse_url(URL, PHP_URL_HOST); $sender_name = Symphony::Configuration()->get('sitename', 'general'); General::sendEmail($email_address['value'], $sender_email, $sender_name, $subject, $body); redirect(URL . '/members/reset-pass/success/'); } // Username take precedence if (isset($_POST['fields']['member-username']) && strlen(trim($_POST['fields']['member-username'])) > 0) { $username = $_POST['fields']['member-username']; } if (isset($_POST['fields']['member-email-address']) && strlen(trim($_POST['fields']['member-email-address'])) > 0) { $email = $_POST['fields']['member-email-address']; } if (is_null($username) && is_null($email)) { $success = false; $result->appendChild(new XMLElement('member-username', NULL, array('type' => 'missing'))); $result->appendChild(new XMLElement('member-email-address', NULL, array('type' => 'missing'))); } else { $members = array(); if (!is_null($email)) { $members = $Members->findMemberIDFromEmail($email); } if (!is_null($username)) { $members[] = $Members->findMemberIDFromUsername($username); } // remove duplicates $members = array_unique($members); try { if (is_array($members) && !empty($members)) { foreach ($members as $member_id) { $Members->sendForgotPasswordEmail($member_id); } redirect(URL . '/members/reset-pass/code/'); } } catch (Exception $e) { // Shouldn't get here, but will catch an invalid member ID if it does } $success = false; } $result->setAttribute('status', $success === true ? 'success' : 'error'); return $result; }
protected function __trigger() { $result = new XMLElement(self::ROOTELEMENT); $fields = $_POST['fields']; $driver = Symphony::ExtensionManager()->create('members'); // Add POST values to the Event XML $post_values = new XMLElement('post-values'); // Create the post data cookie element if (is_array($fields) && !empty($fields)) { General::array_to_xml($post_values, $fields, true); } // If a member is logged in, return early with an error if ($driver->getMemberDriver()->isLoggedIn()) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('You cannot generate a recovery code while being logged in.')))); $result->appendChild($post_values); return $result; } // Trigger the EventPreSaveFilter delegate. We are using this to make // use of the XSS Filter extension that will ensure our data is ok to use $this->notifyEventPreSaveFilter($result, $fields, $post_values); if ($result->getAttribute('result') == 'error') { return $result; } // Add any Email Templates for this event $this->addEmailTemplates('generate-recovery-code-template'); // Check that either a Member: Username or Member: Password field // has been detected $identity = SymphonyMember::setIdentityField($fields, false); if (!$identity instanceof Identity) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement('error', null, array('type' => 'invalid', 'message' => __('No Identity field found.')))); $result->appendChild($post_values); return $result; } // Check that a member exists first before proceeding. if (!isset($fields[$identity->get('element_name')]) or empty($fields[$identity->get('element_name')])) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'missing', 'message' => __('%s is a required field.', array($identity->get('label'))), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } $member_id = $identity->fetchMemberIDBy($fields[$identity->get('element_name')]); if (is_null($member_id)) { $result->setAttribute('result', 'error'); $result->appendChild(new XMLElement($identity->get('element_name'), null, array('type' => 'invalid', 'message' => __('Member not found.'), 'label' => $identity->get('label')))); $result->appendChild($post_values); return $result; } // Generate new password $newPassword = General::generatePassword(); // Set the Entry password to be reset and the current timestamp $auth = extension_Members::getField('authentication'); $status = Field::__OK__; $entry = $driver->getMemberDriver()->fetchMemberFromID($member_id); $entry_data = $entry->getData(); // Generate a Recovery Code with the same logic as a normal password $data = $auth->processRawFieldData(array('password' => General::hash($newPassword . $member_id, 'sha1')), $status); $data['recovery-code'] = $data['password']; $data['reset'] = 'yes'; $data['expires'] = DateTimeObj::get('Y-m-d H:i:s', time()); // Overwrite the password with the old password data. This prevents // a users account from being locked out if it it just reset by a random // member of the public $data['password'] = $entry_data[$auth->get('id')]['password']; $data['length'] = $entry_data[$auth->get('id')]['length']; $data['strength'] = $entry_data[$auth->get('id')]['strength']; Symphony::Database()->update($data, 'tbl_entries_data_' . $auth->get('id'), ' `entry_id` = ' . $member_id); // Trigger the EventFinalSaveFilter delegate. The Email Template Filter // and Email Template Manager extensions use this delegate to send any // emails attached to this event $this->notifyEventFinalSaveFilter($result, $fields, $post_values, $entry); // If a redirect is set, redirect, the page won't be able to receive // the Event XML anyway if (isset($_REQUEST['redirect'])) { redirect($_REQUEST['redirect']); } $result->setAttribute('result', 'success'); $result->appendChild(new XMLElement('recovery-code', $data['recovery-code'])); $result->appendChild($post_values); return $result; }
public function action() { if (isset($_POST['action'])) { $actionParts = array_keys($_POST['action']); $action = end($actionParts); ##Login Attempted if ($action == 'login') { if (empty($_POST['username']) || empty($_POST['password']) || !Administration::instance()->login($_POST['username'], $_POST['password'])) { /** * A failed login attempt into the Symphony backend * * @delegate AuthorLoginFailure * @since Symphony 2.2 * @param string $context * '/login/' * @param string $username * The username of the Author who attempted to login. */ Symphony::ExtensionManager()->notifyMembers('AuthorLoginFailure', '/login/', array('username' => $_POST['username'])); $this->_invalidPassword = true; } else { /** * A successful login attempt into the Symphony backend * * @delegate AuthorLoginSuccess * @since Symphony 2.2 * @param string $context * '/login/' * @param string $username * The username of the Author who logged in. */ Symphony::ExtensionManager()->notifyMembers('AuthorLoginSuccess', '/login/', array('username' => $_POST['username'])); if (isset($_POST['redirect'])) { redirect(URL . str_replace(parse_url(URL, PHP_URL_PATH), '', $_POST['redirect'])); } redirect(SYMPHONY_URL); } ##Reset of password requested } elseif ($action == 'reset') { $author = Symphony::Database()->fetchRow(0, "SELECT `id`, `email`, `first_name` FROM `tbl_authors` WHERE `email` = '" . Symphony::Database()->cleanValue($_POST['email']) . "'"); if (!empty($author)) { Symphony::Database()->delete('tbl_forgotpass', " `expiry` < '" . DateTimeObj::getGMT('c') . "' "); if (!($token = Symphony::Database()->fetchVar('token', 0, "SELECT `token` FROM `tbl_forgotpass` WHERE `expiry` > '" . DateTimeObj::getGMT('c') . "' AND `author_id` = " . $author['id']))) { $token = substr(General::hash(time() . rand(0, 1000)), 0, 6); Symphony::Database()->insert(array('author_id' => $author['id'], 'token' => $token, 'expiry' => DateTimeObj::getGMT('c', time() + 120 * 60)), 'tbl_forgotpass'); } try { $email = Email::create(); $email->recipients = $author['email']; $email->subject = __('New Symphony Account Password'); $email->text_plain = __('Hi %s,', array($author['first_name'])) . self::CRLF . __('A new password has been requested for your account. Login using the following link, and change your password via the Authors area:') . self::CRLF . self::CRLF . ' ' . SYMPHONY_URL . "/login/{$token}/" . self::CRLF . self::CRLF . __('It will expire in 2 hours. If you did not ask for a new password, please disregard this email.') . self::CRLF . self::CRLF . __('Best Regards,') . self::CRLF . __('The Symphony Team'); $email->send(); $this->_email_sent = true; } catch (Exception $e) { } catch (EmailGatewayException $e) { throw new SymphonyErrorPage('Error sending email. ' . $e->getMessage()); } /** * When a password reset has occured and after the Password * Reset email has been sent. * * @delegate AuthorPostPasswordResetSuccess * @since Symphony 2.2 * @param string $context * '/login/' * @param integer $author_id * The ID of the Author who requested the password reset */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordResetSuccess', '/login/', array('author_id' => $author['id'])); } else { /** * When a password reset has been attempted, but Symphony doesn't * recognise the credentials the user has given. * * @delegate AuthorPostPasswordResetFailure * @since Symphony 2.2 * @param string $context * '/login/' * @param string $email * The santizied Email of the Author who tried to request the password reset */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordResetFailure', '/login/', array('email' => Symphony::Database()->cleanValue($_POST['email']))); $this->_email_sent = false; } ##Change of password requested } elseif ($action == 'change' && Administration::instance()->isLoggedIn()) { if (empty($_POST['password']) || empty($_POST['password-confirmation']) || $_POST['password'] != $_POST['password-confirmation']) { $this->_mismatchedPassword = true; } else { $author_id = Administration::instance()->Author->get('id'); $author = AuthorManager::fetchByID($author_id); $author->set('password', General::hash(Symphony::Database()->cleanValue($_POST['password']))); if (!$author->commit() || !Administration::instance()->login($author->get('username'), $_POST['password'])) { redirect(SYMPHONY_URL . "/system/authors/edit/{$author_id}/error/"); } /** * When an Author changes their password as the result of a login * with an emergency token (ie. forgot password). Just after their * new password has been set successfully * * @delegate AuthorPostPasswordChange * @since Symphony 2.2 * @param string $context * '/login/' * @param integer $author_id * The ID of the Author who has just changed their password */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordChange', '/login/', array('author_id' => $author_id)); redirect(SYMPHONY_URL); } } } elseif ($_REQUEST['action'] == 'resetpass' && isset($_REQUEST['token'])) { $author = Symphony::Database()->fetchRow(0, "SELECT t1.`id`, t1.`email`, t1.`first_name`\n\t\t\t\t\t\tFROM `tbl_authors` as t1, `tbl_forgotpass` as t2\n\t\t\t\t\t \tWHERE t2.`token` = '" . Symphony::Database()->cleanValue($_REQUEST['token']) . "' AND t1.`id` = t2.`author_id`\n\t\t\t\t\t \tLIMIT 1"); if (!empty($author)) { $newpass = General::generatePassword(); General::sendEmail($author['email'], Symphony::Database()->fetchVar('email', 0, "SELECT `email` FROM `tbl_authors` ORDER BY `id` ASC LIMIT 1"), __('Symphony Concierge'), __('New Symphony Account Password'), __('Hi %s,', array($author['first_name'])) . self::CRLF . __("As requested, here is your new Symphony Author Password for ") . URL . " " . self::CRLF . " {$newpass}" . self::CRLF . self::CRLF . __('Best Regards,') . self::CRLF . __('The Symphony Team')); Symphony::Database()->update(array('password' => General::hash($newpass)), 'tbl_authors', " `id` = '" . $author['id'] . "' LIMIT 1"); Symphony::Database()->delete('tbl_forgotpass', " `author_id` = '" . $author['id'] . "'"); /** * Just after a Forgot Password email has been sent to the Author * who has requested a password reset. * * @delegate AuthorPostPasswordResetRequest * @since Symphony 2.2 * @param string $context * '/login/' * @param integer $author_id * The ID of the Author who has requested their password be reset */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordResetRequest', '/login/', array('author_id' => $author['id'])); $this->_alert = __('Password reset. Check your email'); } } }