0

I am having trouble in Sending File to my Server. I have checked some other questions tried to resolve most of the issues but at the end i am not able to upload the file Here is my C++ code :

   #define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <tchar.h>
#pragma warning(disable : 4996)
#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 = "perf.txt";   //Filename to be loaded
    static char *filepath = "C:\\perf.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[] = "2e8cd930.ngrok.io";        //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\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;
} 

Here is my PHP code [ upload.php] , i have already changed upload folder Permissions for others to create and Delete files:

<?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);
}
?>

Using Wireshark my Post Request and Response is [ I have already Tried Replacing two new lines with 1 line after Content -Type line but not helped After Changing Delimiter :

    POST /post/upload.php HTTP/1.1
Content-Type: multipart/form-data; boundary=BOUNDARY
User-Agent: WINDOWS
Host: 2e8cd930.ngrok.io
Content-Length: 130
Cache-Control: no-cache

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


Whats Up?
-BOUNDARY-
HTTP/1.1 200 OK
Date: Sat, 25 Nov 2017 11:25:16 GMT
Server: Apache/2.4.27 (Debian)
Content-Length: 10
Content-Type: text/html; charset=UTF-8

Array
(
)

I don't know why my Server reply coming out with Array (). The file is not being uploaded.

  • At least your closing delimiter is wrong as well as the delimiter in the header. — isn’t part of the boundary so remove it from headers. Closing delimiter also needs — in the end. Your sprintfs are also bad since they copy the existing data over and over instead of appending new data. And you’re missing \r before body. – Sami Kuhmonen Nov 25 '17 at 11:00
  • Sorry, i cant understand what you mean. Can you please elaborate or edit in code so i can understand – Shivam Sharma Nov 25 '17 at 11:04

1 Answers1

0

The first problems I can see:

You say in your headers that the delimiter is —BOUNDARY and then use the same string as the actual delimiter. This is wrong. The format is

—DELIMITER
content
—DELIMITER
content
—DELIMITER—

So your headers should say just BOUNDARY as the delimiter.

Content-Type: multipart/form-data; boundary=BOUNDARY

You also need to add the trailing to the closing delimiter.

You also have \r\n\n when separating headers from the body. It should be \r\n\r\n.

These errors will cause the MIME parser not to find any form data anywhere.

Performance-wise you shouldn’t use sprintf to append data by putting the buffer as first and then what you want to append. It’ll cause way too much copying data which is already there. You should use strncat rather since everything is strings to be appended. Or monitoring the string length and using sprintf to the end to append. See this question for more information.

Sami Kuhmonen
  • 30,146
  • 9
  • 61
  • 74