Our blog

 

PHP, cURL, CURLOPT FOLLOWLOCATION and open basedir Or Safe Mode

If you are trying to get a curl script which needs follow on location functionality to run on a server which has either open_basedir or safe mode enabled you will get an error message similar to the following:

CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set

After a bit of digging, some kind soul has put a workaround here

Here is how to use the function

PHP:
  1. function curl($url){
  2. $go = curl_init($url);
  3. curl_setopt ($go, CURLOPT_URL, $url);
  4. //follow on location problems
  5.  
  6. if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')){
  7.  
  8. curl_setopt ($go, CURLOPT_FOLLOWLOCATION, $l);
  9.  
  10. $syn = curl_exec($go);
  11.  
  12. }else{
  13.  
  14. $syn = curl_redir_exec($go);
  15.  
  16. }
  17.  
  18. curl_close($go);
  19. return $syn;
  20. }
  21.  
  22. //follow on location problems workaround
  23.  
  24. function curl_redir_exec($ch)
  25.  
  26. {
  27.  
  28. static $curl_loops = 0;
  29.  
  30. static $curl_max_loops = 20;
  31.  
  32. if ($curl_loops++>= $curl_max_loops)
  33.  
  34. {
  35.  
  36. $curl_loops = 0;
  37.  
  38. return FALSE;
  39.  
  40. }
  41.  
  42. curl_setopt($ch, CURLOPT_HEADER, true);
  43.  
  44. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  45.  
  46. $data = curl_exec($ch);
  47.  
  48. list($header, $data) = explode("\n\n", $data, 2);
  49.  
  50. $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  51.  
  52. if ($http_code == 301 || $http_code == 302)
  53.  
  54. {
  55.  
  56. $matches = array();
  57.  
  58. preg_match('/Location:(.*?)\n/', $header, $matches);
  59.  
  60. $url = @parse_url(trim(array_pop($matches)));
  61.  
  62. if (!$url)
  63.  
  64. {
  65.  
  66. //couldn't process the url to redirect to
  67.  
  68. $curl_loops = 0;
  69.  
  70. return $data;
  71.  
  72. }
  73.  
  74. $last_url = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
  75.  
  76. if (!$url['scheme'])
  77.  
  78. $url['scheme'] = $last_url['scheme'];
  79.  
  80. if (!$url['host'])
  81.  
  82. $url['host'] = $last_url['host'];
  83.  
  84. if (!$url['path'])
  85.  
  86. $url['path'] = $last_url['path'];
  87.  
  88. $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query']?'?'.$url['query']:'');
  89.  
  90. curl_setopt($ch, CURLOPT_URL, $new_url);
  91.  
  92. return curl_redir_exec($ch);
  93.  
  94. } else {
  95.  
  96. $curl_loops=0;
  97.  
  98. return $data;
  99.  
  100. }
  101.  
  102. }

More Reading:

22 Comments

sakao
January 18th, 2009

this is not a working code
as far as i can see
there's no
$go = curl_init($url);
in the first line

 

admin
January 19th, 2009

oops sorry about that- i have add this in there.

 

Karl
February 5th, 2009

Very nice, works like a treat. Am using it with domdocument and xpath to scrape content from various sources.

Quick tip: obvious, but for php novices, you'll need to add something like the following to your code to actually start the process

$html=curl('http://www.urltobeparsed.com');

See here for more info: http://www.merchantos.com/makebeta/php/scraping-links-with-php/

 

Ali
February 25th, 2009

Hello,

I am getting the error

CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set

What can be the possible solution. I didnt understand the above script you have written

 

nd
May 7th, 2009

Nice code!

However, I had a problem with it since
explode("\n\n", $data, 2);

does not work on all platforms. Correct is
explode("\n\r", $data, 2);

Regards,
Andy

 

admin
May 7th, 2009

nice one Andy.

I wonder if we could mod the function to work on any platform..

would swapping \n\n for PHP_EOL work?

 

steve
July 29th, 2009

nd - you're right about the \n\r this worked for me.

also, error in line 6, should be:

if (ini_get('open_basedir') == '' && ini_get('safe_mode') == 'Off'){

in my case I also had to change the safe mode check because safe mode off is an empty string:

if (ini_get('open_basedir') == '' && ini_get('safe_mode' == '')){

 

Andy
September 24th, 2009

Wonderful, saved my life :) I used it on an connector which i wrote for plugging WordPress and CakePHP together. In this constellation, there was no $url["query"] and i got an error message. So this is my solution for that:

$new_url = $url['scheme'].'://'.$url['host'].$url['path'].(array_key_exists('query', $url) && $url['query'] ? '?'.$url['query'] : '');

Maybe it´s usefull for someone.

Nice greetings and a big thank you for this workaround.

Andy

 

test
July 14th, 2010

sdf

 

Funny Images
August 6th, 2010

Yes this is working on my site.

Thanks for solution

 

tim
August 22nd, 2010

What do you called the script before uploading it to the server

 

Mesut
October 12th, 2010

Great job thanks. You helped me to fix this very annoying problem. Thanks very much.

 

Ron
June 4th, 2011

You are a god! ;)

Took me 2 hours of configuring but now it works! Thanks alot! :)

 

budflick
June 15th, 2011

thanks! worked like a charm

 

Daniel
August 2nd, 2011

This saved me A LOT of time. Thank you!

 

Karthik
August 17th, 2011

Awesome script. Really helped me!

Thanks,
Karthik

 

Sand
August 22nd, 2011

Error on Line 94 - Notice: Undefined offset: 1:
list($header, $data) = explode("\n\n", $data, 2);

 

Sand
August 22nd, 2011

list($header, $data) = explode("\n\n", $data, 2);

$header == ??

 

Andrew
August 26th, 2011

Sand, $header is the first element of the $data array, but you may need to change "\n\n" to something which works on your system. See earlier comments.

 

wawan
September 13th, 2011

i have a website using wp.
when i want to install the plugin, i got the alert

Warning: curl_setopt_array() [function.curl-setopt-array]: CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set in /home/greendi4/public_html/kindle/wp-content/plugins/instant_traffic_robot/includes/classes/plugin.class.php on line 847

can you help me with this problem??

 

Andreas
September 27th, 2011

Hi @ all,

i'm using the script on both windows an linux platforms.
Therefore the lines that explodes the header have to be changed.

Insteaf of:
$data = curl_exec($ch);
list($header, $data) = explode("\n\n", $data, 2);

use this:
$data1 = curl_exec($ch);
//Linux
list($header, $data) = explode("\n\n", $data1, 2);
if($data==null) {
//Windows-System
list($header, $data) = explode("\n\r", $data1, 2);
}

Best regards

Andreas

 

Tony Huang
November 3rd, 2011

curl_setopt ($go, CURLOPT_FOLLOWLOCATION, $l);

What is the $l?

 

 

Leave a Reply