Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Vaagish en 5 Febrero 2014, 19:43 pm



Título: Enviar un archivo a un servidor
Publicado por: Vaagish en 5 Febrero 2014, 19:43 pm
Hola amigos,, puse esta consulta acá, y aunque parece simple creo que no lo es,, tanto..

La cosa es así,, tengo que enviar un archivo mediante POST a un servidor, desde un socket (winsock) conectado previamente.. así que supongo que lo que tengo que enviar es un array,, al estilo formulario HTML!

Para los que también entiendan de PHP la cosa es así:

Código
  1. $tmp_name = $_FILES["pictures"]["tmp_name"];
  2. move_uploaded_file($tmp_name, $SaveAs);

$_FILES es un array que recibe la información para saber como guardarla en el servidor,, el asunto es que yo con C++ no puedo enviar un array,, o si?

Aparte, no estoy seguro si se tiene que enviar el array con la información y nada mas o lleva algún encabezado HTTP..

Saludos!!

PD: Puse este tema acá en C++, porque creo que lo mas complicado va a ser armar todo desde el cliente,, si no tengo resultados acá, movemos el tema a WEB y vemos que pasa...


Título: Re: Enviar un archivo a un servidor
Publicado por: Yoel Alejandro en 6 Febrero 2014, 00:35 am
Sí se puede, aunque yo personalmente no lo he intendao (quiero hacerlo en un futuro). Hay una biblioteca de socktes, no se dónde se ubique en sistemas Windows pero en GNU/Linux es <sys/socket.h> y posiblemente haya que añadir <sys/wait.h> y <netinet/in.h>

Luego debes usar algunas funciones como socket, bin, listen (esto en LINUX pero creo que es igual para Windows). En la página http://www.chuidiang.com/clinux/ (http://www.chuidiang.com/clinux/) busca el apartado de sockets y te explican paso a paso cómo debes hacerlo y qué funciones debes usar. Incluso incluyen un ejemplo resuelto, con el código fuente y todo (en Español).

Espero te sirva y ayude ...

====================
Por cierto, como todo esto es para Linux, si quieres que sea compatible con Windows (si es tu caso) usa un compilador de C de GNU para Windows, así muchas de las funciones de GNU funcionarán correctamente en Windows. Descárgate MinGW de la página http://www.mingw.org/ (http://www.mingw.org/) y busca la ruta del ejecutable gcc.exe, luego la añades a la variable de entorno PATH y ya puedes compilar con este compilador de GNU. Si quieres más detalles de cómo hacerlo dime y te indico.

Es posible que si usas otro compilador como el de BorlandC (estoy especulando, la verdad no se a ciencia cierta) no te funcionen los ejemplos para Linux dados en chuidiang.com


Título: Re: Enviar un archivo a un servidor
Publicado por: xv0 en 6 Febrero 2014, 00:50 am
el asunto es que yo con C++ no puedo enviar un array,, o si?

Pues con send o sendto, tienes la informacion en la msdn, y si quieres crear un socket con mas opciones tienes setsockopt y getsockopt.

Un saludo.


Título: Re: Enviar un archivo a un servidor
Publicado por: Vaagish en 6 Febrero 2014, 00:57 am
Hola! Gracias por responder!

Si,, yo los sockets los manejo,, ya pude enviar request simples con información,, el asunto es enviar una imagen, por post.. me gustaría saber como es que un formulario envía la información, y luego recrear esa situación (el envio del formulario) pero con sockets, en C++..

Como puse por ahi,, la conexión la tengo,, y el envio de texto/variables también, pero para las imágenes se hace algo diferente,,

Así se puede enviar un string con el request al servidor..

Código
  1. char HTTPStr[37] = "POST /Proyectos/Uploads/upload.php?";
  2. char HTTPEnd[34] = "HTTP/1.1\nhost: localhost\r\n\r\n";

en el medio de esas dos cadenas debería ir el contenido de la request


Título: Re: Enviar un archivo a un servidor
Publicado por: xv0 en 6 Febrero 2014, 01:22 am
Bueno como bien dijiste tu, no se si tendran que mover esto al subforo de programacion web, creo que hay te ayudaran mejor.

Navegando un poco, encontre estos code.

Código:
http://stackoverflow.com/questions/14728125/how-do-i-send-an-image-over-http-protocol-in-c
http://www.dreamincode.net/forums/topic/203610-simple-http-sending-images-jpeggif/

