diff --git a/lib/Cake/Console/Command/Task/ViewTask.php b/lib/Cake/Console/Command/Task/ViewTask.php
index 6494b90aa..68eef867d 100644
--- a/lib/Cake/Console/Command/Task/ViewTask.php
+++ b/lib/Cake/Console/Command/Task/ViewTask.php
@@ -327,7 +327,7 @@ class ViewTask extends BakeTask {
 		$this->hr();
 		$this->out(__d('cake_console', 'Controller Name: %s', $this->controllerName));
 		$this->out(__d('cake_console', 'Action Name:     %s', $action));
-		$this->out(__d('cake_console', 'Path:            %s', $this->params['app'] . DS . $this->controllerName . DS . Inflector::underscore($action) . ".ctp"));
+		$this->out(__d('cake_console', 'Path:            %s', $this->params['app'] . DS . 'View' . DS . $this->controllerName . DS . Inflector::underscore($action) . ".ctp"));
 		$this->hr();
 		$looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y','n'), 'y');
 		if (strtolower($looksGood) == 'y') {
diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php
index 6ca24960f..e8912d886 100644
--- a/lib/Cake/Model/Datasource/DboSource.php
+++ b/lib/Cake/Model/Datasource/DboSource.php
@@ -1488,7 +1488,7 @@ class DboSource extends DataSource {
 					$query += array('order' => $assocData['order'], 'limit' => $assocData['limit']);
 				} else {
 					$join = array(
-						'table' => $this->fullTableName($linkModel),
+						'table' => $linkModel,
 						'alias' => $association,
 						'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT',
 						'conditions' => trim($this->conditions($conditions, true, false, $model))
@@ -1527,7 +1527,7 @@ class DboSource extends DataSource {
 					$joinKeys = array($assocData['foreignKey'], $assocData['associationForeignKey']);
 					list($with, $joinFields) = $model->joinModel($assocData['with'], $joinKeys);
 
-					$joinTbl = $this->fullTableName($model->{$with});
+					$joinTbl = $model->{$with};
 					$joinAlias = $joinTbl;
 
 					if (is_array($joinFields) && !empty($joinFields)) {
@@ -1537,8 +1537,8 @@ class DboSource extends DataSource {
 						$joinFields = array();
 					}
 				} else {
-					$joinTbl = $this->fullTableName($assocData['joinTable']);
-					$joinAlias = $joinTbl;
+					$joinTbl = $assocData['joinTable'];
+					$joinAlias = $this->fullTableName($assocData['joinTable']);
 				}
 				$query = array(
 					'conditions' => $assocData['conditions'],
@@ -1622,6 +1622,9 @@ class DboSource extends DataSource {
 		if (!empty($data['conditions'])) {
 			$data['conditions'] = trim($this->conditions($data['conditions'], true, false));
 		}
+		if (!empty($data['table'])) {
+			$data['table'] = $this->fullTableName($data['table']);
+		}
 		return $this->renderJoinStatement($data);
 	}
 
@@ -1904,7 +1907,7 @@ class DboSource extends DataSource {
 			if (isset($model->{$assoc}) && $model->useDbConfig == $model->{$assoc}->useDbConfig && $model->{$assoc}->getDataSource()) {
 				$assocData = $model->getAssociated($assoc);
 				$join[] = $this->buildJoinStatement(array(
-					'table' => $this->fullTableName($model->{$assoc}),
+					'table' => $model->{$assoc},
 					'alias' => $assoc,
 					'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT',
 					'conditions' => trim($this->conditions(
diff --git a/lib/Cake/Network/Email/CakeEmail.php b/lib/Cake/Network/Email/CakeEmail.php
index 679d300c4..31e9f68be 100644
--- a/lib/Cake/Network/Email/CakeEmail.php
+++ b/lib/Cake/Network/Email/CakeEmail.php
@@ -626,7 +626,7 @@ class CakeEmail {
 		}
 		if ($this->_messageId !== false) {
 			if ($this->_messageId === true) {
-				$headers['Message-ID'] = '<' . String::UUID() . '@' . env('HTTP_HOST') . '>';
+				$headers['Message-ID'] = '<' . str_replace('-', '', String::UUID()) . '@' . env('HTTP_HOST') . '>';
 			} else {
 				$headers['Message-ID'] = $this->_messageId;
 			}
@@ -639,9 +639,6 @@ class CakeEmail {
 		$headers['MIME-Version'] = '1.0';
 		if (!empty($this->_attachments)) {
 			$headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->_boundary . '"';
-			$headers[] = 'This part of the E-mail should never be seen. If';
-			$headers[] = 'you are reading this, consider upgrading your e-mail';
-			$headers[] = 'client to a MIME-compatible client.';
 		} elseif ($this->_emailFormat === 'text') {
 			$headers['Content-Type'] = 'text/plain; charset=' . $this->charset;
 		} elseif ($this->_emailFormat === 'html') {
diff --git a/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php b/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php
index 7862f7416..58e409d99 100644
--- a/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php
+++ b/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php
@@ -852,7 +852,7 @@ HTMLBLOC;
 		$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
 		$result = DebugCompTransport::$lastEmail;
 
-		$this->assertPattern('/Message-ID: \<[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}@' . env('HTTP_HOST') . '\>\n/', $result);
+		$this->assertPattern('/Message-ID: \<[a-f0-9]{8}[a-f0-9]{4}[a-f0-9]{4}[a-f0-9]{4}[a-f0-9]{12}@' . env('HTTP_HOST') . '\>\n/', $result);
 
 		$this->Controller->EmailTest->messageId = '<22091985.998877@example.com>';
 
diff --git a/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php b/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php
index 455c1c52c..8d64cae34 100644
--- a/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php
+++ b/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php
@@ -3503,6 +3503,41 @@ class ContainableBehaviorTest extends CakeTestCase {
 		$this->assertEqual($expected, $this->Article->hasAndBelongsToMany);
 	}
 
+/**
+ * test that bindModel and unbindModel work with find() calls in between.
+ */
+	function testBindMultipleTimesWithFind() {
+		$binding = array(
+			'hasOne' => array(
+				'ArticlesTag' => array(
+					'foreignKey' => false,
+					'type' => 'INNER',
+					'conditions' => array(
+						'ArticlesTag.article_id = Article.id'
+					)
+				),
+				'Tag' => array(
+					'type' => 'INNER',
+					'foreignKey' => false,
+					'conditions' => array(
+						'ArticlesTag.tag_id = Tag.id'
+					)
+				)
+			)
+		);
+		$this->Article->unbindModel(array('hasAndBelongsToMany' => array('Tag')));
+		$this->Article->bindModel($binding);
+		$result = $this->Article->find('all', array('limit' => 1, 'contain' => array('ArticlesTag', 'Tag')));
+
+		$this->Article->unbindModel(array('hasAndBelongsToMany' => array('Tag')));
+		$this->Article->bindModel($binding);
+		$result = $this->Article->find('all', array('limit' => 1, 'contain' => array('ArticlesTag', 'Tag')));
+
+		$associated = $this->Article->getAssociated();
+		$this->assertEqual('hasAndBelongsToMany', $associated['Tag']);
+		$this->assertFalse(isset($associated['ArticleTag']));
+	}
+
 /**
  * test that autoFields doesn't splice in fields from other databases.
  *
diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php
index 67f9665e1..c107a078b 100644
--- a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php
+++ b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php
@@ -978,6 +978,7 @@ class MysqlTest extends CakeTestCase {
 			'offset' => array(),
 			'group' => array()
 		);
+		$queryData['joins'][0]['table'] = $this->Dbo->fullTableName($queryData['joins'][0]['table']);
 		$this->assertEqual($queryData, $expected);
 
 		$result = $this->Dbo->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null);
diff --git a/lib/Cake/Test/Case/Model/ModelIntegrationTest.php b/lib/Cake/Test/Case/Model/ModelIntegrationTest.php
index 2140ae195..00e2194c0 100644
--- a/lib/Cake/Test/Case/Model/ModelIntegrationTest.php
+++ b/lib/Cake/Test/Case/Model/ModelIntegrationTest.php
@@ -237,6 +237,44 @@ class ModelIntegrationTest extends BaseModelTest {
 		$this->assertFalse(isset($TestModel->Behaviors->Tree));
 	}
 
+/**
+ * testFindWithJoinsOption method
+ *
+ * @access public
+ * @return void
+ */
+	function testFindWithJoinsOption() {
+		$this->loadFixtures('Article', 'User');
+		$TestUser =& new User();
+
+		$options = array (
+			'fields' => array(
+				'user',
+				'Article.published',
+			),
+			'joins' => array (
+				array (
+					'table' => 'articles',
+					'alias' => 'Article',
+					'type'  => 'LEFT',
+					'conditions' => array(
+						'User.id = Article.user_id',
+					),
+				),
+			),
+			'group' => array('User.user'),
+			'recursive' => -1,
+		);
+		$result = $TestUser->find('all', $options);
+		$expected = array(
+			array('User' => array('user' => 'garrett'), 'Article' => array('published' => '')),
+			array('User' => array('user' => 'larry'), 'Article' => array('published' => 'Y')),
+			array('User' => array('user' => 'mariano'), 'Article' => array('published' => 'Y')),
+			array('User' => array('user' => 'nate'), 'Article' => array('published' => ''))
+		);
+		$this->assertEqual($result, $expected);
+	}
+
 /**
  * Tests cross database joins.  Requires $test and $test2 to both be set in DATABASE_CONFIG
  * NOTE: When testing on MySQL, you must set 'persistent' => false on *both* database connections,
diff --git a/lib/Cake/Test/Case/Model/ModelReadTest.php b/lib/Cake/Test/Case/Model/ModelReadTest.php
index ac7949102..45c078bf2 100644
--- a/lib/Cake/Test/Case/Model/ModelReadTest.php
+++ b/lib/Cake/Test/Case/Model/ModelReadTest.php
@@ -4750,7 +4750,7 @@ class ModelReadTest extends BaseModelTest {
  *
  * @return void
  */
-	public function bindWithCustomPrimaryKey() {
+	public function testBindWithCustomPrimaryKey() {
 		$this->loadFixtures('Story', 'StoriesTag', 'Tag');
 		$Model = ClassRegistry::init('StoriesTag');
 		$Model->bindModel(array(
@@ -5234,7 +5234,7 @@ class ModelReadTest extends BaseModelTest {
 				'group' => null,
 				'joins' => array(array(
 					'alias' => 'ArticlesTag',
-					'table' => $this->db->fullTableName('articles_tags'),
+					'table' => 'articles_tags',
 					'conditions' => array(
 						array("ArticlesTag.article_id" => '{$__cakeID__$}'),
 						array("ArticlesTag.tag_id" => $this->db->identifier('Tag.id'))
diff --git a/lib/Cake/Test/Case/Utility/InflectorTest.php b/lib/Cake/Test/Case/Utility/InflectorTest.php
index db14a0c27..14891f452 100644
--- a/lib/Cake/Test/Case/Utility/InflectorTest.php
+++ b/lib/Cake/Test/Case/Utility/InflectorTest.php
@@ -399,9 +399,11 @@ class InflectorTest extends CakeTestCase {
 		$this->assertEquals('Banazzz', Inflector::singularize('Bananas'), 'Was inflected with old rules.');
 
 		Inflector::rules('plural', array(
-			'rules' => array('/(.*)na$/i' => '\1zzz')
+			'rules' => array('/(.*)na$/i' => '\1zzz'),
+			'irregular' => array('corpus' => 'corpora')
 		));
-		$this->assertEqual('Banazzz', Inflector::pluralize('Banana'), 'Was inflected with old rules.');
+		$this->assertEqual(Inflector::pluralize('Banana'), 'Banazzz', 'Was inflected with old rules.');
+		$this->assertEqual(Inflector::pluralize('corpus'), 'corpora', 'Was inflected with old irregular form.');
 	}
 
 /**
diff --git a/lib/Cake/Test/Case/Utility/ValidationTest.php b/lib/Cake/Test/Case/Utility/ValidationTest.php
index bd2d5dbbd..ae718647b 100644
--- a/lib/Cake/Test/Case/Utility/ValidationTest.php
+++ b/lib/Cake/Test/Case/Utility/ValidationTest.php
@@ -1424,6 +1424,8 @@ class ValidationTest extends CakeTestCase {
 		$this->assertTrue(Validation::time('12:01am'));
 		$this->assertTrue(Validation::time('12:01pm'));
 		$this->assertTrue(Validation::time('1pm'));
+		$this->assertTrue(Validation::time('1 pm'));
+		$this->assertTrue(Validation::time('1 PM'));
 		$this->assertTrue(Validation::time('01:00'));
 		$this->assertFalse(Validation::time('1:00'));
 		$this->assertTrue(Validation::time('1:00pm'));
diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php
index c46d38840..42618aafc 100644
--- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php
+++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php
@@ -1048,6 +1048,20 @@ class FormHelperTest extends CakeTestCase {
 		$this->assertTags($result, $expected);
 	}
 
+/**
+ * Test form security with Model.field.0 style inputs
+ *
+ * @return void
+ */
+	function testFormSecurityArrayFields() {
+		$key = 'testKey';
+
+		$this->Form->request->params['_Token']['key'] = $key;
+		$this->Form->create('Address');
+		$this->Form->input('Address.primary.1');
+		$this->assertEqual('Address.primary', $this->Form->fields[0]);
+	}
+
 /**
  * testFormSecurityMultipleInputDisabledFields method
  *
@@ -1416,6 +1430,62 @@ class FormHelperTest extends CakeTestCase {
 		$this->assertTags($result, $expected);
 	}
 
+/**
+ * testEmptyErrorValidation method
+ *
+ * test validation error div when validation message is an empty string
+ *
+ * @access public
+ * @return void
+ */
+	function testEmptyErrorValidation() {
+		$this->Form->validationErrors['Contact']['password'] = '';
+		$result = $this->Form->input('Contact.password');
+		$expected = array(
+			'div' => array('class' => 'input password error'),
+			'label' => array('for' => 'ContactPassword'),
+			'Password',
+			'/label',
+			'input' => array(
+				'type' => 'password', 'name' => 'data[Contact][password]',
+				'id' => 'ContactPassword', 'class' => 'form-error'
+			),
+			array('div' => array('class' => 'error-message')),
+			array(),
+			'/div',
+			'/div'
+		);
+		$this->assertTags($result, $expected);
+	}
+
+/**
+ * testEmptyInputErrorValidation method
+ *
+ * test validation error div when validation message is overriden by an empty string when calling input()
+ *
+ * @access public
+ * @return void
+ */
+	function testEmptyInputErrorValidation() {
+		$this->Form->validationErrors['Contact']['password'] = 'Please provide a password';
+		$result = $this->Form->input('Contact.password', array('error' => ''));
+		$expected = array(
+			'div' => array('class' => 'input password error'),
+			'label' => array('for' => 'ContactPassword'),
+			'Password',
+			'/label',
+			'input' => array(
+				'type' => 'password', 'name' => 'data[Contact][password]',
+				'id' => 'ContactPassword', 'class' => 'form-error'
+			),
+			array('div' => array('class' => 'error-message')),
+			array(),
+			'/div',
+			'/div'
+		);
+		$this->assertTags($result, $expected);
+	}
+
 /**
  * testFormValidationAssociated method
  *
@@ -6147,7 +6217,7 @@ class FormHelperTest extends CakeTestCase {
 
 		$expected = array(
 			'form' => array(
-				'id' => 'ContactAddForm', 'method' => 'post', 
+				'id' => 'ContactAddForm', 'method' => 'post',
 				'onsubmit' => 'someFunction();event.returnValue = false; return false;',
 				'action' => '/contacts/index/param',
 				'accept-charset' => 'utf-8'
diff --git a/lib/Cake/Utility/Inflector.php b/lib/Cake/Utility/Inflector.php
index 736ac9dd1..a27d4752f 100644
--- a/lib/Cake/Utility/Inflector.php
+++ b/lib/Cake/Utility/Inflector.php
@@ -319,7 +319,11 @@ class Inflector {
 						if ($reset) {
 							self::${$var}[$rule] = $pattern;
 						} else {
-							self::${$var}[$rule] = array_merge($pattern, self::${$var}[$rule]);
+							if ($rule === 'uninflected') {
+								self::${$var}[$rule] = array_merge($pattern, self::${$var}[$rule]);
+							} else {
+								self::${$var}[$rule] = $pattern + self::${$var}[$rule];
+							}
 						}
 						unset($rules[$rule], self::${$var}['cache' . ucfirst($rule)]);
 						if (isset(self::${$var}['merged'][$rule])) {
@@ -332,7 +336,7 @@ class Inflector {
 						}
 					}
 				}
-				self::${$var}['rules'] = array_merge($rules, self::${$var}['rules']);
+				self::${$var}['rules'] = $rules + self::${$var}['rules'];
 			break;
 		}
 	}
diff --git a/lib/Cake/Utility/Validation.php b/lib/Cake/Utility/Validation.php
index 13fe05ca9..11a13e7b5 100644
--- a/lib/Cake/Utility/Validation.php
+++ b/lib/Cake/Utility/Validation.php
@@ -356,7 +356,7 @@ class Validation {
  * @return boolean Success
  */
 	public static function time($check) {
-		return self::_check($check, '%^((0?[1-9]|1[012])(:[0-5]\d){0,2}([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%');
+		return self::_check($check, '%^((0?[1-9]|1[012])(:[0-5]\d){0,2} ?([AP]M|[ap]m))$|^([01]\d|2[0-3])(:[0-5]\d){0,2}$%');
 	}
 
 /**
diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt
index 0c5f1a7b9..6e84590c6 100644
--- a/lib/Cake/VERSION.txt
+++ b/lib/Cake/VERSION.txt
@@ -18,4 +18,3 @@
 // +--------------------------------------------------------------------------------------------+ //
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 2.0.0-RC2
-
diff --git a/lib/Cake/View/Helper.php b/lib/Cake/View/Helper.php
index 6f93005ab..5e4944915 100644
--- a/lib/Cake/View/Helper.php
+++ b/lib/Cake/View/Helper.php
@@ -621,7 +621,7 @@ class Helper extends Object {
 
 		$entity = $this->entity();
 		if (!empty($data) && !empty($entity)) {
-			$result = Set::extract($data, implode('.', $entity));
+			$result = Set::extract(implode('.', $entity), $data);
 		}
 
 		$habtmKey = $this->field();
@@ -666,7 +666,7 @@ class Helper extends Object {
 		$options = $this->_name($options);
 		$options = $this->value($options);
 		$options = $this->domId($options);
-		if ($this->tagIsInvalid()) {
+		if ($this->tagIsInvalid() !== false) {
 			$options = $this->addClass($options, 'form-error');
 		}
 		return $options;
diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php
index 360cec701..13b84d6c3 100644
--- a/lib/Cake/View/Helper/FormHelper.php
+++ b/lib/Cake/View/Helper/FormHelper.php
@@ -271,18 +271,24 @@ class FormHelper extends AppHelper {
  * Returns false if given form field described by the current entity has no errors.
  * Otherwise it returns the validation message
  *
- * @return boolean True on errors.
+ * @return mixed Either false when there or no errors, or the error 
+ *    string. The error string could be ''.
  */
 	public function tagIsInvalid() {
 		$entity = $this->entity();
 		$model = array_shift($entity);
+		$errors = array();
 		if (!empty($entity) && isset($this->validationErrors[$model])) {
-			return Set::classicExtract($this->validationErrors[$model], join('.', $entity));
+			$errors = $this->validationErrors[$model];
 		}
-		if (!empty($entity)) {
+		if (!empty($entity) && empty($errors)) {
 			$errors = $this->_introspectModel($model, 'errors');
-			return ($errors) ? Set::classicExtract($errors, join('.', $entity)) : false;
 		}
+		if (empty($errors)) {
+			return false;
+		}
+		$error = Set::classicExtract($errors, join('.', $entity));
+		return $error === null ? false : $error;
 	}
 
 /**
@@ -598,6 +604,11 @@ class FormHelper extends AppHelper {
 			}
 		}
 
+		$last = end($field);
+		if (is_numeric($last) || empty($last)) {
+			array_pop($field);
+		}
+
 		$field = implode('.', $field);
 
 		if ($lock) {
@@ -645,7 +656,9 @@ class FormHelper extends AppHelper {
 		$defaults = array('wrap' => true, 'class' => 'error-message', 'escape' => true);
 		$options = array_merge($defaults, $options);
 		$this->setEntity($field);
-		if (!$error = $this->tagIsInvalid()) {
+
+		$error = $this->tagIsInvalid();
+		if ($error === false) {
 			return null;
 		}
 		if (is_array($text)) {
@@ -664,7 +677,7 @@ class FormHelper extends AppHelper {
 			$text = $tmp;
 		}
 
-		if ($text != null) {
+		if ($text !== null) {
 			$error = $text;
 		}
 		if (is_array($error)) {