/** * Executes all cron jobs in the DB if there are any to run. * * @param boolean $async If true, allows execution to continue by making an asynchronous request to a cron URL */ static function run_cron($async = false) { // check if it's time to run crons, and if crons are already running. $next_cron = HabariDateTime::date_create(Options::get('next_cron', 1)); $time = HabariDateTime::date_create(); if ($next_cron->int > $time->int || Options::get('cron_running') && Options::get('cron_running') > microtime(true)) { return; } // cron_running will timeout in 10 minutes // round cron_running to 4 decimals $run_time = microtime(true) + 600; $run_time = sprintf("%.4f", $run_time); Options::set('cron_running', $run_time); if ($async) { // Timeout is really low so that it doesn't wait for the request to finish $cronurl = URL::get('cron', array('time' => $run_time, 'asyncronous' => Utils::crypt(Options::get('GUID')))); $request = new RemoteRequest($cronurl, 'GET', 1); try { $request->execute(); } catch (RemoteRequest_Timeout $e) { // the request timed out - we knew that would happen } catch (Exception $e) { // some other error occurred. log it. EventLog::log($e->getMessage(), 'err', 'crontab', 'habari', $e); } } else { // @todo why do we usleep() and why don't we just call act_poll_cron()? usleep(5000); if (Options::get('cron_running') != $run_time) { return; } $time = HabariDateTime::date_create(); $crons = DB::get_results('SELECT * FROM {crontab} WHERE start_time <= ? AND next_run <= ? AND active != ?', array($time->sql, $time->sql, 0), 'CronJob'); if ($crons) { foreach ($crons as $cron) { $cron->execute(); } } EventLog::log(_t('CronTab run completed.'), 'debug', 'crontab', 'habari', $crons); // set the next run time to the lowest next_run OR a max of one day. $next_cron = DB::get_value('SELECT next_run FROM {crontab} ORDER BY next_run ASC LIMIT 1', array()); Options::set('next_cron', min(intval($next_cron), $time->modify('+1 day')->int)); Options::set('cron_running', false); } }
/** * Executes all cron jobs in the DB if there are any to run. * * @param boolean $async If true, allows execution to continue by making an asynchronous request to a cron URL */ static function run_cron($async = false) { // check if it's time to run crons, and if crons are already running. $next_cron = HabariDateTime::date_create(Options::get('next_cron')); $time = HabariDateTime::date_create(); if ($next_cron->int > $time->int || Options::get('cron_running') && Options::get('cron_running') > microtime(true)) { return; } // cron_running will timeout in 10 minutes // round cron_running to 4 decimals $run_time = microtime(true) + 600; $run_time = sprintf("%.4f", $run_time); Options::set('cron_running', $run_time); if ($async) { // Timeout is really low so that it doesn't wait for the request to finish $cronurl = URL::get('cron', array('time' => $run_time, 'asyncronous' => Utils::crypt(Options::get('guid')))); $request = new RemoteRequest($cronurl, 'GET', 1); $request->execute(); } else { usleep(5000); if (Options::get('cron_running') != $run_time) { return; } $time = HabariDateTime::date_create(); $crons = DB::get_results('SELECT * FROM {crontab} WHERE start_time <= ? AND next_run <= ?', array($time->sql, $time->sql), 'CronJob'); if ($crons) { foreach ($crons as $cron) { $cron->execute(); } } // set the next run time to the lowest next_run OR a max of one day. $next_cron = DB::get_value('SELECT next_run FROM {crontab} ORDER BY next_run ASC LIMIT 1', array()); Options::set('next_cron', min(intval($next_cron), $time->modify('+1 day')->int)); Options::set('cron_running', false); } }
/** * Handle password reset confirmations */ public function act_password_reset() { Utils::check_request_method(array('GET', 'HEAD', 'POST')); $id = $this->handler_vars['id']; $hash = $this->handler_vars['hash']; $name = ''; if ($user = User::get($id)) { if ($user->info->password_reset == md5($hash)) { // Send a new random password $password = Utils::random_password(); $user->password = Utils::crypt($password); if ($user->update()) { $message = _t("Your password for %1\$s has been reset. Your credentials are as follows---\nUsername: %2\$s\nPassword: %3\$s", array(Site::get_url('habari'), $user->username, $password)); Utils::mail($user->email, _t('[%1$s] Password has been reset for %2$s', array(Options::get('title'), $user->displayname)), $message); Session::notice(_t('A new password has been sent to the user.')); } else { Session::notice(_t('There was a problem resetting the password. It was not reset.')); } // Clear the request - it should only work once unset($user->info->password_reset); $user->info->commit(); $name = $user->username; } else { Session::notice(_t('The supplied password reset token has expired or is invalid.')); } } // Display the login form. $this->login_form($name); }
HabariLocale::set('en-us'); } if (Options::get('system_locale')) { HabariLocale::set_system_locale(Options::get('system_locale')); } // Verify if the database has to be upgraded. if (Version::requires_upgrade()) { $installer = new InstallHandler(); $installer->upgrade_db(); } // If we're doing unit testing, stop here if (defined('UNIT_TEST')) { return; } // if this is an asyncronous call, ignore abort. if (isset($_GET['asyncronous']) && Utils::crypt(Options::get('guid'), $_GET['asyncronous'])) { ignore_user_abort(true); } // Send the Content-Type HTTP header. // @todo Find a better place to put this. header('Content-Type: text/html;charset=utf-8'); /** * Include all the active plugins. * By loading them here they'll have global scope. * * We loop through them twice so we can cache all plugin classes on the first load() call. * This gives about 60% improvement. */ foreach (Plugins::list_active() as $file) { include_once $file; }
/** * Returns an array of tokens used for WSSE authentication * http://www.xml.com/pub/a/2003/12/17/dive.html * http://www.sixapart.com/developers/atom/protocol/atom_authentication.html * @param string|array $nonce a string nonce or an existing array to add nonce parameters to * @param string $timestamp a timestamp * @return array an array of WSSE authentication elements */ public static function WSSE($nonce = '', $timestamp = '') { $wsse = array(); if (is_array($nonce)) { $wsse = $nonce; $nonce = ''; } if ('' === $nonce) { $nonce = Utils::crypt(Options::get('public-GUID') . Utils::nonce()); } if ('' === $timestamp) { $timestamp = date('c'); } $user = User::identify(); $wsse = array_merge($wsse, array('nonce' => $nonce, 'timestamp' => $timestamp, 'digest' => base64_encode(pack('H*', sha1($nonce . $timestamp . $user->password))))); return $wsse; }
/** * Check a user's credentials to see if they are legit * -- calls all auth plugins BEFORE checking local database. * * @todo Actually call plugins * * @param string $who A username or email address * @param string $pw A password * @return object a User object, or false */ public static function authenticate($who, $pw) { if ('' === $who || '' === $pw) { return false; } $user = new StdClass(); $require = false; $user = Plugins::filter('user_authenticate', $user, $who, $pw); if ($user instanceof User) { self::$identity = $user; Plugins::act('user_authenticate_successful', self::$identity); EventLog::log(sprintf(_t('Successful login for %s'), $user->username), 'info', 'authentication', 'habari'); // set the cookie $user->remember(); return self::$identity; } elseif (!is_object($user)) { Plugins::act('user_authenticate_failure', 'plugin'); EventLog::log(sprintf(_t('Login attempt (via authentication plugin) for non-existent user %s'), $who), 'warning', 'authentication', 'habari'); Session::error('Invalid username/password'); self::$identity = null; return false; } if (strpos($who, '@') !== FALSE) { // we were given an email address $user = self::get_by_email($who); } else { $user = self::get_by_name($who); } if (!$user) { // No such user. Plugins::act('user_authenticate_failure', 'non-existent'); EventLog::log(sprintf(_t('Login attempt for non-existent user %s'), $who), 'warning', 'authentication', 'habari'); Session::error('Invalid username/password'); self::$identity = null; return false; } if (Utils::crypt($pw, $user->password)) { // valid credentials were supplied self::$identity = $user; Plugins::act('user_authenticate_successful', self::$identity); EventLog::log(sprintf(_t('Successful login for %s'), $user->username), 'info', 'authentication', 'habari'); // set the cookie $user->remember(); return self::$identity; } else { // Wrong password. Plugins::act('user_authenticate_failure', 'bad_pass'); EventLog::log(sprintf(_t('Wrong password for user %s'), $user->username), 'warning', 'authentication', 'habari'); Session::error('Invalid username/password'); self::$identity = null; return false; } }
/** * Handles POST requests from the Users listing (ie: creating a new user) */ public function post_users() { $this->fetch_users(); $extract = $this->handler_vars->filter_keys('newuser', 'delete', 'new_pass1', 'new_pass2', 'new_email', 'new_username'); foreach ($extract as $key => $value) { ${$key} = $value; } if (isset($newuser)) { $action = 'newuser'; } elseif (isset($delete)) { $action = 'delete'; } $error = ''; if (isset($action) && 'newuser' == $action) { if (!isset($new_pass1) || !isset($new_pass2) || empty($new_pass1) || empty($new_pass2)) { Session::error(_t('Password is required.'), 'adduser'); } else { if ($new_pass1 !== $new_pass2) { Session::error(_t('Password mis-match.'), 'adduser'); } } if (!isset($new_email) || empty($new_email) || !strstr($new_email, '@')) { Session::error(_t('Please supply a valid email address.'), 'adduser'); } if (!isset($new_username) || empty($new_username)) { Session::error(_t('Please supply a user name.'), 'adduser'); } // safety check to make sure no such username exists $user = User::get_by_name($new_username); if (isset($user->id)) { Session::error(_t('That username is already assigned.'), 'adduser'); } if (!Session::has_errors('adduser')) { $user = new User(array('username' => $new_username, 'email' => $new_email, 'password' => Utils::crypt($new_pass1))); if ($user->insert()) { Session::notice(sprintf(_t("Added user '%s'"), $new_username)); } else { $dberror = DB::get_last_error(); Session::error($dberror[2], 'adduser'); } } else { $settings = array(); if (isset($username)) { $settings['new_username'] = $new_username; } if (isset($new_email)) { $settings['new_email'] = $new_email; } $this->theme->assign('settings', $settings); } } else { if (isset($action) && 'delete' == $action) { $this->update_users($this->handler_vars); } } $this->theme->display('users'); }
public function action_publish_post(Post $post, FormUI $form) { if ($post->content_type == Post::type('entry')) { $post->info->password = Utils::crypt($form->postpass->value); } }
public function action_auth_ajax_wp_import_users() { // get the values post'd in $inputs = $_POST->filter_keys(array('db_name', 'db_host', 'db_user', 'db_pass', 'db_prefix', 'category_import', 'import_index')); $inputs = $inputs->getArrayCopy(); // make sure we have all our default values $inputs = array_merge($this->default_values, $inputs); // get the wpdb $wpdb = $this->wp_connect($inputs['db_host'], $inputs['db_name'], $inputs['db_user'], $inputs['db_pass']); // if we couldn't connect, error out if (!$wpdb) { EventLog::log(_t('Failed to import from "%s"', array($inputs['db_name']))); Session::error(_t('Failed to import from "%s"', array($inputs['db_name']))); echo '<p>' . _t('Failed to connect using the given database connection details.') . '</p>'; } // we connected just fine, let's get moving! // begin a transaction. if we error out at any point, we want to roll back to before import began DB::begin_transaction(); // fetch all the users from the wordpress database $wp_users = $wpdb->get_results('select id, user_login, user_pass, user_email, user_url, display_name from ' . $inputs['db_prefix'] . 'users'); echo '<p>' . _t('Importing Users…') . '</p>'; foreach ($wp_users as $wp_user) { // see if a user with this username already exists $user = User::get_by_name($wp_user->user_login); if ($user !== false) { // if the user exists, save their old ID into an info attribute $user->info->wp_id = intval($wp_user->id); // and update $user->update(); echo '<p>' . _t('Associated imported user %1$s with existing user %2$s', array($wp_user->user_login, $user->username)) . '</p>'; EventLog::log(_t('Associated imported user %1$s with existing user %2$s', array($wp_user->user_login, $user->username))); } else { // no user exists, we need to create one try { $u = new User(); $u->username = $wp_user->user_login; $u->email = $wp_user->user_email; // set their password so the user will be able to login. they're auto-added to the 'authenticated' ACL group $u->password = Utils::crypt($wp_user->user_pass); $u->info->wp_id = intval($wp_user->id); $u->info->displayname = $wp_user->display_name; if ($wp_user->user_url != '') { $u->info->url = $wp_user->user_url; } // and save it $u->insert(); echo '<p>' . _t('Created new user %1$s. Their old ID was %2$d.', array($u->username, $wp_user->id)) . '</p>'; EventLog::log(_t('Created new user %1$s. Their old ID was %2$d.', array($u->username, $wp_user->id))); } catch (Exception $e) { // no idea why we might error out, but catch it if we do EventLog::log($e->getMessage, 'err'); echo '<p class="error">' . _t('There was an error importing user %s. See the EventLog for the error message. ', array($wp_user->user_login)) . '</p>'; echo '<p>' . _t('Rolling back changes…') . '</p>'; // rollback all changes before we return so the import hasn't changed anything yet DB::rollback(); // and return so they don't get AJAX to send them on to the next step return false; } } } // if we've finished without an error, commit the import DB::commit(); // get the next ajax url $ajax_url = URL::get('auth_ajax', array('context' => 'wp_import_posts')); // and spit out ajax to send them to the next step - posts! echo $this->get_ajax($ajax_url, $inputs); }
/** * Creates the administrator user from form information * * @return mixed. the user on success, false on failure */ private function create_admin_user() { $admin_username = $this->handler_vars['admin_username']; $admin_email = $this->handler_vars['admin_email']; $admin_pass = $this->handler_vars['admin_pass1']; if ($admin_pass[0] == '{') { // looks like we might have a crypted password $password = $admin_pass; // but let's double-check $algo = strtolower(substr($admin_pass, 1, 3)); if ('ssh' != $algo && 'sha' != $algo) { // we do not have a crypted password // so let's encrypt it $password = Utils::crypt($admin_pass); } } else { $password = Utils::crypt($admin_pass); } // Insert the admin user $user = User::create(array('username' => $admin_username, 'email' => $admin_email, 'password' => $password)); return $user; }
/** * function action_plugins_loaded * checks for the presence of our cookie, and uses that to establish the session for the user **/ public function action_init() { // first, let's see if an active session is in effect $user = User::identify(); if (0 < $user->id) { // no sense processing any further if we already know // about this user. return; } // make sure we don't try to accidentially re-use the anonymous // user object later. probably unnecessary. unset($user); // does our cookie exist on the user's PC? $cookiename = 'P_' . md5(Options::get('GUID') . '_Persistence'); if (!isset($_COOKIE[$cookiename])) { // no? bail out return; } $cookie = $_COOKIE[$cookiename]; $result = DB::get_row('SELECT user_id,value FROM {userinfo} WHERE name=?', array('persistence_' . $cookie)); if (!$result) { return; } if (time() > $result->value) { // the cookie has expired return; } $user = User::get_by_id($result->user_id); // make sure the hash value stored in the cookie is correct for this user if (!Utils::crypt($user->username . $user->id . $result->value, $cookie)) { // hash doesn't match, so bail out unset($user); return; } // we got here, so let's remember this user $user->remember(); // and store a log entry EventLog::log('Successful login by cookie for ' . $user->username, 'info', 'authentication', 'persistence'); }
public function testCrypt() { $crypt = Utils::crypt($this->plaintext); $this->assertRegExp('/^{SSHA512}/', $crypt); $this->assertEquals(101, strlen($crypt)); // Test the hash-compare works $hash = "{SSHA512}p9F5CeA1xrB2ypnI6tl9B2ol/+Et7qObtZfUawRRNck5MxFQtnRkdfAgPwbUlGMf3GcTwvPcv1/fNAEtHxrcozekoMU="; $this->assertTrue(Utils::crypt($this->plaintext, $hash)); }
function test_crypt() { $crypt = Utils::crypt($this->plaintext); $this->assert_true(strpos($crypt, '{SSHA512}') === 0); $this->assert_equal(101, strlen($crypt)); // Test the hash-compare works $hash = "{SSHA512}p9F5CeA1xrB2ypnI6tl9B2ol/+Et7qObtZfUawRRNck5MxFQtnRkdfAgPwbUlGMf3GcTwvPcv1/fNAEtHxrcozekoMU="; $this->assert_true(Utils::crypt($this->plaintext, $hash)); }
public function register_user($form) { $group = UserGroup::get($form->get_option('group_name')); $user = new User(array('username' => $form->username, 'email' => $form->email, 'password' => Utils::crypt($form->password))); if ($user->insert()) { $group->add($user); if ($form->get_option('standalone')) { $user->remember(); $redirect = URL::get('register_success'); } else { Session::notice(sprintf(_t("Added user '%s'", __CLASS__), $form->username)); $redirect = ""; } // Let plugins alter the redirect location. Yes, the string is loooong, but it's propably unique, too. $redirect = Plugins::filter('register_user_success_redirect_location', $redirect, $form); Utils::redirect($redirect); } else { $dberror = DB::get_last_error(); Session::error($dberror[2], 'adduser'); } }
/** * Success method for the add_user form * @param FormUI $form The add_user form */ public function do_add_user(FormUI $form) { $user = new User(array('username' => $form->username->value, 'email' => $form->email->value, 'password' => Utils::crypt($form->password->value))); if ($user->insert()) { Session::notice(_t("Added user '%s'", array($form->username->value))); $form->clear(); } else { $dberror = DB::get_last_error(); Session::error($dberror[2], 'adduser'); } }
private function get_mail_data($comment, $reply) { $ret = array(); $eol_tag = '--EOL--'; $fp = $this->find_file(self::MAIL_FILENAME); $post = Post::get(array('id' => $comment->post_id)); /* prepare for vars used in template file */ $site_name = Options::get('title'); $site_link = Site::get_url('habari'); $post_title = $post->title; $post_link = $post->permalink; $comment_id = $comment->id; $comment_author = $comment->name; $comment_content = str_replace("\r\n", "\n", $comment->content); $comment_content = str_replace("\n", $eol_tag, $comment_content); $reply_id = $reply->id; $reply_author = $reply->name; $reply_content = str_replace("\r\n", "\n", $reply->content); $reply_content = str_replace("\n", $eol_tag, $reply_content); $unsubscribe_link = $site_link . '/tc_unsubscribe?id=' . base64_encode($comment->email . ',' . $comment_id . ',' . Utils::crypt($comment->email . $comment_id)); ob_start(); include $fp; $cont = ob_get_clean(); $pieces = explode(self::END_DEL, $cont); $ret['subject'] = substr($pieces[0], strpos($pieces[0], self::SUBJECT_DEL) + strlen(self::SUBJECT_DEL . PHP_EOL)); $ret['text'] = substr($pieces[1], strpos($pieces[1], self::TEXT_DEL) + strlen(self::TEXT_DEL . PHP_EOL)); $ret['text'] = str_replace($eol_tag, PHP_EOL, $ret['text']); $ret['html'] = substr($pieces[2], strpos($pieces[2], self::HTML_DEL) + strlen(self::HTML_DEL . PHP_EOL)); $ret['html'] = str_replace($eol_tag, '<br />' . PHP_EOL, $ret['html']); return $ret; }