En el ejemplo que muestras tu, creas el encabezado con esas "definiciones" (vamos a llamarlas asi) POST y HTTP/1.1, en esos ejemplos las definiciones son mas extensas, supongo que seria encontrar la definicion adecuada y crear el encabezado correcto y enviar el paquete.

Un saludo.


Título: Re: Enviar un archivo a un servidor
Publicado por: Vaagish en 6 Febrero 2014, 05:43 am
Citar
Navegando un poco, encontre estos code.

Código:
http://stackoverflow.com/questions/14728125/how-do-i-send-an-image-over-http-protocol-in-c
http://www.dreamincode.net/forums/topic/203610-simple-http-sending-images-jpeggif/

Excelente!! Creo que con eso lo puedo resolver!! Gracias!!!

Saludos!!


Título: Re: Enviar un archivo a un servidor
Publicado por: Yoel Alejandro en 7 Febrero 2014, 02:44 am
Que bueno que puedas resolver con eso!!!

Por si acaso te sirve, el envío de un formulario a un servidor consiste simplemente de un mensaje HTTP de tipo GET o un POST, que en su cuerpo contiene parejas de nombre-valor. El atributo "name" de cada control del formulario seguido se su "value".

En el caso de imágenes es igual, pero el contenido del mensaje es simplemente el flujo de bits que forma la imagen. Es decir, el contenido bruto del fichero de imagen. Pero en la cabecera del mensaje debes especificar el tipo MIME del documento, que por ejemplo para una imagen GIF debe ser  "image/gif"


Título: Re: Enviar un archivo a un servidor
Publicado por: Vaagish en 7 Febrero 2014, 03:52 am
Citar
Insertar Cita
Que bueno que puedas resolver con eso!!!

Por si acaso te sirve, el envío de un formulario a un servidor consiste simplemente de un mensaje HTTP de tipo GET o un POST, que en su cuerpo contiene parejas de nombre-valor. El atributo "name" de cada control del formulario seguido se su "value".

En el caso de imágenes es igual, pero el contenido del mensaje es simplemente el flujo de bits que forma la imagen. Es decir, el contenido bruto del fichero de imagen. Pero en la cabecera del mensaje debes especificar el tipo MIME del documento, que por ejemplo para una imagen GIF debe ser  "image/gif"

Gracias por tu respuesta! Estuve leyendo sobre el tema y es asi como decis.. ahora estoy tratando de esnifar los paquetes con un programa,, en cuanto consiga la cadena correcta la posteo aca!

Saludos!


Título: Re: Enviar un archivo a un servidor
Publicado por: Vaagish en 8 Febrero 2014, 07:41 am
Bueno,, después de muchas horas de lucha,, no lo he conseguido.. voy a dejar el código de la parte que tendría que hacer la magia,, pero no la hace..

Código
  1. #include "main.h"
  2. #include "conexion.h"
  3.  
  4. #include <iostream>
  5. using namespace std;
  6.  
  7. char A[64] = "POST /Proyectos/Uploads/uploader.php HTTP/1.1\nhost: localhost\r\n";
  8. char B[27] = "Content-type: image/jpeg\r\n";
  9. char C[23] = "Content-Length: 3024\r\n";
  10. char D[3] = "\r\n";
  11.  
  12. char ConnString[] = "";
  13.  
  14.  
  15. int main()
  16. {
  17.  
  18. SOCKET Sock = Conectar();
  19. HANDLE Rec_Handle = CreateThread(NULL, 0, Recibir, NULL, NORMAL_PRIORITY_CLASS, NULL);
  20.  
  21. // ARCHIVO
  22. FILE *Archivo;
  23. char Buff[3024];
  24. Archivo = fopen("auto.jpg", "rb");
  25. int Tamano = fread(Buff, 1, 3024, Archivo);
  26. fclose(Archivo);
  27. // ******************************************
  28.  
  29. strcat(ConnString, A);
  30. strcat(ConnString, B);
  31. strcat(ConnString, C);
  32. strcat(ConnString, D);
  33.  
  34. int Total = strlen(ConnString) + Tamano;
  35.  
  36. strcat(ConnString, Buff);
  37.  
  38. send(Sock, ConnString, Total, 0);
  39.  
  40. cin.get();
  41. return 0;
  42. }

