summaryrefslogtreecommitdiff
path: root/system/helpers/request.php
diff options
context:
space:
mode:
authorBharat Mediratta <bharat@menalto.com>2009-11-24 19:20:36 -0800
committerBharat Mediratta <bharat@menalto.com>2009-11-24 19:20:36 -0800
commit9b6663f87a7e679ffba691cf516191fc840cf978 (patch)
tree20cf9f3aaf93b4ba69d282dcf10d259db4a752de /system/helpers/request.php
parent82ee5f9d338017c69331b2907f37a468ced8c66e (diff)
Update to Kohana r4684 which is now Kohana 2.4 and has substantial
changes.
Diffstat (limited to 'system/helpers/request.php')
-rw-r--r--system/helpers/request.php480
1 files changed, 430 insertions, 50 deletions
diff --git a/system/helpers/request.php b/system/helpers/request.php
index 4203d0e5..4770d64b 100644
--- a/system/helpers/request.php
+++ b/system/helpers/request.php
@@ -2,35 +2,48 @@
/**
* Request helper class.
*
- * $Id: request.php 4355 2009-05-15 17:18:28Z kiall $
+ * $Id: request.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
- * @copyright (c) 2007-2008 Kohana Team
- * @license http://kohanaphp.com/license.html
+ * @copyright (c) 2007-2009 Kohana Team
+ * @license http://kohanaphp.com/license
*/
class request_Core {
// Possible HTTP methods
protected static $http_methods = array('get', 'head', 'options', 'post', 'put', 'delete');
- // Content types from client's HTTP Accept request header (array)
+ // Character sets from client's HTTP Accept-Charset request header
+ protected static $accept_charsets;
+
+ // Content codings from client's HTTP Accept-Encoding request header
+ protected static $accept_encodings;
+
+ // Language tags from client's HTTP Accept-Language request header
+ protected static $accept_languages;
+
+ // Content types from client's HTTP Accept request header
protected static $accept_types;
+ // The current user agent and its parsed attributes
+ protected static $user_agent;
+
/**
* Returns the HTTP referrer, or the default if the referrer is not set.
*
* @param mixed default to return
+ * @param bool Remove base URL
* @return string
*/
- public static function referrer($default = FALSE)
+ public static function referrer($default = FALSE, $remove_base = FALSE)
{
if ( ! empty($_SERVER['HTTP_REFERER']))
{
// Set referrer
$ref = $_SERVER['HTTP_REFERER'];
- if (strpos($ref, url::base(FALSE)) === 0)
+ if ($remove_base === TRUE AND (strpos($ref, url::base(FALSE)) === 0))
{
// Remove the base URL from the referrer
$ref = substr($ref, strlen(url::base(FALSE)));
@@ -84,10 +97,59 @@ class request_Core {
$method = strtolower($_SERVER['REQUEST_METHOD']);
if ( ! in_array($method, request::$http_methods))
- throw new Kohana_Exception('request.unknown_method', $method);
+ throw new Kohana_Exception('Invalid request method :method:', array(':method:' => $method));
return $method;
- }
+ }
+
+ /**
+ * Retrieves current user agent information
+ * keys: browser, version, platform, mobile, robot
+ *
+ * @param string key
+ * @return mixed NULL or the parsed value
+ */
+ public static function user_agent($key = 'agent')
+ {
+ // Retrieve raw user agent without parsing
+ if ($key === 'agent')
+ {
+ if (request::$user_agent === NULL)
+ return request::$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
+
+ if (is_array(request::$user_agent))
+ return request::$user_agent['agent'];
+
+ return request::$user_agent;
+ }
+
+ if ( ! is_array(request::$user_agent))
+ {
+ request::$user_agent['agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
+
+ // Parse the user agent and extract basic information
+ foreach (Kohana::config('user_agents') as $type => $data)
+ {
+ foreach ($data as $fragment => $name)
+ {
+ if (stripos(request::$user_agent['agent'], $fragment) !== FALSE)
+ {
+ if ($type === 'browser' AND preg_match('|'.preg_quote($fragment).'[^0-9.]*+([0-9.][0-9.a-z]*)|i', request::$user_agent['agent'], $match))
+ {
+ // Set the browser version
+ request::$user_agent['version'] = $match[1];
+ }
+
+ // Set the agent name
+ request::$user_agent[$type] = $name;
+ break;
+ }
+ }
+ }
+ }
+
+ return isset(request::$user_agent[$key]) ? request::$user_agent[$key] : NULL;
+ }
/**
* Returns boolean of whether client accepts content type.
@@ -98,7 +160,7 @@ class request_Core {
*/
public static function accepts($type = NULL, $explicit_check = FALSE)
{
- request::parse_accept_header();
+ request::parse_accept_content_header();
if ($type === NULL)
return request::$accept_types;
@@ -107,6 +169,56 @@ class request_Core {
}
/**
+ * Returns boolean indicating if the client accepts a charset
+ *
+ * @param string
+ * @return boolean
+ */
+ public static function accepts_charset($charset = NULL)
+ {
+ request::parse_accept_charset_header();
+
+ if ($charset === NULL)
+ return request::$accept_charsets;
+
+ return (request::accepts_charset_at_quality($charset) > 0);
+ }
+
+ /**
+ * Returns boolean indicating if the client accepts an encoding
+ *
+ * @param string
+ * @param boolean set to TRUE to disable wildcard checking
+ * @return boolean
+ */
+ public static function accepts_encoding($encoding = NULL, $explicit_check = FALSE)
+ {
+ request::parse_accept_encoding_header();
+
+ if ($encoding === NULL)
+ return request::$accept_encodings;
+
+ return (request::accepts_encoding_at_quality($encoding, $explicit_check) > 0);
+ }
+
+ /**
+ * Returns boolean indicating if the client accepts a language tag
+ *
+ * @param string language tag
+ * @param boolean set to TRUE to disable prefix and wildcard checking
+ * @return boolean
+ */
+ public static function accepts_language($tag = NULL, $explicit_check = FALSE)
+ {
+ request::parse_accept_language_header();
+
+ if ($tag === NULL)
+ return request::$accept_languages;
+
+ return (request::accepts_language_at_quality($tag, $explicit_check) > 0);
+ }
+
+ /**
* Compare the q values for given array of content types and return the one with the highest value.
* If items are found to have the same q value, the first one encountered in the given array wins.
* If all items in the given array have a q value of 0, FALSE is returned.
@@ -117,24 +229,103 @@ class request_Core {
*/
public static function preferred_accept($types, $explicit_check = FALSE)
{
- // Initialize
- $mime_types = array();
$max_q = 0;
$preferred = FALSE;
- // Load q values for all given content types
- foreach (array_unique($types) as $type)
+ foreach ($types as $type)
+ {
+ $q = request::accepts_at_quality($type, $explicit_check);
+
+ if ($q > $max_q)
+ {
+ $max_q = $q;
+ $preferred = $type;
+ }
+ }
+
+ return $preferred;
+ }
+
+ /**
+ * Compare the q values for a given array of character sets and return the
+ * one with the highest value. If items are found to have the same q value,
+ * the first one encountered takes precedence. If all items in the given
+ * array have a q value of 0, FALSE is returned.
+ *
+ * @param array character sets
+ * @return mixed
+ */
+ public static function preferred_charset($charsets)
+ {
+ $max_q = 0;
+ $preferred = FALSE;
+
+ foreach ($charsets as $charset)
+ {
+ $q = request::accepts_charset_at_quality($charset);
+
+ if ($q > $max_q)
+ {
+ $max_q = $q;
+ $preferred = $charset;
+ }
+ }
+
+ return $preferred;
+ }
+
+ /**
+ * Compare the q values for a given array of encodings and return the one with
+ * the highest value. If items are found to have the same q value, the first
+ * one encountered takes precedence. If all items in the given array have
+ * a q value of 0, FALSE is returned.
+ *
+ * @param array encodings
+ * @param boolean set to TRUE to disable wildcard checking
+ * @return mixed
+ */
+ public static function preferred_encoding($encodings, $explicit_check = FALSE)
+ {
+ $max_q = 0;
+ $preferred = FALSE;
+
+ foreach ($encodings as $encoding)
{
- $mime_types[$type] = request::accepts_at_quality($type, $explicit_check);
+ $q = request::accepts_encoding_at_quality($encoding, $explicit_check);
+
+ if ($q > $max_q)
+ {
+ $max_q = $q;
+ $preferred = $encoding;
+ }
}
- // Look for the highest q value
- foreach ($mime_types as $type => $q)
+ return $preferred;
+ }
+
+ /**
+ * Compare the q values for a given array of language tags and return the
+ * one with the highest value. If items are found to have the same q value,
+ * the first one encountered takes precedence. If all items in the given
+ * array have a q value of 0, FALSE is returned.
+ *
+ * @param array language tags
+ * @param boolean set to TRUE to disable prefix and wildcard checking
+ * @return mixed
+ */
+ public static function preferred_language($tags, $explicit_check = FALSE)
+ {
+ $max_q = 0;
+ $preferred = FALSE;
+
+ foreach ($tags as $tag)
{
+ $q = request::accepts_language_at_quality($tag, $explicit_check);
+
if ($q > $max_q)
{
$max_q = $q;
- $preferred = $type;
+ $preferred = $tag;
}
}
@@ -142,18 +333,18 @@ class request_Core {
}
/**
- * Returns quality factor at which the client accepts content type.
+ * Returns quality factor at which the client accepts content type
*
* @param string content type (e.g. "image/jpg", "jpg")
* @param boolean set to TRUE to disable wildcard checking
* @return integer|float
*/
- public static function accepts_at_quality($type = NULL, $explicit_check = FALSE)
+ public static function accepts_at_quality($type, $explicit_check = FALSE)
{
- request::parse_accept_header();
+ request::parse_accept_content_header();
// Normalize type
- $type = strtolower((string) $type);
+ $type = strtolower($type);
// General content type (e.g. "jpg")
if (strpos($type, '/') === FALSE)
@@ -178,62 +369,251 @@ class request_Core {
if (isset(request::$accept_types[$type[0]][$type[1]]))
return request::$accept_types[$type[0]][$type[1]];
- // Wildcard match (if not checking explicitly)
- if ($explicit_check === FALSE AND isset(request::$accept_types[$type[0]]['*']))
- return request::$accept_types[$type[0]]['*'];
+ if ($explicit_check === FALSE)
+ {
+ // Wildcard match
+ if (isset(request::$accept_types[$type[0]]['*']))
+ return request::$accept_types[$type[0]]['*'];
- // Catch-all wildcard match (if not checking explicitly)
- if ($explicit_check === FALSE AND isset(request::$accept_types['*']['*']))
- return request::$accept_types['*']['*'];
+ // Catch-all wildcard match
+ if (isset(request::$accept_types['*']['*']))
+ return request::$accept_types['*']['*'];
+ }
// Content type not accepted
return 0;
}
/**
- * Parses client's HTTP Accept request header, and builds array structure representing it.
+ * Returns quality factor at which the client accepts a charset
+ *
+ * @param string charset (e.g., "ISO-8859-1", "utf-8")
+ * @return integer|float
+ */
+ public static function accepts_charset_at_quality($charset)
+ {
+ request::parse_accept_charset_header();
+
+ // Normalize charset
+ $charset = strtolower($charset);
+
+ // Exact match
+ if (isset(request::$accept_charsets[$charset]))
+ return request::$accept_charsets[$charset];
+
+ if (isset(request::$accept_charsets['*']))
+ return request::$accept_charsets['*'];
+
+ if ($charset === 'iso-8859-1')
+ return 1;
+
+ return 0;
+ }
+
+ /**
+ * Returns quality factor at which the client accepts an encoding
+ *
+ * @param string encoding (e.g., "gzip", "deflate")
+ * @param boolean set to TRUE to disable wildcard checking
+ * @return integer|float
+ */
+ public static function accepts_encoding_at_quality($encoding, $explicit_check = FALSE)
+ {
+ request::parse_accept_encoding_header();
+
+ // Normalize encoding
+ $encoding = strtolower($encoding);
+
+ // Exact match
+ if (isset(request::$accept_encodings[$encoding]))
+ return request::$accept_encodings[$encoding];
+
+ if ($explicit_check === FALSE)
+ {
+ if (isset(request::$accept_encodings['*']))
+ return request::$accept_encodings['*'];
+
+ if ($encoding === 'identity')
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns quality factor at which the client accepts a language
+ *
+ * @param string tag (e.g., "en", "en-us", "fr-ca")
+ * @param boolean set to TRUE to disable prefix and wildcard checking
+ * @return integer|float
+ */
+ public static function accepts_language_at_quality($tag, $explicit_check = FALSE)
+ {
+ request::parse_accept_language_header();
+
+ $tag = explode('-', strtolower($tag), 2);
+
+ if (isset(request::$accept_languages[$tag[0]]))
+ {
+ if (isset($tag[1]))
+ {
+ // Exact match
+ if (isset(request::$accept_languages[$tag[0]][$tag[1]]))
+ return request::$accept_languages[$tag[0]][$tag[1]];
+
+ // A prefix matches
+ if ($explicit_check === FALSE AND isset(request::$accept_languages[$tag[0]]['*']))
+ return request::$accept_languages[$tag[0]]['*'];
+ }
+ else
+ {
+ // No subtags
+ if (isset(request::$accept_languages[$tag[0]]['*']))
+ return request::$accept_languages[$tag[0]]['*'];
+ }
+ }
+
+ if ($explicit_check === FALSE AND isset(request::$accept_languages['*']))
+ return request::$accept_languages['*'];
+
+ return 0;
+ }
+
+ /**
+ * Parses a HTTP Accept or Accept-* header for q values
*
- * @return void
+ * @param string header data
+ * @return array
+ */
+ protected static function parse_accept_header($header)
+ {
+ $result = array();
+
+ // Remove linebreaks and parse the HTTP Accept header
+ foreach (explode(',', str_replace(array("\r", "\n"), '', strtolower($header))) as $entry)
+ {
+ // Explode each entry in content type and possible quality factor
+ $entry = explode(';', trim($entry), 2);
+
+ $q = (isset($entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $entry[1], $match)) ? (float) $match[1] : 1;
+
+ // Overwrite entries with a smaller q value
+ if ( ! isset($result[$entry[0]]) OR $q > $result[$entry[0]])
+ {
+ $result[$entry[0]] = $q;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Parses a client's HTTP Accept-Charset header
*/
- protected static function parse_accept_header()
+ protected static function parse_accept_charset_header()
{
// Run this function just once
- if (request::$accept_types !== NULL)
+ if (request::$accept_charsets !== NULL)
return;
- // Initialize accept_types array
- request::$accept_types = array();
+ // No HTTP Accept-Charset header found
+ if (empty($_SERVER['HTTP_ACCEPT_CHARSET']))
+ {
+ // Accept everything
+ request::$accept_charsets['*'] = 1;
+ }
+ else
+ {
+ request::$accept_charsets = request::parse_accept_header($_SERVER['HTTP_ACCEPT_CHARSET']);
+ }
+ }
+
+ /**
+ * Parses a client's HTTP Accept header
+ */
+ protected static function parse_accept_content_header()
+ {
+ // Run this function just once
+ if (request::$accept_types !== NULL)
+ return;
// No HTTP Accept header found
if (empty($_SERVER['HTTP_ACCEPT']))
{
// Accept everything
request::$accept_types['*']['*'] = 1;
- return;
}
-
- // Remove linebreaks and parse the HTTP Accept header
- foreach (explode(',', str_replace(array("\r", "\n"), '', $_SERVER['HTTP_ACCEPT'])) as $accept_entry)
+ else
{
- // Explode each entry in content type and possible quality factor
- $accept_entry = explode(';', trim($accept_entry), 2);
+ request::$accept_types = array();
+
+ foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT']) as $type => $q)
+ {
+ // Explode each content type (e.g. "text/html")
+ $type = explode('/', $type, 2);
+
+ // Skip invalid content types
+ if ( ! isset($type[1]))
+ continue;
+
+ request::$accept_types[$type[0]][$type[1]] = $q;
+ }
+ }
+ }
+
+ /**
+ * Parses a client's HTTP Accept-Encoding header
+ */
+ protected static function parse_accept_encoding_header()
+ {
+ // Run this function just once
+ if (request::$accept_encodings !== NULL)
+ return;
- // Explode each content type (e.g. "text/html")
- $type = explode('/', $accept_entry[0], 2);
+ // No HTTP Accept-Encoding header found
+ if ( ! isset($_SERVER['HTTP_ACCEPT_ENCODING']))
+ {
+ // Accept everything
+ request::$accept_encodings['*'] = 1;
+ }
+ elseif ($_SERVER['HTTP_ACCEPT_ENCODING'] === '')
+ {
+ // Accept only identity
+ request::$accept_encodings['identity'] = 1;
+ }
+ else
+ {
+ request::$accept_encodings = request::parse_accept_header($_SERVER['HTTP_ACCEPT_ENCODING']);
+ }
+ }
- // Skip invalid content types
- if ( ! isset($type[1]))
- continue;
+ /**
+ * Parses a client's HTTP Accept-Language header
+ */
+ protected static function parse_accept_language_header()
+ {
+ // Run this function just once
+ if (request::$accept_languages !== NULL)
+ return;
- // Assume a default quality factor of 1 if no custom q value found
- $q = (isset($accept_entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $accept_entry[1], $match)) ? (float) $match[1] : 1;
+ // No HTTP Accept-Language header found
+ if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
+ {
+ // Accept everything
+ request::$accept_languages['*'] = 1;
+ }
+ else
+ {
+ request::$accept_languages = array();
- // Populate accept_types array
- if ( ! isset(request::$accept_types[$type[0]][$type[1]]) OR $q > request::$accept_types[$type[0]][$type[1]])
+ foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT_LANGUAGE']) as $tag => $q)
{
- request::$accept_types[$type[0]][$type[1]] = $q;
+ // Explode each language (e.g. "en-us")
+ $tag = explode('-', $tag, 2);
+
+ request::$accept_languages[$tag[0]][isset($tag[1]) ? $tag[1] : '*'] = $q;
}
}
}
-} // End request \ No newline at end of file
+} // End request