Initial Kohana install
[speedfreak] / Server / system / helpers / request.php
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3  * Request helper class.
4  *
5  * $Id: request.php 4355 2009-05-15 17:18:28Z kiall $
6  *
7  * @package    Core
8  * @author     Kohana Team
9  * @copyright  (c) 2007-2008 Kohana Team
10  * @license    http://kohanaphp.com/license.html
11  */
12 class request_Core {
13
14         // Possible HTTP methods
15         protected static $http_methods = array('get', 'head', 'options', 'post', 'put', 'delete');
16
17         // Content types from client's HTTP Accept request header (array)
18         protected static $accept_types;
19
20         /**
21          * Returns the HTTP referrer, or the default if the referrer is not set.
22          *
23          * @param   mixed   default to return
24          * @return  string
25          */
26         public static function referrer($default = FALSE)
27         {
28                 if ( ! empty($_SERVER['HTTP_REFERER']))
29                 {
30                         // Set referrer
31                         $ref = $_SERVER['HTTP_REFERER'];
32
33                         if (strpos($ref, url::base(FALSE)) === 0)
34                         {
35                                 // Remove the base URL from the referrer
36                                 $ref = substr($ref, strlen(url::base(FALSE)));
37                         }
38                 }
39
40                 return isset($ref) ? $ref : $default;
41         }
42
43         /**
44          * Returns the current request protocol, based on $_SERVER['https']. In CLI
45          * mode, NULL will be returned.
46          *
47          * @return  string
48          */
49         public static function protocol()
50         {
51                 if (PHP_SAPI === 'cli')
52                 {
53                         return NULL;
54                 }
55                 elseif ( ! empty($_SERVER['HTTPS']) AND $_SERVER['HTTPS'] === 'on')
56                 {
57                         return 'https';
58                 }
59                 else
60                 {
61                         return 'http';
62                 }
63         }
64
65         /**
66          * Tests if the current request is an AJAX request by checking the X-Requested-With HTTP
67          * request header that most popular JS frameworks now set for AJAX calls.
68          *
69          * @return  boolean
70          */
71         public static function is_ajax()
72         {
73                 return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
74         }
75
76         /**
77          * Returns current request method.
78          *
79          * @throws  Kohana_Exception in case of an unknown request method
80          * @return  string
81          */
82         public static function method()
83         {
84                 $method = strtolower($_SERVER['REQUEST_METHOD']);
85
86                 if ( ! in_array($method, request::$http_methods))
87                         throw new Kohana_Exception('request.unknown_method', $method);
88
89                 return $method;
90          }
91
92         /**
93          * Returns boolean of whether client accepts content type.
94          *
95          * @param   string   content type
96          * @param   boolean  set to TRUE to disable wildcard checking
97          * @return  boolean
98          */
99         public static function accepts($type = NULL, $explicit_check = FALSE)
100         {
101                 request::parse_accept_header();
102
103                 if ($type === NULL)
104                         return request::$accept_types;
105
106                 return (request::accepts_at_quality($type, $explicit_check) > 0);
107         }
108
109         /**
110          * Compare the q values for given array of content types and return the one with the highest value.
111          * If items are found to have the same q value, the first one encountered in the given array wins.
112          * If all items in the given array have a q value of 0, FALSE is returned.
113          *
114          * @param   array    content types
115          * @param   boolean  set to TRUE to disable wildcard checking
116          * @return  mixed    string mime type with highest q value, FALSE if none of the given types are accepted
117          */
118         public static function preferred_accept($types, $explicit_check = FALSE)
119         {
120                 // Initialize
121                 $mime_types = array();
122                 $max_q = 0;
123                 $preferred = FALSE;
124
125                 // Load q values for all given content types
126                 foreach (array_unique($types) as $type)
127                 {
128                         $mime_types[$type] = request::accepts_at_quality($type, $explicit_check);
129                 }
130
131                 // Look for the highest q value
132                 foreach ($mime_types as $type => $q)
133                 {
134                         if ($q > $max_q)
135                         {
136                                 $max_q = $q;
137                                 $preferred = $type;
138                         }
139                 }
140
141                 return $preferred;
142         }
143
144         /**
145          * Returns quality factor at which the client accepts content type.
146          *
147          * @param   string   content type (e.g. "image/jpg", "jpg")
148          * @param   boolean  set to TRUE to disable wildcard checking
149          * @return  integer|float
150          */
151         public static function accepts_at_quality($type = NULL, $explicit_check = FALSE)
152         {
153                 request::parse_accept_header();
154
155                 // Normalize type
156                 $type = strtolower((string) $type);
157
158                 // General content type (e.g. "jpg")
159                 if (strpos($type, '/') === FALSE)
160                 {
161                         // Don't accept anything by default
162                         $q = 0;
163
164                         // Look up relevant mime types
165                         foreach ((array) Kohana::config('mimes.'.$type) as $type)
166                         {
167                                 $q2 = request::accepts_at_quality($type, $explicit_check);
168                                 $q = ($q2 > $q) ? $q2 : $q;
169                         }
170
171                         return $q;
172                 }
173
174                 // Content type with subtype given (e.g. "image/jpg")
175                 $type = explode('/', $type, 2);
176
177                 // Exact match
178                 if (isset(request::$accept_types[$type[0]][$type[1]]))
179                         return request::$accept_types[$type[0]][$type[1]];
180
181                 // Wildcard match (if not checking explicitly)
182                 if ($explicit_check === FALSE AND isset(request::$accept_types[$type[0]]['*']))
183                         return request::$accept_types[$type[0]]['*'];
184
185                 // Catch-all wildcard match (if not checking explicitly)
186                 if ($explicit_check === FALSE AND isset(request::$accept_types['*']['*']))
187                         return request::$accept_types['*']['*'];
188
189                 // Content type not accepted
190                 return 0;
191         }
192
193         /**
194          * Parses client's HTTP Accept request header, and builds array structure representing it.
195          *
196          * @return  void
197          */
198         protected static function parse_accept_header()
199         {
200                 // Run this function just once
201                 if (request::$accept_types !== NULL)
202                         return;
203
204                 // Initialize accept_types array
205                 request::$accept_types = array();
206
207                 // No HTTP Accept header found
208                 if (empty($_SERVER['HTTP_ACCEPT']))
209                 {
210                         // Accept everything
211                         request::$accept_types['*']['*'] = 1;
212                         return;
213                 }
214
215                 // Remove linebreaks and parse the HTTP Accept header
216                 foreach (explode(',', str_replace(array("\r", "\n"), '', $_SERVER['HTTP_ACCEPT'])) as $accept_entry)
217                 {
218                         // Explode each entry in content type and possible quality factor
219                         $accept_entry = explode(';', trim($accept_entry), 2);
220
221                         // Explode each content type (e.g. "text/html")
222                         $type = explode('/', $accept_entry[0], 2);
223
224                         // Skip invalid content types
225                         if ( ! isset($type[1]))
226                                 continue;
227
228                         // Assume a default quality factor of 1 if no custom q value found
229                         $q = (isset($accept_entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $accept_entry[1], $match)) ? (float) $match[1] : 1;
230
231                         // Populate accept_types array
232                         if ( ! isset(request::$accept_types[$type[0]][$type[1]]) OR $q > request::$accept_types[$type[0]][$type[1]])
233                         {
234                                 request::$accept_types[$type[0]][$type[1]] = $q;
235                         }
236                 }
237         }
238
239 } // End request