Mostrando entradas con la etiqueta opciones. Mostrar todas las entradas
Mostrando entradas con la etiqueta opciones. Mostrar todas las entradas

jueves, 1 de mayo de 2014

[Parte 5] CURL en PHP

Funciones interesantes

curl_multi_init


Una de las extensiones mas usadas en PHP es cURL, y es genial para devolver documentos remotos. Para situaciones donde necesitas devolver multiples documentos se usa curl_multi_init y curl_multi_exec trabajan mejor con multiples documentos.

La funcion curl_multi_exec es muy poderosa, pero en la documentacion de PHP la hacen ver mas dificil de lo que realmente es. Aqui una demostracion usando Google, Bing y Facebook todos devueltos:

 $urls = array('http://www.google.com/', 'http://www.facebook.com/', 'http://www.bing.com/');
$url_count = count($urls); // cuenta el numero de urls

$curl_array = array(); // creamos un array llamado curl_array
$ch = curl_multi_init(); // iniciamos un multirecurso curl
// para las urls hay una clave que contiene su url
foreach($urls as $count => $url) {
 $curl_array[$count] = curl_init($url); // establecemos la url en una sesion curl refiriendonos a cada 1 con su clave
 curl_setopt($curl_array[$count], CURLOPT_FOLLOWLOCATION, 1); // le damos una opcion de seguir el header location
 curl_setopt($curl_array[$count], CURLOPT_RETURNTRANSFER, 1); // devolvemos el contenido
 curl_multi_add_handle($ch, $curl_array[$count]); // añadimos a cada url con sus opciones en el multirecurso
}
// mientras se esten ejecutando las urls realiza lo siguiente
do {
 curl_multi_exec($ch, $exec);
} while($exec > 0);


En este ejemplo hay 3 urls establecidas para devolverse al mismo tiempo. 


curl_multi_getcontent

Para leer el contenido de las peticiones que hicimos anteriormente podriamos usar la funcion curl_multi_getcontent. Vamos a ver como podemos hacerlo... (el codigo siguiente se puede añadir al anterior):


 //para cada url devolvemos el contenido junto con la url
foreach($urls as $count => $url) {
 $returned = curl_multi_getcontent($curl_array[$count]);
 echo "$url - $returned";
}



Cerrar el manejador de cURL


Algunos programadores prefieren usar curl_close() despues de haberlo usado. Usted en lugar de utilizar curl_close() deberia utilizar curl_multi_close(), y curl_multi_remove_handle() despues de que el contenido se haya devuelto. Veamos un ejemplo:



//para cada url eliminamos el manejador, cerramos la peticion multi recurso y cada peticion de una sesion curl la cerramos 
foreach($urls as $count => $url) {
 curl_multi_remove_handle($ch, $curl_array[$count]);
}

curl_multi_close($ch); 

foreach($urls as $count => $url) {
 curl_close($curl_array[$count]);
}


Como anteriormente dijimos el codigo anterior puede añadirse a lo que habiamos puesto antes... de esta manera todo el codigo quedaria asi:


 <?php
$urls = array('http://www.google.com/', 'http://www.facebook.com/', 'http://www.bing.com/');
$url_count = count($urls);

$curl_array = array();
$ch = curl_multi_init();

foreach($urls as $count => $url) {
 $curl_array[$count] = curl_init($url);
 curl_setopt($curl_array[$count], CURLOPT_FOLLOWLOCATION, 1);
 curl_setopt($curl_array[$count], CURLOPT_RETURNTRANSFER, 1);
 curl_multi_add_handle($ch, $curl_array[$count]);
}

do {
 curl_multi_exec($ch, $exec);
} while($exec > 0);
foreach($urls as $count => $url) {
 $returned = curl_multi_getcontent($curl_array[$count]);
 echo "$url - $returned";
}
foreach($urls as $count => $url) {
 curl_multi_remove_handle($ch, $curl_array[$count]);
}

curl_multi_close($ch); 