Asumimos que en conexion.cpp estan las funciones para conectarse (cosa que hace bien) y devuelve un SOCKET (para poder usar send luego en main.cpp), tambien esta la funcion recibir, que se inicia como un hilo, y que tambien funciona bien,, porque del servidor me llega "Ha ocurrido un error, la imagen no se subio", con las respectivas cabeceras HTTP. Bueno,, probablemente el error este en mi cabecera HTTP, que esta formada por A,B,C y D.. No puedo mas con esto jajaja

Saludos!!

EDIT: Me parece que no se debe utilizar strcat con archivo binarios... Sugerencias para unir un puntero char con datos binarios??

EDIT: Ya arregle con memcpy el item anterior..


Título: Re: Enviar un archivo a un servidor
Publicado por: xv0 en 9 Febrero 2014, 05:00 am
La funcion strcat trabaja con cadenas, eso significa que al encontrar un valor nulo 0, esta dejara de copiar, y a ser un valor binario segurisimo que hay un 0.

Tendrias que usar memcpy, prueba si funciona, si no tendrias que repasar esas cabzeras, y bueno no estoy muy metido en C/C++ pero los punteros se podrian arreglar y todas esas funciones tambien.

Un saludo.


Título: Re: Enviar un archivo a un servidor
Publicado por: Vaagish en 9 Febrero 2014, 07:18 am
Citar
La funcion strcat trabaja con cadenas, eso significa que al encontrar un valor nulo 0, esta dejara de copiar, y a ser un valor binario segurisimo que hay un 0.

Sip,, ya lo había arreglado..

Citar
los punteros se podrian arreglar y todas esas funciones tambien.

Jajaja yo sabia que no escapaba del ojo meticuloso.. es una basura el código,, pero deberia funcionar,, entonces lo arreglo  :P voy a poner una actualización del code:

Código
  1. #include "main.h"
  2. #include "conexion.h"
  3.  
  4. #include <iostream>
  5. using namespace std;
  6.  
  7. char A[65] = "POST /Proyectos/Uploads/uploader.php HTTP/1.1\r\nhost: 127.0.0.1\r\n";
  8. char B[27] = "Content-type: image/jpeg\r\n";
  9. char C[23] = "Content-Length: 3024\r\n";
  10. char D[3] = "\r\n";
  11.  
  12. char ConnString[3141] = "";
  13.  
  14.  
  15. int main()
  16. {
  17.  
  18. SOCKET Sock = Conectar();
  19. HANDLE Rec_Handle = CreateThread(NULL, 0, Recibir, NULL, NORMAL_PRIORITY_CLASS, NULL);
  20.  
  21. // ARCHIVO
  22. FILE *Archivo;
  23. char Buff[3024];
  24. Archivo = fopen("auto.jpg", "rb");
  25. int Tamano = fread(Buff, 1, 3024, Archivo);
  26. fclose(Archivo);
  27. // ******************************************
  28.  
  29. strcat(ConnString, A);
  30. strcat(ConnString, B);
  31. strcat(ConnString, C);
  32. strcat(ConnString, D);
  33.  
  34. memcpy(ConnString + strlen(ConnString), Buff, Tamano);
  35.  
  36. send(Sock, ConnString, 3138, 0);
  37.  
  38. // closesocket(Sock);
  39.  
  40. cin.get();
  41. return 0;
  42. }

Bueno,, en fin.. ya estoy a un pelo de hacer mis propias funciones en PHP y C++ para subir archivos,, (capaz que me queda hasta mejor).. abro el archivo como binario,, lo divido en partes,, le mando al server la cantidad de partes y el nombre,, y después lo uno y lo escribo con PHP y listo,,, me parece que va a ser mas fácil y multi proposito!

Saludos!!


Título: Re: Enviar un archivo a un servidor
Publicado por: xv0 en 9 Febrero 2014, 07:31 am
Bueno por la forma de expresarte seguro que ya resolviste el problema, pero segun lo que e visto, en la expresion "Content-Length:" tienes que poner solo la longitud del archivo a enviar, no tienes que sumarlo todo.

No comprendo porque declaras las ordenes en cuatro punteros, porque no lo haces en uno? Solamente tendrias que agrandar el puntero para añadir la imagen, o asi lo veo yo.

Un saludo.