Jump to content

sford999

Members
  • Posts

    119
  • Joined

  • Last visited

Profile Information

  • Gender
    Male

sford999's Achievements

Member

Member (2/5)

1

Reputation

  1. Try this <?php session_start(); if ($_SESSION['logged_in'] && $_SESSION['logged_in'] != ''){ echo "You are logged in<br/>"; }else { echo "You are not logged in<br/>"; } ?>
  2. Its in html/_header.inc.php The login form <?php define('ADMIN_IGNORE_LOGIN', true); include_once('_local_auth.inc.php'); include_once('html/_loginHeader.inc.php'); ?> <div class="container"> <form class="form-signin" action="http://www.codingforums.com/index.php" enctype="multipart/form-data" method="post"> <h2 class="form-signin-heading">Please sign in</h2> <?php if ($_REQUEST['error']) { adminFunctions::setError("Incorrect login details, please try again."); } echo adminFunctions::compileErrorHtml(); ?> <div class="input-group margin-bottom-sm"><span class="input-group-addon"><i class="fa fa-user-plus fa-fw"></i></i></span> <input class="form-control" type="text" placeholder="Username" name="username" id="username" /> </div> <div class="input-group" style="margin-top:10px;"><span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span> <input class="form-control" type="password" placeholder="Password" name="password" id="password" /> </div> <button class="btn btn-lg btn-primary btn-block" type="submit"><i class="fa fa-sign-in fa-fw"></i> Sign in</button> </form> </div> <?php include_once('html/_loginFooter.inc.php'); ?> Top of html/_header.inc.php <?php $Auth = Auth::getAuth(); Top of index.php <?php define('ADMIN_PAGE_TITLE', 'Dashboard'); define('MIN_ACCESS_LEVEL', 10); // allow moderators include_once('_local_auth.inc.php'); include_once('html/_header.inc.php'); auth.class.php <?php class Auth { // Singleton object. Leave $me alone. private static $me; public $id; public $username; public $level_id; public $user; // DBObject User object (if available) // Call with no arguments to attempt to restore a previous logged in session // which then falls back to a guest user (which can then be logged in using // $this->login($username, $rawPassword). Or pass a user_id to simply login that user. The // $seriously is just a safeguard to be certain you really do want to blindly // login a user. Set it to true. private function __construct($userToImpersonate = null) { $this->id = null; $this->username = null; $this->level_id = 0; $this->level = UserPeer::getLevelLabel($this->level_id); $this->user = null; if (class_exists('User') && (is_subclass_of('User', 'DBObject'))) { $this->user = new User(); } if (!is_null($userToImpersonate)) { return $this->impersonate($userToImpersonate); } if ($this->attemptSessionLogin()) { return; } } /** * Standard singleton * @return Auth */ public static function getAuth($userToImpersonate = null) { if (is_null(self::$me)) { self::$me = new Auth($userToImpersonate); } return self::$me; } // You'll typically call this function when a user logs in using // a form. Pass in their username and password. // Takes a username and a *plain text* password public function login($username, $rawPassword, $fromLoginForm = false) { $rs = $this->convertPassword($username, $rawPassword); if ($rs == false) { return false; } return $this->attemptLogin($username, $rawPassword, false, $fromLoginForm); } // manage convertions to sha256, this code is only for migration public function convertPassword($username, $rawPassword) { // get database $db = Database::getDatabase(); // check for existing user $user = $db->getRow('SELECT id, password FROM users WHERE username = ' . $db->quote($username)); if ($user === false) { return false; } // see if it matches the one entered if ($user['password'] == md5($rawPassword)) { // create new password $sha256Password = Password::createHash($rawPassword); // update user with new $db->query('UPDATE users SET password = :password WHERE id = :id', array('password' => $sha256Password, 'id' => $user['id'])); } return true; } public function logout() { $Config = Config::getConfig(); $this->id = null; $this->username = null; $this->level_id = 0; $this->level = 'guest'; $this->user = null; if (class_exists('User') && (is_subclass_of('User', 'DBObject'))) { $this->user = new User(); } $_SESSION['user'] = ''; unset($_SESSION['user']); session_destroy(); setcookie('spf', '.', time() - 3600, '/', $Config->authDomain); } // Is a user logged in? This was broken out into its own function // in case extra logic is ever required beyond a simple bool value. public function loggedIn() { return $this->level_id > 0; } // Helper function that redirects away from 'admin only' pages public function requireAdmin() { // check for login attempts if (isset($_REQUEST['username']) && isset($_REQUEST['password'])) { $this->login($_REQUEST['username'], $_REQUEST['password']); } // ensure it's an admin user $this->requireAccessLevel(20, ADMIN_WEB_ROOT . "/login.php?error=1"); } // Helper function that redirects away from 'member only' pages public function requireUser($url) { $this->requireAccessLevel(1, $url); } /* * Function to handle access rights and minimum permission levels for access. * The higher the number the greater the permission requirement. See the * database table called 'user_level' for the permission level_ids. * * @param type $level */ public function requireAccessLevel($minRequiredLevel = 0, $redirectOnFailure = 'login.php') { // check for login attempts if (isset($_REQUEST['username']) && isset($_REQUEST['password'])) { $this->login($_REQUEST['username'], $_REQUEST['password']); } // check account level if ($this->level_id >= $minRequiredLevel) { return true; } if (strlen($redirectOnFailure)) { coreFunctions::redirect($redirectOnFailure); } return false; } public function hasAccessLevel($minRequiredLevel = 0) { return $this->requireAccessLevel($minRequiredLevel, null); } // Login a user simply by passing in their username or id. Does // not check against a password. Useful for allowing an admin user // to temporarily login as a standard user for troubleshooting. // Takes an id or username public function impersonate($userToImpersonate) { $db = Database::getDatabase(); if (is_int($userToImpersonate)) { $row = $db->getRow('SELECT * FROM users WHERE id = ' . (int)$userToImpersonate.' LIMIT 1'); } else { $row = $db->getRow('SELECT * FROM users WHERE username = ' . $db->quote($userToImpersonate).' LIMIT 1'); } if (is_array($row)) { $this->id = $row['id']; $this->username = $row['username']; $this->email = $row['email']; $this->level_id = $row['level_id']; $this->level = UserPeer::getLevelLabel($this->level_id); // load any additional user info if DBObject and User are available $this->user = new User(); $this->user->id = $row['id']; $this->user->load($row); $this->storeSessionData(); return true; } return false; } // Attempt to login using data stored in the current session private function attemptSessionLogin() { if (isset($_SESSION['user'])) { $sessionAuth = unserialize($_SESSION['user']); if (is_object($sessionAuth)) { foreach ($sessionAuth AS $k => $v) { $this->$k = $v; } } return true; } return false; } // The function that actually verifies an attempted login and // processes it if successful. // Takes a username and a raw password public function attemptLogin($username, $rawPassword, $sessionLogin = false, $fromLoginForm = false) { $db = Database::getDatabase(); $Config = Config::getConfig(); // We SELECT * so we can load the full user record into the user DBObject later $row = $db->getRow('SELECT * FROM users WHERE username = ' . $db->quote($username)); if ($row === false) { // log failure Auth::logFailedLoginAttempt(coreFunctions::getUsersIPAddress(), $loginUsername); return false; } // validate password if ($sessionLogin == false) { if (Password::validatePassword($rawPassword, $row['password']) === false) { // log failure Auth::logFailedLoginAttempt(coreFunctions::getUsersIPAddress(), $loginUsername); return false; } } // check for mcrypt, required for login if(!function_exists('mcrypt_create_iv')) { return false; } // make sure account is active if ($row['status'] != "active") { return false; } else { // check user isn't banned from logging in $bannedIp = bannedIP::getBannedIPData(); if ($bannedIp) { if ($bannedIp['banType'] == 'Login') { return false; } } } // stop account sharing if($fromLoginForm == true) { Auth::clearSessionByUserId($row['id']); } $this->id = $row['id']; $this->username = $row['username']; $this->email = $row['email']; $this->level_id = $row['level_id']; $this->level = UserPeer::getLevelLabel($this->level_id); $this->paidExpiryDate = $row['paidExpiryDate']; $this->paymentTracker = $row['paymentTracker']; // load any additional user info if DBObject and User are available $this->user = new User(); $this->user->id = $row['id']; $this->user->load($row); // update lastlogindate $iPAddress = coreFunctions::getUsersIPAddress(); if ($sessionLogin == false) { $db->query('UPDATE users SET lastlogindate = NOW(), lastloginip = :ip WHERE id = :id', array('ip' => $iPAddress, 'id' => $this->id)); } // remove any failed logins for the IP address Auth::clearAllLoginAttemptsForIp($iPAddress); // log IP address for login if($fromLoginForm == true) { Auth::logSuccessfulLogin($this->id, $iPAddress); } // setup session $this->storeSessionData(); return true; } public function getAccountScreenName() { $label = $this->user->username; if (strlen($label) > 12) { $label = substr($label, 0, 12) . '...'; } return $label; } // stores current object in session private function storeSessionData() { //if (headers_sent()) //{ // die('Error: Headers already sent, can not set session data. This is likely due to a config file or plugin file which has been damaged on upload with extra spacing in it.'); // return false; //} $_SESSION['user'] = serialize($this); } private function createHashedPassword($rawPassword) { return MD5($rawPassword); } public static function logFailedLoginAttempt($ipAddress, $loginUsername = '') { // clear anything older than 24 hours self::clearOldLoginAttempts(); // get database $db = Database::getDatabase(); // add failed login attempt $dbInsert = new DBObject("login_failure", array("ip_address", "date_added", "username")); $dbInsert->ip_address = $ipAddress; $dbInsert->date_added = coreFunctions::sqlDateTime(); $dbInsert->username = $loginUsername; $dbInsert->insert(); // block IP address if greater than x failed logins if ((int) SITE_CONFIG_SECURITY_BLOCK_IP_LOGIN_ATTEMPTS > 0) { $failedAttempts = (int) $db->getValue('SELECT COUNT(id) AS total FROM login_failure WHERE ip_address = ' . $db->quote($ipAddress)); if ($failedAttempts >= SITE_CONFIG_SECURITY_BLOCK_IP_LOGIN_ATTEMPTS) { // add IP address to block list $dbInsert = new DBObject("banned_ips", array("ipAddress", "banType", "banNotes", "dateBanned", "banExpiry")); $dbInsert->ipAddress = $ipAddress; $dbInsert->banType = 'Login'; $dbInsert->banNotes = 'Banned after too many failed logins.'; $dbInsert->dateBanned = coreFunctions::sqlDateTime(); $dbInsert->banExpiry = date('Y-m-d H:i:s', strtotime('+24 hours')); $dbInsert->insert(); } } } public static function clearOldLoginAttempts() { // get database $db = Database::getDatabase(); // clear anything older than 24 hours $db->query('DELETE FROM login_failure WHERE date_added < DATE_SUB(NOW(), INTERVAL 24 HOUR)'); } public static function clearAllLoginAttemptsForIp($ipAddress) { // get database $db = Database::getDatabase(); // clear anything older than 24 hours $db->query('DELETE FROM login_failure WHERE ip_address = ' . $db->quote($ipAddress)); } public static function logSuccessfulLogin($userId, $ipAddress) { // clear anything older than 1 month self::clearOldSuccessfulLogins(); // get database $db = Database::getDatabase(); // try to find country code based on IP address $countryCode = Stats::getCountry($ipAddress); if (($countryCode == 'unknown') || ($countryCode == 'ZZ') || (!$countryCode)) { $countryCode = ''; } $countryCode = substr($countryCode, 0, 2); // add failed login attempt $dbInsert = new DBObject("login_success", array("ip_address", "date_added", "user_id", "country_code")); $dbInsert->ip_address = $ipAddress; $dbInsert->date_added = coreFunctions::sqlDateTime(); $dbInsert->user_id = $userId; $dbInsert->country_code = $countryCode; $dbInsert->insert(); } public static function clearOldSuccessfulLogins() { // get database $db = Database::getDatabase(); // clear anything older than 1 month $db->query('DELETE FROM login_success WHERE date_added < DATE_SUB(NOW(), INTERVAL 1 MONTH)'); } public static function clearSessionByUserId($userId) { // deletes any existing sessions for the same user id $db = Database::getDatabase(); $db->query('DELETE FROM sessions WHERE user_id = ' . (int) $userId); } }
  3. This has been bugging me for about an hour now, appreciate it if someone can see what I'm missing. Logs in successfully, redirects to index.php then the following error appears and kills the page. PHP Fatal error: Call to a member function requireAccessLevel() on a non-object in H:\server\htdocs\ys\admin\_local_auth.inc.php on line 16 _local_auth.inc.php require_once('../inc/master.inc.php'); // admin functions require_once(ADMIN_ROOT . '/_admin_functions.inc.php'); if(!defined('ADMIN_IGNORE_LOGIN')) { if(defined('MIN_ACCESS_LEVEL')) { $Auth->requireAccessLevel(MIN_ACCESS_LEVEL, ADMIN_WEB_ROOT . "/login.php"); } else { $Auth->requireAdmin(); } $userObj = $Auth->getAuth(); } master.inc.php // Determine our absolute document root define('DOC_ROOT', realpath(dirname(__FILE__) . '/../')); define('CORE_ROOT', DOC_ROOT); // set timezone if (!ini_get('date.timezone')) { date_default_timezone_set('GMT'); } require_once(CORE_ROOT . '/inc/objects.class.php'); // autoloader function __autoload($className) { if (file_exists(CORE_ROOT . '/inc/' . lcfirst($className) . '.class.php')) { require_once(CORE_ROOT . '/inc/' . lcfirst($className) . '.class.php'); } } // add missing function if (!function_exists('array_replace_recursive')) { function array_replace_recursive($array, $array1) { $rs = array(); foreach ($array AS $k => $arrayItem) { $rs[$k] = $arrayItem; if (isset($array1[$k])) { $rs[$k] = $array1[$k]; } } return $rs; } } // load our config settings $config = Config::getConfig(); Config::initConfigIntoMemory(); // setup database conn $db = Database::getDatabase(); // setup error handler log::initErrorHandler(); // store session info in the database? if ($config->useDBSessions === true) { DBSession::register(); } // initialize our session session_name($config->sessionName); // how long to keep sessions active before expiring session_set_cookie_params((int) SITE_CONFIG_SESSION_EXPIRY); // start session if (!isset($sessionStarted) || ($sessionStarted == false)) { session_start(); }
  4. Try this: <span class='ipsType_smaller desc lighter blend_links'><a href='" . $this->registry->getClass('output')->formatUrl( $this->registry->getClass('output')->buildUrl( "app=members&module=profile&section=status&type=single&status_id={$status['status_id']}", "public",'' ), array($status['member_id'], $status['members_seo_name']), "members_status_single" ) . "'>{$this->lang->words['ps_updated']} " . $this->registry->getClass('class_localization')->getDate($status['status_date'],"manual{%d %b}", 0) . " ยท " . intval($status['status_replies']) . " {$this->lang->words['ps_comments']}</a></span> You could also rebuild the skin caches from the admin CP which will replace the skin_cache files with new ones. (Also 3.3.4 is out of date when 3.4.6 is the newest version )
  5. Basically I want to group a bunch of rows together to get the oldest entry which is a unix time stamp, so I can compare that to another variable. I would like to know if this query is correct to get the oldest entry in "table.replyUnixTime"? SELECT table.*, MAX(table.replyUnixTime) AS lastReply FROM table GROUP BY table.replyId ORDER BY lastReply DESC Thanks
  6. I've completely re-written the function in a different way and got it working now. Now to write the restore function lol
  7. That's ok if the server the site is hosted on has exec() or shell_exec() functions enabled, I'm trying to write the php script so that it does not need those functions. The only part that's tripping me up now is: foreach($tables as $table) { $result = $db->getRow('SELECT * FROM '.$table); $num_fields = $db->result->columnCount(); $return .= 'DROP TABLE IF EXISTS '.$table.';'; $row2 = $db->getRow('SHOW CREATE TABLE '.$table); $return .= "\n\n".$row2[1].";\n\n"; for ($i = 0; $i < $num_fields; $i++) { foreach($result as $row) { $return .= 'INSERT INTO `'.$table.'` VALUES('; for($j=0; $j<$num_fields; $j++) { $row[$j] = addslashes($row[$j]); $row[$j] = preg_replace("#\n#", "\\n", $row[$j]); if (isset($row[$j])) { $return .= '\''.$row[$j].'\'' ; } else { $return .= '""'; } if ($j<($num_fields-1)) { $return .= ', '; } } $return .= ");\n"; } } $return .="\n"; } I'm not exactly sure how I write it so that it uses array_map() and implode() as mentioned previously.
  8. Hi, I have the following function to back up the MySQL database, but its not doing it correctly function backup($tables, $backupfolder, $zip) { $db = Database::getDatabase(); $backupfolder = $_SERVER['DOCUMENT_ROOT'].'/'.$backupfolder; $database = _CONFIG_DB_NAME; // Get all of the tables if (!$tables) { $tables = array(); $result = $db->query('SHOW TABLES'); if ($result) { while ($row = $db->getRow($result)) { $tables[] = $row[0]; } } else { // Error } } else { $tables = is_array($tables) ? $tables : explode(',', $tables); } // If we have tables in the $tables array, process them if ($tables) { $return = ''; // Cycle through the array foreach($tables as $table) { $result = $db->getRow('SELECT * FROM '.$table); $num_fields = $db->result->columnCount(); $return .= 'DROP TABLE IF EXISTS '.$table.';'; $row2 = $db->getRow('SHOW CREATE TABLE '.$table); $return .= "\n\n".$row2[1].";\n\n"; for ($i = 0; $i < $num_fields; $i++) { foreach($result as $row) { $return .= 'INSERT INTO `'.$table.'` VALUES('; for($j=0; $j<$num_fields; $j++) { $row[$j] = addslashes($row[$j]); $row[$j] = preg_replace("#\n#", "\\n", $row[$j]); if (isset($row[$j])) { $return .= '\''.$row[$j].'\'' ; } else { $return .= '""'; } if ($j<($num_fields-1)) { $return .= ', '; } } $return .= ");\n"; } } $return .="\n"; } // Save the backup file $handle = fopen($backupfolder.$filename,'w+'); if(fwrite($handle, $return)) { fclose($handle); // Success } else { // Error } } } But its not backing up correctly as its putting each character into separate columns. Example: INSERT INTO `users` VALUES('a', 'd', 'm', 'i', 'n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); INSERT INTO `users` VALUES('a', 'd', 'm', 'i', 'n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); INSERT INTO `users` VALUES('5', 'f', '4', 'd', 'c', 'c', '3', 'b', '5', 'a', 'a', '7', '6', '5', 'd', '6', '1', 'd', '8'); INSERT INTO `users` VALUES('5', 'f', '4', 'd', 'c', 'c', '3', 'b', '5', 'a', 'a', '7', '6', '5', 'd', '6', '1', 'd', '8'); INSERT INTO `users` VALUES('a', 'd', 'm', 'i', 'n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); INSERT INTO `users` VALUES('a', 'd', 'm', 'i', 'n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); Can anyone see what's wrong here?
  9. Even when using a normal submit button it does exactly the same thing, reloads when its not supposed to and doesn't show any results
  10. You can use the code below which will give you URLs like this: ht tp://www.domain.com/somepage RewriteEngine On RewriteBase / RewriteRule ^index$ index.php [QSA,L] RewriteRule ^contact$ contact.php [QSA,L] RewriteRule ^search$ search.php [QSA,L] RewriteRule ^privacy-policy$ privacy.php [QSA,L] RewriteRule ^terms-of-service$ terms.php [QSA,L]
  11. I have the following code which is supposed to submit the form without reloading and display the results in the div "s-results", but what its doing is reloading and not showing the results, there is nothing in the errorlogs to show why and it's got me stumped, so any help would be appreciated. <?php error_reporting(E_ALL); // Is the plugin activated include_once($_SERVER['DOCUMENT_ROOT'].'/includes/master.inc.php'); include_once('functions.php'); ?> <script> $(document).ready(function(){ $('#dosubmit').click(function(){ showValues(); }); $(function() { $('#search').bind('#dosubmit',function(){ showValues(); return false; }); }); function showValues() { //this will pass the form input $.post('search/includes/search-results.php', { query: search.query.value }, //then print the result function(result){ $('#s-results').html(result).show(); }); } }); </script> <?php echo '<form action="index.php" name="search" id="search" method="post" enctype="multipart/form-data">'; echo '<div class="loadContent ui-corner-all" style="width:100%;margin-top:20px;"><div class="loadContentInternal contentPageWrapper">'; echo '<h2>'.t('search_files', 'Search Files').'</h2>'; echo '<img src="plugins/search/assets/img/icons/24px.png" style="vertical-align:middle;" /> '; echo '<input type="text" class="uiStyle" style="height:35px;font-size:22px;font-weight:normal;" name="query" id="query" size="45" /><input type="image" src="search/assets/img/search_element.png" style="vertical-align:top;margin-bottom:2px;" name="submit" id="dosubmit" />'; echo '</form>'; echo '<div id="s-results"></div>'; echo '</div>'; echo '</div>'; ?> search-results.php <?php if(empty($_POST)) { exit("Direct access is not allowed."); } include_once($_SERVER['DOCUMENT_ROOT'].'/includes/master.inc.php'); include_once('functions.php'); // Make sure the search query is safe before continuing $query = makesafe($_REQUEST['query']); $results = $db->getRows("SELECT * FROM file WHERE originalName LIKE '%".$query."%' AND statusId = '1' LIMIT 30"); echo '<div class="loadContent ui-corner-all" style="width:100%;margin-top:20px;"><div class="loadContentInternal contentPageWrapper">'; if(!$query) { echo t('search_searched_nothing', 'You didn\'t enter anything to search for.'); } elseif(!$results) { echo '<h2>'.t('search_results', 'Search Results').' - '.stripslashes($query).'</h2>'; echo t('search_no_files_found', 'Nothing Found'); } else { echo '<h2>'.t('search_results', 'Search Results').' - '.stripslashes($query).'</h2>'; // table header echo '<table width="90%" align="left" padding="3px" border="0">'; foreach($results as $result) { // Results echo '<tr>'; echo '<td width="50%" align="left" style="border-collapse:collapse;border-bottom:1px solid #ccc;">'.$result['originalName'].'</td>'; echo '<td width="25%" align="left" style="border-collapse:collapse;border-bottom:1px solid #ccc;">'.formatSize($result['fsize']).'</td>'; echo '<td width="25%" align="left" style="border-collapse:collapse;border-bottom:1px solid #ccc;"><a href="'._CONFIG_SITE_PROTOCOL.'://'._CONFIG_SITE_HOST_URL.'/'.$result['shortUrl'].'" target="_blank">'.t('search_load_file', '[Download PDF]').'</a></td>'; echo '</tr>'; } echo '</table>'; echo '<div class="clear"><!-- --></div>'; } echo '</div></div>'; echo '<div class="clear"><!-- --></div>'; ?>
  12. $code is passed as a variable in the URL using $_GET The information on $dates & $users are stored in a single row in the database. INSERT INTO `table_codes` (`id`, `code`, `date_redeemed`, `user_redeemed`) VALUES (7, 'BBB', '1368140499|1368140500|1368140501|1368140502', 'name|name2|name3|name4');
  13. I have the code below which is meant to loop through each array showing the respective data from each array, but it is only displaying date - name And not all 4 items in the array The info in the database is stored as date_redeemed column = 1368140499|1368140500|1368140501|1368140502 user_redeemed column = name|name2|name3|name4 $result = $db->getRow("SELECT * FROM table_codes WHERE code= '$code' LIMIT 1"); $dates = explode('|', $result['date_redeemed']); $users = explode('|', $result['user_redeemed']); foreach(array_combine($dates, $users) as $date => $user) { $getUser = $db->getRow("SELECT * FROM users WHERE id = '".$user."'"); echo date('d/m/Y', $date).' - '.$user; } Doing print_r() on both the $dates & $users variables show all items in the arrays Array ( [0] => 1368140499 [1] => 1368140500 [2] => 1368140501 [3] => 1368140502 ) Array ( [0] => name [1] => name2 [2] => name3 [3] => name4 ) Any insight/help is appreciated
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.