foreach($urls as $count => $url) {
 curl_close($curl_array[$count]);
}
?>

Fuente: http://www.fusionswift.com/2011/08/php-curl_multi_exec-example/



curl_setopt_array()


Con esta funcion podemos configurar multiples opciones para una transferencia cURL. Veamos un ejemplo:



 <?php
 // creamos un nuevo recurso curl
 $ch = curl_init();
 // establecemos las opciones apropiadas para la url
 $options = array(
  CURLOPT_URL => 'http://www.google.com/',
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_USERAGENT => 'Googlebot/2.1 (+http://www.google.com/bot.html)',
  CURLOPT_RETURNTRANSFER => true
  );
 curl_setopt_array($ch, $options);
 $output = curl_exec($ch);
 curl_close($ch);
 echo $output;
?>



curl_getinfo()


Esta funcion obtiene informacion relativa a una transferencia especifica. Los valores que devuelve son los siguientes:


  • "url"
  • "content_type"
  • "http_code"
  • "header_size"
  • "request_size"
  • "filetime"
  • "ssl_verify_result"
  • "redirect_count"
  • "total_time"
  • "namelookup_time"
  • "connect_time"
  • "pretransfer_time"
  • "size_upload"
  • "size_download"
  • "speed_download"
  • "speed_upload"
  • "download_content_length"
  • "upload_content_length"
  • "starttransfer_time"
  • "redirect_time"
  • "certinfo"
  • "request_header" 





curl_version()

Obtiene la informacion de la version de cURL





cURL File

Como veíamos en la parte 4 de curl, subiamos un archivo con el uso de @, pero apartir de PHP 5.5.0 ese prefijo esta obsoleto, por lo que se recomienda utilizar esta funcion.

CURLFile::__Construct--curl_file_create - Crea un objeto CURLFile

Estilo orientado a objetos:


public CURLFile::__construct ( string $filename [, string $mimetype [, string $postname ]] )

Estilo orientado a procedimientos:


CURLFile curl_file_create ( string $filename [, string $mimetype [, string $postname ]] )

Crea un objeto CurlFile, utilizado para transferir (upload) un fichero con CURLOPT_POSTFIELDS.

filename - indica la ruta de acceso al fichero a ser transferido
mimetype - Tipo mime del fichero
postname - nombre del fichero

Ejemplo, estilo orientado a objetos:



 <?php
/* http://example.com/upload.php:
<?php var_dump($_FILES); ?>
*/

// Crea un gestor cURL
$ch = curl_init('http://example.com/upload.php');

// Crea un objeto CURLFile
$cfile = new CURLFile('cats.jpg','image/jpeg','test_name');

// Asigna los datos POST 
$data = array('test_file' => $cfile);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

// Ejecuta el gestor
curl_exec($ch);
?>


Estilo por procedimientos:



 <?php
/* http://example.com/upload.php:
<?php var_dump($_FILES); ?>
*/

// Crea un gestor cURL
$ch = curl_init('http://example.com/upload.php');

// Crea un objeto CURLFile
$cfile = curl_file_create('cats.jpg','image/jpeg','test_name');

// Asigna los datos POST
$data = array('test_file' => $cfile);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

// Ejecuta el gestor
curl_exec($ch);
?>


Usar cURL con Expresiones regulares

Como en ejemplos anteriores usabamos la funcion preg_match y preg_match_all para ver si se encontraba determinado texto o link para poder mostrar el resultado que necesitabamos, para mas informacion sobre expresiones regulares por favor consulte:
http://www.arthusu.com.mx/2013/07/phpexpresiones-regulares-pcre.html

