Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • ArrayLib
  • BBCodeParser
  • Convert
  • Cookie
  • DataDifferencer
  • Geoip
  • HTMLCleaner
  • HTTP
  • i18n
  • Profiler
  • ShortcodeParser
  • SSHTMLBBCodeParser
  • SSHTMLBBCodeParser_Filter
  • SSHTMLBBCodeParser_Filter_Basic
  • SSHTMLBBCodeParser_Filter_EmailLinks
  • SSHTMLBBCodeParser_Filter_Extended
  • SSHTMLBBCodeParser_Filter_Images
  • SSHTMLBBCodeParser_Filter_Links
  • SSHTMLBBCodeParser_Filter_Lists
  • TextParser
  • Translatable_Transformation
  • XML
  1 <?php
  2 /**
  3  * A class with HTTP-related helpers.
  4  * Like Debug, this is more a bundle of methods than a class ;-)
  5  * 
  6  * @package sapphire
  7  * @subpackage misc
  8  */
  9 class HTTP {
 10 
 11     static $userName;
 12     static $password;
 13 
 14     /**
 15      * Turns a local system filename into a URL by comparing it to the script filename
 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         // Count the number of extra folders the script is in.
 33         // $prefix = str_repeat("../", substr_count(substr($_SERVER[SCRIPT_FILENAME],$commonBaseLength)));
 34     }
 35 
 36     /**
 37      * Turn all relative URLs in the content to absolute URLs
 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      * Rewrite all the URLs in the given content, evaluating the given string as PHP code
 46      *
 47      * Put $URL where you want the URL to appear, however, you can't embed $URL in strings
 48      * Some example code:
 49      *  '"../../" . $URL'
 50      *  'myRewriter($URL)'
 51      *  '(substr($URL,0,1)=="/") ? "../" . substr($URL,1) : $URL'
 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         // Make
 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      * Will try to include a GET parameter for an existing URL,
 78      * preserving existing parameters and fragments.
 79      * If no URL is given, falls back to $_SERVER['REQUEST_URI'].
 80      * Uses parse_url() to dissect the URL, and http_build_query() to reconstruct it
 81      * with the additional parameter. Converts any '&' (ampersand)
 82      * URL parameter separators to the more XHTML compliant '&amp;'.
 83      * 
 84      * CAUTION: If the URL is determined to be relative,
 85      * it is prepended with Director::absoluteBaseURL().
 86      * This method will always return an absolute URL because
 87      * Director::makeRelative() can lead to inconsistent results.
 88      * 
 89      * @param String $varname
 90      * @param String $varvalue
 91      * @param String $currentURL Relative or absolute URL (Optional).
 92      * @param String $separator Separator for http_build_query(). (Optional).
 93      * @return String Absolute URL
 94      */
 95     public static function setGetVar($varname, $varvalue, $currentURL = null, $separator = '&amp;') {
 96         $uri = $currentURL ? $currentURL : Director::makeRelative($_SERVER['REQUEST_URI']);
 97 
 98         $isRelative = false;
 99         // We need absolute URLs for parse_url()
100         if(Director::is_relative_url($uri)) {
101             $uri = Director::absoluteURL(Director::baseURL()) . $uri;
102             $isRelative = true;
103         }
104 
105         // try to parse uri
106         $parts = parse_url($uri);
107         if(!$parts) {
108             throw new InvalidArgumentException("Can't parse URL: " . $uri);
109         }
110 
111         // Parse params and add new variable
112         $params = array();
113         if(isset($parts['query'])) parse_str($parts['query'], $params);
114         $params[$varname] = $varvalue;
115         
116         // Generate URI segments and formatting
117         $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http';
118         $user = (isset($parts['user']) && $parts['user'] != '')  ? $parts['user'] : '';
119 
120         if($user != '') {
121             // format in either user:pass@host.com or user@host.com
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         // handle URL params which are existing / new
130         $params = ($params) ?  '?' . http_build_query($params, null, $separator) : '';
131         if ($params == '?') $params = '';
132 
133         // keep fragments (anchors) intact.
134         $fragment = (isset($parts['fragment']) && $parts['fragment'] != '') ?  '#'.$parts['fragment'] : '';
135         
136         // Recompile URI segments   
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      * Search for all tags with a specific attribute, then return the value of that attribute in a flat array.
151      *
152      * @param string $content
153      * @param array $attributes an array of tags to attributes, for example "[a] => 'href', [div] => 'id'"
154      * @return array
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      * Get mime type based on extension
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      * Load the mime-type data from the system file
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         // Fail-over for if people don't have /etc/mime.types on their server.  it's unclear how important this actually is
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      * Send an HTTP request to the host.
228      *
229      * @return String Response text
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      * Send a HTTP POST request through fsockopen().
256      *
257      * @param string $host Absolute URI without path, e.g. http://silverstripe.com
258      * @param string $path Path with leading slash
259      * @param array|string $data Payload for the request
260      * @param string $name Parametername for the payload (only if passed as a string)
261      * @param string $query
262      * @param string $port
263      * @return string Raw HTTP-result including headers
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      * Set the maximum age of this page in web caches, in seconds
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      * Add the appropriate caching headers to the response, including If-Modified-Since / 304 handling.
319      *
320      * @param SS_HTTPResponse The SS_HTTPResponse object to augment.  Omitted the argument or passing a string is deprecated; in these
321      * cases, the headers are output directly.
322      */
323     static function add_cache_headers($body = null) {
324         // Validate argument
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         // Development sites have frequently changing templates; this can get stuffed up by the code
331         // below.
332         if(Director::isDev()) {
333             if(!headers_sent()) header("Cache-Control: no-cache, max-age=0, must-revalidate");
334             return;
335         }
336         
337         // The headers have been sent and we don't have an SS_HTTPResponse object to attach things to; no point in us trying.
338         if(headers_sent() && !$body) return;
339         
340         // Popuplate $responseHeaders with all the headers that we want to build 
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             // bdc: now we must check for DUMB IE6:
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             // 304 response detection
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         // Now that we've generated them, either output them or attach them to the SS_HTTPResponse as appropriate
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      * Return an {@link http://www.faqs.org/rfcs/rfc2822 RFC 2822} date in the
391      * GMT timezone (a timestamp is always in GMT: the number of seconds
392      * since January 1 1970 00:00:00 GMT)
393      */
394     static function gmt_date($timestamp) {
395         return gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
396     }
397     
398     /* 
399      * Return static variable cache_age in second
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. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0