2010-03-24 9 views
15

에 따라 곱슬 곱슬이 오류 메시지를 받았습니다.위치 오류

open_basedir은 ""입니다.

어떻게 해결할 수 있습니까? 당신의 open_basedir 또는 safe_mode가 하나가 활성화되어야합니다 경우 조건에서 볼 수 있듯이

+0

참조 된 사이트 링크를 쉽게 추출 할 수 있습니다. http://stackoverflow.com/a/3520085/669677 –

+0

여기에 답변 됨 : http://stackoverflow.com/a/6918742/2165415 –

답변

5

이 경고 메시지를 인쇄 할 수있는 유일한 장소는 내선/컬/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; 
    } 
} 

입니다.

+0

이 문제를 극복 할 수있는 방법이 있습니까? ? 사용자 정의 위치 추적 기능 또는 유사한 기능을 사용합니다. – embedded

+4

'curl_getinfo ($ ch, CURLINFO_HTTP_CODE)'를 사용할 수 있으며 301 또는 302를 반환하면 Location : 헤더를 가져옵니다. – VolkerK

+0

이것은 zsalab의 구현입니다. – dolmen

2

비슷한 상황이 발생하여 아래에서 해결책을 찾았습니다. 일반적으로 어디로 리디렉션되는지를 아는 경우이 방법이 도움이 될 수 있습니다.

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; 
    } 
} 
1

실제 환경에서는 테스트하지 않았지만 curl_exec로 투명성이 더 높습니다 (헤더 및 returntransfer 옵션에는 문제 없음).

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

이 구현에는 두 가지 문제가 있습니다. 1. 오류가 발생하면 오류가 발생합니다. 2. 최종 URL의 요청은 두 번 완료됩니다 (헤더 용, 전체 용) – dolmen

+0

'ini_get ('safe_mode'== 'Off')'Typo (괄호는 'safe_mode'를 묶어야하며 모든 곳에서 작동하지 않습니다) – Ruben

13

해결 방법은 PHP 코드에서 리디렉션을 구현하는 것입니다.

내 구현은 다음과 같습니다. 그것은 그것은 CURLOPT_HEADERFUNCTION

코드와 호환되지 않는 CURLOPT_RETURNTRANSFER

  • 을 강제

    1. : 그것은 두 가지 알려진 제한이 이미 $curl 인스턴스가 이미 구성되어있는 경우

      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; 
          } 
      } 
      
  • +3

    필자의 경우,'CURLOPT_FOLLOWLOCATION = true '동작을 복제하기 위해 do 루프의 if 조건에'&& $ code! = 303' (기타 참조)를 추가해야했습니다. – Ruben

    +0

    관련 블로그 게시물 [cURL : safe_mode 사용 또는 open_basedir 설정 (2012 년 3 월 31 일 Slopjong)으로 위치 추적] (http://slopjong.de/2012/03/31/curl-follow-locations-with-safe_mode-enabled - 또는 - open_basedir-set /) - 완벽하지는 않지만 누군가 코드를 검토하고 싶다면 도움이 될 수 있습니다. – hakre

    0

    및 FOLLOWLOCATION이 활성화 된 curl_exec을 시뮬레이트하고 싶다면 다음 중 하나를 사용하십시오.

    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; 
    } 
    

    참고 : 이미이 옵션을 지정한 경우이 함수를 호출 할 때 URL을 제공하지 마십시오.이 옵션은 재귀 적 용도로만 사용됩니다.

    나는이 코드의 대답에서 영감을 얻어 여러 헤더를 관리하기 위해 몇 가지 사항을 추가했습니다.

    이 기능은 ie6에 대한 추한 해킹과 같습니다. 가능한 경우 호스팅을 변경하십시오 .--).

    1

    그냥 참고 : 코드

    모든 해답은 여기에 수동으로 Location: 헤더를 찾기 위해 컬 요청에서 헤더를 구문 분석합니다.

    그러나 PHP 5.3.7부터 curl_getinfo()과 함께 사용할 수있는 CURLINFO_REDIRECT_URL 옵션이 있습니다. 요청을 두 번 할 필요가 없습니다. 헤더를 사용하지 않으려는 경우 필요하지 않으며 정규 표현식을 사용할 필요가 없습니다.