Como en el ejemplo de subidas de archivos en la parte 4  de curl, veíamos un upload con el cual sacábamos los links usando expresiones regulares:



 <?php
   set_time_limit(0);
   $url = "http://www0.xup.in/exec/xupload.php?uid=&key=";
   $user_agent = "Mozilla/5.0 (Windows NT 6.1; rv:28.0) Gecko/20100101 Firefox/28.0";
   $referer = "http://www.xup.in/";
   $directory=dirname(__FILE__).'\files/';
   if(isset($_FILES['f1'])){
      move_uploaded_file($_FILES['f1']['tmp_name'],"files/".$_FILES['f1']['name']);
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
      curl_setopt($ch, CURLOPT_REFERER, $referer);
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_POSTFIELDS, array("F1"=>"@".$directory.$_FILES['f1']['name']));
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
      $result = curl_exec($ch);
      if(curl_errno($ch))
  {
      echo 'Curl error: ' . curl_error($ch);
  }
      curl_close($ch);
      unlink($directory.$_FILES['f1']['name']);
      //echo $result;
      preg_match_all('/<input type="text" name="t1" size="90" class="inp" value="(.*?)" onclick="highlight\(this\);" \/>/', $result, $matches);
      //echo '<p><img src="'.$matches[1][0].'" alt="img" /></p>';
      echo '<p><b>Link: <a href="'.$matches[1][0].'" target="_blank">Archive Link</a></p>';
      //print_r($matches);
   }else{
      echo '
         <form action="upload_curl.php" method="post" enctype="multipart/form-data">
            <label for="f1">Filename:</label>
            <input type="file" name="f1" id="f1"><br>
            <input type="submit" name="submit" value="Submit">
         </form>

      ';   
   }
?>
 

domingo, 27 de abril de 2014

[Parte 4] CURL en PHP

Cabecera post personalizada a un host remoto 

Esto sucede cuando solo podemos ver ciertas partes de un sitio web, el sitio necesita unas cabeceras especiales, que tendriamos que olfatear con algun intermediario tal como puede ser: Live HTTP HEADERS, HTTPFox, Burp Suite, Tamper Data...


En este ejemplo estoy olfateando las cabeceras HTTP usando de intermediario HTTPFox (Complemento de firefox).

En este caso nosotros usaremos la opcion CURLOPT_HTTPHEADER.

CURLOPT_HTTPHEADER - Un array de campos a configurar para el Header HTTP, en el formato: array('Content-Type: text/plain','Content-length: 100');

CURLOPT_HEADER - TRUE para incluir el header en el OUTPUT.

 <?php

 $url = "https://tuhost.com/";
 $referer = "https://tuhost.com";

 $ch = curl_init(); // iniciamos curl
 curl_setopt($ch, CURLOPT_URL, $url); // establecemos la url
 curl_setopt($ch, CURLOPT_VERBOSE, 1); // muestra como pasa todo
 curl_setopt($ch, CURLOPT_HEADER, 1); // muestra las cabeceras que el servidor nos devuelve
 curl_setopt($ch, CURLOPT_STDERR, fopen('log_curl.txt','a+')); // en este archivo se guarda lo de verbose
 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/plain')); //modificamos nuestra cabecera
 curl_setopt($ch, CURLOPT_REFERER, $referer); // ponemos desde donde venimos
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // devolvemos el contenido de la pagina
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // quitamos la verificacion del certificado
 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // seguimos cualquier redireccion
 curl_setopt($ch, CURLOPT_COOKIEFILE, fopen('cookies.txt','a+')); // le decimos donde van las cookies
 curl_setopt($ch, CURLOPT_COOKIEJAR, fopen('cookies.txt','a+')); // le decimos que escriba las cookies aqui

 $result = curl_exec($ch); // ejecutamos y guardamos
 
  curl_close($ch); // cerramos curl, liberamos memoria

 print $result; // mostramos el resultado

?>

Subir un archivo a un sitio remoto usando un formulario HTML

Tu debes usar un formulario utilizando el metodo POST pero con algunos cambios. En este ejemplo, donde el formulario contiene enctype='multipart/form-data'. Usamos el array superglobal $_FILE para leer el archivo y pasarlo por los campos post con el signo @. Tal como lo siguiente:

 curl_setopt($ch, CURLOPT_POSTFIELDS, array("$field_name"=>"@".$_FILES['file']['tmp_name']));

