Send POST file C ++

I am trying to post a text file via POST to my upload.php form in php on my localhost webserver using C ++.

Here is my PHP code for the request:

<?php
$uploaddir = 'upload/';

if (is_uploaded_file(isset($_FILES['file']['tmp_name'])?($_FILES['file'['tmp_name']):0)) 
{
    $uploadfile = $uploaddir . basename($_FILES['file']['name']);
    echo "File ". $_FILES['file']['name'] ." uploaded successfully. ";

    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) 
    {
        echo "File was moved! ";
    }
    else
    {
        print_r($_FILES);
    }
}
else 
{
    print_r($_FILES);
}
?>

      

The directory upload

exists in the same directory as upload.php (content above).

Here is the code I'm using to prepare the http request and send it:

#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <tchar.h>

#pragma comment(lib,"wininet.lib")
#define ERROR_OPEN_FILE       10
#define ERROR_MEMORY          11
#define ERROR_SIZE            12
#define ERROR_INTERNET_OPEN   13
#define ERROR_INTERNET_CONN   14
#define ERROR_INTERNET_REQ    15
#define ERROR_INTERNET_SEND   16

using namespace std;

int main()
{
 // Local variables
 static char *filename   = "test.txt";   //Filename to be loaded
 static char *filepath   = "C:\\wamp\\www\\post\\test.txt";   //Filename to be loaded
 static char *type       = "text/plain";
 static char boundary[]  = "--BOUNDARY---";            //Header boundary
 static char nameForm[]  = "file";     //Input form name
 static char iaddr[]     = "localhost";        //IP address
 static char url[]       = "/post/upload.php";         //URL

 char hdrs[512]={'-'};                  //Headers
 char * buffer;                   //Buffer containing file + headers
 char * content;                  //Buffer containing file
 FILE * pFile;                    //File pointer
 long lSize;                      //File size
 size_t result;                   

 // Open file
 pFile = fopen ( filepath , "rb" );
 if (pFile==NULL) 
 {
     printf("ERROR_OPEN_FILE");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("OPEN_FILE\n");

 // obtain file size:
 fseek (pFile , 0 , SEEK_END);
 lSize = ftell (pFile);
 rewind (pFile);

 // allocate memory to contain the whole file:
 content = (char*) malloc (sizeof(char)*(lSize+1));
 if (content == NULL) 
 {
     printf("ERROR_MEMORY");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("MEMORY_ALLOCATED\t \"%d\" \n",&lSize);
 // copy the file into the buffer:
 result = fread (content,1,lSize,pFile);
 if (result != lSize) 
 {
     printf("ERROR_SIZE");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("SIZE_OK\n");

 content[lSize] = '\0';

 // terminate
 fclose (pFile);
 printf("FILE_CLOSE\n");
 //allocate memory to contain the whole file + HEADER
 buffer = (char*) malloc (sizeof(char)*lSize + 2048);

 //print header
 sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
 sprintf(buffer,"%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",boundary,nameForm,filename);
 sprintf(buffer,"%sContent-Type: %s\r\n",buffer,type);
 sprintf(buffer,"%s\r\n%s",buffer,content);
 sprintf(buffer,"%s\r\n--%s--\r\n",buffer,boundary);

 printf("%s", buffer);

 //Open internet connection
 HINTERNET hSession = InternetOpen("WINDOWS",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
 if(hSession==NULL) 
 {
     printf("ERROR_INTERNET_OPEN");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("INTERNET_OPENED\n");

 HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
 if(hConnect==NULL) 
 {
     printf("ERROR_INTERNET_CONN");
     getchar();
     return ERROR_INTERNET_CONN;
 }
 printf("INTERNET_CONNECTED\n");

 HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",_T(url),NULL, NULL, NULL,INTERNET_FLAG_RELOAD, 1);
 if(hRequest==NULL) 
  {
     printf("ERROR_INTERNET_REQ");
     getchar();

 }
 printf("INTERNET_REQ_OPEN\n");

 BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, strlen(buffer));

 if(!sent) 
 {
     printf("ERROR_INTERNET_SEND");
     getchar();
     return ERROR_INTERNET_CONN;
 }
 printf("INTERNET_SEND_OK\n");

 InternetCloseHandle(hSession);
 InternetCloseHandle(hConnect);
 InternetCloseHandle(hRequest);

 getchar();
 return 0;
}

      

When I run upload.exe (content above). I am getting the following output:

OPEN_FILE
MEMORY_ALLOCATED    "1832340"
SIZE_OK
FILE_CLOSE
---BOUNDARY---
Content Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
test
---BOUNDARY---
INTERNET_OPENED
INTERNET_CONNECTED
INTERNET_REQ_OPEN
INTERNET_SEND_OK

      

Here is the PHP error log:

[12-Nov-2014 20:09:58 Europe/Paris] PHP Stack trace:
[12-Nov-2014 20:09:58 Europe/Paris] PHP   1. {main}() C:\wamp\www\post\upload.php:0

      

I am a little confused what this means. This is mistake?

Everything seems to pass (note: the content of test.txt is a "test"). Although when I look at the catalog upload

. The test.txt file is missing. The directory is empty. Can anyone help me understand what is the problem? Thanks you!

BUMP Nobody knows how to do this, or is it impossible? Because if that's not possible, just tell me so I can stop wasting time searching.

+3


source to share


1 answer


Testing your client in C ++ I found that the variable content

that contains the contents of the file does not end with a character NULL

, so when you copy with it sprintf

, you copy random bytes as long as it NULL

appears.

Change the selection to this:

 content = (char*) malloc (sizeof(char)*(lSize+1));

      

And after reading the contents of the file, do the following:

content[lSize] = '\0';

      

Also, I'm pretty sure I BOUNDARY

should start on a new line. So make this change too:

 sprintf(buffer,"%s\r\n--%s--\r\n",buffer,boundary);

      

Edit:

Comparing a normal HTML form request, I can see that the content should start after two lines, so change that as well:

sprintf(buffer,"%s\r\n%s",buffer,content);

      

Edit2:



After testing with PHP code, I found some more issues with C ++ code. (By the way, there is a typo in the PHP code: missing ]

in the if statement)

The border is not configured correctly.

The mime format should be as follows:

--BOUNDARY
Content-Disposition: form-data; name="file"; filename="test2.txt"
Content-Type: text/plain

test
--BOUNDARY

      

The HTTP header should look like this: Content-Type: multipart / form-data; border = BORDERS

So it sprintf

should look like this:

sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",boundary,nameForm,filename);
sprintf(buffer,"%sContent-Type: %s\r\n",buffer,type);
sprintf(buffer,"%s\r\n%s",buffer,content);
sprintf(buffer,"%s\r\n--%s\r\n",buffer,boundary);

      

After doing all the fixes in this post, the code should work.

Summarizing:

  • I would recommend using a virtual machine setup to debug these problems more easily because then you can use Wireshark \ Fidler \ Burp. (You can also try configuring a proxy for localhost, never tried this yourself. You can also try using your external Internet IP and configure your router for port forwarding, but it's too complicated for this kind of task).
  • If that doesn't help, NetCat can help. Not so easy and friendly, but does the job.
  • Just comparing the working example to your query will output exactly what is missing. For this I used Beyond Compare. Always work with comparison software as the human eye can deceive easily.
  • The most obvious one was to read the Mime spec and see what exactly is missing.
+1


source







All Articles