簡體   English   中英

通過C ++套接字將二進制文件發布到PHP

[英]POST binary file to PHP via C++ socket

我正在嘗試通過套接字發送二進制文件。 我捕獲了Curl標頭,以嘗試對其進行反向工程。 我的應用程序和curl請求對我來說似乎相同,但是PHP腳本無法接收該文件。

這是我的代碼:

#include <iostream>
#include <string>
#include <fstream>
#include <winsock.h>
#pragma comment(lib, "wsock32.lib")

/***************** PROTOTYPE *******************/
int SockRecv(SOCKET sock);
int SockSend(SOCKET sock, std::string request);
std::streamoff FileSize(std::string filename);
int HTTP_POST(SOCKET sock, std::string host, std::string filename);
int SendFile(SOCKET sock, std::string filename);
/***************** PROTOTYPE *******************/

int main(){

        /* Standard networking stuff */
        u_short Port = 8080;
        const char* IP = "192.168.1.140";
        std::string host(IP);
        host += ":" + std::to_string(Port);

        WSAData wsa;
        WSAStartup(MAKEWORD(1, 1), &wsa);
        SOCKET sock;
        sockaddr_in RemoteSin;
        RemoteSin.sin_family = AF_INET;
        RemoteSin.sin_port = htons(Port);

        if ((RemoteSin.sin_addr.S_un.S_addr = inet_addr(IP)) == INADDR_NONE){
                std::cout << "Error setting IP: " << GetLastError() << std::endl;
                return 1;
        }
        if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR){
                std::cout << "Error creating socket" << std::endl;
                return 1;
        }

        if (connect(sock, (sockaddr *)&RemoteSin, sizeof(sockaddr_in)) == SOCKET_ERROR){
                std::cout << "Error connecting to remote host: " << GetLastError() << std::endl;
                return 1;
        }

        /* Sending the binary file */
        HTTP_POST(sock, host, "test.exe");

        /* Closing and cleaning connection */
        closesocket(sock);
        WSACleanup();

        getchar();
}

std::streamoff FileSize(std::string filename){

        std::ifstream file(filename, std::ios::binary | std::ios::ate);
        return file.tellg();
}

int HTTP_POST(SOCKET sock, std::string host, std::string filename){

        std::string header;
        std::streamoff lenght = FileSize(filename);

        /* Pre-building body to get the size  */
        std::string strSize = "------------------------448eacc7eda1d5ef45\r\n";
        strSize += "Content-Disposition: form-data; name=\"uploadedfile\"; ";
        strSize += "filename=\"" + filename + "\"\r\n";
        strSize += "Content-Type: application/octet-stream\r\n\r\n";
        strSize += "\r\n------------------------448eacc7eda1d5ef45--\r\n";

        /* Calculating Content-Lenght */
        lenght = lenght + strSize.size();

        /* Building header */
        header = "POST /upload.php HTTP/1.1\r\n";
        header += "User-Agent: Bot\r\n";
        header += "Host: " + host + "\r\n";
        header += "Accept: */*\r\n";
        header += "Content-Length: " + std::to_string(lenght) + "\r\n";
        //      header += "Expect: 100-continue\r\n"; // Curl send this but I think this is not required and might only complicate things      
        header += "Content-Type: multipart/form-data-stream; ";
        header += "boundary=------------------------448eacc7eda1d5ef45\r\n\r\n";

        /* Appending first part of body to header */
        header += "------------------------448eacc7eda1d5ef45\r\n";
        header += "Content-Disposition: form-data; name=\"uploadedfile\"; ";
        header += "filename=\"" + filename + "\"\r\n";
        header += "Content-Type: application/octet-stream\r\n\r\n";

        /* Sending header with first part of body */
        if (!SockSend(sock, header)) {

                /* Sending binary file */
                if (!SendFile(sock, filename)){

                        /* Closing body by sending end of boundary string */
                        std::string header_end = "\r\n------------------------448eacc7eda1d5ef45--\r\n";
                        if (!SockSend(sock, header_end)){

                                /* Printing server response to stdout */
                                if (!SockRecv(sock)){
                                        return 0;
                                }

                                return 1;
                        }
                }
        }
        return 1;
}