En este ejemplo les muestro como subimos un archivo remotamente a la pagina xup.in:

 <?php
   set_time_limit(0);
   $url = "http://www0.xup.in/exec/xupload.php?uid=&key=";
   $user_agent = "Mozilla/5.0 (Windows NT 6.1; rv:28.0) Gecko/20100101 Firefox/28.0";
   $referer = "http://www.xup.in/";
   $directory=dirname(__FILE__).'\files/';
   if(isset($_FILES['f1'])){
      move_uploaded_file($_FILES['f1']['tmp_name'],"files/".$_FILES['f1']['name']);
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
      curl_setopt($ch, CURLOPT_REFERER, $referer);
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_POSTFIELDS, array("F1"=>"@".$directory.$_FILES['f1']['name']));
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
      $result = curl_exec($ch);
      if(curl_errno($ch))
  {
      echo 'Curl error: ' . curl_error($ch);
  }
      curl_close($ch);
      unlink($directory.$_FILES['f1']['name']);
      //echo $result;
      preg_match_all('/<input type="text" name="t1" size="90" class="inp" value="(.*?)" onclick="highlight\(this\);" \/>/', $result, $matches);
      //echo '<p><img src="'.$matches[1][0].'" alt="img" /></p>';
      echo '<p><b>Link: <a href="'.$matches[1][0].'" target="_blank">Archive Link</a></p>';
      //print_r($matches);
   }else{
      echo '
         <form action="upload_curl.php" method="post" enctype="multipart/form-data">
            <label for="f1">Filename:</label>
            <input type="file" name="f1" id="f1"><br>
            <input type="submit" name="submit" value="Submit">
         </form>

      ';   
   }
?>


En este caso tenemos un uploader y una carpeta llamada files/ en la cual se sube el fihcero luego envia una peticion subiendo el fichero y por ultimo nos envia el enlace, una cosa importante aqui es que agregamos la funcion curl_error($ch) que nos muestra si ocurre un error en cURL. Con la funcion curl_errno($ch) nos arroja un numero el cual tiene un mensaje especifico de error.

Nota: Recuerda que siempre que hago referencia a $ch es por que ahi se almacena la sesion de cURL.

Subir un archivo por FTP

Tu tienes la opcion en cURL de usar todos los comandos FTP. Por ejemplo, si quieres subir un archivo:

 <?php
if(isset($_POST['enviar'])){
    $ftp_user = "tuusuario";
    $ftp_pass = "tucontraseña";
    $url = "tuurloipdetuweb";
    $ftp_server = "ftp://". $ftp_user . ":" . $ftp_pass . "@" . $url;
    $archivo_a_subir = realpath($_FILES['userfile']['tmp_name']);
    $tamaño_del_archivo = filesize($archivo_a_subir);
    $fp = fopen($archivo_a_subir, 'rb');
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $ftp_server . $_FILES['userfile']['name']);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_UPLOAD, 1);
    curl_setopt($ch, CURLOPT_INFILE, $fp);
    curl_setopt($ch, CURLOPT_INFILESIZE, $tamaño_del_archivo);
    if(curl_errno($ch)){
        echo "Ha ocurrido un error: " . curl_error($ch);
    }
    $result = curl_exec($ch);
    curl_close($ch);
    echo "Archivo subido correctamente<br />";
    print $result;
}else{
    echo '
        <form action="" method="post" enctype="multipart/form-data">
            <p><input type="file" name="userfile" /></p>
            <p><input type="submit" name="enviar" value="Subir!" /></p>
        </form>
    ';
}
?>

CURLOPT_INFILE - El fichero que el proceso de transferencia debe leer a la hora de subir el archivo.

CURLOPT_INFILESIZE - El tamaño esperado en bytes, del fichero cuando se esta subiendo un fichero al sitio remoto. Tenganse en cuenta que el uso de esta opcion no detendra a libcurl a la hora de enviar mas datos, exactamente lo que se envia depende de CURLOPT_READFUNCTION.

