curl follow location error

前端 未结 6 1022
耶瑟儿~
耶瑟儿~ 2020-11-27 06:48

I got this error message:

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

safe_mode i

相关标签:
6条回答
  • 2020-11-27 07:23

    If you already have a $curl instance already configured and just want to simulate curl_exec with FOLLOWLOCATION enabled, you can use this one:

    function curl_follow_exec($curl, $url = null)
    {
        curl_setopt($curl, CURLOPT_HEADER, true);
        if (!is_null($url))
        {
            $opts = array (
                CURLOPT_URL => $url,
                CURLOPT_POST => false,
                CURLOPT_PUT => false,
            );
            curl_setopt_array($curl, $opts);
        }
        $data = curl_exec($curl);
        $status = curl_getinfo($curl);
        $arr = explode("\r\n\r\n", $data);
        while (strpos(reset($arr), 'HTTP/1.1 100 Continue') !== false)
        {
            array_shift($arr);
        }
        $header = $arr[0];
        $body = implode("\r\n", array_slice($arr, 1));
        if ($status['http_code'] == 301 || $status['http_code'] == 302)
        {
            $matches = array ();
            preg_match("/(Location:|URI:)[^(\n)]*/", $header, $matches);
            $url = trim(str_replace($matches[1], "", $matches[0]));
            return curl_follow_exec($curl, $url);
        }
        return $body;
    }
    

    Note: don't provide an URL when calling this function if you already specified the option, it is just used for recursive purposes.

    I inspired this code from the accepted answer, and added some stuffs to manage multiple headers.

    This function is like an ugly hack for ie6: if you can, change your hosting :-).

    0 讨论(0)
  • 2020-11-27 07:24

    Never tested in real environment but has more transparency with curl_exec (no problem with header and returntransfer options).

    function curl_exec_follow(/*resource*/ $ch, /*int*/ $maxredirect = 5) {
        if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        } else {
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
            $newurl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
    
            $rch = curl_copy_handle($ch);
            curl_setopt($rch, CURLOPT_HEADER, true);
            curl_setopt($rch, CURLOPT_NOBODY, true);
            curl_setopt($rch, CURLOPT_RETURNTRANSFER, true);
            do {
                curl_setopt($rch, CURLOPT_URL, $newurl);
                $header = curl_exec($rch);
                if (curl_errno($rch)) {
                    $code = 0;
                } else {
                    $code = curl_getinfo($rch, CURLINFO_HTTP_CODE);
                    if ($code == 301 || $code == 302) {
                        preg_match('/Location:(.*?)\n/', $header, $matches);
                        $newurl = trim(array_pop($matches));
                    } else {
                        $code = 0;
                    }
                }
            } while ($code && $maxredirect--);
            curl_close($rch);
            curl_setopt($ch, CURLOPT_URL, $newurl);
        }
        return curl_exec($ch);
    }
    
    0 讨论(0)
  • 2020-11-27 07:31

    The workaround is to implement redirection in PHP code.

    Here is my own implementation. It has two known limitations:

    1. It will force CURLOPT_RETURNTRANSFER
    2. It is incompatible with CURLOPT_HEADERFUNCTION

    The code:

    function curl_exec_follow(/*resource*/ &$ch, /*int*/ $redirects = 20, /*bool*/ $curlopt_header = false) {
        if ((!ini_get('open_basedir') && !ini_get('safe_mode')) || $redirects < 1) {
            curl_setopt($ch, CURLOPT_HEADER, $curlopt_header);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $redirects > 0);
            curl_setopt($ch, CURLOPT_MAXREDIRS, $redirects);
            return curl_exec($ch);
        } else {
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
            curl_setopt($ch, CURLOPT_HEADER, true);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_FORBID_REUSE, false);
    
            do {
                $data = curl_exec($ch);
                if (curl_errno($ch))
                    break;
                $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                if ($code != 301 && $code != 302)
                    break;
                $header_start = strpos($data, "\r\n")+2;
                $headers = substr($data, $header_start, strpos($data, "\r\n\r\n", $header_start)+2-$header_start);
                if (!preg_match("!\r\n(?:Location|URI): *(.*?) *\r\n!", $headers, $matches))
                    break;
                curl_setopt($ch, CURLOPT_URL, $matches[1]);
            } while (--$redirects);
            if (!$redirects)
                trigger_error('Too many redirects. When following redirects, libcurl hit the maximum amount.', E_USER_WARNING);
            if (!$curlopt_header)
                $data = substr($data, strpos($data, "\r\n\r\n")+4);
            return $data;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 07:34

    Just a note:

    All answers with code here manually parse the headers from a curl request to find a Location: header.

    However, since PHP 5.3.7, there is an option CURLINFO_REDIRECT_URL you can use with curl_getinfo(). No need to do requests twice, no need to enable headers if you don't want them, no need for regexps.

    0 讨论(0)
  • 2020-11-27 07:35

    I encountered a similar situation a while back and found the solution below. If you know generally where you'll be redirected to this might work for you.

        function curl($url, $postVars)
    {
        $go = curl_init($url);
        curl_setopt ($go, CURLOPT_URL, $url);
        curl_setopt($go, CURLOPT_VERBOSE, 1);
    
        //follow on location problems
        if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off'))
        {
            curl_setopt ($go, CURLOPT_FOLLOWLOCATION, $l);
            $syn = curl_exec($go);
            if(curl_error($go))
                return false;
        }
        else
            $syn = curl_redir_exec($go, $postVars);
        curl_close($go);
        return $syn;
    }
    
    function curl_redir_exec($ch, $postVars)
    {
        static $curl_loops = 0;
        static $curl_max_loops = 20;
        if ($curl_loops++>= $curl_max_loops)
        {
            $curl_loops = 0;
            return FALSE;
        }
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postVars);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    
        $data = curl_exec($ch);
        if(curl_error($ch))
            return false;
        list($header, $data) = explode("\n\r", $data, 2);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
        $redirect_page = "[0-9]*.html";
        $base_redirect = "http://example.com/";
    
        if ($http_code == 301 || $http_code == 302)
        {
            $matches = array();
            $pregs = eregi($redirect_page, $data, $matches);
            $new_url = $base_redirect . $matches[0];
            if (!$new_url)
            {
                //couldn't process the url to redirect to
                $curl_loops = 0;
                return $data;
            }
            curl_setopt($ch, CURLOPT_URL, $new_url);
    
            return curl_redir_exec($ch, $postVars);
        }
        else
        {
            $curl_loops=0;
            return $data;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 07:45

    The only place where this warning message is printed is in ext/curl/interface.c

    if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
      if (Z_LVAL_PP(zvalue) != 0) {
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set");
        RETVAL_FALSE;
        return 1;
      }
    }
    

    As you can see from the if-condition either open_basedir or safe_mode must be enabled.

    0 讨论(0)
提交回复
热议问题