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 :).
 

No hay comentarios:

Publicar un comentario