Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- function curl_exec_follow($ch, $max=5) {
- $response = false;
- // Common cURL options that need to be turned on for this to work and return consistently
- curl_setopt($ch, CURLOPT_HEADER,true);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
- if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
- // Can just use FOLLOWLOCATION, still need to parse the headers/status/content though.
- // to maintain a consistent return.
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($ch, CURLOPT_MAXREDIRS, $max);
- $response = curl_exec($ch);
- if ($response !== false) {
- $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
- $response = array(
- 'headers' => substr($response, 0, $headerSize),
- 'content' => substr($response, $headerSize),
- 'status' => curl_getinfo($ch, CURLINFO_HTTP_CODE)
- );
- }
- }
- else {
- // explicitly turn FOLLOWLOCATION off, just in case servers do weird things.
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
- // use a local copy of the cURL handle.
- $local = curl_copy_handle($ch);
- $redirected = false;
- $target = curl_getinfo($local, CURLINFO_EFFECTIVE_URL);
- $last = parse_url($target); // need to maintain a reference to the last redirect in case following redirects are relative paths.
- if (empty($last['hostname'])) {
- // relative path on the server, very trivial attempt to build a correct path so it may not work in all cases
- $last = parse_url("http" . (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 's://' : '://') . $_SERVER['HTTP_HOST'] . $target);
- }
- $redirectCodes = array(301,302,307); // no support for 305 proxy redirects...yet :)
- $headers = array(); // maintain the headers throughout the redirection.
- do {
- curl_setopt($local, CURLOPT_URL, $target);
- if (!($response = curl_exec($local))) {
- break;
- }
- $code = curl_getinfo($local, CURLINFO_HTTP_CODE);
- $headerSize = curl_getinfo($local, CURLINFO_HEADER_SIZE);
- $header = substr($response, 0, $headerSize);
- $headers[] = rtrim($header);
- $redirected = in_array($code, $redirectCodes);
- if ($redirected) {
- if (preg_match('/^(?:Location|URI):\\s*([^\\r\\n]+)/m', $header, $matches) !== 1) {
- trigger_error("Requested resource is redirecting incorrectly.", E_USER_WARNING);
- $redirected = false; // set the loop-breaking condition.
- $response = false; // invalidate the response
- }
- $target = parse_url(trim($matches[1]));
- if (empty($target['scheme'])) { // relative redirect, use the last url
- $target = $last['scheme'] . '://' . $last['host'] . $target['path'];
- $last = parse_url($target);
- }
- elseif ($target['scheme'] === 'file') {
- // Redirecting into the file:// protocol, can be unsafe
- trigger_error("Requested resource is attempting to redirect to files on the local system.", E_USER_WARNING);
- $redirected = false; // set the loop-breaking condition.
- $response = false; // invalidate the response
- }
- else {
- $target = trim($matches[1]);
- $last = parse_url($target);
- }
- if ($code === 302) {
- // Many browsers implemented the 302-redirect in this way. i.e subsequent redirects
- // used the GET method, even when the original method used POST.
- // See http://en.wikipedia.org/wiki/HTTP_302 for more information.
- curl_setopt($local, CURLOPT_HTTPGET, true);
- }
- }
- } while($redirected && --$max >= 0);
- if ($response !== false) {
- $response = array(
- 'headers' => implode("\r\n\r\n", $headers), // standard is an CRLF seperator between headers as far as I know.
- 'content' => substr($response, curl_getinfo($local, CURLINFO_HEADER_SIZE)),
- 'status' => curl_getinfo($local, CURLINFO_HTTP_CODE)
- );
- }
- curl_close($local);
- }
- return $response;
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement