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:

  • no matching posts found..
8 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

 

 

Leave a Reply