0

Having problems with uploading a file from c++ to a PHP form. Iv seen the posts similar to my issue.

And according to the documentation laid out in each, and in HERE my code by all accounts should be correct.

I also cannot use CURL for my implementation. As much as I would like too.

Iv tried encoding all the data into BASE64 to alleviate any file data problems, but no dice.

Iv double checked my php.ini file to allow uploads. And tested the PHP page with a simple HTML page that allows me to upload a file. All good, the form gives correct results.

Basically the headers I send to the server is:

Host: dzwxgames.com
Connection: close
Content-Length: 418
Origin: http://dzwxgames.com
Content-Type: multipart/form-data; boundary=WrbKitFormBoundaryXtRo8bh7ZpnTrTwd
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36
Pragma: no-cache

--WrbKitFormBoundaryXtRo8bh7ZpnTrTwd
Content-Disposition: form-data; name="file"; filename="02-11-2019 09-44.log"
Content-Type: text/plain;
Content-Transfer-Encoding: BASE64

W0FsdF1bVGFiXVtUYWJdW1RhYl1bQ11bRF1bU3BhY2VdW1VdW1BdW1RhYl1bRW50ZXJdW0xdW1NdW0VudGVyXVtDXVtEXVtTcGFjZV1bLl1bLl1bL11bRW50ZXJdW0xdW1NdW0VudGVyXVtBbHRdW1RhYl1bVGFiXVtUYWJdW1RhYl1bQWx0XVtUYWJdW1RhYl0=
--WrbKitFormBoundaryXtRo8bh7ZpnTrTwd--

Which my PHP page returns:

HTTP/1.1 200 OK
Date: Sun, 03 Nov 2019 09:09:19 GMT
Server: Apache/2.4.29 (Ubuntu)
Content-Length: 35
Connection: close
Content-Type: text/plain; charset=utf-8


NULL
Array
(
)
File does not exist.

The code for the php page is simple:

if (!isset($_FILES['file']['error'])){
       var_dump($_FILES['file']);
       print_r($_FILES);
       throw new RuntimeException('File does not exist.');
}

Finaly my C++ Code is:

bool sendFileToRemoteServer(std::filesystem::path file, const std::string& url,const std::string& iaddr) {
    std::string headder = "";       //Headder information
    std::string datahead = "";
    std::string content = "";

    if (!File::fastFileToString(file.string(), content)) {
        std::cout << "ERROR_FILE_OPEN" << std::endl;
        return false;
    }

    content = base64_encode(reinterpret_cast<const unsigned char*>(content.c_str()),content.length());

    datahead += "--WrbKitFormBoundaryXtRo8bh7ZpnTrTwd\r\n";
    datahead += "Content-Disposition: form-data; name=\"file\"; filename=\"" + file.filename().string() +"\"\r\n";  //Content - Disposition : form - data; name = "fileToUpload"; filename = "testMac.cpp"
    datahead += "Content-Type: text/plain;\r\n";
    datahead += "Content-Transfer-Encoding: BASE64\r\n\n";
    datahead += content;
    datahead += "\r\n--WrbKitFormBoundaryXtRo8bh7ZpnTrTwd--\r\n";

    //datahead = base64_encode(reinterpret_cast<const unsigned char*>(datahead.c_str()), datahead.length());

    //Build Headder
    headder += "Host: " + iaddr + "\r\n";                                       //Host: localhost
    headder += "Connection: close\r\n";                                         //Connection : keep - alive
    headder += "Content-Length: " + std::to_string(datahead.size()) + "\r\n";   //Content - Length : 800
    headder += "Origin: http://dzwxgames.com\r\n";
    //headder += "Content-Transfer-Encoding: base64\r\n";
    headder += "Content-Type: multipart/form-data; boundary=WrbKitFormBoundaryXtRo8bh7ZpnTrTwd\r\n";    //Content - Type : multipart / form - data; boundary = WrbKitFormBoundaryXtRo8bh7ZpnTrTwd
    headder += "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36\r\n";                                            //User - Agent: 1337
    headder += "Pragma: no-cache\r\n\r\n";                                     
    std::cout << "SENT HEAD:" << std::endl;
    std::cout << headder;
    std::cout << datahead;

    //Open internet connection
    HINTERNET hSession = InternetOpen("WINDOWS", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hSession == NULL){
        printLastError(GetLastError());
        printf("ERROR_INTERNET_OPEN");
        return false;
    }

    HINTERNET hConnect = InternetConnect(hSession, iaddr.c_str(), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
    if (hConnect == NULL){
        printLastError(GetLastError());
        printf("ERROR_INTERNET_CONN");
        return false;
    }

    HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST", _T(url.c_str()), NULL, NULL, NULL, INTERNET_FLAG_RELOAD, 1);
    if (hRequest == NULL){
        printLastError(GetLastError());
        printf("ERROR_INTERNET_REQ");
        return false;
    }

    if (!HttpSendRequestA(hRequest, headder.c_str(), headder.size(), (void*)datahead.c_str(), datahead.size())){
        printLastError(GetLastError());
        printf("ERROR_INTERNET_SEND");
        return false;
    }

    //Request Done, get responce

    DWORD dwSize = 0;
    if (!InternetQueryDataAvailable(hRequest, &dwSize, 0, 0)) {
        printLastError(GetLastError());
        printf("ERROR_InternetQueryDataAvailable");
        return false;
    }

    char* responce = new char[dwSize + 1];
    DWORD dwlpsizeread = 0;
    if (!InternetReadFile(hRequest, responce, dwSize, &dwlpsizeread)) {
        printLastError(GetLastError());
        printf("ERROR_InternetReadFile");
        return false;
    }

    printf("\nRESPONCE HEAD : \n");
    SampleCodeOne(hRequest);
    responce[dwSize] = 0;
    std::cout << responce << std::endl;

    delete[] responce;

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

    return true;
}

What am I missing? I cant seem to find the problem.

Steven Venham
  • 600
  • 1
  • 3
  • 18
  • File upload request format is only needed when uploading via a browser. Otherwise just send the file as a raw POST body, and write the body to a file on the server. The name can be a url parameter. – rustyx Nov 03 '19 at 10:08

1 Answers1

0

After checking with wire-shark, I found a 301 Error header sent back to me, with my force upgrade to HTTPS. After removing the HTTPS for testing, This fixed the error. Now I just have to fix the error code 3 on upload now. EUGH.

For some reason, HttpQueryInfo did not report the error 301. Instead it resent the packet to the new address, but without the data being encrypted, it had no idea what to do with it.

Funny enough, Apache silently discarded the un-encrypted data since it could not be encrypted. Nothing in the logs, no mention. Odd.

Not sure if intended. But ok.

Steven Venham
  • 600
  • 1
  • 3
  • 18