diff --git a/cake/console/templates/default/actions/controller_actions.ctp b/cake/console/templates/default/actions/controller_actions.ctp index b02ad7647..0a4c9d311 100644 --- a/cake/console/templates/default/actions/controller_actions.ctp +++ b/cake/console/templates/default/actions/controller_actions.ctp @@ -72,7 +72,7 @@ if (!$this->->exists()) { throw new NotFoundException(__('Invalid ')); } - if ($this->request->is('post')) { + if ($this->request->is('post') || $this->request->is('put')) { if ($this->->save($this->request->data)) { $this->Session->setFlash(__('The has been saved')); diff --git a/cake/libs/cake_session.php b/cake/libs/cake_session.php index 91ed52f02..2d201f81d 100644 --- a/cake/libs/cake_session.php +++ b/cake/libs/cake_session.php @@ -100,13 +100,6 @@ class CakeSession { */ public static $sessionTime = false; -/** - * Keeps track of keys to watch for writes on - * - * @var array - */ - public static $watchKeys = array(); - /** * Current Session id * @@ -151,14 +144,8 @@ class CakeSession { if (($checkAgent === true || $checkAgent === null) && env('HTTP_USER_AGENT') != null) { self::$_userAgent = md5(env('HTTP_USER_AGENT') . Configure::read('Security.salt')); } - - if ($start === true) { - self::_setPath($base); - self::_setHost(env('HTTP_HOST')); - } - if (isset($_SESSION) || $start === true) { - self::start(); - } + self::_setPath($base); + self::_setHost(env('HTTP_HOST')); } /** @@ -232,6 +219,9 @@ class CakeSession { * @return boolean True if variable is there */ public static function check($name = null) { + if (!self::started() && !self::start()) { + return false; + } if (empty($name)) { return false; } @@ -264,9 +254,6 @@ class CakeSession { */ public static function delete($name) { if (self::check($name)) { - if (in_array($name, self::$watchKeys)) { - throw new CakeSessionException(__('Deleting session key {%s}', $name)); - } self::__overwrite($_SESSION, Set::remove($_SESSION, $name)); return (self::check($name) == false); } @@ -374,6 +361,9 @@ class CakeSession { * @return mixed The value of the session variable */ public static function read($name = null) { + if (!self::started() && !self::start()) { + return false; + } if (is_null($name)) { return self::__returnSessionVars(); } @@ -402,40 +392,6 @@ class CakeSession { return false; } -/** - * Tells Session to write a notification when a certain session path or subpath is written to - * - * @param mixed $var The variable path to watch - * @return void - */ - public static function watch($var) { - if (empty($var)) { - return false; - } - if (!in_array($var, self::$watchKeys, true)) { - self::$watchKeys[] = $var; - } - } - -/** - * Tells Session to stop watching a given key path - * - * @param mixed $var The variable path to watch - * @return void - */ - public static function ignore($var) { - if (!in_array($var, self::$watchKeys)) { - return; - } - foreach (self::$watchKeys as $i => $key) { - if ($key == $var) { - unset(self::$watchKeys[$i]); - self::$watchKeys = array_values(self::$watchKeys); - return; - } - } - } - /** * Writes value to given session variable name. * @@ -444,6 +400,9 @@ class CakeSession { * @return boolean True if the write was successful, false if the write failed */ public static function write($name, $value = null) { + if (!self::started() && !self::start()) { + return false; + } if (empty($name)) { return false; } @@ -452,9 +411,6 @@ class CakeSession { $write = array($name => $value); } foreach ($write as $key => $val) { - if (in_array($key, self::$watchKeys)) { - throw new CakeSessionException(__('Writing session key {%s}: %s', $key, var_export($val, true))); - } self::__overwrite($_SESSION, Set::insert($_SESSION, $key, $val)); if (Set::classicExtract($_SESSION, $key) !== $val) { return false; @@ -672,6 +628,10 @@ class CakeSession { * @return void */ protected static function _checkValid() { + if (!self::started() && !self::start()) { + self::$valid = false; + return false; + } if (self::read('Config')) { $sessionConfig = Configure::read('Session'); diff --git a/cake/libs/cake_socket.php b/cake/libs/cake_socket.php index 3bcb7ca0a..e6f51ee54 100644 --- a/cake/libs/cake_socket.php +++ b/cake/libs/cake_socket.php @@ -100,6 +100,7 @@ class CakeSocket { * Connect the socket to the given host and port. * * @return boolean Success + * @throws SocketException */ public function connect() { if ($this->connection != null) { @@ -112,7 +113,6 @@ class CakeSocket { } if ($this->config['persistent'] == true) { - $tmp = null; $this->connection = @pfsockopen($scheme.$this->config['host'], $this->config['port'], $errNum, $errStr, $this->config['timeout']); } else { $this->connection = @fsockopen($scheme.$this->config['host'], $this->config['port'], $errNum, $errStr, $this->config['timeout']); @@ -120,6 +120,7 @@ class CakeSocket { if (!empty($errNum) || !empty($errStr)) { $this->setLastError($errStr, $errNum); + throw new SocketException($errStr, $errNum); } $this->connected = is_resource($this->connection); @@ -137,9 +138,8 @@ class CakeSocket { public function host() { if (Validation::ip($this->config['host'])) { return gethostbyaddr($this->config['host']); - } else { - return gethostbyaddr($this->address()); } + return gethostbyaddr($this->address()); } /** @@ -150,9 +150,8 @@ class CakeSocket { public function address() { if (Validation::ip($this->config['host'])) { return $this->config['host']; - } else { - return gethostbyname($this->config['host']); } + return gethostbyname($this->config['host']); } /** @@ -163,9 +162,8 @@ class CakeSocket { public function addresses() { if (Validation::ip($this->config['host'])) { return array($this->config['host']); - } else { - return gethostbynamel($this->config['host']); } + return gethostbynamel($this->config['host']); } /** @@ -176,9 +174,8 @@ class CakeSocket { public function lastError() { if (!empty($this->lastError)) { return $this->lastError['num'] . ': ' . $this->lastError['str']; - } else { - return null; } + return null; } /** @@ -186,6 +183,7 @@ class CakeSocket { * * @param integer $errNum Error code * @param string $errStr Error string + * @return void */ public function setLastError($errNum, $errStr) { $this->lastError = array('num' => $errNum, 'str' => $errStr); @@ -229,17 +227,8 @@ class CakeSocket { return false; } return $buffer; - } else { - return false; } - } - -/** - * Abort socket operation. - * - * @return boolean Success - */ - public function abort() { + return false; } /** @@ -272,6 +261,7 @@ class CakeSocket { /** * Resets the state of this Socket instance to it's initial state (before Object::__construct got executed) * + * @param array $state Array with key and values to reset * @return boolean True on success */ public function reset($state = null) { diff --git a/cake/libs/controller/component_collection.php b/cake/libs/controller/component_collection.php index 90ec17f17..b644902a9 100644 --- a/cake/libs/controller/component_collection.php +++ b/cake/libs/controller/component_collection.php @@ -78,7 +78,7 @@ class ComponentCollection extends ObjectCollection { )); } if (!class_exists($componentClass)) { - throw new MissingComponentFileException(array( + throw new MissingComponentClassException(array( 'file' => Inflector::underscore($component) . '.php', 'class' => $componentClass )); diff --git a/cake/libs/controller/components/session.php b/cake/libs/controller/components/session.php index 77ab43a4d..af4474c6c 100644 --- a/cake/libs/controller/components/session.php +++ b/cake/libs/controller/components/session.php @@ -33,17 +33,6 @@ if (!class_exists('cakesession')) { */ class SessionComponent extends Component { -/** - * Constructor automatically starts the session. - * - * @param ComponentCollection $collection A ComponentCollection this component can use to lazy load its components - * @param array $settings Array of configuration settings. - */ - public function __construct(ComponentCollection $collection, $settings = array()) { - parent::__construct($collection, $settings); - CakeSession::start(); - } - /** * Get / Set the userAgent * diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 724fa93aa..e9d0754d4 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -429,7 +429,6 @@ class Controller extends Object { is_array($this->uses) && !empty($appVars['uses']) ) { $this->uses = array_merge($this->uses, array_diff($appVars['uses'], $this->uses)); - var_dump($this->uses); } $this->_mergeVars($merge, 'AppController', true); } diff --git a/cake/libs/error/exceptions.php b/cake/libs/error/exceptions.php index b6d49061d..dc8538334 100644 --- a/cake/libs/error/exceptions.php +++ b/cake/libs/error/exceptions.php @@ -430,6 +430,14 @@ class CakeSessionException extends CakeException { } */ class ConfigureException extends CakeException { } +/** + * Exception class for Socket. This exception will be thrown from CakeSocket, HttpSocket and HttpResponse when it + * encounters an error. + * + * @package cake.libs + */ +class SocketException extends CakeException { } + /** * Exception class for Xml. This exception will be thrown from Xml when it * encounters an error. diff --git a/cake/libs/http/basic_authentication.php b/cake/libs/http/basic_authentication.php new file mode 100644 index 000000000..111246210 --- /dev/null +++ b/cake/libs/http/basic_authentication.php @@ -0,0 +1,68 @@ +request['header']['Authorization'] = self::_generateHeader($authInfo['user'], $authInfo['pass']); + } + } + +/** + * Proxy Authentication + * + * @param HttpSocket $http + * @param array $proxyInfo + * @return void + * @see http://www.ietf.org/rfc/rfc2617.txt + */ + public static function proxyAuthentication(HttpSocket $http, &$proxyInfo) { + if (isset($proxyInfo['user'], $proxyInfo['pass'])) { + $http->request['header']['Proxy-Authorization'] = self::_generateHeader($proxyInfo['user'], $proxyInfo['pass']); + } + } + +/** + * Generate basic [proxy] authentication header + * + * @param string $user + * @param string $pass + * @return string + */ + protected static function _generateHeader($user, $pass) { + return 'Basic ' . base64_encode($user . ':' . $pass); + } + +} diff --git a/cake/libs/http/digest_authentication.php b/cake/libs/http/digest_authentication.php new file mode 100644 index 000000000..21f7ea8e6 --- /dev/null +++ b/cake/libs/http/digest_authentication.php @@ -0,0 +1,106 @@ +request['header']['Authorization'] = self::_generateHeader($http, $authInfo); + } + } + +/** + * Retrive information about the authetication + * + * @param HttpSocket $http + * @parma array $authInfo + * @return boolean + */ + protected static function _getServerInformation(HttpSocket $http, &$authInfo) { + $originalRequest = $http->request; + $http->configAuth(false); + $http->request($http->request); + $http->request = $originalRequest; + $http->configAuth('Digest', $authInfo); + + if (empty($http->response['header']['WWW-Authenticate'])) { + return false; + } + preg_match_all('@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@', $http->response['header']['WWW-Authenticate'], $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $authInfo[$match[1]] = $match[2]; + } + if (!empty($authInfo['qop']) && empty($authInfo['nc'])) { + $authInfo['nc'] = 1; + } + return true; + } + +/** + * Generate the header Authorization + * + * @param HttpSocket $http + * @param array $authInfo + * @return string + */ + protected static function _generateHeader(HttpSocket $http, &$authInfo) { + $a1 = md5($authInfo['user'] . ':' . $authInfo['realm'] . ':' . $authInfo['pass']); + $a2 = md5($http->request['method'] . ':' . $http->request['uri']['path']); + + if (empty($authInfo['qop'])) { + $response = md5($a1 . ':' . $authInfo['nonce'] . ':' . $a2); + } else { + $authInfo['cnonce'] = uniqid(); + $nc = sprintf('%08x', $authInfo['nc']++); + $response = md5($a1 . ':' . $authInfo['nonce'] . ':' . $nc . ':' . $authInfo['cnonce'] . ':auth:' . $a2); + } + + $authHeader = 'Digest '; + $authHeader .= 'username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $authInfo['user']) . '", '; + $authHeader .= 'realm="' . $authInfo['realm'] . '", '; + $authHeader .= 'nonce="' . $authInfo['nonce'] . '", '; + $authHeader .= 'uri="' . $http->request['uri']['path'] . '", '; + $authHeader .= 'response="' . $response . '"'; + if (!empty($authInfo['opaque'])) { + $authHeader .= ', opaque="' . $authInfo['opaque'] . '"'; + } + if (!empty($authInfo['qop'])) { + $authHeader .= ', qop="auth", nc=' . $nc . ', cnonce="' . $authInfo['cnonce'] . '"'; + } + return $authHeader; + } +} diff --git a/cake/libs/http_response.php b/cake/libs/http_response.php new file mode 100644 index 000000000..ade1b14f4 --- /dev/null +++ b/cake/libs/http_response.php @@ -0,0 +1,438 @@ +parseResponse($message); + } + } + +/** + * Body content + * + * @return string + */ + public function body() { + return (string)$this->body; + } + +/** + * Get header in case insensitive + * + * @param string $name Header name + * @return mixed String if header exists or null + */ + public function getHeader($name, $headers = null) { + if (!is_array($headers)) { + $headers =& $this->headers; + } + if (isset($headers[$name])) { + return $headers[$name]; + } + foreach ($headers as $key => $value) { + if (strcasecmp($key, $name) == 0) { + return $value; + } + } + return null; + } + +/** + * If return is 200 (OK) + * + * @return boolean + */ + public function isOk() { + return $this->code == 200; + } + +/** + * Parses the given message and breaks it down in parts. + * + * @param string $message Message to parse + * @return void + * @throw SocketException + */ + public function parseResponse($message) { + if (!is_string($message)) { + throw new SocketException(__('Invalid response.')); + } + + if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) { + throw new SocketException(__('Invalid HTTP response.')); + } + + list(, $statusLine, $header) = $match; + $this->raw = $message; + $this->body = (string)substr($message, strlen($match[0])); + + if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $statusLine, $match)) { + $this->httpVersion = $match[1]; + $this->code = $match[2]; + $this->reasonPhrase = $match[3]; + } + + $this->headers = $this->_parseHeader($header); + $transferEncoding = $this->getHeader('Transfer-Encoding'); + $decoded = $this->_decodeBody($this->body, $transferEncoding); + $this->body = $decoded['body']; + + if (!empty($decoded['header'])) { + $this->headers = $this->_parseHeader($this->_buildHeader($this->headers) . $this->_buildHeader($decoded['header'])); + } + + if (!empty($this->headers)) { + $this->cookies = $this->parseCookies($this->headers); + } + } + +/** + * Generic function to decode a $body with a given $encoding. Returns either an array with the keys + * 'body' and 'header' or false on failure. + * + * @param string $body A string continaing the body to decode. + * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding. + * @return mixed Array of response headers and body or false. + */ + protected function _decodeBody($body, $encoding = 'chunked') { + if (!is_string($body)) { + return false; + } + if (empty($encoding)) { + return array('body' => $body, 'header' => false); + } + $decodeMethod = '_decode' . Inflector::camelize(str_replace('-', '_', $encoding)) . 'Body'; + + if (!is_callable(array(&$this, $decodeMethod))) { + return array('body' => $body, 'header' => false); + } + return $this->{$decodeMethod}($body); + } + +/** + * Decodes a chunked message $body and returns either an array with the keys 'body' and 'header' or false as + * a result. + * + * @param string $body A string continaing the chunked body to decode. + * @return mixed Array of response headers and body or false. + * @throws SocketException + */ + protected function _decodeChunkedBody($body) { + if (!is_string($body)) { + return false; + } + + $decodedBody = null; + $chunkLength = null; + + while ($chunkLength !== 0) { + if (!preg_match("/^([0-9a-f]+) *(?:;(.+)=(.+))?\r\n/iU", $body, $match)) { + throw new SocketException(__('HttpSocket::_decodeChunkedBody - Could not parse malformed chunk.')); + } + + $chunkSize = 0; + $hexLength = 0; + $chunkExtensionName = ''; + $chunkExtensionValue = ''; + if (isset($match[0])) { + $chunkSize = $match[0]; + } + if (isset($match[1])) { + $hexLength = $match[1]; + } + if (isset($match[2])) { + $chunkExtensionName = $match[2]; + } + if (isset($match[3])) { + $chunkExtensionValue = $match[3]; + } + + $body = substr($body, strlen($chunkSize)); + $chunkLength = hexdec($hexLength); + $chunk = substr($body, 0, $chunkLength); + if (!empty($chunkExtensionName)) { + /** + * @todo See if there are popular chunk extensions we should implement + */ + } + $decodedBody .= $chunk; + if ($chunkLength !== 0) { + $body = substr($body, $chunkLength + strlen("\r\n")); + } + } + + $entityHeader = false; + if (!empty($body)) { + $entityHeader = $this->_parseHeader($body); + } + return array('body' => $decodedBody, 'header' => $entityHeader); + } + +/** + * Parses an array based header. + * + * @param array $header Header as an indexed array (field => value) + * @return array Parsed header + */ + protected function _parseHeader($header) { + if (is_array($header)) { + return $header; + } elseif (!is_string($header)) { + return false; + } + + preg_match_all("/(.+):(.+)(?:(?_unescapeToken($field); + + if (!isset($header[$field])) { + $header[$field] = $value; + } else { + $header[$field] = array_merge((array)$header[$field], (array)$value); + } + } + return $header; + } + +/** + * Parses cookies in response headers. + * + * @param array $header Header array containing one ore more 'Set-Cookie' headers. + * @return mixed Either false on no cookies, or an array of cookies recieved. + * @todo Make this 100% RFC 2965 confirm + */ + public function parseCookies($header) { + $cookieHeader = $this->getHeader('Set-Cookie', $header); + if (!$cookieHeader) { + return false; + } + + $cookies = array(); + foreach ((array)$cookieHeader as $cookie) { + if (strpos($cookie, '";"') !== false) { + $cookie = str_replace('";"', "{__cookie_replace__}", $cookie); + $parts = str_replace("{__cookie_replace__}", '";"', explode(';', $cookie)); + } else { + $parts = preg_split('/\;[ \t]*/', $cookie); + } + + list($name, $value) = explode('=', array_shift($parts), 2); + $cookies[$name] = compact('value'); + + foreach ($parts as $part) { + if (strpos($part, '=') !== false) { + list($key, $value) = explode('=', $part); + } else { + $key = $part; + $value = true; + } + + $key = strtolower($key); + if (!isset($cookies[$name][$key])) { + $cookies[$name][$key] = $value; + } + } + } + return $cookies; + } + +/** + * Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs) + * + * @param string $token Token to unescape + * @param array $chars + * @return string Unescaped token + * @todo Test $chars parameter + */ + protected function _unescapeToken($token, $chars = null) { + $regex = '/"([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])"/'; + $token = preg_replace($regex, '\\1', $token); + return $token; + } + +/** + * Gets escape chars according to RFC 2616 (HTTP 1.1 specs). + * + * @param boolean $hex true to get them as HEX values, false otherwise + * @param array $chars + * @return array Escape chars + * @todo Test $chars parameter + */ + protected function _tokenEscapeChars($hex = true, $chars = null) { + if (!empty($chars)) { + $escape = $chars; + } else { + $escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " "); + for ($i = 0; $i <= 31; $i++) { + $escape[] = chr($i); + } + $escape[] = chr(127); + } + + if ($hex == false) { + return $escape; + } + $regexChars = ''; + foreach ($escape as $key => $char) { + $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); + } + return $escape; + } + +/** + * ArrayAccess - Offset Exists + * + * @param mixed $offset + * @return boolean + */ + public function offsetExists($offset) { + return in_array($offset, array('raw', 'status', 'header', 'body', 'cookies')); + } + +/** + * ArrayAccess - Offset Get + * + * @param mixed $offset + * @return mixed + */ + public function offsetGet($offset) { + switch ($offset) { + case 'raw': + $firstLineLength = strpos($this->raw, "\r\n") + 2; + if ($this->raw[$firstLineLength] === "\r") { + $header = null; + } else { + $header = substr($this->raw, $firstLineLength, strpos($this->raw, "\r\n\r\n") - $firstLineLength) . "\r\n"; + } + return array( + 'status-line' => $this->httpVersion . ' ' . $this->code . ' ' . $this->reasonPhrase . "\r\n", + 'header' => $header, + 'body' => $this->body, + 'response' => $this->raw + ); + case 'status': + return array( + 'http-version' => $this->httpVersion, + 'code' => $this->code, + 'reason-phrase' => $this->reasonPhrase + ); + case 'header': + return $this->headers; + case 'body': + return $this->body; + case 'cookies': + return $this->cookies; + } + return null; + } + +/** + * ArrayAccess - 0ffset Set + * + * @param mixed $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset, $value) { + return; + } + +/** + * ArrayAccess - Offset Unset + * + * @param mixed @offset + * @return void + */ + public function offsetUnset($offset) { + return; + } + +/** + * Instance as string + * + * @return string + */ + public function __toString() { + return $this->body(); + } + +} diff --git a/cake/libs/http_socket.php b/cake/libs/http_socket.php index 7433b2bf8..b1df3f25d 100644 --- a/cake/libs/http_socket.php +++ b/cake/libs/http_socket.php @@ -31,29 +31,19 @@ App::import('Core', 'Router'); */ class HttpSocket extends CakeSocket { -/** - * Object description - * - * @var string - * @access public - */ - public $description = 'HTTP-based DataSource Interface'; - /** * When one activates the $quirksMode by setting it to true, all checks meant to * enforce RFC 2616 (HTTP/1.1 specs). * will be disabled and additional measures to deal with non-standard responses will be enabled. * * @var boolean - * @access public */ public $quirksMode = false; /** - * The default values to use for a request + * Contain information about the last request (read only) * * @var array - * @access public */ public $request = array( 'method' => 'GET', @@ -67,11 +57,6 @@ class HttpSocket extends CakeSocket { 'query' => null, 'fragment' => null ), - 'auth' => array( - 'method' => 'Basic', - 'user' => null, - 'pass' => null - ), 'version' => '1.1', 'body' => '', 'line' => null, @@ -84,33 +69,23 @@ class HttpSocket extends CakeSocket { ); /** -* The default structure for storing the response -* -* @var array -* @access public -*/ - public $response = array( - 'raw' => array( - 'status-line' => null, - 'header' => null, - 'body' => null, - 'response' => null - ), - 'status' => array( - 'http-version' => null, - 'code' => null, - 'reason-phrase' => null - ), - 'header' => array(), - 'body' => '', - 'cookies' => array() - ); - -/** - * Default configuration settings for the HttpSocket + * Contain information about the last response (read only) + * + * @var array + */ + public $response = null; + +/** + * Response classname + * + * @var string + */ + public $responseClass = 'HttpResponse'; + +/** + * Configuration settings for the HttpSocket and the requests * * @var array - * @access public */ public $config = array( 'persistent' => false, @@ -124,22 +99,30 @@ class HttpSocket extends CakeSocket { 'host' => 'localhost', 'port' => 80 ), - 'auth' => array( - 'method' => 'Basic', - 'user' => null, - 'pass' => null - ), 'cookies' => array() ) ); /** - * String that represents a line break. + * Authentication settings * - * @var string - * @access public + * @var array */ - public $lineBreak = "\r\n"; + protected $_auth = array(); + +/** + * Proxy settings + * + * @var array + */ + protected $_proxy = array(); + +/** + * Resource to receive the content of request + * + * @var mixed + */ + protected $_contentResource = null; /** * Build an HTTP Socket using the specified configuration. @@ -175,12 +158,72 @@ class HttpSocket extends CakeSocket { parent::__construct($this->config); } +/** + * Set authentication settings + * + * @param string $method Authentication method (ie. Basic, Digest). If empty, disable authentication + * @param mixed $user Username for authentication. Can be an array with settings to authentication class + * @param string $pass Password for authentication + * @return void + */ + public function configAuth($method, $user = null, $pass = null) { + if (empty($method)) { + $this->_auth = array(); + return; + } + if (is_array($user)) { + $this->_auth = array($method => $user); + return; + } + $this->_auth = array($method => compact('user', 'pass')); + } + +/** + * Set proxy settings + * + * @param mixed $host Proxy host. Can be an array with settings to authentication class + * @param integer $port Port. Default 3128. + * @param string $method Proxy method (ie, Basic, Digest). If empty, disable proxy authentication + * @param string $user Username if your proxy need authentication + * @param string $pass Password to proxy authentication + * @return void + */ + public function configProxy($host, $port = 3128, $method = null, $user = null, $pass = null) { + if (empty($host)) { + $this->_proxy = array(); + return; + } + if (is_array($host)) { + $this->_proxy = $host + array('host' => null); + return; + } + $this->_proxy = compact('host', 'port', 'method', 'user', 'pass'); + } + +/** + * Set the resource to receive the request content. This resource must support fwrite. + * + * @param mixed $resource Resource or false to disable the resource use + * @return void + * @throw SocketException + */ + public function setContentResource($resource) { + if ($resource === false) { + $this->_contentResource = null; + return; + } + if (!is_resource($resource)) { + throw new SocketException(__('Invalid resource.')); + } + $this->_contentResource = $resource; + } + /** * Issue the specified request. HttpSocket::get() and HttpSocket::post() wrap this * method and provide a more granular interface. * * @param mixed $request Either an URI string, or an array defining host/uri - * @return mixed false on error, request body on success + * @return mixed false on error, HttpResponse on success */ public function request($request = array()) { $this->reset(false); @@ -195,10 +238,6 @@ class HttpSocket extends CakeSocket { $request['uri'] = null; } $uri = $this->_parseUri($request['uri']); - $hadAuth = false; - if (is_array($uri) && array_key_exists('user', $uri)) { - $hadAuth = true; - } if (!isset($uri['host'])) { $host = $this->config['host']; } @@ -208,25 +247,33 @@ class HttpSocket extends CakeSocket { } $request['uri'] = $this->url($request['uri']); $request['uri'] = $this->_parseUri($request['uri'], true); - $this->request = Set::merge($this->request, $this->config['request'], $request); + $this->request = Set::merge($this->request, array_diff_key($this->config['request'], array('cookies' => true)), $request); - if (!$hadAuth && !empty($this->config['request']['auth']['user'])) { - $this->request['uri']['user'] = $this->config['request']['auth']['user']; - $this->request['uri']['pass'] = $this->config['request']['auth']['pass']; - } $this->_configUri($this->request['uri']); + $Host = $this->request['uri']['host']; + if (!empty($this->config['request']['cookies'][$Host])) { + if (!isset($this->request['cookies'])) { + $this->request['cookies'] = array(); + } + if (!isset($request['cookies'])) { + $request['cookies'] = array(); + } + $this->request['cookies'] = array_merge($this->request['cookies'], $this->config['request']['cookies'][$Host], $request['cookies']); + } + if (isset($host)) { $this->config['host'] = $host; } + $this->_setProxy(); + $this->request['proxy'] = $this->_proxy; + $cookies = null; if (is_array($this->request['header'])) { - $this->request['header'] = $this->_parseHeader($this->request['header']); if (!empty($this->request['cookies'])) { $cookies = $this->buildCookies($this->request['cookies']); } - $Host = $this->request['uri']['host']; $schema = ''; $port = 0; if (isset($this->request['uri']['schema'])) { @@ -245,12 +292,11 @@ class HttpSocket extends CakeSocket { $this->request['header'] = array_merge(compact('Host'), $this->request['header']); } - if (isset($this->request['auth']['user']) && isset($this->request['auth']['pass'])) { - $this->request['header']['Authorization'] = $this->request['auth']['method'] . " " . base64_encode($this->request['auth']['user'] . ":" . $this->request['auth']['pass']); - } - if (isset($this->request['uri']['user']) && isset($this->request['uri']['pass'])) { - $this->request['header']['Authorization'] = $this->request['auth']['method'] . " " . base64_encode($this->request['uri']['user'] . ":" . $this->request['uri']['pass']); + if (isset($this->request['uri']['user'], $this->request['uri']['pass'])) { + $this->configAuth('Basic', $this->request['uri']['user'], $this->request['uri']['pass']); } + $this->_setAuth(); + $this->request['auth'] = $this->_auth; if (is_array($this->request['body'])) { $this->request['body'] = $this->_httpSerialize($this->request['body']); @@ -275,9 +321,10 @@ class HttpSocket extends CakeSocket { } if ($this->quirksMode === false && $this->request['line'] === false) { - return $this->response = false; + return false; } + $this->request['raw'] = ''; if ($this->request['line'] !== false) { $this->request['raw'] = $this->request['line']; } @@ -291,20 +338,46 @@ class HttpSocket extends CakeSocket { $this->write($this->request['raw']); $response = null; + $inHeader = true; while ($data = $this->read()) { - $response .= $data; + if ($this->_contentResource) { + if ($inHeader) { + $response .= $data; + $pos = strpos($response, "\r\n\r\n"); + if ($pos !== false) { + $pos += 4; + $data = substr($response, $pos); + fwrite($this->_contentResource, $data); + + $response = substr($response, 0, $pos); + $inHeader = false; + } + } else { + fwrite($this->_contentResource, $data); + fflush($this->_contentResource); + } + } else { + $response .= $data; + } } - if ($connectionType == 'close') { + if ($connectionType === 'close') { $this->disconnect(); } - $this->response = $this->_parseResponse($response); - if (!empty($this->response['cookies'])) { - $this->config['request']['cookies'] = array_merge($this->config['request']['cookies'], $this->response['cookies']); + if (!App::import('Lib', $this->responseClass)) { + throw new SocketException(__('Class %s not found.', $this->responseClass)); + } + $responseClass = $this->responseClass; + $this->response = new $responseClass($response); + if (!empty($this->response->cookies)) { + if (!isset($this->config['request']['cookies'][$Host])) { + $this->config['request']['cookies'][$Host] = array(); + } + $this->config['request']['cookies'][$Host] = array_merge($this->config['request']['cookies'][$Host], $this->response->cookies); } - return $this->response['body']; + return $this->response; } /** @@ -394,7 +467,7 @@ class HttpSocket extends CakeSocket { } /** - * Normalizes urls into a $uriTemplate. If no template is provided + * Normalizes urls into a $uriTemplate. If no template is provided * a default one will be used. Will generate the url using the * current config information. * @@ -426,10 +499,10 @@ class HttpSocket extends CakeSocket { } if (is_string($url)) { if ($url{0} == '/') { - $url = $this->config['request']['uri']['host'].':'.$this->config['request']['uri']['port'] . $url; + $url = $this->config['request']['uri']['host'] . ':' . $this->config['request']['uri']['port'] . $url; } if (!preg_match('/^.+:\/\/|\*|^\//', $url)) { - $url = $this->config['request']['uri']['scheme'].'://'.$url; + $url = $this->config['request']['uri']['scheme'] . '://' . $url; } } elseif (!is_array($url) && !empty($url)) { return false; @@ -449,159 +522,57 @@ class HttpSocket extends CakeSocket { } /** - * Parses the given message and breaks it down in parts. + * Set authentication in request * - * @param string $message Message to parse - * @return array Parsed message (with indexed elements such as raw, status, header, body) + * @return void + * @throws SocketException */ - protected function _parseResponse($message) { - if (is_array($message)) { - return $message; - } elseif (!is_string($message)) { - return false; + protected function _setAuth() { + if (empty($this->_auth)) { + return; } - - static $responseTemplate; - - if (empty($responseTemplate)) { - $classVars = get_class_vars(__CLASS__); - $responseTemplate = $classVars['response']; + $method = key($this->_auth); + $authClass = Inflector::camelize($method) . 'Authentication'; + if (!App::import('Lib', 'http/' . $authClass)) { + throw new SocketException(__('Unknown authentication method.')); } - - $response = $responseTemplate; - - if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) { - return false; + if (!method_exists($authClass, 'authentication')) { + throw new SocketException(sprintf(__('The %s do not support authentication.'), $authClass)); } - - list($null, $response['raw']['status-line'], $response['raw']['header']) = $match; - $response['raw']['response'] = $message; - $response['raw']['body'] = substr($message, strlen($match[0])); - - if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $response['raw']['status-line'], $match)) { - $response['status']['http-version'] = $match[1]; - $response['status']['code'] = (int)$match[2]; - $response['status']['reason-phrase'] = $match[3]; - } - - $response['header'] = $this->_parseHeader($response['raw']['header']); - $transferEncoding = null; - if (isset($response['header']['Transfer-Encoding'])) { - $transferEncoding = $response['header']['Transfer-Encoding']; - } - $decoded = $this->_decodeBody($response['raw']['body'], $transferEncoding); - $response['body'] = $decoded['body']; - - if (!empty($decoded['header'])) { - $response['header'] = $this->_parseHeader($this->_buildHeader($response['header']).$this->_buildHeader($decoded['header'])); - } - - if (!empty($response['header'])) { - $response['cookies'] = $this->parseCookies($response['header']); - } - - foreach ($response['raw'] as $field => $val) { - if ($val === '') { - $response['raw'][$field] = null; - } - } - - return $response; + call_user_func("$authClass::authentication", $this, &$this->_auth[$method]); } /** - * Generic function to decode a $body with a given $encoding. Returns either an array with the keys - * 'body' and 'header' or false on failure. + * Set the proxy configuration and authentication * - * @param string $body A string continaing the body to decode. - * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding. - * @return mixed Array of response headers and body or false. + * @return void + * @throws SocketException */ - protected function _decodeBody($body, $encoding = 'chunked') { - if (!is_string($body)) { - return false; + protected function _setProxy() { + if (empty($this->_proxy) || !isset($this->_proxy['host'], $this->_proxy['port'])) { + return; } - if (empty($encoding)) { - return array('body' => $body, 'header' => false); + $this->config['host'] = $this->_proxy['host']; + $this->config['port'] = $this->_proxy['port']; + + if (empty($this->_proxy['method']) || !isset($this->_proxy['user'], $this->_proxy['pass'])) { + return; } - $decodeMethod = '_decode'.Inflector::camelize(str_replace('-', '_', $encoding)).'Body'; - - if (!is_callable(array(&$this, $decodeMethod))) { - if (!$this->quirksMode) { - trigger_error(__('HttpSocket::_decodeBody - Unknown encoding: %s. Activate quirks mode to surpress error.', h($encoding)), E_USER_WARNING); - } - return array('body' => $body, 'header' => false); + $authClass = Inflector::camelize($this->_proxy['method']) . 'Authentication'; + if (!App::import('Lib', 'http/' . $authClass)) { + throw new SocketException(__('Unknown authentication method for proxy.')); } - return $this->{$decodeMethod}($body); - } - -/** - * Decodes a chunked message $body and returns either an array with the keys 'body' and 'header' or false as - * a result. - * - * @param string $body A string continaing the chunked body to decode. - * @return mixed Array of response headers and body or false. - */ - protected function _decodeChunkedBody($body) { - if (!is_string($body)) { - return false; + if (!method_exists($authClass, 'proxyAuthentication')) { + throw new SocketException(sprintf(__('The %s do not support proxy authentication.'), $authClass)); } - - $decodedBody = null; - $chunkLength = null; - - while ($chunkLength !== 0) { - if (!preg_match("/^([0-9a-f]+) *(?:;(.+)=(.+))?\r\n/iU", $body, $match)) { - if (!$this->quirksMode) { - trigger_error(__('HttpSocket::_decodeChunkedBody - Could not parse malformed chunk. Activate quirks mode to do this.'), E_USER_WARNING); - return false; - } - break; - } - - $chunkSize = 0; - $hexLength = 0; - $chunkExtensionName = ''; - $chunkExtensionValue = ''; - if (isset($match[0])) { - $chunkSize = $match[0]; - } - if (isset($match[1])) { - $hexLength = $match[1]; - } - if (isset($match[2])) { - $chunkExtensionName = $match[2]; - } - if (isset($match[3])) { - $chunkExtensionValue = $match[3]; - } - - $body = substr($body, strlen($chunkSize)); - $chunkLength = hexdec($hexLength); - $chunk = substr($body, 0, $chunkLength); - if (!empty($chunkExtensionName)) { - /** - * @todo See if there are popular chunk extensions we should implement - */ - } - $decodedBody .= $chunk; - if ($chunkLength !== 0) { - $body = substr($body, $chunkLength+strlen("\r\n")); - } - } - - $entityHeader = false; - if (!empty($body)) { - $entityHeader = $this->_parseHeader($body); - } - return array('body' => $decodedBody, 'header' => $entityHeader); + call_user_func("$authClass::proxyAuthentication", $this, &$this->_proxy); } /** * Parses and sets the specified URI into current request configuration. * * @param mixed $uri URI, See HttpSocket::_parseUri() - * @return array Current configuration settings + * @return boolean If uri has merged in config */ protected function _configUri($uri = null) { if (empty($uri)) { @@ -619,19 +590,18 @@ class HttpSocket extends CakeSocket { } $config = array( 'request' => array( - 'uri' => array_intersect_key($uri, $this->config['request']['uri']), - 'auth' => array_intersect_key($uri, $this->config['request']['auth']) + 'uri' => array_intersect_key($uri, $this->config['request']['uri']) ) ); $this->config = Set::merge($this->config, $config); $this->config = Set::merge($this->config, array_intersect_key($this->config['request']['uri'], $this->config)); - return $this->config; + return true; } /** * Takes a $uri array and turns it into a fully qualified URL string * - * @param mixed $uri Either A $uri array, or a request string. Will use $this->config if left empty. + * @param mixed $uri Either A $uri array, or a request string. Will use $this->config if left empty. * @param string $uriTemplate The Uri template/format to use. * @return mixed A fully qualified URL formated according to $uriTemplate, or false on failure */ @@ -665,7 +635,7 @@ class HttpSocket extends CakeSocket { $uriTemplate = str_replace(':%port', null, $uriTemplate); } foreach ($uri as $property => $value) { - $uriTemplate = str_replace('%'.$property, $value, $uriTemplate); + $uriTemplate = str_replace('%' . $property, $value, $uriTemplate); } if ($uriTemplate === '/*') { @@ -740,7 +710,7 @@ class HttpSocket extends CakeSocket { * - ?key[subKey]=value * - ?key[]=value1&key[]=value2 * - * A leading '?' mark in $query is optional and does not effect the outcome of this function. + * A leading '?' mark in $query is optional and does not effect the outcome of this function. * For the complete capabilities of this implementation take a look at HttpSocketTest::testparseQuery() * * @param mixed $query A query string to parse into an array or an array to return directly "as is" @@ -803,6 +773,7 @@ class HttpSocket extends CakeSocket { * @param array $request Needs to contain a 'uri' key. Should also contain a 'method' key, otherwise defaults to GET. * @param string $versionToken The version token to use, defaults to HTTP/1.1 * @return string Request line + * @throws SocketException */ protected function _buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') { $asteriskMethods = array('OPTIONS'); @@ -810,8 +781,7 @@ class HttpSocket extends CakeSocket { if (is_string($request)) { $isValid = preg_match("/(.+) (.+) (.+)\r\n/U", $request, $match); if (!$this->quirksMode && (!$isValid || ($match[2] == '*' && !in_array($match[3], $asteriskMethods)))) { - trigger_error(__('HttpSocket::_buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.'), E_USER_WARNING); - return false; + throw new SocketException(__('HttpSocket::_buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.')); } return $request; } elseif (!is_array($request)) { @@ -822,13 +792,16 @@ class HttpSocket extends CakeSocket { $request['uri'] = $this->_parseUri($request['uri']); $request = array_merge(array('method' => 'GET'), $request); - $request['uri'] = $this->_buildUri($request['uri'], '/%path?%query'); + if (!empty($this->_proxy['host'])) { + $request['uri'] = $this->_buildUri($request['uri'], '%scheme://%host:%port/%path?%query'); + } else { + $request['uri'] = $this->_buildUri($request['uri'], '/%path?%query'); + } if (!$this->quirksMode && $request['uri'] === '*' && !in_array($request['method'], $asteriskMethods)) { - trigger_error(__('HttpSocket::_buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.', implode(',', $asteriskMethods)), E_USER_WARNING); - return false; + throw new SocketException(__('HttpSocket::_buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.', implode(',', $asteriskMethods))); } - return $request['method'].' '.$request['uri'].' '.$versionToken.$this->lineBreak; + return $request['method'] . ' ' . $request['uri'] . ' ' . $versionToken . "\r\n"; } /** @@ -851,6 +824,7 @@ class HttpSocket extends CakeSocket { * Builds the header. * * @param array $header Header to build + * @param string $mode * @return string Header built from array */ protected function _buildHeader($header, $mode = 'standard') { @@ -860,6 +834,17 @@ class HttpSocket extends CakeSocket { return false; } + $fieldsInHeader = array(); + foreach ($header as $key => $value) { + $lowKey = strtolower($key); + if (array_key_exists($lowKey, $fieldsInHeader)) { + $header[$fieldsInHeader[$lowKey]] = $value; + unset($header[$key]); + } else { + $fieldsInHeader[$lowKey] = $key; + } + } + $returnHeader = ''; foreach ($header as $field => $contents) { if (is_array($contents) && $mode == 'standard') { @@ -869,144 +854,37 @@ class HttpSocket extends CakeSocket { $contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $content); $field = $this->_escapeToken($field); - $returnHeader .= $field.': '.$contents.$this->lineBreak; + $returnHeader .= $field . ': ' . $contents . "\r\n"; } } return $returnHeader; } -/** - * Parses an array based header. - * - * @param array $header Header as an indexed array (field => value) - * @return array Parsed header - */ - protected function _parseHeader($header) { - if (is_array($header)) { - foreach ($header as $field => $value) { - unset($header[$field]); - $field = strtolower($field); - preg_match_all('/(?:^|(?<=-))[a-z]/U', $field, $offsets, PREG_OFFSET_CAPTURE); - - foreach ($offsets[0] as $offset) { - $field = substr_replace($field, strtoupper($offset[0]), $offset[1], 1); - } - $header[$field] = $value; - } - return $header; - } elseif (!is_string($header)) { - return false; - } - - preg_match_all("/(.+):(.+)(?:(?lineBreak . "|\$)/Uis", $header, $matches, PREG_SET_ORDER); - - $header = array(); - foreach ($matches as $match) { - list(, $field, $value) = $match; - - $value = trim($value); - $value = preg_replace("/[\t ]\r\n/", "\r\n", $value); - - $field = $this->_unescapeToken($field); - - $field = strtolower($field); - preg_match_all('/(?:^|(?<=-))[a-z]/U', $field, $offsets, PREG_OFFSET_CAPTURE); - foreach ($offsets[0] as $offset) { - $field = substr_replace($field, strtoupper($offset[0]), $offset[1], 1); - } - - if (!isset($header[$field])) { - $header[$field] = $value; - } else { - $header[$field] = array_merge((array)$header[$field], (array)$value); - } - } - return $header; - } - -/** - * Parses cookies in response headers. - * - * @param array $header Header array containing one ore more 'Set-Cookie' headers. - * @return mixed Either false on no cookies, or an array of cookies recieved. - * @access public - * @todo Make this 100% RFC 2965 confirm - */ - function parseCookies($header) { - if (!isset($header['Set-Cookie'])) { - return false; - } - - $cookies = array(); - foreach ((array)$header['Set-Cookie'] as $cookie) { - if (strpos($cookie, '";"') !== false) { - $cookie = str_replace('";"', "{__cookie_replace__}", $cookie); - $parts = str_replace("{__cookie_replace__}", '";"', explode(';', $cookie)); - } else { - $parts = preg_split('/\;[ \t]*/', $cookie); - } - - list($name, $value) = explode('=', array_shift($parts), 2); - $cookies[$name] = compact('value'); - - foreach ($parts as $part) { - if (strpos($part, '=') !== false) { - list($key, $value) = explode('=', $part); - } else { - $key = $part; - $value = true; - } - - $key = strtolower($key); - if (!isset($cookies[$name][$key])) { - $cookies[$name][$key] = $value; - } - } - } - return $cookies; - } - /** * Builds cookie headers for a request. * * @param array $cookies Array of cookies to send with the request. * @return string Cookie header string to be sent with the request. - * @access public * @todo Refactor token escape mechanism to be configurable */ - function buildCookies($cookies) { + public function buildCookies($cookies) { $header = array(); foreach ($cookies as $name => $cookie) { - $header[] = $name.'='.$this->_escapeToken($cookie['value'], array(';')); + $header[] = $name . '=' . $this->_escapeToken($cookie['value'], array(';')); } - $header = $this->_buildHeader(array('Cookie' => implode('; ', $header)), 'pragmatic'); - return $header; - } - -/** - * Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs) - * - * @param string $token Token to unescape - * @return string Unescaped token - * @access protected - * @todo Test $chars parameter - */ - function _unescapeToken($token, $chars = null) { - $regex = '/"(['.join('', $this->_tokenEscapeChars(true, $chars)).'])"/'; - $token = preg_replace($regex, '\\1', $token); - return $token; + return $this->_buildHeader(array('Cookie' => implode('; ', $header)), 'pragmatic'); } /** * Escapes a given $token according to RFC 2616 (HTTP 1.1 specs) * * @param string $token Token to escape + * @param array $chars * @return string Escaped token - * @access protected * @todo Test $chars parameter */ - function _escapeToken($token, $chars = null) { - $regex = '/(['.join('', $this->_tokenEscapeChars(true, $chars)).'])/'; + protected function _escapeToken($token, $chars = null) { + $regex = '/([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])/'; $token = preg_replace($regex, '"\\1"', $token); return $token; } @@ -1015,11 +893,11 @@ class HttpSocket extends CakeSocket { * Gets escape chars according to RFC 2616 (HTTP 1.1 specs). * * @param boolean $hex true to get them as HEX values, false otherwise + * @param array $chars * @return array Escape chars - * @access protected * @todo Test $chars parameter */ - function _tokenEscapeChars($hex = true, $chars = null) { + protected function _tokenEscapeChars($hex = true, $chars = null) { if (!empty($chars)) { $escape = $chars; } else { @@ -1035,7 +913,7 @@ class HttpSocket extends CakeSocket { } $regexChars = ''; foreach ($escape as $key => $char) { - $escape[$key] = '\\x'.str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); + $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); } return $escape; } @@ -1052,7 +930,7 @@ class HttpSocket extends CakeSocket { if (empty($initalState)) { $initalState = get_class_vars(__CLASS__); } - if ($full == false) { + if (!$full) { $this->request = $initalState['request']; $this->response = $initalState['response']; return true; diff --git a/cake/libs/view/helpers/session.php b/cake/libs/view/helpers/session.php index 0f6aa002d..b12fa3190 100644 --- a/cake/libs/view/helpers/session.php +++ b/cake/libs/view/helpers/session.php @@ -31,19 +31,6 @@ if (!class_exists('CakeSession')) { */ class SessionHelper extends AppHelper { -/** - * Constructor. Starts the session if it has not already been started - * - * @param View $view View instance for this helper - * @param array $settings Settings for the helper. - * @return void - */ - public function __construct(View $view, $settings = array()) { - parent::__construct($view, $settings); - if (!CakeSession::started()) { - CakeSession::start(); - } - } /** * Used to read a session values set in a controller for a key or return values for all keys. * diff --git a/cake/tests/cases/console/libs/task_collection.test.php b/cake/tests/cases/console/libs/task_collection.test.php index da7d6eaef..b89de158c 100644 --- a/cake/tests/cases/console/libs/task_collection.test.php +++ b/cake/tests/cases/console/libs/task_collection.test.php @@ -118,25 +118,4 @@ class TaskCollectionTest extends CakeTestCase { $this->assertEquals(array('Extract'), $result, 'loaded tasks is wrong'); } -/** - * test normalizeObjectArray - * - * @return void - */ - function testnormalizeObjectArray() { - $tasks = array( - 'Html', - 'Foo.Bar' => array('one', 'two'), - 'Something', - 'Banana.Apple' => array('foo' => 'bar') - ); - $result = TaskCollection::normalizeObjectArray($tasks); - $expected = array( - 'Html' => array('class' => 'Html', 'settings' => array()), - 'Bar' => array('class' => 'Foo.Bar', 'settings' => array('one', 'two')), - 'Something' => array('class' => 'Something', 'settings' => array()), - 'Apple' => array('class' => 'Banana.Apple', 'settings' => array('foo' => 'bar')), - ); - $this->assertEquals($expected, $result); - } } \ No newline at end of file diff --git a/cake/tests/cases/libs/all_socket.test.php b/cake/tests/cases/libs/all_socket.test.php index 60802436e..01af39255 100644 --- a/cake/tests/cases/libs/all_socket.test.php +++ b/cake/tests/cases/libs/all_socket.test.php @@ -34,10 +34,12 @@ class AllSocketTest extends PHPUnit_Framework_TestSuite { * @return void */ public static function suite() { - $suite = new PHPUnit_Framework_TestSuite('All Socket related class tests'); + $suite = new CakeTestSuite('All Socket related class tests'); $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'cake_socket.test.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'http_socket.test.php'); + $suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'http_response.test.php'); + $suite->addTestDirectory(CORE_TEST_CASES . DS . 'libs' . DS . 'http'); return $suite; } } \ No newline at end of file diff --git a/cake/tests/cases/libs/cake_session.test.php b/cake/tests/cases/libs/cake_session.test.php index 02fda57e7..e25c9416d 100644 --- a/cake/tests/cases/libs/cake_session.test.php +++ b/cake/tests/cases/libs/cake_session.test.php @@ -88,7 +88,6 @@ class CakeSessionTest extends CakeTestCase { 'ini' => array(), )); TestCakeSession::init(); - TestCakeSession::$watchKeys = array(); } /** @@ -136,10 +135,10 @@ class CakeSessionTest extends CakeTestCase { */ function testSessionPath() { TestCakeSession::init('/index.php'); - $this->assertEqual('/', TestCakeSession::$path); + $this->assertEquals(TestCakeSession::$path, '/'); TestCakeSession::init('/sub_dir/index.php'); - $this->assertEqual('/sub_dir/', TestCakeSession::$path); + $this->assertEquals(TestCakeSession::$path, '/sub_dir/'); } /** @@ -150,7 +149,7 @@ class CakeSessionTest extends CakeTestCase { */ function testCakeSessionPathEmpty() { TestCakeSession::init(''); - $this->assertEqual('/', TestCakeSession::$path, 'Session path is empty, with "" as $base needs to be / %s'); + $this->assertEquals(TestCakeSession::$path, '/', 'Session path is empty, with "" as $base needs to be /'); } /** @@ -161,7 +160,7 @@ class CakeSessionTest extends CakeTestCase { */ function testCakeSessionPathContainsQuestion() { TestCakeSession::init('/index.php?'); - $this->assertEqual('/', TestCakeSession::$path); + $this->assertEquals(TestCakeSession::$path, '/'); } /** @@ -173,7 +172,7 @@ class CakeSessionTest extends CakeTestCase { function testSetHost() { TestCakeSession::init(); TestCakeSession::setHost('cakephp.org'); - $this->assertEqual('cakephp.org', TestCakeSession::$host); + $this->assertEquals(TestCakeSession::$host, 'cakephp.org'); } /** @@ -185,7 +184,7 @@ class CakeSessionTest extends CakeTestCase { function testSetHostWithPort() { TestCakeSession::init(); TestCakeSession::setHost('cakephp.org:443'); - $this->assertEqual('cakephp.org', TestCakeSession::$host); + $this->assertEquals(TestCakeSession::$host, 'cakephp.org'); } /** @@ -238,14 +237,14 @@ class CakeSessionTest extends CakeTestCase { function testSimpleRead() { TestCakeSession::write('testing', '1,2,3'); $result = TestCakeSession::read('testing'); - $this->assertEqual($result, '1,2,3'); + $this->assertEquals('1,2,3', $result); TestCakeSession::write('testing', array('1' => 'one', '2' => 'two','3' => 'three')); $result = TestCakeSession::read('testing.1'); - $this->assertEqual($result, 'one'); + $this->assertEquals('one', $result); $result = TestCakeSession::read('testing'); - $this->assertEqual($result, array('1' => 'one', '2' => 'two', '3' => 'three')); + $this->assertEquals(array('1' => 'one', '2' => 'two', '3' => 'three'), $result); $result = TestCakeSession::read(); $this->assertTrue(isset($result['testing'])); @@ -254,7 +253,7 @@ class CakeSessionTest extends CakeTestCase { TestCakeSession::write('This.is.a.deep.array.my.friend', 'value'); $result = TestCakeSession::read('This.is.a.deep.array.my.friend'); - $this->assertEqual('value', $result); + $this->assertEquals($result, 'value'); } /** @@ -305,13 +304,15 @@ class CakeSessionTest extends CakeTestCase { * @return void */ function testId() { - $expected = session_id(); + TestCakeSession::destroy(); + $result = TestCakeSession::id(); - $this->assertEqual($result, $expected); + $expected = session_id(); + $this->assertEquals($expected, $result); TestCakeSession::id('MySessionId'); $result = TestCakeSession::id(); - $this->assertEqual($result, 'MySessionId'); + $this->assertEquals('MySessionId', $result); } /** @@ -321,10 +322,9 @@ class CakeSessionTest extends CakeTestCase { * @return void */ function testStarted() { - $this->assertTrue(TestCakeSession::started()); - unset($_SESSION); $_SESSION = null; + $this->assertFalse(TestCakeSession::started()); $this->assertTrue(TestCakeSession::start()); $this->assertTrue(TestCakeSession::started()); @@ -339,11 +339,11 @@ class CakeSessionTest extends CakeTestCase { function testError() { TestCakeSession::read('Does.not.exist'); $result = TestCakeSession::error(); - $this->assertEqual($result, "Does.not.exist doesn't exist"); + $this->assertEquals("Does.not.exist doesn't exist", $result); TestCakeSession::delete('Failing.delete'); $result = TestCakeSession::error(); - $this->assertEqual($result, "Failing.delete doesn't exist"); + $this->assertEquals("Failing.delete doesn't exist", $result); } /** @@ -364,47 +364,6 @@ class CakeSessionTest extends CakeTestCase { $this->assertFalse(TestCakeSession::check('Clearing')); } -/** - * testWatchVar method - * - * @expectedException CakeSessionException - * @access public - * @return void - */ - function testWatchVarWrite() { - $this->assertFalse(TestCakeSession::watch(null)); - - TestCakeSession::write('Watching', "I'm watching you"); - TestCakeSession::watch('Watching'); - TestCakeSession::write('Watching', 'They found us!'); - } - -/** - * Test that deleting watched vars causes exceptions - * - * @expectedException CakeSessionException - * @return void - */ - function testWatchVarDelete() { - TestCakeSession::write('Watching', 'I am watching you.'); - - TestCakeSession::watch('Watching'); - TestCakeSession::delete('Watching'); - } - -/** - * testIgnore method - * - * @access public - * @return void - */ - function testIgnore() { - TestCakeSession::write('Watching', "I'm watching you"); - TestCakeSession::watch('Watching'); - TestCakeSession::ignore('Watching'); - $this->assertTrue(TestCakeSession::write('Watching', 'They found us!')); - } - /** * testDestroy method * @@ -448,7 +407,7 @@ class CakeSessionTest extends CakeTestCase { */ function testCheckKeyWithSpaces() { $this->assertTrue(TestCakeSession::write('Session Test', "test")); - $this->assertEqual(TestCakeSession::check('Session Test'), 'test'); + $this->assertEquals('test', TestCakeSession::check('Session Test')); TestCakeSession::delete('Session Test'); $this->assertTrue(TestCakeSession::write('Session Test.Test Case', "test")); @@ -476,7 +435,7 @@ class CakeSessionTest extends CakeTestCase { $this->assertTrue($result); $result = TestCakeSession::read($key); - $this->assertEqual($result, 'haxored'); + $this->assertEquals('haxored', $result); } /** @@ -487,17 +446,17 @@ class CakeSessionTest extends CakeTestCase { */ function testReadingSavedEmpty() { TestCakeSession::write('SessionTestCase', 0); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 0); + $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), '0'); + $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), null); + $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); } /** @@ -541,24 +500,24 @@ class CakeSessionTest extends CakeTestCase { TestCakeSession::start(); TestCakeSession::write('SessionTestCase', 0); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 0); + $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), '0'); + $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), null); + $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 'This is a Test'); + $this->assertEquals('This is a Test', TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); TestCakeSession::write('SessionTestCase', 'This was updated'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 'This was updated'); + $this->assertEquals('This was updated', TestCakeSession::read('SessionTestCase')); TestCakeSession::destroy(); $this->assertNull(TestCakeSession::read('SessionTestCase')); @@ -623,24 +582,24 @@ class CakeSessionTest extends CakeTestCase { TestCakeSession::destroy(); TestCakeSession::write('SessionTestCase', 0); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 0); + $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), '0'); + $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), null); + $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 'This is a Test'); + $this->assertEquals('This is a Test', TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); TestCakeSession::write('SessionTestCase', 'This was updated'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 'This was updated'); + $this->assertEquals('This was updated', TestCakeSession::read('SessionTestCase')); TestCakeSession::destroy(); $this->assertNull(TestCakeSession::read('SessionTestCase')); @@ -686,23 +645,23 @@ class CakeSessionTest extends CakeTestCase { TestCakeSession::start(); TestCakeSession::write('SessionTestCase', 0); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 0); + $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), '0'); + $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), null); + $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 'This is a Test'); + $this->assertEquals('This is a Test', TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'Some additional data'); - $this->assertEqual(TestCakeSession::read('SessionTestCase'), 'Some additional data'); + $this->assertEquals('Some additional data', TestCakeSession::read('SessionTestCase')); TestCakeSession::destroy(); $this->assertNull(TestCakeSession::read('SessionTestCase')); @@ -728,21 +687,21 @@ class CakeSessionTest extends CakeTestCase { TestCakeSession::destroy(); TestCakeSession::write('Test', 'some value'); - $this->assertEqual(CakeSession::$sessionTime, time() + $timeoutSeconds); - $this->assertEqual($_SESSION['Config']['countdown'], 10); - $this->assertEqual($_SESSION['Config']['time'], CakeSession::$sessionTime); - $this->assertEqual(CakeSession::$time, time()); - $this->assertEqual($_SESSION['Config']['time'], time() + $timeoutSeconds); + $this->assertEquals(time() + $timeoutSeconds, CakeSession::$sessionTime); + $this->assertEquals(10, $_SESSION['Config']['countdown']); + $this->assertEquals(CakeSession::$sessionTime, $_SESSION['Config']['time']); + $this->assertEquals(time(), CakeSession::$time); + $this->assertEquals(time() + $timeoutSeconds, $_SESSION['Config']['time']); Configure::write('Session.harden', true); TestCakeSession::destroy(); TestCakeSession::write('Test', 'some value'); - $this->assertEqual(CakeSession::$sessionTime, time() + $timeoutSeconds); - $this->assertEqual($_SESSION['Config']['countdown'], 10); - $this->assertEqual($_SESSION['Config']['time'], CakeSession::$sessionTime); - $this->assertEqual(CakeSession::$time, time()); - $this->assertEqual($_SESSION['Config']['time'], CakeSession::$time + $timeoutSeconds); + $this->assertEquals(time() + $timeoutSeconds, CakeSession::$sessionTime); + $this->assertEquals(10, $_SESSION['Config']['countdown']); + $this->assertEquals(CakeSession::$sessionTime, $_SESSION['Config']['time']); + $this->assertEquals(time(), CakeSession::$time); + $this->assertEquals(CakeSession::$time + $timeoutSeconds, $_SESSION['Config']['time']); } } diff --git a/cake/tests/cases/libs/cake_socket.test.php b/cake/tests/cases/libs/cake_socket.test.php index 48b304060..8359db3bb 100644 --- a/cake/tests/cases/libs/cake_socket.test.php +++ b/cake/tests/cases/libs/cake_socket.test.php @@ -101,6 +101,30 @@ class CakeSocketTest extends CakeTestCase { $this->assertTrue($this->Socket->connected); } +/** + * data provider function for testInvalidConnection + * + * @return array + */ + public static function invalidConnections() { + return array( + array(array('host' => 'invalid.host')), + array(array('host' => '127.0.0.1', 'port' => '70000')) + ); + } + +/** + * testInvalidConnection method + * + * @dataProvider invalidConnections + * @expectedException SocketException + * return void + */ + public function testInvalidConnection($data) { + $this->Socket->config = array_merge($this->Socket->config, $data); + $this->Socket->connect(); + } + /** * testSocketHost method * diff --git a/cake/tests/cases/libs/controller/component_collection.test.php b/cake/tests/cases/libs/controller/component_collection.test.php index ff96199b1..ecdac7775 100644 --- a/cake/tests/cases/libs/controller/component_collection.test.php +++ b/cake/tests/cases/libs/controller/component_collection.test.php @@ -119,162 +119,6 @@ class ComponentCollectionTest extends CakeTestCase { $this->assertEquals(array('Security'), $result, 'enabled components is wrong'); } -/** - * creates mock classes for testing - * - * @return void - */ - protected function _makeMockClasses() { - if (!class_exists('TriggerMockCookieComponent')) { - $this->getMock('CookieComponent', array(), array(), 'TriggerMockCookieComponent', false); - $this->getMock('SecurityComponent', array(), array(), 'TriggerMockSecurityComponent', false); - } - } - -/** - * test triggering callbacks. - * - * @return void - */ - function testTrigger() { - $controller = null; - $this->_makeMockClasses(); - $this->Components->load('TriggerMockCookie'); - $this->Components->load('TriggerMockSecurity'); - - $this->Components->TriggerMockCookie->expects($this->once())->method('startup') - ->with(null); - $this->Components->TriggerMockSecurity->expects($this->once())->method('startup') - ->with(null); - - $this->mockObjects[] = $this->Components->TriggerMockCookie; - $this->mockObjects[] = $this->Components->TriggerMockSecurity; - - $this->assertNull($this->Components->trigger('startup', array(&$controller))); - } - -/** - * test that the initalize callback is triggered on all components even those that are disabled. - * - * @return void - */ - function testTriggerWithTriggerDisabledObjects() { - $controller = 'Not a controller'; - - $this->_makeMockClasses(); - $this->Components->load('TriggerMockCookie', array(), false); - $this->Components->load('TriggerMockSecurity'); - - $this->Components->TriggerMockCookie->expects($this->once())->method('initialize') - ->with($controller); - $this->Components->TriggerMockSecurity->expects($this->once())->method('initialize') - ->with($controller); - - $this->mockObjects[] = $this->Components->TriggerMockCookie; - $this->mockObjects[] = $this->Components->TriggerMockSecurity; - - $result = $this->Components->trigger('initialize', array(&$controller), array('triggerDisabled' => true)); - $this->assertNull($result); - } - -/** - * test trigger and disabled helpers. - * - * @return void - */ - function testTriggerWithDisabledComponents() { - $controller = null; - $this->_makeMockClasses(); - $this->Components->load('TriggerMockCookie'); - $this->Components->load('TriggerMockSecurity'); - - $this->Components->TriggerMockCookie->expects($this->once())->method('startup') - ->with($controller); - $this->Components->TriggerMockSecurity->expects($this->never())->method('startup'); - - $this->mockObjects[] = $this->Components->TriggerMockCookie; - $this->mockObjects[] = $this->Components->TriggerMockSecurity; - - $this->Components->disable('TriggerMockSecurity'); - - $this->assertNull($this->Components->trigger('startup', array(&$controller))); - } - -/** - * test that the collectReturn option works. - * - * @return void - */ - function testTriggerWithCollectReturn() { - $controller = null; - $this->_makeMockClasses(); - $this->Components->load('TriggerMockCookie'); - $this->Components->load('TriggerMockSecurity'); - - $this->Components->TriggerMockCookie->expects($this->once())->method('startup') - ->will($this->returnValue(array('one', 'two'))); - $this->Components->TriggerMockSecurity->expects($this->once())->method('startup') - ->will($this->returnValue(array('three', 'four'))); - - $this->mockObjects[] = $this->Components->TriggerMockCookie; - $this->mockObjects[] = $this->Components->TriggerMockSecurity; - - $result = $this->Components->trigger('startup', array(&$controller), array('collectReturn' => true)); - $expected = array( - array('one', 'two'), - array('three', 'four') - ); - $this->assertEquals($expected, $result); - } - -/** - * test that trigger with break & breakOn works. - * - * @return void - */ - function testTriggerWithBreak() { - $controller = null; - $this->_makeMockClasses(); - $this->Components->load('TriggerMockCookie'); - $this->Components->load('TriggerMockSecurity'); - - $this->Components->TriggerMockCookie->expects($this->once())->method('startup') - ->will($this->returnValue(false)); - $this->Components->TriggerMockSecurity->expects($this->never())->method('startup'); - - $this->mockObjects[] = $this->Components->TriggerMockCookie; - $this->mockObjects[] = $this->Components->TriggerMockSecurity; - - $result = $this->Components->trigger( - 'startup', - array(&$controller), - array('break' => true, 'breakOn' => false) - ); - $this->assertFalse($result); - } - -/** - * test normalizeObjectArray - * - * @return void - */ - function testnormalizeObjectArray() { - $components = array( - 'Html', - 'Foo.Bar' => array('one', 'two'), - 'Something', - 'Banana.Apple' => array('foo' => 'bar') - ); - $result = ComponentCollection::normalizeObjectArray($components); - $expected = array( - 'Html' => array('class' => 'Html', 'settings' => array()), - 'Bar' => array('class' => 'Foo.Bar', 'settings' => array('one', 'two')), - 'Something' => array('class' => 'Something', 'settings' => array()), - 'Apple' => array('class' => 'Banana.Apple', 'settings' => array('foo' => 'bar')), - ); - $this->assertEquals($expected, $result); - } - /** * test getting the controller out of the collection * diff --git a/cake/tests/cases/libs/controller/components/session.test.php b/cake/tests/cases/libs/controller/components/session.test.php index bf605f1df..a2fa96410 100644 --- a/cake/tests/cases/libs/controller/components/session.test.php +++ b/cake/tests/cases/libs/controller/components/session.test.php @@ -143,6 +143,7 @@ class SessionComponentTest extends CakeTestCase { */ function testSessionIdConsistentAcrossRequestAction() { $Session = new SessionComponent($this->ComponentCollection); + $Session->check('Test'); $this->assertTrue(isset($_SESSION)); $Object = new Object(); @@ -287,6 +288,7 @@ class SessionComponentTest extends CakeTestCase { function testSessionId() { unset($_SESSION); $Session = new SessionComponent($this->ComponentCollection); + $Session->check('test'); $this->assertEquals(session_id(), $Session->id()); } diff --git a/cake/tests/cases/libs/http/basic_authentication.test.php b/cake/tests/cases/libs/http/basic_authentication.test.php new file mode 100644 index 000000000..f886a6686 --- /dev/null +++ b/cake/tests/cases/libs/http/basic_authentication.test.php @@ -0,0 +1,66 @@ + + * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests + * @package cake + * @subpackage cake.tests.cases.libs.http + * @since CakePHP(tm) v 2.0.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::import('Core', 'HttpSocket'); +App::import('Lib', 'http/BasicAuthentication'); + +/** + * BasicMethodTest class + * + * @package cake + * @subpackage cake.tests.cases.libs.http + */ +class BasicMethodTest extends CakeTestCase { + +/** + * testAuthentication method + * + * @return void + */ + public function testAuthentication() { + $http = new HttpSocket(); + $auth = array( + 'method' => 'Basic', + 'user' => 'mark', + 'pass' => 'secret' + ); + + BasicAuthentication::authentication($http, $auth); + $this->assertEqual($http->request['header']['Authorization'], 'Basic bWFyazpzZWNyZXQ='); + } + +/** + * testProxyAuthentication method + * + * @return void + */ + public function testProxyAuthentication() { + $http = new HttpSocket(); + $proxy = array( + 'method' => 'Basic', + 'user' => 'mark', + 'pass' => 'secret' + ); + + BasicAuthentication::proxyAuthentication($http, $proxy); + $this->assertEqual($http->request['header']['Proxy-Authorization'], 'Basic bWFyazpzZWNyZXQ='); + } + +} \ No newline at end of file diff --git a/cake/tests/cases/libs/http/digest_authentication.test.php b/cake/tests/cases/libs/http/digest_authentication.test.php new file mode 100644 index 000000000..2166aee24 --- /dev/null +++ b/cake/tests/cases/libs/http/digest_authentication.test.php @@ -0,0 +1,197 @@ + + * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests + * @package cake + * @subpackage cake.tests.cases.libs.http + * @since CakePHP(tm) v 2.0.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ + +App::import('Core', 'HttpSocket'); +App::import('Lib', 'http/DigestAuthentication'); + +class DigestHttpSocket extends HttpSocket { + +/** + * nextHeader attribute + * + * @var string + */ + public $nextHeader = ''; + +/** + * request method + * + * @param mixed $request + * @return void + */ + public function request($request) { + if ($request === false) { + if (isset($this->response['header']['WWW-Authenticate'])) { + unset($this->response['header']['WWW-Authenticate']); + } + return; + } + $this->response['header']['WWW-Authenticate'] = $this->nextHeader; + } + +} + +/** + * DigestAuthenticationTest class + * + * @package cake + * @subpackage cake.tests.cases.libs.http + */ +class DigestAuthenticationTest extends CakeTestCase { + +/** + * Socket property + * + * @var mixed null + */ + public $HttpSocket = null; + +/** + * This function sets up a HttpSocket instance we are going to use for testing + * + * @return void + */ + public function setUp() { + $this->HttpSocket = new DigestHttpSocket(); + $this->HttpSocket->request['method'] = 'GET'; + $this->HttpSocket->request['uri']['path'] = '/'; + } + +/** + * We use this function to clean up after the test case was executed + * + * @return void + */ + function tearDown() { + unset($this->HttpSocket); + } + +/** + * testBasic method + * + * @return void + */ + public function testBasic() { + $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; + $this->assertFalse(isset($this->HttpSocket->request['header']['Authorization'])); + + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $this->assertTrue(isset($this->HttpSocket->request['header']['Authorization'])); + $this->assertEqual($auth['realm'], 'The batcave'); + $this->assertEqual($auth['nonce'], '4cded326c6c51'); + } + +/** + * testQop method + * + * @return void + */ + public function testQop() { + $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $expected = 'Digest username="admin", realm="The batcave", nonce="4cded326c6c51", uri="/", response="da7e2a46b471d77f70a9bb3698c8902b"'; + $this->assertEqual($expected, $this->HttpSocket->request['header']['Authorization']); + $this->assertFalse(isset($auth['qop'])); + $this->assertFalse(isset($auth['nc'])); + + $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51",qop="auth"'; + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $expected = '@Digest username="admin", realm="The batcave", nonce="4cded326c6c51", uri="/", response="[a-z0-9]{32}", qop="auth", nc=00000001, cnonce="[a-z0-9]+"@'; + $this->assertPattern($expected, $this->HttpSocket->request['header']['Authorization']); + $this->assertEqual($auth['qop'], 'auth'); + $this->assertEqual($auth['nc'], 2); + } + +/** + * testOpaque method + * + * @return void + */ + public function testOpaque() { + $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $this->assertFalse(strpos($this->HttpSocket->request['header']['Authorization'], 'opaque="d8ea7aa61a1693024c4cc3a516f49b3c"')); + + $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51",opaque="d8ea7aa61a1693024c4cc3a516f49b3c"'; + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'opaque="d8ea7aa61a1693024c4cc3a516f49b3c"') > 0); + } + +/** + * testMultipleRequest method + * + * @return void + */ + public function testMultipleRequest() { + $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51",qop="auth"'; + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'nc=00000001') > 0); + $this->assertEqual($auth['nc'], 2); + + DigestAuthentication::authentication($this->HttpSocket, $auth); + $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'nc=00000002') > 0); + $this->assertEqual($auth['nc'], 3); + $responsePos = strpos($this->HttpSocket->request['header']['Authorization'], 'response='); + $response = substr($this->HttpSocket->request['header']['Authorization'], $responsePos + 10, 32); + + $this->HttpSocket->nextHeader = ''; + DigestAuthentication::authentication($this->HttpSocket, $auth); + $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'nc=00000003') > 0); + $this->assertEqual($auth['nc'], 4); + $responsePos = strpos($this->HttpSocket->request['header']['Authorization'], 'response='); + $response2 = substr($this->HttpSocket->request['header']['Authorization'], $responsePos + 10, 32); + $this->assertNotEqual($response, $response2); + } + +/** + * testPathChanged method + * + * @return void + */ + public function testPathChanged() { + $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; + $this->HttpSocket->request['uri']['path'] = '/admin'; + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $responsePos = strpos($this->HttpSocket->request['header']['Authorization'], 'response='); + $response = substr($this->HttpSocket->request['header']['Authorization'], $responsePos + 10, 32); + $this->assertNotEqual($response, 'da7e2a46b471d77f70a9bb3698c8902b'); + } + +/** + * testNoDigestResponse method + * + * @return void + */ + public function testNoDigestResponse() { + $this->HttpSocket->nextHeader = false; + $this->HttpSocket->request['uri']['path'] = '/admin'; + $auth = array('user' => 'admin', 'pass' => '1234'); + DigestAuthentication::authentication($this->HttpSocket, $auth); + $this->assertFalse(isset($this->HttpSocket->request['header']['Authorization'])); + } + +} \ No newline at end of file diff --git a/cake/tests/cases/libs/http_response.test.php b/cake/tests/cases/libs/http_response.test.php new file mode 100644 index 000000000..5d1647ebf --- /dev/null +++ b/cake/tests/cases/libs/http_response.test.php @@ -0,0 +1,509 @@ + + * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests + * @package cake + * @subpackage cake.tests.cases.libs + * @since CakePHP(tm) v 1.2.0.4206 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +App::import('Core', 'HttpResponse'); + +/** + * TestHttpResponse class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class TestHttpResponse extends HttpResponse { + +/** + * Convenience method for testing protected method + * + * @param array $header Header as an indexed array (field => value) + * @return array Parsed header + */ + public function parseHeader($header) { + return parent::_parseHeader($header); + } + +/** + * Convenience method for testing protected method + * + * @param string $body A string continaing the body to decode + * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding + * @return mixed Array or false + */ + public function decodeBody($body, $encoding = 'chunked') { + return parent::_decodeBody($body, $encoding); + } + +/** + * Convenience method for testing protected method + * + * @param string $body A string continaing the chunked body to decode + * @return mixed Array or false + */ + public function decodeChunkedBody($body) { + return parent::_decodeChunkedBody($body); + } + +/** + * Convenience method for testing protected method + * + * @param string $token Token to unescape + * @return string Unescaped token + */ + public function unescapeToken($token, $chars = null) { + return parent::_unescapeToken($token, $chars); + } + +/** + * Convenience method for testing protected method + * + * @param boolean $hex true to get them as HEX values, false otherwise + * @return array Escape chars + */ + public function tokenEscapeChars($hex = true, $chars = null) { + return parent::_tokenEscapeChars($hex, $chars); + } + +} + +/** + * HttpResponseTest class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class HttpResponseTest extends CakeTestCase { +/** + * This function sets up a HttpResponse + * + * @return void + */ + public function setUp() { + $this->HttpResponse = new TestHttpResponse(); + } + +/** + * testBody + * + * @return void + */ + public function testBody() { + $this->HttpResponse->body = 'testing'; + $this->assertEqual($this->HttpResponse->body(), 'testing'); + + $this->HttpResponse->body = null; + $this->assertIdentical($this->HttpResponse->body(), ''); + } + +/** + * testToString + * + * @return void + */ + public function testToString() { + $this->HttpResponse->body = 'other test'; + $this->assertEqual($this->HttpResponse->body(), 'other test'); + $this->assertEqual((string)$this->HttpResponse, 'other test'); + $this->assertTrue(strpos($this->HttpResponse, 'test') > 0); + + $this->HttpResponse->body = null; + $this->assertEqual((string)$this->HttpResponse, ''); + } + +/** + * testGetHeadr + * + * @return void + */ + public function testGetHeader() { + $this->HttpResponse->headers = array( + 'foo' => 'Bar', + 'Some' => 'ok', + 'HeAdEr' => 'value', + 'content-Type' => 'text/plain' + ); + + $this->assertEqual($this->HttpResponse->getHeader('foo'), 'Bar'); + $this->assertEqual($this->HttpResponse->getHeader('Foo'), 'Bar'); + $this->assertEqual($this->HttpResponse->getHeader('FOO'), 'Bar'); + $this->assertEqual($this->HttpResponse->getHeader('header'), 'value'); + $this->assertEqual($this->HttpResponse->getHeader('Content-Type'), 'text/plain'); + $this->assertIdentical($this->HttpResponse->getHeader(0), null); + + $this->assertEqual($this->HttpResponse->getHeader('foo', false), 'Bar'); + $this->assertEqual($this->HttpResponse->getHeader('foo', array('foo' => 'not from class')), 'not from class'); + } + +/** + * testIsOk + * + * @return void + */ + public function testIsOk() { + $this->HttpResponse->code = 0; + $this->assertFalse($this->HttpResponse->isOk()); + $this->HttpResponse->code = -1; + $this->assertFalse($this->HttpResponse->isOk()); + $this->HttpResponse->code = 201; + $this->assertFalse($this->HttpResponse->isOk()); + $this->HttpResponse->code = 'what?'; + $this->assertFalse($this->HttpResponse->isOk()); + $this->HttpResponse->code = 200; + $this->assertTrue($this->HttpResponse->isOk()); + } + +/** + * Test that HttpSocket::parseHeader can take apart a given (and valid) $header string and turn it into an array. + * + * @return void + */ + public function testParseHeader() { + $r = $this->HttpResponse->parseHeader(array('foo' => 'Bar', 'fOO-bAr' => 'quux')); + $this->assertEquals($r, array('foo' => 'Bar', 'fOO-bAr' => 'quux')); + + $r = $this->HttpResponse->parseHeader(true); + $this->assertEquals($r, false); + + $header = "Host: cakephp.org\t\r\n"; + $r = $this->HttpResponse->parseHeader($header); + $expected = array( + 'Host' => 'cakephp.org' + ); + $this->assertEquals($r, $expected); + + $header = "Date:Sat, 07 Apr 2007 10:10:25 GMT\r\nX-Powered-By: PHP/5.1.2\r\n"; + $r = $this->HttpResponse->parseHeader($header); + $expected = array( + 'Date' => 'Sat, 07 Apr 2007 10:10:25 GMT', + 'X-Powered-By' => 'PHP/5.1.2' + ); + $this->assertEquals($r, $expected); + + $header = "people: Jim,John\r\nfoo-LAND: Bar\r\ncAKe-PHP: rocks\r\n"; + $r = $this->HttpResponse->parseHeader($header); + $expected = array( + 'people' => 'Jim,John', + 'foo-LAND' => 'Bar', + 'cAKe-PHP' => 'rocks' + ); + $this->assertEquals($r, $expected); + + $header = "People: Jim,John,Tim\r\nPeople: Lisa,Tina,Chelsea\r\n"; + $r = $this->HttpResponse->parseHeader($header); + $expected = array( + 'People' => array('Jim,John,Tim', 'Lisa,Tina,Chelsea') + ); + $this->assertEquals($r, $expected); + + $header = "Multi-Line: I am a \r\nmulti line\t\r\nfield value.\r\nSingle-Line: I am not\r\n"; + $r = $this->HttpResponse->parseHeader($header); + $expected = array( + 'Multi-Line' => "I am a\r\nmulti line\r\nfield value.", + 'Single-Line' => 'I am not' + ); + $this->assertEquals($r, $expected); + + $header = "Esc\"@\"ped: value\r\n"; + $r = $this->HttpResponse->parseHeader($header); + $expected = array( + 'Esc@ped' => 'value' + ); + $this->assertEquals($r, $expected); + } + +/** + * testParseResponse method + * + * @return void + */ + public function testParseResponse() { + $tests = array( + 'simple-request' => array( + 'response' => array( + 'status-line' => "HTTP/1.x 200 OK\r\n", + 'header' => "Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n", + 'body' => "
It's good to be html
" + ), + 'expectations' => array( + 'httpVersion' => 'HTTP/1.x', + 'code' => 200, + 'reasonPhrase' => 'OK', + 'headers' => array('Date' => 'Mon, 16 Apr 2007 04:14:16 GMT', 'Server' => 'CakeHttp Server'), + 'body' => "It's good to be html
" + ) + ), + 'no-header' => array( + 'response' => array( + 'status-line' => "HTTP/1.x 404 OK\r\n", + 'header' => null + ), + 'expectations' => array( + 'code' => 404, + 'headers' => array() + ) + ) + ); + + $testResponse = array(); + $expectations = array(); + + foreach ($tests as $name => $test) { + $testResponse = array_merge($testResponse, $test['response']); + $testResponse['response'] = $testResponse['status-line'] . $testResponse['header'] . "\r\n" . $testResponse['body']; + $this->HttpResponse->parseResponse($testResponse['response']); + $expectations = array_merge($expectations, $test['expectations']); + + foreach ($expectations as $property => $expectedVal) { + $this->assertEquals($this->HttpResponse->{$property}, $expectedVal, 'Test "' . $name . '": response.' . $property . ' - %s'); + } + + foreach (array('status-line', 'header', 'body', 'response') as $field) { + $this->assertEquals($this->HttpResponse['raw'][$field], $testResponse[$field], 'Test response.raw.' . $field . ': %s'); + } + } + } + +/** + * data provider function for testInvalidParseResponseData + * + * @return array + */ + public static function invalidParseResponseDataProvider() { + return array( + array(array('foo' => 'bar')), + array(true), + array("HTTP Foo\r\nBar: La"), + array('HTTP/1.1 TEST ERROR') + ); + } + +/** + * testInvalidParseResponseData + * + * @dataProvider invalidParseResponseDataProvider + * @expectedException SocketException + * return void + */ + public function testInvalidParseResponseData($value) { + $this->HttpResponse->parseResponse($value); + } + +/** + * testDecodeBody method + * + * @return void + */ + public function testDecodeBody() { + $r = $this->HttpResponse->decodeBody(true); + $this->assertEquals($r, false); + + $r = $this->HttpResponse->decodeBody('Foobar', false); + $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); + + $encoding = 'chunked'; + $sample = array( + 'encoded' => "19\r\nThis is a chunked message\r\n0\r\n", + 'decoded' => array('body' => "This is a chunked message", 'header' => false) + ); + + $r = $this->HttpResponse->decodeBody($sample['encoded'], $encoding); + $this->assertEquals($r, $sample['decoded']); + } + +/** + * testDecodeFooCoded + * + * @return void + */ + public function testDecodeFooCoded() { + $r = $this->HttpResponse->decodeBody(true); + $this->assertEquals($r, false); + + $r = $this->HttpResponse->decodeBody('Foobar', false); + $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); + + $encoding = 'foo-bar'; + $sample = array( + 'encoded' => '!Foobar!', + 'decoded' => array('body' => '!Foobar!', 'header' => false), + ); + + $r = $this->HttpResponse->decodeBody($sample['encoded'], $encoding); + $this->assertEquals($r, $sample['decoded']); + } + +/** + * testDecodeChunkedBody method + * + * @return void + */ + public function testDecodeChunkedBody() { + $r = $this->HttpResponse->decodeChunkedBody(true); + $this->assertEquals($r, false); + + $encoded = "19\r\nThis is a chunked message\r\n0\r\n"; + $decoded = "This is a chunked message"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], false); + + $encoded = "19 \r\nThis is a chunked message\r\n0\r\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + + $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\n"; + $decoded = "This is a chunked message\nThat is cool\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], false); + + $encoded = "19\r\nThis is a chunked message\r\nE;foo-chunk=5\r\n\nThat is cool\n\r\n0\r\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], false); + + $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n"; + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r['body'], $decoded); + $this->assertEquals($r['header'], array('foo-header' => 'bar', 'cake' => 'PHP')); + + $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; + $this->expectError(); + $r = $this->HttpResponse->decodeChunkedBody($encoded); + $this->assertEquals($r, false); + } + +/** + * testParseCookies method + * + * @return void + */ + public function testParseCookies() { + $header = array( + 'Set-Cookie' => array( + 'foo=bar', + 'people=jim,jack,johnny";";Path=/accounts', + 'google=not=nice' + ), + 'Transfer-Encoding' => 'chunked', + 'Date' => 'Sun, 18 Nov 2007 18:57:42 GMT', + ); + $cookies = $this->HttpResponse->parseCookies($header); + $expected = array( + 'foo' => array( + 'value' => 'bar' + ), + 'people' => array( + 'value' => 'jim,jack,johnny";"', + 'path' => '/accounts', + ), + 'google' => array( + 'value' => 'not=nice', + ) + ); + $this->assertEqual($cookies, $expected); + + $header['Set-Cookie'][] = 'cakephp=great; Secure'; + $expected['cakephp'] = array('value' => 'great', 'secure' => true); + $cookies = $this->HttpResponse->parseCookies($header); + $this->assertEqual($cookies, $expected); + + $header['Set-Cookie'] = 'foo=bar'; + unset($expected['people'], $expected['cakephp'], $expected['google']); + $cookies = $this->HttpResponse->parseCookies($header); + $this->assertEqual($cookies, $expected); + } + +/** + * Test that escaped token strings are properly unescaped by HttpSocket::unescapeToken + * + * @return void + */ + public function testUnescapeToken() { + $this->assertEquals($this->HttpResponse->unescapeToken('Foo'), 'Foo'); + + $escape = $this->HttpResponse->tokenEscapeChars(false); + foreach ($escape as $char) { + $token = 'My-special-"' . $char . '"-Token'; + $unescapedToken = $this->HttpResponse->unescapeToken($token); + $expectedToken = 'My-special-' . $char . '-Token'; + + $this->assertEquals($unescapedToken, $expectedToken, 'Test token unescaping for ASCII '.ord($char)); + } + + $token = 'Extreme-":"Token-" "-""""@"-test'; + $escapedToken = $this->HttpResponse->unescapeToken($token); + $expectedToken = 'Extreme-:Token- -"@-test'; + $this->assertEquals($expectedToken, $escapedToken); + } + +/** + * testArrayAccess + * + * @return void + */ + public function testArrayAccess() { + $this->HttpResponse->httpVersion = 'HTTP/1.1'; + $this->HttpResponse->code = 200; + $this->HttpResponse->reasonPhrase = 'OK'; + $this->HttpResponse->headers = array( + 'Server' => 'CakePHP', + 'ContEnt-Type' => 'text/plain' + ); + $this->HttpResponse->cookies = array( + 'foo' => array('value' => 'bar'), + 'bar' => array('value' => 'foo') + ); + $this->HttpResponse->body = 'This is a test!'; + $this->HttpResponse->raw = "HTTP/1.1 200 OK\r\nServer: CakePHP\r\nContEnt-Type: text/plain\r\n\r\nThis is a test!"; + + $expected1 = "HTTP/1.1 200 OK\r\n"; + $this->assertEqual($this->HttpResponse['raw']['status-line'], $expected1); + $expected2 = "Server: CakePHP\r\nContEnt-Type: text/plain\r\n"; + $this->assertEqual($this->HttpResponse['raw']['header'], $expected2); + $expected3 = 'This is a test!'; + $this->assertEqual($this->HttpResponse['raw']['body'], $expected3); + $expected = $expected1 . $expected2 . "\r\n" . $expected3; + $this->assertEqual($this->HttpResponse['raw']['response'], $expected); + + $expected = 'HTTP/1.1'; + $this->assertEqual($this->HttpResponse['status']['http-version'], $expected); + $expected = 200; + $this->assertEqual($this->HttpResponse['status']['code'], $expected); + $expected = 'OK'; + $this->assertEqual($this->HttpResponse['status']['reason-phrase'], $expected); + + $expected = array( + 'Server' => 'CakePHP', + 'ContEnt-Type' => 'text/plain' + ); + $this->assertEqual($this->HttpResponse['header'], $expected); + + $expected = 'This is a test!'; + $this->assertEqual($this->HttpResponse['body'], $expected); + + $expected = array( + 'foo' => array('value' => 'bar'), + 'bar' => array('value' => 'foo') + ); + $this->assertEqual($this->HttpResponse['cookies'], $expected); + + $this->HttpResponse->raw = "HTTP/1.1 200 OK\r\n\r\nThis is a test!"; + $this->assertIdentical($this->HttpResponse['raw']['header'], null); + } + +} \ No newline at end of file diff --git a/cake/tests/cases/libs/http_socket.test.php b/cake/tests/cases/libs/http_socket.test.php index 5b3f79e0c..cefd649e2 100644 --- a/cake/tests/cases/libs/http_socket.test.php +++ b/cake/tests/cases/libs/http_socket.test.php @@ -19,6 +19,65 @@ */ App::import('Core', 'HttpSocket'); +/** + * TestAuthentication class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class TestAuthentication { + +/** + * authentication method + * + * @param HttpSocket $http + * @param array $authInfo + * @return void + */ + public static function authentication(HttpSocket $http, &$authInfo) { + $http->request['header']['Authorization'] = 'Test ' . $authInfo['user'] . '.' . $authInfo['pass']; + } + +/** + * proxyAuthentication method + * + * @param HttpSocket $http + * @param array $proxyInfo + * @return void + */ + public static function proxyAuthentication(HttpSocket $http, &$proxyInfo) { + $http->request['header']['Proxy-Authorization'] = 'Test ' . $proxyInfo['user'] . '.' . $proxyInfo['pass']; + } + +} + +/** + * CustomResponse + * + */ +class CustomResponse { + +/** + * First 10 chars + * + * @var string + */ + public $first10; + +/** + * Constructor + * + */ + public function __construct($message) { + $this->first10 = substr($message, 0, 10); + } + +} + +/** + * TestHttpSocket + * + */ class TestHttpSocket extends HttpSocket { /** @@ -27,7 +86,7 @@ class TestHttpSocket extends HttpSocket { * @param mixed $uri URI (see {@link _parseUri()}) * @return array Current configuration settings */ - function configUri($uri = null) { + public function configUri($uri = null) { return parent::_configUri($uri); } @@ -38,7 +97,7 @@ class TestHttpSocket extends HttpSocket { * @param mixed $base If true use default URI config, otherwise indexed array to set 'scheme', 'host', 'port', etc. * @return array Parsed URI */ - function parseUri($uri = null, $base = array()) { + public function parseUri($uri = null, $base = array()) { return parent::_parseUri($uri, $base); } @@ -49,7 +108,7 @@ class TestHttpSocket extends HttpSocket { * @param string $uriTemplate The Uri template/format to use * @return string A fully qualified URL formated according to $uriTemplate */ - function buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { + public function buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { return parent::_buildUri($uri, $uriTemplate); } @@ -59,61 +118,20 @@ class TestHttpSocket extends HttpSocket { * @param array $header Header to build * @return string Header built from array */ - function buildHeader($header, $mode = 'standard') { + public function buildHeader($header, $mode = 'standard') { return parent::_buildHeader($header, $mode); } -/** - * Convenience method for testing protected method - * - * @param string $message Message to parse - * @return array Parsed message (with indexed elements such as raw, status, header, body) - */ - function parseResponse($message) { - return parent::_parseResponse($message); - } - -/** - * Convenience method for testing protected method - * - * @param array $header Header as an indexed array (field => value) - * @return array Parsed header - */ - function parseHeader($header) { - return parent::_parseHeader($header); - } - /** * Convenience method for testing protected method * * @param mixed $query A query string to parse into an array or an array to return directly "as is" * @return array The $query parsed into a possibly multi-level array. If an empty $query is given, an empty array is returned. */ - function parseQuery($query) { + public function parseQuery($query) { return parent::_parseQuery($query); } -/** - * Convenience method for testing protected method - * - * @param string $body A string continaing the body to decode - * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding - * @return mixed Array or false - */ - function decodeBody($body, $encoding = 'chunked') { - return parent::_decodeBody($body, $encoding); - } - -/** - * Convenience method for testing protected method - * - * @param string $body A string continaing the chunked body to decode - * @return mixed Array or false - */ - function decodeChunkedBody($body) { - return parent::_decodeChunkedBody($body); - } - /** * Convenience method for testing protected method * @@ -121,7 +139,7 @@ class TestHttpSocket extends HttpSocket { * @param string $versionToken The version token to use, defaults to HTTP/1.1 * @return string Request line */ - function buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') { + public function buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') { return parent::_buildRequestLine($request, $versionToken); } @@ -131,7 +149,7 @@ class TestHttpSocket extends HttpSocket { * @param boolean $hex true to get them as HEX values, false otherwise * @return array Escape chars */ - function tokenEscapeChars($hex = true, $chars = null) { + public function tokenEscapeChars($hex = true, $chars = null) { return parent::_tokenEscapeChars($hex, $chars); } @@ -141,19 +159,10 @@ class TestHttpSocket extends HttpSocket { * @param string $token Token to escape * @return string Escaped token */ - function EscapeToken($token, $chars = null) { + public function EscapeToken($token, $chars = null) { return parent::_escapeToken($token, $chars); } -/** - * Convenience method for testing protected method - * - * @param string $token Token to unescape - * @return string Unescaped token - */ - function unescapeToken($token, $chars = null) { - return parent::_unescapeToken($token, $chars); - } } /** @@ -168,7 +177,6 @@ class HttpSocketTest extends CakeTestCase { * Socket property * * @var mixed null - * @access public */ public $Socket = null; @@ -176,17 +184,15 @@ class HttpSocketTest extends CakeTestCase { * RequestSocket property * * @var mixed null - * @access public */ public $RequestSocket = null; /** * This function sets up a TestHttpSocket instance we are going to use for testing * - * @access public * @return void */ - function setUp() { + public function setUp() { if (!class_exists('MockHttpSocket')) { $this->getMock('TestHttpSocket', array('read', 'write', 'connect'), array(), 'MockHttpSocket'); $this->getMock('TestHttpSocket', array('read', 'write', 'connect', 'request'), array(), 'MockHttpSocketRequests'); @@ -199,20 +205,18 @@ class HttpSocketTest extends CakeTestCase { /** * We use this function to clean up after the test case was executed * - * @access public * @return void */ - function tearDown() { + public function tearDown() { unset($this->Socket, $this->RequestSocket); } /** * Test that HttpSocket::__construct does what one would expect it to do * - * @access public * @return void */ - function testConstruct() { + public function testConstruct() { $this->Socket->reset(); $baseConfig = $this->Socket->config; $this->Socket->expects($this->never())->method('connect'); @@ -220,13 +224,12 @@ class HttpSocketTest extends CakeTestCase { $baseConfig['host'] = 'foo-bar'; $baseConfig['protocol'] = getprotobyname($baseConfig['protocol']); $this->assertEquals($this->Socket->config, $baseConfig); + $this->Socket->reset(); $baseConfig = $this->Socket->config; $this->Socket->__construct('http://www.cakephp.org:23/'); - $baseConfig['host'] = 'www.cakephp.org'; - $baseConfig['request']['uri']['host'] = 'www.cakephp.org'; - $baseConfig['port'] = 23; - $baseConfig['request']['uri']['port'] = 23; + $baseConfig['host'] = $baseConfig['request']['uri']['host'] = 'www.cakephp.org'; + $baseConfig['port'] = $baseConfig['request']['uri']['port'] = 23; $baseConfig['protocol'] = getprotobyname($baseConfig['protocol']); $this->assertEquals($this->Socket->config, $baseConfig); @@ -238,269 +241,275 @@ class HttpSocketTest extends CakeTestCase { /** * Test that HttpSocket::configUri works properly with different types of arguments * - * @access public * @return void */ - function testConfigUri() { + public function testConfigUri() { $this->Socket->reset(); $r = $this->Socket->configUri('https://bob:secret@www.cakephp.org:23/?query=foo'); $expected = array( 'persistent' => false, - 'host' => 'www.cakephp.org', - 'protocol' => 'tcp', - 'port' => 23, - 'timeout' => 30, + 'host' => 'www.cakephp.org', + 'protocol' => 'tcp', + 'port' => 23, + 'timeout' => 30, 'request' => array( 'uri' => array( - 'scheme' => 'https' - , 'host' => 'www.cakephp.org' - , 'port' => 23 - ), - 'auth' => array( - 'method' => 'Basic' - , 'user' => 'bob' - , 'pass' => 'secret' - ), - 'cookies' => array(), - ) - ); - $this->assertEquals($this->Socket->config, $expected); - $this->assertEquals($r, $expected); - $r = $this->Socket->configUri(array('host' => 'www.foo-bar.org')); - $expected['host'] = 'www.foo-bar.org'; - $expected['request']['uri']['host'] = 'www.foo-bar.org'; - $this->assertEquals($this->Socket->config, $expected); - $this->assertEquals($r, $expected); - - $r = $this->Socket->configUri('http://www.foo.com'); - $expected = array( - 'persistent' => false, - 'host' => 'www.foo.com', - 'protocol' => 'tcp', - 'port' => 80, - 'timeout' => 30, - 'request' => array( - 'uri' => array( - 'scheme' => 'http' - , 'host' => 'www.foo.com' - , 'port' => 80 - ), - 'auth' => array( - 'method' => 'Basic' - , 'user' => null - , 'pass' => null + 'scheme' => 'https', + 'host' => 'www.cakephp.org', + 'port' => 23 ), 'cookies' => array() ) ); $this->assertEquals($this->Socket->config, $expected); - $this->assertEquals($r, $expected); + $this->assertTrue($r); + $r = $this->Socket->configUri(array('host' => 'www.foo-bar.org')); + $expected['host'] = 'www.foo-bar.org'; + $expected['request']['uri']['host'] = 'www.foo-bar.org'; + $this->assertEquals($this->Socket->config, $expected); + $this->assertTrue($r); + + $r = $this->Socket->configUri('http://www.foo.com'); + $expected = array( + 'persistent' => false, + 'host' => 'www.foo.com', + 'protocol' => 'tcp', + 'port' => 80, + 'timeout' => 30, + 'request' => array( + 'uri' => array( + 'scheme' => 'http', + 'host' => 'www.foo.com', + 'port' => 80 + ), + 'cookies' => array() + ) + ); + $this->assertEquals($this->Socket->config, $expected); + $this->assertTrue($r); $r = $this->Socket->configUri('/this-is-broken'); $this->assertEquals($this->Socket->config, $expected); - $this->assertEquals($r, false); + $this->assertFalse($r); $r = $this->Socket->configUri(false); $this->assertEquals($this->Socket->config, $expected); - $this->assertEquals($r, false); + $this->assertFalse($r); } /** * Tests that HttpSocket::request (the heart of the HttpSocket) is working properly. * - * @access public * @return void */ - function testRequest() { + public function testRequest() { $this->Socket->reset(); $response = $this->Socket->request(true); $this->assertFalse($response); $tests = array( - 0 => array( - 'request' => 'http://www.cakephp.org/?foo=bar' - , 'expectation' => array( + array( + 'request' => 'http://www.cakephp.org/?foo=bar', + 'expectation' => array( 'config' => array( - 'persistent' => false - , 'host' => 'www.cakephp.org' - , 'protocol' => 'tcp' - , 'port' => 80 - , 'timeout' => 30 - , 'request' => array( + 'persistent' => false, + 'host' => 'www.cakephp.org', + 'protocol' => 'tcp', + 'port' => 80, + 'timeout' => 30, + 'request' => array( 'uri' => array ( - 'scheme' => 'http' - , 'host' => 'www.cakephp.org' - , 'port' => 80, - ) - , 'auth' => array( - 'method' => 'Basic' - ,'user' => null - ,'pass' => null + 'scheme' => 'http', + 'host' => 'www.cakephp.org', + 'port' => 80 ), 'cookies' => array(), + ) + ), + 'request' => array( + 'method' => 'GET', + 'uri' => array( + 'scheme' => 'http', + 'host' => 'www.cakephp.org', + 'port' => 80, + 'user' => null, + 'pass' => null, + 'path' => '/', + 'query' => array('foo' => 'bar'), + 'fragment' => null ), - ) - , 'request' => array( - 'method' => 'GET' - , 'uri' => array( - 'scheme' => 'http' - , 'host' => 'www.cakephp.org' - , 'port' => 80 - , 'user' => null - , 'pass' => null - , 'path' => '/' - , 'query' => array('foo' => 'bar') - , 'fragment' => null - ) - , 'auth' => array( - 'method' => 'Basic' - , 'user' => null - , 'pass' => null - ) - , 'version' => '1.1' - , 'body' => '' - , 'line' => "GET /?foo=bar HTTP/1.1\r\n" - , 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n" - , 'raw' => "" - , 'cookies' => array(), + 'version' => '1.1', + 'body' => '', + 'line' => "GET /?foo=bar HTTP/1.1\r\n", + 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n", + 'raw' => "", + 'cookies' => array(), + 'proxy' => array(), + 'auth' => array() ) ) - ) - , 1 => array( + ), + array( 'request' => array( 'uri' => array( - 'host' => 'www.cakephp.org' - , 'query' => '?foo=bar' + 'host' => 'www.cakephp.org', + 'query' => '?foo=bar' ) ) - ) - , 2 => array( + ), + array( 'request' => 'www.cakephp.org/?foo=bar' - ) - , 3 => array( - 'request' => array('host' => '192.168.0.1', 'uri' => 'http://www.cakephp.org/?foo=bar') - , 'expectation' => array( + ), + array( + 'request' => array( + 'host' => '192.168.0.1', + 'uri' => 'http://www.cakephp.org/?foo=bar' + ), + 'expectation' => array( 'request' => array( 'uri' => array('host' => 'www.cakephp.org') - ) - , 'config' => array( + ), + 'config' => array( 'request' => array( 'uri' => array('host' => 'www.cakephp.org') - ) - , 'host' => '192.168.0.1' + ), + 'host' => '192.168.0.1' ) ) - ) - , 'reset4' => array( + ), + 'reset4' => array( 'request.uri.query' => array() - ) - , 4 => array( - 'request' => array('header' => array('Foo@woo' => 'bar-value')) - , 'expectation' => array( + ), + array( + 'request' => array( + 'header' => array('Foo@woo' => 'bar-value') + ), + 'expectation' => array( 'request' => array( - 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n" - , 'line' => "GET / HTTP/1.1\r\n" + 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n", + 'line' => "GET / HTTP/1.1\r\n" ) ) - ) - , 5 => array( - 'request' => array('header' => array('Foo@woo' => 'bar-value', 'host' => 'foo.com'), 'uri' => 'http://www.cakephp.org/') - , 'expectation' => array( + ), + array( + 'request' => array('header' => array('Foo@woo' => 'bar-value', 'host' => 'foo.com'), 'uri' => 'http://www.cakephp.org/'), + 'expectation' => array( 'request' => array( 'header' => "Host: foo.com\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n" - ) - , 'config' => array( + ), + 'config' => array( 'host' => 'www.cakephp.org' ) ) - ) - , 6 => array( - 'request' => array('header' => "Foo: bar\r\n") - , 'expectation' => array( + ), + array( + 'request' => array('header' => "Foo: bar\r\n"), + 'expectation' => array( 'request' => array( 'header' => "Foo: bar\r\n" ) ) - ) - , 7 => array( - 'request' => array('header' => "Foo: bar\r\n", 'uri' => 'http://www.cakephp.org/search?q=http_socket#ignore-me') - , 'expectation' => array( + ), + array( + 'request' => array('header' => "Foo: bar\r\n", 'uri' => 'http://www.cakephp.org/search?q=http_socket#ignore-me'), + 'expectation' => array( 'request' => array( 'uri' => array( - 'path' => '/search' - , 'query' => array('q' => 'http_socket') - , 'fragment' => 'ignore-me' - ) - , 'line' => "GET /search?q=http_socket HTTP/1.1\r\n" + 'path' => '/search', + 'query' => array('q' => 'http_socket'), + 'fragment' => 'ignore-me' + ), + 'line' => "GET /search?q=http_socket HTTP/1.1\r\n" ) ) - ) - , 'reset8' => array( + ), + 'reset8' => array( 'request.uri.query' => array() - ) - , 8 => array( - 'request' => array('method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')) - , 'expectation' => array( + ), + array( + 'request' => array( + 'method' => 'POST', + 'uri' => 'http://www.cakephp.org/posts/add', + 'body' => array( + 'name' => 'HttpSocket-is-released', + 'date' => 'today' + ) + ), + 'expectation' => array( 'request' => array( - 'method' => 'POST' - , 'uri' => array( - 'path' => '/posts/add' - , 'fragment' => null - ) - , 'body' => "name=HttpSocket-is-released&date=today" - , 'line' => "POST /posts/add HTTP/1.1\r\n" - , 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" - , 'raw' => "name=HttpSocket-is-released&date=today" + 'method' => 'POST', + 'uri' => array( + 'path' => '/posts/add', + 'fragment' => null + ), + 'body' => "name=HttpSocket-is-released&date=today", + 'line' => "POST /posts/add HTTP/1.1\r\n", + 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n", + 'raw' => "name=HttpSocket-is-released&date=today" ) ) - ) - , 9 => array( - 'request' => array('method' => 'POST', 'uri' => 'http://www.cakephp.org:8080/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')) - , 'expectation' => array( + ), + array( + 'request' => array( + 'method' => 'POST', + 'uri' => 'http://www.cakephp.org:8080/posts/add', + 'body' => array( + 'name' => 'HttpSocket-is-released', + 'date' => 'today' + ) + ), + 'expectation' => array( 'config' => array( - 'port' => 8080 - , 'request' => array( + 'port' => 8080, + 'request' => array( 'uri' => array( 'port' => 8080 ) ) - ) - , 'request' => array( + ), + 'request' => array( 'uri' => array( 'port' => 8080 - ) - , 'header' => "Host: www.cakephp.org:8080\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" + ), + 'header' => "Host: www.cakephp.org:8080\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" ) ) - ) - , 10 => array( - 'request' => array('method' => 'POST', 'uri' => 'https://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')) - , 'expectation' => array( + ), + array( + 'request' => array( + 'method' => 'POST', + 'uri' => 'https://www.cakephp.org/posts/add', + 'body' => array( + 'name' => 'HttpSocket-is-released', + 'date' => 'today' + ) + ), + 'expectation' => array( 'config' => array( - 'port' => 443 - , 'request' => array( + 'port' => 443, + 'request' => array( 'uri' => array( - 'scheme' => 'https' - , 'port' => 443 + 'scheme' => 'https', + 'port' => 443 ) ) - ) - , 'request' => array( + ), + 'request' => array( 'uri' => array( - 'scheme' => 'https' - , 'port' => 443 - ) - , 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" + 'scheme' => 'https', + 'port' => 443 + ), + 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" ) ) - ) - , 11 => array( + ), + array( 'request' => array( - 'method' => 'POST', - 'uri' => 'https://www.cakephp.org/posts/add', - 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'), - 'cookies' => array('foo' => array('value' => 'bar')) - ) - , 'expectation' => array( + 'method' => 'POST', + 'uri' => 'https://www.cakephp.org/posts/add', + 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'), + 'cookies' => array('foo' => array('value' => 'bar')) + ), + 'expectation' => array( 'request' => array( 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\nCookie: foo=bar\r\n", 'cookies' => array( @@ -526,10 +535,10 @@ class HttpSocketTest extends CakeTestCase { $this->Socket->request($test['request']); $raw = $expectation['request']['raw']; - $expectation['request']['raw'] = $expectation['request']['line'].$expectation['request']['header']."\r\n".$raw; + $expectation['request']['raw'] = $expectation['request']['line'] . $expectation['request']['header'] . "\r\n" . $raw; $r = array('config' => $this->Socket->config, 'request' => $this->Socket->request); - $v = $this->assertEquals($r, $expectation, '%s in test #'.$i.' '); + $v = $this->assertEquals($r, $expectation, 'Failed test #' . $i . ' '); $expectation['request']['raw'] = $raw; } @@ -548,10 +557,9 @@ class HttpSocketTest extends CakeTestCase { /** * testRequest2 method * - * @access public * @return void */ - function testRequest2() { + public function testRequest2() { $this->Socket->reset(); $request = array('uri' => 'htpp://www.cakephp.org/'); $number = mt_rand(0, 9999999); @@ -561,17 +569,16 @@ class HttpSocketTest extends CakeTestCase { $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); $this->Socket->expects($this->once())->method('write') ->with("GET / HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"); - $response = $this->Socket->request($request); + $response = (string)$this->Socket->request($request); $this->assertEquals($response, "It's good to be html
" - ) - , 'expectations' => array( - 'status.http-version' => 'HTTP/1.x', - 'status.code' => 200, - 'status.reason-phrase' => 'OK', - 'header' => $this->Socket->parseHeader("Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n"), - 'body' => "It's good to be html
" - ) - ), - 'no-header' => array( - 'response' => array( - 'status-line' => "HTTP/1.x 404 OK\r\n", - 'header' => null, - ) - , 'expectations' => array( - 'status.code' => 404, - 'header' => array() - ) - ), - 'chunked' => array( - 'response' => array( - 'header' => "Transfer-Encoding: chunked\r\n", - 'body' => "19\r\nThis is a chunked message\r\n0\r\n" - ), - 'expectations' => array( - 'body' => "This is a chunked message", - 'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\n") - ) - ), - 'enitity-header' => array( - 'response' => array( - 'body' => "19\r\nThis is a chunked message\r\n0\r\nFoo: Bar\r\n" - ), - 'expectations' => array( - 'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\nFoo: Bar\r\n") - ) - ), - 'enitity-header-combine' => array( - 'response' => array( - 'header' => "Transfer-Encoding: chunked\r\nFoo: Foobar\r\n" - ), - 'expectations' => array( - 'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\nFoo: Foobar\r\nFoo: Bar\r\n") - ) - ) - ); - - $testResponse = array(); - $expectations = array(); - - foreach ($tests as $name => $test) { - - $testResponse = array_merge($testResponse, $test['response']); - $testResponse['response'] = $testResponse['status-line'].$testResponse['header']."\r\n".$testResponse['body']; - $r = $this->Socket->parseResponse($testResponse['response']); - $expectations = array_merge($expectations, $test['expectations']); - - foreach ($expectations as $property => $expectedVal) { - $val = Set::extract($r, $property); - $this->assertEquals($val, $expectedVal, 'Test "'.$name.'": response.'.$property.' - %s'); - } - - foreach (array('status-line', 'header', 'body', 'response') as $field) { - $this->assertEquals($r['raw'][$field], $testResponse[$field], 'Test response.raw.'.$field.': %s'); - } - } - } - -/** - * testDecodeBody method - * - * @access public - * @return void - */ - function testDecodeBody() { - $this->Socket->reset(); - - $r = $this->Socket->decodeBody(true); - $this->assertEquals($r, false); - - $r = $this->Socket->decodeBody('Foobar', false); - $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); - - $encoding = 'chunked'; - $sample = array( - 'encoded' => "19\r\nThis is a chunked message\r\n0\r\n", - 'decoded' => array('body' => "This is a chunked message", 'header' => false) - ); - - $r = $this->Socket->decodeBody($sample['encoded'], $encoding); - $this->assertEquals($r, $sample['decoded']); - } - - function testDecodeFooCoded() { - $this->Socket->reset(); - - $r = $this->Socket->decodeBody(true); - $this->assertEquals($r, false); - - $r = $this->Socket->decodeBody('Foobar', false); - $this->assertEquals($r, array('body' => 'Foobar', 'header' => false)); - - $encoding = 'foo-bar'; - $sample = array( - 'encoded' => '!Foobar!', - 'decoded' => array('body' => '!Foobar!', 'header' => false), - ); - - $this->Socket->quirksMode = true; - $r = $this->Socket->decodeBody($sample['encoded'], $encoding); - $this->assertEquals($r, $sample['decoded']); - $this->Socket->quirksMode = false; - - $this->expectError(); - $r = $this->Socket->decodeBody($sample['encoded'], $encoding); - $this->assertEquals($r, $sample['decoded']); - } - -/** - * testDecodeChunkedBody method - * - * @access public - * @return void - */ - function testDecodeChunkedBody() { - $this->Socket->reset(); - - $r = $this->Socket->decodeChunkedBody(true); - $this->assertEquals($r, false); - - $encoded = "19\r\nThis is a chunked message\r\n0\r\n"; - $decoded = "This is a chunked message"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $encoded = "19 \r\nThis is a chunked message\r\n0\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\n"; - $decoded = "This is a chunked message\nThat is cool\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $encoded = "19\r\nThis is a chunked message\r\nE;foo-chunk=5\r\n\nThat is cool\n\r\n0\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], array('Foo-Header' => 'bar', 'Cake' => 'PHP')); - - $this->Socket->quirksMode = true; - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], array('Foo-Header' => 'bar', 'Cake' => 'PHP')); - - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r['body'], $decoded); - $this->assertEquals($r['header'], false); - - $this->Socket->quirksMode = false; - $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; - $this->expectError(); - $r = $this->Socket->decodeChunkedBody($encoded); - $this->assertEquals($r, false); - } - /** * testBuildRequestLine method * - * @access public * @return void */ - function testBuildRequestLine() { + public function testBuildRequestLine() { $this->Socket->reset(); $this->Socket->quirksMode = true; @@ -1012,7 +999,7 @@ class HttpSocketTest extends CakeTestCase { $request['method'] = 'GET'; $this->Socket->quirksMode = true; $r = $this->Socket->buildRequestLine($request); - $this->assertEquals($r, "GET * HTTP/1.1\r\n"); + $this->assertEquals($r, "GET * HTTP/1.1\r\n"); $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n"); $this->assertEquals($r, "GET * HTTP/1.1\r\n"); @@ -1021,10 +1008,9 @@ class HttpSocketTest extends CakeTestCase { /** * testBadBuildRequestLine method * - * @access public * @return void */ - function testBadBuildRequestLine() { + public function testBadBuildRequestLine() { $this->expectError(); $r = $this->Socket->buildRequestLine('Foo'); } @@ -1032,10 +1018,9 @@ class HttpSocketTest extends CakeTestCase { /** * testBadBuildRequestLine2 method * - * @access public * @return void */ - function testBadBuildRequestLine2() { + public function testBadBuildRequestLine2() { $this->expectError(); $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n"); } @@ -1043,10 +1028,9 @@ class HttpSocketTest extends CakeTestCase { /** * Asserts that HttpSocket::parseUri is working properly * - * @access public * @return void */ - function testParseUri() { + public function testParseUri() { $this->Socket->reset(); $uri = $this->Socket->parseUri(array('invalid' => 'uri-string')); @@ -1077,7 +1061,7 @@ class HttpSocketTest extends CakeTestCase { $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.cakephp.org', - 'path' => '/', + 'path' => '/' )); $uri = $this->Socket->parseUri('http://www.cakephp.org', true); @@ -1142,7 +1126,7 @@ class HttpSocketTest extends CakeTestCase { $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.google.com', - 'port' => 8080, + 'port' => 8080 )); $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1¶m2=value2%3Dvalue3'); @@ -1171,10 +1155,9 @@ class HttpSocketTest extends CakeTestCase { /** * Tests that HttpSocket::buildUri can turn all kinds of uri arrays (and strings) into fully or partially qualified URI's * - * @access public * @return void */ - function testBuildUri() { + public function testBuildUri() { $this->Socket->reset(); $r = $this->Socket->buildUri(true); @@ -1238,10 +1221,9 @@ class HttpSocketTest extends CakeTestCase { /** * Asserts that HttpSocket::parseQuery is working properly * - * @access public * @return void */ - function testParseQuery() { + public function testParseQuery() { $this->Socket->reset(); $query = $this->Socket->parseQuery(array('framework' => 'cakephp')); @@ -1290,16 +1272,10 @@ class HttpSocketTest extends CakeTestCase { $query = $this->Socket->parseQuery('a[][]=foo&a[bar]=php&a[][]=bar&a[][]=cake'); $expectedQuery = array( 'a' => array( - 0 => array( - 0 => 'foo' - ), + array('foo'), 'bar' => 'php', - 1 => array( - 0 => 'bar' - ), - array( - 0 => 'cake' - ) + array('bar'), + array('cake') ) ); $this->assertEquals($query, $expectedQuery); @@ -1345,10 +1321,9 @@ class HttpSocketTest extends CakeTestCase { * Tests that HttpSocket::buildHeader can turn a given $header array into a proper header string according to * HTTP 1.1 specs. * - * @access public * @return void */ - function testBuildHeader() { + public function testBuildHeader() { $this->Socket->reset(); $r = $this->Socket->buildHeader(true); @@ -1380,118 +1355,13 @@ class HttpSocketTest extends CakeTestCase { } -/** - * Test that HttpSocket::parseHeader can take apart a given (and valid) $header string and turn it into an array. - * - * @access public - * @return void - */ - function testParseHeader() { - $this->Socket->reset(); - - $r = $this->Socket->parseHeader(array('foo' => 'Bar', 'fOO-bAr' => 'quux')); - $this->assertEquals($r, array('Foo' => 'Bar', 'Foo-Bar' => 'quux')); - - $r = $this->Socket->parseHeader(true); - $this->assertEquals($r, false); - - $header = "Host: cakephp.org\t\r\n"; - $r = $this->Socket->parseHeader($header); - $expected = array( - 'Host' => 'cakephp.org' - ); - $this->assertEquals($r, $expected); - - $header = "Date:Sat, 07 Apr 2007 10:10:25 GMT\r\nX-Powered-By: PHP/5.1.2\r\n"; - $r = $this->Socket->parseHeader($header); - $expected = array( - 'Date' => 'Sat, 07 Apr 2007 10:10:25 GMT' - , 'X-Powered-By' => 'PHP/5.1.2' - ); - $this->assertEquals($r, $expected); - - $header = "people: Jim,John\r\nfoo-LAND: Bar\r\ncAKe-PHP: rocks\r\n"; - $r = $this->Socket->parseHeader($header); - $expected = array( - 'People' => 'Jim,John' - , 'Foo-Land' => 'Bar' - , 'Cake-Php' => 'rocks' - ); - $this->assertEquals($r, $expected); - - $header = "People: Jim,John,Tim\r\nPeople: Lisa,Tina,Chelsea\r\n"; - $r = $this->Socket->parseHeader($header); - $expected = array( - 'People' => array('Jim,John,Tim', 'Lisa,Tina,Chelsea') - ); - $this->assertEquals($r, $expected); - - $header = "Multi-Line: I am a \r\nmulti line\t\r\nfield value.\r\nSingle-Line: I am not\r\n"; - $r = $this->Socket->parseHeader($header); - $expected = array( - 'Multi-Line' => "I am a\r\nmulti line\r\nfield value." - , 'Single-Line' => 'I am not' - ); - $this->assertEquals($r, $expected); - - $header = "Esc\"@\"ped: value\r\n"; - $r = $this->Socket->parseHeader($header); - $expected = array( - 'Esc@ped' => 'value' - ); - $this->assertEquals($r, $expected); - } - -/** - * testParseCookies method - * - * @access public - * @return void - */ - function testParseCookies() { - $header = array( - 'Set-Cookie' => array( - 'foo=bar', - 'people=jim,jack,johnny";";Path=/accounts', - 'google=not=nice' - ), - 'Transfer-Encoding' => 'chunked', - 'Date' => 'Sun, 18 Nov 2007 18:57:42 GMT', - ); - $cookies = $this->Socket->parseCookies($header); - $expected = array( - 'foo' => array( - 'value' => 'bar' - ), - 'people' => array( - 'value' => 'jim,jack,johnny";"', - 'path' => '/accounts', - ), - 'google' => array( - 'value' => 'not=nice', - ) - ); - $this->assertEqual($cookies, $expected); - - $header['Set-Cookie'][] = 'cakephp=great; Secure'; - $expected['cakephp'] = array('value' => 'great', 'secure' => true); - $cookies = $this->Socket->parseCookies($header); - $this->assertEqual($cookies, $expected); - - $header['Set-Cookie'] = 'foo=bar'; - unset($expected['people'], $expected['cakephp'], $expected['google']); - $cookies = $this->Socket->parseCookies($header); - $this->assertEqual($cookies, $expected); - } - /** * testBuildCookies method * * @return void - * @access public * @todo Test more scenarios */ - function testBuildCookies() { + public function testBuildCookies() { $cookies = array( 'foo' => array( 'value' => 'bar' @@ -1509,10 +1379,9 @@ class HttpSocketTest extends CakeTestCase { /** * Tests that HttpSocket::_tokenEscapeChars() returns the right characters. * - * @access public * @return void */ - function testTokenEscapeChars() { + public function testTokenEscapeChars() { $this->Socket->reset(); $expected = array( @@ -1535,19 +1404,18 @@ class HttpSocketTest extends CakeTestCase { /** * Test that HttpSocket::escapeToken is escaping all characters as descriped in RFC 2616 (HTTP 1.1 specs) * - * @access public * @return void */ - function testEscapeToken() { + public function testEscapeToken() { $this->Socket->reset(); $this->assertEquals($this->Socket->escapeToken('Foo'), 'Foo'); $escape = $this->Socket->tokenEscapeChars(false); foreach ($escape as $char) { - $token = 'My-special-'.$char.'-Token'; + $token = 'My-special-' . $char . '-Token'; $escapedToken = $this->Socket->escapeToken($token); - $expectedToken = 'My-special-"'.$char.'"-Token'; + $expectedToken = 'My-special-"' . $char . '"-Token'; $this->assertEquals($escapedToken, $expectedToken, 'Test token escaping for ASCII '.ord($char)); } @@ -1558,40 +1426,13 @@ class HttpSocketTest extends CakeTestCase { $this->assertEquals($expectedToken, $escapedToken); } -/** - * Test that escaped token strings are properly unescaped by HttpSocket::unescapeToken - * - * @access public - * @return void - */ - function testUnescapeToken() { - $this->Socket->reset(); - - $this->assertEquals($this->Socket->unescapeToken('Foo'), 'Foo'); - - $escape = $this->Socket->tokenEscapeChars(false); - foreach ($escape as $char) { - $token = 'My-special-"'.$char.'"-Token'; - $unescapedToken = $this->Socket->unescapeToken($token); - $expectedToken = 'My-special-'.$char.'-Token'; - - $this->assertEquals($unescapedToken, $expectedToken, 'Test token unescaping for ASCII '.ord($char)); - } - - $token = 'Extreme-":"Token-" "-""""@"-test'; - $escapedToken = $this->Socket->unescapeToken($token); - $expectedToken = 'Extreme-:Token- -"@-test'; - $this->assertEquals($expectedToken, $escapedToken); - } - /** * This tests asserts HttpSocket::reset() resets a HttpSocket instance to it's initial state (before Object::__construct * got executed) * - * @access public * @return void */ - function testReset() { + public function testReset() { $this->Socket->reset(); $initialState = get_class_vars('HttpSocket'); @@ -1612,10 +1453,9 @@ class HttpSocketTest extends CakeTestCase { * This tests asserts HttpSocket::reset(false) resets certain HttpSocket properties to their initial state (before * Object::__construct got executed). * - * @access public * @return void */ - function testPartialReset() { + public function testPartialReset() { $this->Socket->reset(); $partialResetProperties = array('request', 'response'); diff --git a/cake/tests/cases/libs/object_collection.test.php b/cake/tests/cases/libs/object_collection.test.php index ac5fb5a4c..3eecfd70d 100644 --- a/cake/tests/cases/libs/object_collection.test.php +++ b/cake/tests/cases/libs/object_collection.test.php @@ -209,11 +209,11 @@ class ObjectCollectionTest extends CakeTestCase { } /** - * test trigger and disabled helpers. + * test trigger and disabled objects * * @return void */ - function testTriggerWithDisabledComponents() { + function testTriggerWithDisabledObjects() { $this->_makeMockClasses(); $this->Objects->load('TriggerMockFirst'); $this->Objects->load('TriggerMockSecond'); diff --git a/cake/tests/cases/libs/view/helper_collection.test.php b/cake/tests/cases/libs/view/helper_collection.test.php index 403bbc8e7..d5f1480dd 100644 --- a/cake/tests/cases/libs/view/helper_collection.test.php +++ b/cake/tests/cases/libs/view/helper_collection.test.php @@ -116,75 +116,4 @@ class HelperCollectionTest extends CakeTestCase { $this->assertEquals(array('Form'), $result, 'loaded helpers is wrong'); } -/** - * test triggering callbacks. - * - * @return void - */ - function testTrigger() { - if (!class_exists('TriggerMockHtmlHelper')) { - $this->getMock('HtmlHelper', array(), array($this->View), 'TriggerMockHtmlHelper'); - $this->getMock('FormHelper', array(), array($this->View), 'TriggerMockFormHelper'); - } - - $this->Helpers->load('TriggerMockHtml'); - $this->Helpers->load('TriggerMockForm'); - - $this->Helpers->TriggerMockHtml->expects($this->once())->method('beforeRender') - ->with('one', 'two'); - $this->Helpers->TriggerMockForm->expects($this->once())->method('beforeRender') - ->with('one', 'two'); - - $this->mockObjects[] = $this->Helpers->TriggerMockForm; - - $this->assertNull($this->Helpers->trigger('beforeRender', array('one', 'two'))); - } - -/** - * test trigger and disabled helpers. - * - * @return void - */ - function testTriggerWithDisabledHelpers() { - if (!class_exists('TriggerMockHtmlHelper')) { - $this->getMock('HtmlHelper', array(), array(), 'TriggerMockHtmlHelper', false); - $this->getMock('FormHelper', array(), array(), 'TriggerMockFormHelper', false); - } - - $this->Helpers->load('TriggerMockHtml'); - $this->Helpers->load('TriggerMockForm'); - - $this->Helpers->TriggerMockHtml->expects($this->once())->method('beforeRender') - ->with('one', 'two'); - $this->Helpers->TriggerMockForm->expects($this->never())->method('beforeRender'); - - $this->mockObjects[] = $this->Helpers->TriggerMockForm; - $this->mockObjects[] = $this->Helpers->TriggerMockHtml; - - $this->Helpers->disable('TriggerMockForm'); - - $this->assertNull($this->Helpers->trigger('beforeRender', array('one', 'two'))); - } - -/** - * test normalizeObjectArray - * - * @return void - */ - function testnormalizeObjectArray() { - $helpers = array( - 'Html', - 'Foo.Bar' => array('one', 'two'), - 'Something', - 'Banana.Apple' => array('foo' => 'bar') - ); - $result = ObjectCollection::normalizeObjectArray($helpers); - $expected = array( - 'Html' => array('class' => 'Html', 'settings' => array()), - 'Bar' => array('class' => 'Foo.Bar', 'settings' => array('one', 'two')), - 'Something' => array('class' => 'Something', 'settings' => array()), - 'Apple' => array('class' => 'Banana.Apple', 'settings' => array('foo' => 'bar')), - ); - $this->assertEquals($expected, $result); - } } \ No newline at end of file