Eliminar un archivo y mostrarlos por FTP

Tu tienes la opcion de usar comandos FTP con cURL. Alguna lista de comandos puedes encontrarla en: http://en.wikipedia.org/wiki/List_of_FTP_commands

Veamos un ejemplo de Eliminar un archivo y como mostrar los archivos tambien de una carpeta.

 <!DOCTYPE html>
<html>
<head>
 <title>ELIMINAR ARCHIVOS FTP</title>
 <meta charset="utf8">
</head>
<body>
<h1>Eliminar archivo</h1>
<form action="" method="post">
 <p><b>Nombre de la carpeta: </b><input type="text" name="carpeta" placeholder="tucarpeta/" /><small>No es necesario especificarla</small></p>
 <p><b>Nombre del archivo: </b><input type="text" name="archivo" placeholder="archivo.jpg" /></p>
 <input type="submit" name="enviar" />
</form>
<h1>Mostrar archivos de la carpeta</h1>
<form action="" method="post">
 <p><b>Nombre de la carpeta: </b><input type="text" name="directorio" placeholder="tucarpeta/" /><small>Es necesario especificarla para mostrar el contenido del directorio</small></p>
 <input type="submit" name="enviar2" />
</form>
<?php
 /* Variables para el FTP */
 $ftp_user = "tuusuario";
    $ftp_pass = "tucontraseña";
    $url = "tuhost.com/";

    $ftp_server = "ftp://". $ftp_user . ":" . $ftp_pass . "@" . $url;

    /* Funcion para eliminar el archivo */
    if(isset($_POST['enviar'])){
    function delete($carpeta = null , $archivo){
     global $ftp_user, $ftp_pass, $url, $ftp_server;
  if($carpeta == null){
   $carpeta = "public_html/";
  }
  $postfields[] = "CWD ". $carpeta;
  $postfields[] = "DELE " . $archivo;

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $ftp_server);
  curl_setopt($ch, CURLOPT_POSTQUOTE, $postfields);
  $result = curl_exec($ch);
  if(curl_errno($ch)){
   echo curl_error($ch);
  }
  curl_close($ch);

  print $result;
 }
    $carpeta = $_POST['carpeta'];
    $archivo = $_POST['archivo'];
    delete($carpeta,$archivo);

 }
 /* Listar directorio */
 if(isset($_POST['enviar2'])){
  function listar_dir($directorio){
   global $ftp_user, $ftp_pass;
   $url = "tuhost.com/".$directorio;
   $ftp_server = "ftp://". $ftp_user . ":" . $ftp_pass . "@" . $url;
   $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, $ftp_server);
   curl_setopt($ch, CURLOPT_FTPLISTONLY, 1);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
   $output = curl_exec($ch);
   if(curl_errno($ch)){
     echo curl_error($ch);
    }
   curl_close($ch);
   $files = explode("\n", $output);
   print_r($files);
  }
  $directorio = $_POST['directorio'];
  listar_dir($directorio);
 }
?>
</body>
</html>

CURLOPT_POSTQUOTE - Un array de comandos FTP a ejecutar en el servidor despues de que se realice la peticion FTP.

CURLOPT_FTPLISTONLY - TRUE para solo listar nombres de un directorio FTP.


Opciones LibcURL

Podemos ver una lista de opciones sobre la libreria cURL en: http://www.php.net/manual/es/function.curl-setopt.php

Rastrear peticiones

Rastrear las peticiones o ver sus cabeceras, es una manera de saber si estamos haciendo bien algo en cURL, existen muchas herramientas las cuales podemos utilizar como intermediario para poder ver las peticiones, como vimos arriba usabamos HTTP FOX.
Y como comentabamos esta disponible tambien Burp Suite, Live HTTP Headers, Tamper Data, etc.

 
Hasta aqui la parte de este tutorial, nos vemos en la proxima parte que espero sea la ultima :).