int SockSend(SOCKET sock, std::string request){

        if (send(sock, request.c_str(), strlen(request.c_str()), 0) == SOCKET_ERROR){
                return 1;
        }
        return 0;
}

int SockRecv(SOCKET sock){

        char reply[1024];
        ZeroMemory(reply, 1024);
        if (recv(sock, reply, 1024, 0) == SOCKET_ERROR){
                return 1;
        }
        std::cout << reply << std::endl;

        return 0;
}

int SendFile(SOCKET sock, std::string filename){

        char buf[1040];
        std::ifstream infile;
        infile.open(filename.c_str(), std::ios::in | std::ios::binary);

        if (infile.fail() == 1)
        {
                infile.close();
                return 1;
        }

        while (!infile.eof())
        {
                infile.read(buf, sizeof(buf));
                if (send(sock, buf, infile.gcount(), 0) == SOCKET_ERROR){
                        return 1;
                }
        }

        infile.close();
        return 0;
}

這是接收PHP腳本:

<?php

// Where the file is going to be placed
$target_path = "upload/";

/* Add the original filename to our target path.  
Result is "uploads/filename.extension" */
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
    echo "The file ".  basename( $_FILES['uploadedfile']['name']).
    " has been uploaded";
} else{
    echo "There was an error uploading the file, please try again!";
}

?>

使用此curl請求:

curl --form "uploadedfile=@test.exe" http://192.168.1.140:8080/upload.php

這是成功上傳的樣子:

Request:
POST /upload.php HTTP/1.1
User-Agent: curl/7.35.0
Host: 192.168.1.140:8080
Accept: */*
Content-Length: 69328
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------bfaa9a39adfbb3c1

--------------------------bfaa9a39adfbb3c1
Content-Disposition: form-data; name="uploadedfile"; filename="test.exe"
Content-Type: application/octet-stream

/* Binary data */
--------------------------bfaa9a39adfbb3c1--

Response:
HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Server: nginx/1.2.6 (Ubuntu)
Date: Tue, 08 Apr 2014 19:45:38 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.4.9-4ubuntu2.4
Content-Length: 35

The file test.exe has been uploaded 

然后使用我的C ++應用程序,這就是失敗的上傳的樣子:

Request:
POST /upload.php HTTP/1.1
User-Agent: Bot
Host: 192.168.1.140:8080
Accept: */*
Content-Length: 69328
Content-Type: multipart/form-data-stream; boundary=------------------------448eacc7eda1d5ef45

------------------------448eacc7eda1d5ef45
Content-Disposition: form-data; name="uploadedfile"; filename="test.exe"
Content-Type: application/octet-stream

/* Binary data */
------------------------448eacc7eda1d5ef45--

Response:
HTTP/1.1 200 OK
Server: nginx/1.2.6 (Ubuntu)
Date: Tue, 08 Apr 2014 19:45:49 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.4.9-4ubuntu2.4
Content-Length: 56

There was an error uploading the file, please try again!

我省略了“期望:100-繼續”,因為我認為這是可選的。 否則,這兩個請求在我看來都是完全一樣的。 三重檢查了我能做的一切,但現在我被困在那里。

感謝您的輸入!

您使用了錯誤的標題:

    header += "Content-Type: multipart/form-data-stream; ";
                                                ^^^^^^^---- wrong type

它應該只是multipart/form-data

至於您的PHP代碼,您將無法檢查上傳成功/有效,只是假設一切正常:

if ($_FILES['uploadedfile']['error'] !== UPLOAD_ERR_OK) {
    die("Upload failed with error code" . $_FILES['uploadedfile']['error']);
}

如果您只進行了很少的錯誤處理,就會被告知沒有上載,而不是稍后嘗試移動不存在的文件時才發現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM