Ver Mensaje Individual
  #1 (permalink)  
Antiguo 19/05/2010, 00:27
Avatar de Triby
Triby
Mod on free time
 
Fecha de Ingreso: agosto-2008
Ubicación: $MX->Gto['León'];
Mensajes: 10.106
Antigüedad: 16 años, 4 meses
Puntos: 2237
[Aporte] cURL y safe_mode = 'On' para API's (Twitter y Bit.ly)

Integrando las API's de Twitter y Bit.ly (Obtener enlaces cortos) en un servidor dedicado no tuve mayor problema, pero, en ambientes compartidos, donde normalmente PHP corre en modo seguro (safe_mode = 'On') se genera una advertencia:

Cita:
CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an open_basedir is set
Basandome en las funciones encontradas en: http://www.edmondscommerce.co.uk/cur...-or-safe-mode/ hice lo siguiente para obtener las variables que ambas clases (Twitter y Bitly) requieren: $response, $headers, $errorNumber, $errorMessage.

Código PHP:
Ver original
  1. function sm_curl($options){
  2.     // Hay que seguir redireccionamientos?
  3.     $follow = (isset($options[CURLOPT_FOLLOWLOCATION])) ? $options[CURLOPT_FOLLOWLOCATION] : false;
  4.  
  5.     // Instanciamos cURL
  6.     $go = curl_init();
  7.     $response = array();
  8.     if(ini_get('open_basedir') != '' || ini_get('safe_mode' == 'On') && $follow) {
  9.         // Aqui entramos solo si hay que seguir redireccionamientos y
  10.         // open_basedir o safe_mode estan activos
  11.  
  12.         // Eliminamos la opcion CURL para seguir redireccionamientos
  13.         unset($options[CURLOPT_FOLLOWLOCATION]);
  14.  
  15.         // Establecemos las opciones
  16.         curl_setopt_array($go, $options);
  17.  
  18.         // Ejecutamos y seguimos redireccionamientos
  19.         $response = curl_redir_exec($go);
  20.     } else {
  21.         curl_setopt_array($go, $options);
  22.         // Ejecutar
  23.         $response['response'] = curl_exec($go);
  24.         $response['headers'] = curl_getinfo($go);
  25.  
  26.         // Obtener errores
  27.         $response['errorNumber'] = curl_errno($go);
  28.         $response['errorMessage'] = curl_error($go);
  29.     }
  30.     curl_close($go);
  31.     return $response;
  32. }
  33.  
  34. // Seguir redireccionamientos con open_basedir o safe_mode = On
  35. function curl_redir_exec($ch) {
  36.     static $curl_loops = 0;
  37.     static $curl_max_loops = 20;
  38.     if ($curl_loops++>= $curl_max_loops) {
  39.         $curl_loops = 0;
  40.         return array('response' => '', 'headers' => '', 'errorNumber' => '47', 'errorMessage' => 'Too many redirects');
  41.     }
  42.     curl_setopt($ch, CURLOPT_HEADER, true);
  43.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  44.     $data = curl_exec($ch);
  45.     $data = str_replace("\n\r", "\n", $data);
  46.     list($header, $data) = explode("\n\n", $data);
  47.     $headers = curl_getinfo($ch);
  48.     $http_code = $headers['http_code'];
  49.     if ($http_code == 301 || $http_code == 302) {
  50.         $matches = array();
  51.         preg_match('/Location:(.*?)\n/', $header, $matches);
  52.         $url = @parse_url(trim(array_pop($matches)));
  53.         if (!$url) {
  54.             //couldn't process the url to redirect to
  55.             $curl_loops = 0;
  56.             return array('response' => '', 'headers' => '', 'errorNumber' => 3, 'errorMessage' => 'The URL was not properly formatted (redirect).');
  57.         }
  58.         $last_url = parse_url(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
  59.         if (!$url['scheme'])
  60.             $url['scheme'] = $last_url['scheme'];
  61.         if (!$url['host'])
  62.             $url['host'] = $last_url['host'];
  63.         if (!$url['path'])
  64.             $url['path'] = $last_url['path'];
  65.         $new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query']?'?'.$url['query']:'');
  66.         curl_setopt($ch, CURLOPT_URL, $new_url);
  67.         return curl_redir_exec($ch);
  68.     } else {
  69.         $curl_loops=0;
  70.         return array(
  71.             'response' => $data,
  72.             'headers' => $headers,
  73.             'errorNumber' => curl_errno($ch),
  74.             'errorMessage' => curl_error($ch),
  75.         );
  76.     }
  77. }

$options es una matriz donde se incluyen todas las opciones cURL a ejecutar, por ejemplo, en la funcion doCall() de la clase Bitly es:

Código PHP:
Ver original
  1. // set options
  2.         $options[CURLOPT_URL] = $url;
  3.         $options[CURLOPT_PORT] = self::API_PORT;
  4.         $options[CURLOPT_USERAGENT] = $this->getUserAgent();
  5.         $options[CURLOPT_FOLLOWLOCATION] = true;
  6.         $options[CURLOPT_RETURNTRANSFER] = true;
  7.         $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();

La ejecucion original es:
Código PHP:
Ver original
  1. // init
  2.         $curl = curl_init();
  3.  
  4.         // set options
  5.         curl_setopt_array($curl, $options);
  6.  
  7.         // execute
  8.         $response = curl_exec($curl);
  9.         $headers = curl_getinfo($curl);
  10.  
  11.         // fetch errors
  12.         $errorNumber = curl_errno($curl);
  13.         $errorMessage = curl_error($curl);
  14.  
  15.         // close
  16.         curl_close($curl);

Y hay que reemplazarla por:
Código PHP:
Ver original
  1. $data = sm_curl($options);
  2.         extract($data);

Tengo un archivo common.php donde guardo las rutinas de uso mas frecuente o que son requeridas por dos o mas scripts en mis sitios, aqui coloque las funciones sm_curl() y curl_redir_exec().

Tanto para Twitter, como para Bit.ly, uso las clases creadas por Tijs Verkoyen que pueden descargar en: http://classes.verkoyen.eu/
__________________
- León, Guanajuato
- GV-Foto