Browse Source

Merge remote-tracking branch 'origin/2.6' into 3.0

Conflicts:
	.travis.yml
	app/Console/cake.bat
	lib/Cake/Cache/Engine/MemcachedEngine.php
	lib/Cake/Console/Templates/skel/Console/cake.bat
	lib/Cake/Console/cake.bat
	lib/Cake/Model/Model.php
	lib/Cake/Model/ModelValidator.php
	lib/Cake/Model/Validator/CakeValidationSet.php
	lib/Cake/Test/Case/Console/Command/Task/ModelTaskTest.php
	lib/Cake/Test/Case/Model/ModelValidationTest.php
	lib/Cake/Test/Case/View/Helper/FormHelperTest.php
	lib/Cake/Test/test_app/Model/Extract.php
	lib/Cake/Test/test_app/Model/PersisterOne.php
	lib/Cake/View/Helper/FormHelper.php
mark_story 11 years ago
parent
commit
f646faef5d

+ 1 - 0
.travis.yml

@@ -27,6 +27,7 @@ matrix:
     - php: hhvm-nightly
       env: HHVM=1 DB=mysql db_class='Cake\Database\Driver\Mysql' db_dsn='mysql:host=0.0.0.0;dbname=cakephp_test' db_database='cakephp_test' db_login='travis' db_password=''
 
+
 before_script:
   - composer self-update
   - composer install --prefer-source --no-interaction --dev

+ 9 - 0
src/Cache/Engine/MemcachedEngine.php

