EvilZone
Programming and Scripting => C - C++ => : Kulverstukas February 23, 2014, 05:13:11 PM
-
Finally I had the time to revisit it again. Many moons ago I tried to understand how Multipart file upload works and kinda didn't succeed, but then again I didn't put that much effort into it. I did it now because I have a project on my hands which requires this, whole theory didn't seem very hard and I was able to produce working code for client and server sides in a few hours.
Sending multipart requests is great for file uploading and other large quantities of data. I won't go about and write a tutorial on how to send these requests, instead I will point you to an awesome RFC (http://www.ietf.org/rfc/rfc1867.txt) and this tutorial (http://www.tutorialspoint.com/http/http_header_fields.htm).
While browsing I had found a working example done in Python. Cannot remember where I found it or to who it belongs, but anyway, that example code can be found in my projects folder here (http://9v.lt/projects/python/PythonicMultiPartSender/send_multipart.py).
And so based on the docs and that example code I was able to produce a CPP project for my own needs. I tried to make it very simple to adapt for other projects. The project can be found here (http://9v.lt/projects/C/MultiPartSender/main.cpp), and along with it I made a simple PHP script (http://9v.lt/projects/C/MultiPartSender/MultiPartSender.zip) that receives the commands and acts upon them, it's also a part of other bigger project...
Here's a C++ code I produced:
/*
Author: Kulverstukas
Date: 2014.02.23
Website: http://9v.lt; Evilzone.org
Description:
Simple prototype of Multipart POST sending in C++
*/
#include <iostream>
#include <winsock2.h>
#include <string>
#include <fstream>
#include "windows.h"
#include "stdio.h"
using namespace std;
#define PORT 80
#define IP "127.0.0.1"
#define HOST "locahost"
#define RECEIVER "/receive_data.php"
#define COMPNAME "compname"
#define PROGRAM "program"
#define FILENAME "file"
#define BOUNDARY "----------Evil_B0uNd4Ry_$"
#define DUMMY_DATA "c2FzYXNhc2FzZGRmZGZkY2Q="
#define DUMMY_FILE "dummy.txt"
//------------------------------------
string constructBody(string args[2], string file[2]);
string readFile(string fileName);
//------------------------------------
int main() {
// initiate the socket!
SOCKET dataSock;
WSADATA wsaData;
int error = WSAStartup(0x0202, &wsaData);
if (error != 0) {
WSACleanup();
exit(1); // oh shit, this shouldn't happen!
}
// all internets, engage!
SOCKADDR_IN target;
target.sin_family = AF_INET;
target.sin_port = htons(PORT);
target.sin_addr.s_addr = inet_addr(IP);
dataSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (dataSock == INVALID_SOCKET) {
exit(1); // Houston, we have a problem!
}
connect(dataSock, (SOCKADDR*)&target, sizeof(target));
string programNames[5][2] = {{"KULVERTOP", "Chrome"}, {"KULVERTOP", "Firefox"}, {"KULVERTOP", "InternetExplorer"}, {"KULVERTOP", "Opera"}, {"KULVERTOP", "Skype"}};
string file[2] = {FILENAME, "Default.txt"};
int a = sizeof(programNames)/sizeof(programNames[0]);
for (int i = 0; i < a; i++) {
printf("Sending data for %s\n", (programNames[i][1]).c_str());
string body = constructBody(programNames[i], file);
char header[1024];
sprintf(header, "POST %s HTTP 1.1\r\n"
"Host: %s\r\n"
"Content-Length: %d\r\n"
"Connection: Keep-Alive\r\n"
"Content-Type: multipart/form-data; boundary=%s\r\n"
"Accept-Charset: utf-8\r\n\r\n", RECEIVER, IP, strlen(body.c_str()), BOUNDARY);
// printf("%s\n\n", header);
int p = send(dataSock, header, strlen(header), 0);
// printf("p == %d\n", p);
int k = send(dataSock, body.c_str(), strlen(body.c_str()), 0);
// printf("k == %d\n", k);
// char buff[1024];
// recv(dataSock, buff, 1024, 0);
// printf("%s\n\n", buff);
}
closesocket(dataSock);
WSACleanup();
}
string readFile(string fileName) {
string fileContents;
ifstream tmp(fileName.c_str());
getline(tmp, fileContents);
tmp.close();
return fileContents;
}
string constructBody(string args[2], string file[2]) {
string body;
string CRLF = "\r\n";
// first we add the args
body.append("--"+string(BOUNDARY)+CRLF);
body.append("Content-Disposition: form-data; name=\""+string(COMPNAME)+"\""+CRLF);
body.append(CRLF);
body.append(args[0]+CRLF);
body.append("--"+string(BOUNDARY)+CRLF);
body.append("Content-Disposition: form-data; name=\""+string(PROGRAM)+"\""+CRLF);
body.append(CRLF);
body.append(args[1]+CRLF);
// now we add the file
body.append("--"+string(BOUNDARY)+CRLF);
body.append("Content-Disposition: form-data; name=\""+string(FILENAME)+"\"; filename=\""+string(DUMMY_FILE)+"\""+CRLF);
body.append("Content-Type: text/plain"+CRLF);
body.append(CRLF);
body.append(DUMMY_DATA+CRLF);
body.append("--"+string(BOUNDARY)+"--"+CRLF);
body.append(CRLF);
// printf(body.c_str()); exit(0);
return body;
}
-
How many time the for loop gets executed?
-
The for loop loops for the number of program names. This is because sizeof( any array name ) gives the size of the array and sizeof( any item in that array ) gives the size of an item in the array. Therefore dividing the 1st by the 2nd equals the number of items in an array.
... Sorry I'm kinda bad at explaining things
@OP:
Nice, good that you went back and pushed through to learn it.