Reputation: 79
So I am attempting to upload files to a server from a windows 7 client using winsock. In order to do this I have setup the socket and then created an HTTP POST request that is supposed to send all of the data to a PHP file on the server which will then upload it. The code to create the request is...
#include <winsock2.h>
#include <windows.h>
#include <iostream>
using namespace std;
int main (int argc, char* argv[]){
WSADATA wsaData;
char* fileName = argv[1];
WSAStartup(MAKEWORD(2,2), &wsaData);
SOCKET Socket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct hostent *host;
host = gethostbyname("localhost");
SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(80);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
cout << "Connecting...\n";
connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr);
cout << "Connected.\n";
char *header="POST /upload.php HTTP/1.1\r\n"
"Host: localhost\r\n"
"Content-Type: multipart/form-data; boundary=myboundary\r\n"
"Connection: close\r\n"
"\r\n--myboundary\r\n"
"Content-Type: application/octet-stream\r\n"
"Content-Disposition: form-data; name=\"myfile\"; filename=\"myfile.ext\"\r\n"
"Content-Transfer-Encoding: 8bit\r\n"
"\r\n";
// Open the existing file.
HANDLE hFile = CreateFile(fileName, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
int size = GetFileSize(hFile, NULL);
send(Socket,header, strlen(header),0);
//send the file to the server
int bytesSent = 0;
do{
char buff[300];
DWORD dwBytesRead;
//Copy file into array buff
if(!ReadFile(hFile, buff, 300, &dwBytesRead, NULL)){
cout << GetLastError << endl;
return 1;
}
bytesSent += send(Socket, buff, dwBytesRead, 0);
cout << "Bytes Sent " << bytesSent << endl;
}while(bytesSent < size);
char *footer = "\r\n--myboundary--\r\n";
send(Socket, footer, strlen(footer), 0);
closesocket(Socket);
WSACleanup();
cout<<endl<<endl;
return 0;
}
While the PHP code to receive the file is...
<?php
$target_dir = "recvFile/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
// Check if file already exists
if (file_exists($target_file)) {
echo "File already exists";
$uploadOk = 0;
}
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "File to large";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "ERROR File not uploaded";
// if everything is ok, try to upload file
} else {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
} else {
echo "ERROR uploading file";
}
}
?>
But there is never anything within $_FILES and so the upload always fails. Did I create the HTTP request incorrectly? Do I need to specifically say that the file is after myboundary? Also if there is a resource that has examples of creating HTTP requests from scratch it would be really helpful because for some reason wireshark doesn't even see the request which makes it even harder to figure out what's going on.
PS This is my first time asking a question on StackOverflow so if there is some formatting or conduct that I messed up please let me know so I can fix it!
Upvotes: 1
Views: 6622
Reputation: 79
The issue that I was having was actually relatively simple to fix. First I needed to add a user-agent, second I needed to define a content-length which was the length of the ENTIRE http request (not just the data portion). My finished HTTP Request then appears as:
POST /upload.php HTTP/1.1
Host: localhost
Content-Length: 800
Content-Type: multipart/form-data; boundary=WrbKitFormBoundaryXtRo8bh7ZpnTrTwd
User-Agent: 1337
Connection: keep-alive
--WrbKitFormBoundaryXtRo8bh7ZpnTrTwd
Content-Disposition: form-data; name="fileToUpload"; filename="testMac.cpp"
Content-Type: application/octet-stream
//SEND RAW FILE DATA HERE
--WrbKitFormBoundaryXtRo8bh7ZpnTrTwd
Upvotes: 3