@@ -59,6 +59,8 @@ class MemcachedEngine extends CacheEngine {
  *    appropriate serializer support.
  * - `servers` String or array of memcached servers. If an array MemcacheEngine will use
  *    them as a pool.
+ * - `options` - Additional options for the memcached client. Should be an array of option => value.
+ *    Use the Memcached::OPT_* constants as keys.
  *
  * @var array
  */
@@ -73,6 +75,7 @@ class MemcachedEngine extends CacheEngine {
 		'probability' => 100,
 		'serialize' => 'php',
 		'servers' => ['127.0.0.1'],
+		'options' => [],
 	];
 
 /**
@@ -140,6 +143,12 @@ class MemcachedEngine extends CacheEngine {
 			return false;
 		}
 
+		if (is_array($this->_config['options'])) {
+			foreach ($this->_config['options'] as $opt => $value) {
+				$this->_Memcached->setOption($opt, $value);
+			}
+		}
+
 		if ($this->_config['login'] !== null && $this->_config['password'] !== null) {
 			if (!method_exists($this->_Memcached, 'setSaslAuthData')) {
 				throw new Error\Exception(

+ 6 - 6
src/Console/Command/Task/ExtractTask.php

@@ -123,7 +123,7 @@ class ExtractTask extends Shell {
 			);
 			$response = $this->in($message, null, $defaultPath);
 			if (strtoupper($response) === 'Q') {
-				$this->out(__d('cake_console', 'Extract Aborted'));
+				$this->err(__d('cake_console', 'Extract Aborted'));
 				return $this->_stop();
 			} elseif (strtoupper($response) === 'D' && count($this->_paths)) {
 				$this->out();
@@ -197,7 +197,7 @@ class ExtractTask extends Shell {
 			while (true) {
 				$response = $this->in($message, null, rtrim($this->_paths[0], DS) . DS . 'Locale');
 				if (strtoupper($response) === 'Q') {
-					$this->out(__d('cake_console', 'Extract Aborted'));
+					$this->err(__d('cake_console', 'Extract Aborted'));
 					return $this->_stop();
 				} elseif ($this->_isPathUsable($response)) {
 					$this->_output = $response . DS;
@@ -619,16 +619,16 @@ class ExtractTask extends Shell {
  * @return void
  */
 	protected function _markerError($file, $line, $marker, $count) {
-		$this->out(__d('cake_console', "Invalid marker content in %s:%s\n* %s(", $file, $line, $marker));
+		$this->err(__d('cake_console', "Invalid marker content in %s:%s\n* %s(", $file, $line, $marker));
 		$count += 2;
 		$tokenCount = count($this->_tokens);
 		$parenthesis = 1;
 
 		while ((($tokenCount - $count) > 0) && $parenthesis) {
 			if (is_array($this->_tokens[$count])) {
-				$this->out($this->_tokens[$count][1], false);
+				$this->err($this->_tokens[$count][1], false);
 			} else {
-				$this->out($this->_tokens[$count], false);
+				$this->err($this->_tokens[$count], false);
 				if ($this->_tokens[$count] === '(') {
 					$parenthesis++;
 				}
@@ -639,7 +639,7 @@ class ExtractTask extends Shell {
 			}
 			$count++;
 		}
-		$this->out("\n", true);
+		$this->err("\n", true);
 	}
 
 /**

+ 15 - 1
src/Validation/Validation.php

@@ -99,12 +99,26 @@ class Validation {
  * @param int $max Maximum value in range (inclusive)
  * @return bool Success
  */
-	public static function between($check, $min, $max) {
+	public static function lengthBetween($check, $min, $max) {
 		$length = mb_strlen($check);
 		return ($length >= $min && $length <= $max);
 	}
 
 /**
+ * Alias of Validator::lengthBetween() for backwards compatibility.
+ *
+ * @see Validator::lengthBetween()
+ * @deprecated Deprecated since 2.6, use Validator::lengthBetween() instead.
+ * @param string $check Value to check for length
+ * @param integer $min Minimum value in range (inclusive)
+ * @param integer $max Maximum value in range (inclusive)
+ * @return boolean Success
+ */
+	public static function between($check, $min, $max) {
+		return self::lengthBetween($check, $min, $max);
+	}
+
+/**
  * Returns true if field is left blank -OR- only whitespace characters are present in its value
  * Whitespace characters include Space, Tab, Carriage Return, Newline
  *

+ 20 - 9
src/View/Helper/FormHelper.php

@@ -18,6 +18,7 @@ use Cake\Core\Configure;
 use Cake\Error;
 use Cake\ORM\Entity;
 use Cake\ORM\TableRegistry;
+use Cake\Routing\Router;
 use Cake\Utility\Hash;
 use Cake\Utility\Inflector;
 use Cake\Utility\Security;
@@ -305,9 +306,12 @@ class FormHelper extends Helper {
 		}
 		unset($options['templates']);
 
-		$action = $this->url($this->_formUrl($context, $options));
+		$url = $this->_formUrl($context, $options);
+		$action = $this->url($url);
 		unset($options['url'], $options['action'], $options['idPrefix']);
 
+		$this->_lastAction($url);
+
 		$htmlAttributes = [];
 		switch (strtolower($options['type'])) {
 			case 'get':
@@ -346,13 +350,6 @@ class FormHelper extends Helper {
 			$append = $templater->format('hiddenblock', ['content' => $append]);
 		}
 
-		$this->_lastAction = $action;
-		if (strpos($action, '://')) {
-			$query = parse_url($action, PHP_URL_QUERY);
-			$query = $query ? '?' . $query : '';
-			$this->_lastAction = parse_url($action, PHP_URL_PATH) . $query;
-		}
-
 		$actionAttr = $templater->formatAttributes(['action' => $action, 'escape' => false]);
 		return $templater->format('formstart', [
 			'attrs' => $templater->formatAttributes($htmlAttributes) . $actionAttr
@@ -399,6 +396,19 @@ class FormHelper extends Helper {
 	}
 
 /**
+ * Correctly store the last created form action URL.
+ *
+ * @param string|array $url The URL of the last form.
+ * @return void
+ */
+	protected function _lastAction($url) {
+		$action = Router::url($url, true);
+		$query = parse_url($action, PHP_URL_QUERY);
+		$query = $query ? '?' . $query : '';
+		$this->_lastAction = parse_url($action, PHP_URL_PATH) . $query;
+	}
+
+/**
  * Return a CSRF input if the request data is present.
  * Used to secure forms in conjunction with CsrfComponent &
  * SecurityComponent
@@ -1456,10 +1466,11 @@ class FormHelper extends Helper {
 			unset($options['target']);
 		}
 
+		$this->_lastAction($url);
+
 		$out = $this->formatTemplate('formstart', [
 			'attrs' => $this->templater()->formatAttributes($formOptions)
 		]);
-		$this->_lastAction = $formOptions['action'];
 		$out .= $this->hidden('_method', ['value' => $requestMethod]);
 		$out .= $this->_csrfField();
 

+ 19 - 1
tests/TestCase/Cache/Engine/MemcachedEngineTest.php

@@ -114,7 +114,8 @@ class MemcachedEngineTest extends TestCase {
 			'login' => null,
 			'password' => null,
 			'groups' => array(),
-			'serialize' => 'php'
+			'serialize' => 'php',
+			'options' => array()
 		);
 		$this->assertEquals($expecting, $config);
 	}
@@ -145,6 +146,23 @@ class MemcachedEngineTest extends TestCase {
 	}
 
 /**
+ * test setting options
+ *
+ * @return void
+ */
+	public function testOptionsSetting() {
+		$memcached = new TestMemcachedEngine();
+		$memcached->init(array(
+			'engine' => 'Memcached',
+			'servers' => array('127.0.0.1:11211'),
+			'options' => array(
+				Memcached::OPT_BINARY_PROTOCOL => true
+			)
+		));
+		$this->assertEquals(1, $memcached->getMemcached()->getOption(Memcached::OPT_BINARY_PROTOCOL));
+	}
+
+/**
  * test accepts only valid serializer engine
  *
  * @return  void

+ 7 - 7
tests/TestCase/Validation/ValidationTest.php

@@ -203,17 +203,17 @@ class ValidationTest extends TestCase {
 	}
 
 /**
- * testBetween method
+ * testLengthBetween method
  *
  * @return void
  */
-	public function testBetween() {
-		$this->assertTrue(Validation::between('abcdefg', 1, 7));
-		$this->assertTrue(Validation::between('', 0, 7));
-		$this->assertTrue(Validation::between('אกあアꀀ豈', 1, 7));
+	public function testLengthBetween() {
+		$this->assertTrue(Validation::lengthBetween('abcdefg', 1, 7));
+		$this->assertTrue(Validation::lengthBetween('', 0, 7));
+		$this->assertTrue(Validation::lengthBetween('אกあアꀀ豈', 1, 7));
 
-		$this->assertFalse(Validation::between('abcdefg', 1, 6));
-		$this->assertFalse(Validation::between('ÆΔΩЖÇ', 1, 3));
+		$this->assertFalse(Validation::lengthBetween('abcdefg', 1, 6));
+		$this->assertFalse(Validation::lengthBetween('ÆΔΩЖÇ', 1, 3));
 	}
 
 /**

+ 37 - 0
tests/TestCase/View/Helper/FormHelperTest.php

@@ -1617,6 +1617,43 @@ class FormHelperTest extends TestCase {
 	}
 
 /**
+ * Test that URL, HTML and identifer show up in their hashs.
+ *
+ * @return void
+ */
+	public function testSecuredFormUrlHasHtmlAndIdentifer() {
+		$this->Form->request['_Token'] = array('key' => 'testKey');
+
+		$expected = 'ece0693fb1b19ca116133db1832ac29baaf41ce5%3A';
+		$res = $this->Form->create($this->article, array(
+			'url' => array(
+				'controller' => 'articles',
+				'action' => 'view',
+				'?' => array(
+					'page' => 1,
+					'limit' => 10,
+					'html' => '<>"',
+				),
+				'#' => 'result',
+			),
+		));
+		$result = $this->Form->secure();
+		$this->assertContains($expected, $result);
+
+		$this->Form->create($this->article, array(
+			'url' => 'http://localhost/articles/view?page=1&limit=10&html=%3C%3E%22#result'
+		));
+		$result = $this->Form->secure();
+		$this->assertContains($expected, $result, 'Full URL should only use path and query.');
+
+		$this->Form->create($this->article, array(
+			'url' => '/articles/view?page=1&limit=10&html=%3C%3E%22#result'
+		));
+		$result = $this->Form->secure();
+		$this->assertContains($expected, $result, 'URL path + query should work.');
+	}
+
+/**
  * test error message display
  *
  * @return void