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. * * @param array content types * @param boolean set to TRUE to disable wildcard checking * @return mixed string mime type with highest q value, FALSE if none of the given types are accepted */ 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) { $mime_types[$type] = request::accepts_at_quality($type, $explicit_check); } // Look for the highest q value foreach ($mime_types as $type => $q) { if ($q > $max_q) { $max_q = $q; $preferred = $type; } } return $preferred; } /** * 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) { request::parse_accept_header(); // Normalize type $type = strtolower((string) $type); // General content type (e.g. "jpg") if (strpos($type, '/') === FALSE) { // Don't accept anything by default $q = 0; // Look up relevant mime types foreach ((array) Kohana::config('mimes.'.$type) as $type) { $q2 = request::accepts_at_quality($type, $explicit_check); $q = ($q2 > $q) ? $q2 : $q; } return $q; } // Content type with subtype given (e.g. "image/jpg") $type = explode('/', $type, 2); // Exact match 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]]['*']; // Catch-all wildcard match (if not checking explicitly) if ($explicit_check === FALSE AND 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. * * @return void */ protected static function parse_accept_header() { // Run this function just once if (request::$accept_types !== NULL) return; // Initialize accept_types array request::$accept_types = array(); // 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) { // Explode each entry in content type and possible quality factor $accept_entry = explode(';', trim($accept_entry), 2); // Explode each content type (e.g. "text/html") $type = explode('/', $accept_entry[0], 2); // Skip invalid content types if ( ! isset($type[1])) continue; // 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; // Populate accept_types array if ( ! isset(request::$accept_types[$type[0]][$type[1]]) OR $q > request::$accept_types[$type[0]][$type[1]]) { request::$accept_types[$type[0]][$type[1]] = $q; } } } } // End request