1 <?php
2 3 4 5 6 7 8
9 class HTTP {
10
11 static $userName;
12 static $password;
13
14 15 16
17 static function filename2url($filename) {
18 $slashPos = -1;
19 while(($slashPos = strpos($filename, "/", $slashPos+1)) !== false) {
20 if(substr($filename, 0, $slashPos) == substr($_SERVER['SCRIPT_FILENAME'],0,$slashPos)) {
21 $commonLength = $slashPos;
22 } else {
23 break;
24 }
25 }
26
27 $urlBase = substr($_SERVER['PHP_SELF'], 0, -(strlen($_SERVER['SCRIPT_FILENAME']) - $commonLength));
28 $url = $urlBase . substr($filename, $commonLength);
29 $protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] != 'off') ? "https" : "http";
30 return "$protocol://". $_SERVER['HTTP_HOST'] . $url;
31
32
33
34 }
35
36 37 38
39 static function absoluteURLs($html) {
40 $html = str_replace('$CurrentPageURL', $_SERVER['REQUEST_URI'], $html);
41 return HTTP::urlRewriter($html, '(substr($URL,0,1) == "/") ? ( Director::protocolAndHost() . $URL ) : ( (ereg("^[A-Za-z]+:", $URL)) ? $URL : Director::absoluteBaseURL() . $URL )' );
42 }
43
44 45 46 47 48 49 50 51 52
53 static function urlRewriter($content, $code) {
54 $attribs = array("src","background","a" => "href","link" => "href", "base" => "href");
55 foreach($attribs as $tag => $attrib) {
56 if(!is_numeric($tag)) $tagPrefix = "$tag ";
57 else $tagPrefix = "";
58
59 $regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *\")([^\"]*)(\")/ie";
60 $regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *')([^']*)(')/ie";
61 $regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *)([^\"' ]*)( )/ie";
62 }
63 $regExps[] = '/(background-image:[^;]*url *\()([^)]+)(\))/ie';
64 $regExps[] = '/(background:[^;]*url *\()([^)]+)(\))/ie';
65
66
67 $code = 'stripslashes("$1") . (' . str_replace('$URL', 'stripslashes("$2")', $code) . ') . stripslashes("$3")';
68
69 foreach($regExps as $regExp) {
70 $content = preg_replace($regExp, $code, $content);
71 }
72
73 return $content;
74 }
75
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
95 public static function setGetVar($varname, $varvalue, $currentURL = null, $separator = '&') {
96 $uri = $currentURL ? $currentURL : Director::makeRelative($_SERVER['REQUEST_URI']);
97
98 $isRelative = false;
99
100 if(Director::is_relative_url($uri)) {
101 $uri = Director::absoluteURL(Director::baseURL()) . $uri;
102 $isRelative = true;
103 }
104
105
106 $parts = parse_url($uri);
107 if(!$parts) {
108 throw new InvalidArgumentException("Can't parse URL: " . $uri);
109 }
110
111
112 $params = array();
113 if(isset($parts['query'])) parse_str($parts['query'], $params);
114 $params[$varname] = $varvalue;
115
116
117 $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
118 $user = (isset($parts['user']) && $parts['user'] != '') ? $parts['user'] : '';
119
120 if($user != '') {
121
122 $user .= (isset($parts['pass']) && $parts['pass'] != '') ? ':' . $parts['pass'] . '@' : '@';
123 }
124
125 $host = (isset($parts['host'])) ? $parts['host'] : '';
126 $port = (isset($parts['port']) && $parts['port'] != '') ? ':'.$parts['port'] : '';
127 $path = (isset($parts['path']) && $parts['path'] != '') ? $parts['path'] : '';
128
129
130 $params = ($params) ? '?' . http_build_query($params, null, $separator) : '';
131 if ($params == '?') $params = '';
132
133
134 $fragment = (isset($parts['fragment']) && $parts['fragment'] != '') ? '#'.$parts['fragment'] : '';
135
136
137 $newUri = $scheme . '://' . $user . $host . $port . $path . $params . $fragment;
138
139 if($isRelative) return Director::makeRelative($newUri);
140
141 return $newUri;
142 }
143
144 static function RAW_setGetVar($varname, $varvalue, $currentURL = null) {
145 $url = self::setGetVar($varname, $varvalue, $currentURL);
146 return Convert::xml2raw($url);
147 }
148
149 150 151 152 153 154 155
156 public static function findByTagAndAttribute($content, $attributes) {
157 $regexes = array();
158
159 foreach($attributes as $tag => $attribute) {
160 $regexes[] = "/<{$tag} [^>]*$attribute *= *([\"'])(.*?)\\1[^>]*>/i";
161 $regexes[] = "/<{$tag} [^>]*$attribute *= *([^ \"'>]+)/i";
162 }
163
164 $result = array();
165
166 if($regexes) foreach($regexes as $regex) {
167 if(preg_match_all($regex, $content, $matches)) {
168 $result = array_merge_recursive($result, (isset($matches[2]) ? $matches[2] : $matches[1]));
169 }
170 }
171
172 return count($result) ? $result : null;
173 }
174
175 static function getLinksIn($content) {
176 return self::findByTagAndAttribute($content, array("a" => "href"));
177 }
178
179 static function getImagesIn($content) {
180 return self::findByTagAndAttribute($content, array("img" => "src"));
181 }
182
183 184 185
186 static function getMimeType($filename) {
187 global $global_mimetypes;
188 if(!$global_mimetypes) self::loadMimeTypes();
189 $ext = strtolower(substr($filename,strrpos($filename,'.')+1));
190 if(isset($global_mimetypes[$ext])) return $global_mimetypes[$ext];
191 }
192
193 194 195
196 static function loadMimeTypes() {
197 if(@file_exists('/etc/mime.types')) {
198 $mimeTypes = file('/etc/mime.types');
199 foreach($mimeTypes as $typeSpec) {
200 if(($typeSpec = trim($typeSpec)) && substr($typeSpec,0,1) != "#") {
201 $parts = preg_split("/[ \t\r\n]+/", $typeSpec);
202 if(sizeof($parts) > 1) {
203 $mimeType = array_shift($parts);
204 foreach($parts as $ext) {
205 $ext = strtolower($ext);
206 $mimeData[$ext] = $mimeType;
207 }
208 }
209 }
210 }
211
212
213 } else {
214 $mimeData = array(
215 "doc" => "application/msword",
216 "xls" => "application/vnd.ms-excel",
217 "rtf" => "application/rtf",
218 );
219 }
220
221 global $global_mimetypes;
222 $global_mimetypes = $mimeData;
223 return $mimeData;
224 }
225
226 227 228 229 230
231 static function sendRequest( $host, $path, $query, $port = 80 ) {
232 $socket = fsockopen( $host, $port, $errno, $error );
233
234 if( !$socket )
235 return $error;
236
237 if( $query )
238 $query = '?' . $query;
239
240 if( self::$userName && self::$password ) {
241 $auth = "Authorization: Basic " . base64_encode( self::$userName . ':' . self::$password ) . "\r\n";
242 } else {
243 $auth = '';
244 }
245
246 $request = "GET {$path}{$query} HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n{$auth}\r\n";
247
248 fwrite( $socket, $request );
249 $response = stream_get_contents( $socket );
250
251 return $response;
252 }
253
254 255 256 257 258 259 260 261 262 263 264
265 static function sendPostRequest($host, $path, $data, $name = null, $query = '', $port = 80, $getResponse = true) {
266 $socket = fsockopen($host, $port, $errno, $error);
267
268 if(!$socket)
269 return $error;
270
271 if(self::$userName && self::$password)
272 $auth = "Authorization: Basic " . base64_encode(self::$userName . ':' . self::$password) . "\r\n";
273 else
274 $auth = '';
275
276 if($query)
277 $query = '?' . $query;
278
279 $dataStr = (is_array($data)) ? http_build_query($data) : $name . '=' . urlencode($data);
280 $request = "POST {$path}{$query} HTTP/1.1\r\nHost: $host\r\n{$auth}Content-Type: application/x-www-form-urlencoded\r\nContent-Length: " . strlen($dataStr) . "\r\n\r\n";
281 $request .= $dataStr . "\r\n\r\n";
282
283 fwrite($socket, $request);
284
285 if($getResponse){
286 $response = stream_get_contents($socket);
287 return $response;
288 }
289
290 }
291
292 protected static $cache_age = 0, $modification_date = null;
293 protected static $etag = null;
294
295 296 297
298 static function set_cache_age($age) {
299 self::$cache_age = $age;
300 }
301
302 static function register_modification_date($dateString) {
303 $timestamp = strtotime($dateString);
304 if($timestamp > self::$modification_date)
305 self::$modification_date = $timestamp;
306 }
307
308 static function register_modification_timestamp($timestamp) {
309 if($timestamp > self::$modification_date)
310 self::$modification_date = $timestamp;
311 }
312
313 static function register_etag($etag) {
314 self::$etag = $etag;
315 }
316
317 318 319 320 321 322
323 static function ($body = null) {
324
325 if($body && !($body instanceof SS_HTTPResponse)) {
326 user_error("HTTP::add_cache_headers() must be passed an SS_HTTPResponse object", E_USER_WARNING);
327 $body = null;
328 }
329
330
331
332 if(Director::isDev()) {
333 if(!headers_sent()) header("Cache-Control: no-cache, max-age=0, must-revalidate");
334 return;
335 }
336
337
338 if(headers_sent() && !$body) return;
339
340
341 $responseHeaders = array();
342 if(function_exists('apache_request_headers')) {
343 $requestHeaders = apache_request_headers();
344 if(isset($requestHeaders['X-Requested-With']) && $requestHeaders['X-Requested-With'] == 'XMLHttpRequest') self::$cache_age = 0;
345
346 if(isset($requestHeaders['x-requested-with']) && $requestHeaders['x-requested-with'] == 'XMLHttpRequest') self::$cache_age = 0;
347 }
348
349 if(self::$cache_age > 0) {
350 $responseHeaders["Cache-Control"] = "max-age=" . self::$cache_age . ", must-revalidate";
351 $responseHeaders["Pragma"] = "";
352 } else {
353 $responseHeaders["Cache-Control"] = "no-cache, max-age=0, must-revalidate";
354 }
355
356 if(self::$modification_date && self::$cache_age > 0) {
357 $responseHeaders["Last-Modified"] =self::gmt_date(self::$modification_date);
358
359
360 if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
361 $ifModifiedSince = strtotime(stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']));
362 if($ifModifiedSince >= self::$modification_date) {
363 if($body) {
364 $body->setStatusCode(304);
365 $body->setBody('');
366 } else {
367 header('HTTP/1.0 304 Not Modified');
368 die();
369 }
370 }
371 }
372
373 $expires = time() + self::$cache_age;
374 $responseHeaders["Expires"] = self::gmt_date($expires);
375 }
376
377 if(self::$etag) {
378 $responseHeaders['ETag'] = self::$etag;
379 }
380
381
382 foreach($responseHeaders as $k => $v) {
383 if($body) $body->addHeader($k, $v);
384 else if(!headers_sent()) header("$k: $v");
385 }
386 }
387
388
389 390 391 392 393
394 static function gmt_date($timestamp) {
395 return gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
396 }
397
398 399 400
401 static function get_cache_age() {
402 return self::$cache_age;
403 }
404
405 }
406
407 ?>
408
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-