Hi,
I have a C++ routine(client-side) which uploads an xml file to a web server by making a socket connection and sending all the post request through that socket.
On the server side I have a cgi script which receives all the data and creates a file in the specified directory.
If I am uploading only the file all works well, however I want to send data of other fields too (field1, field2 ..etc), this fails the post request and even the file is not uploaded.
I think it has something to do with the Boundary Strings that need to be sent with each part of the form-data.
However I am unable to understand how to do that.
Greatly appreciate any help.
Here is my code snippet for preparing the post request for sending the form-data
If required I can upload the server side cgi too.
Thanks,
Mohit
I have a C++ routine(client-side) which uploads an xml file to a web server by making a socket connection and sending all the post request through that socket.
On the server side I have a cgi script which receives all the data and creates a file in the specified directory.
If I am uploading only the file all works well, however I want to send data of other fields too (field1, field2 ..etc), this fails the post request and even the file is not uploaded.
I think it has something to do with the Boundary Strings that need to be sent with each part of the form-data.
However I am unable to understand how to do that.
Greatly appreciate any help.
Here is my code snippet for preparing the post request for sending the form-data
Code:
int Send_to_DB_via_HTTP(char* Traveller_output_buffer, unsigned data_len, string fileName, string servIP, string url)
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* server address */
unsigned short echoServPort; /* server port */
char *echoString; /* String to send to echo server */
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
unsigned int echoStringLen; /* Length of string to echo */
int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv()
and total bytes read */
int first_form_len=0;
int second_form_len=0;
int hidden_data_len=0;
unsigned count = 0;
int count1 = 0;
int count2 = 0;
char buf[2000];
int n;
const char *m_servIP;
const char *m_url;
m_servIP = servIP.c_str();
m_url = url.c_str();
echoServPort = 80;
/*Create a reliable, stream socket using TCP */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
cout << " socket () failed" << endl;
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = PF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = inet_addr(m_servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
/* Establish the connection to the echo server */
int k;
k = connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr));
if (k < 0)
{
cout<< "Error Connecting to " << servIP << endl;
return -1;
}
else
cout << "Connection Successfull to " << servIP << endl;
//Start the form off with the boundary string
hidden_data_len += snprintf(
&Buffer3[hidden_data_len],
sizeof(Buffer3) - hidden_data_len,
"%s%s\r\n",
"--", BOUNDARY_STRING);
hidden_data_len += snprintf(
&Buffer3[hidden_data_len],
sizeof(Buffer3) - (hidden_data_len),
"Content-Disposition: form-data;name=\"field1\"\r\n\r\n%s_auto_end\r\n",
syssn_no );
//End of multi-part form
hidden_data_len += snprintf(
&Buffer3[hidden_data_len],
sizeof(Buffer3) - (hidden_data_len),
"%s%s%s\r\n",
"--",BOUNDARY_STRING,"--" );
first_form_len += snprintf(
&buffer1[first_form_len],
sizeof(buffer1) - first_form_len,
"%s%s\r\n",
"--",BOUNDARY_STRING );
//Some random filename - must end in .dat because web server checks
//This is the data portion of the form - the flat file will be sent in this section
first_form_len += snprintf(
&buffer1[first_form_len],
sizeof(buffer1) - first_form_len,
"Content-Disposition: form-data; name=\"flat_file\"; filename=\"travellerdata.dat\"\r\n" );
first_form_len += snprintf(
&buffer1[first_form_len],
sizeof(buffer1) - first_form_len,
"Content-Type: text/plain\r\n\r\n" );
//Prepare the ending part of the form-data - this follows the flat file contents
//Start the form off with the boundary string
/*second_form_len += snprintf(
&buffer1[first_form_len+second_form_len],
sizeof(buffer1) - (first_form_len+second_form_len),
"%s%s\r\n",
"--",BOUNDARY_STRING );*/
// Put together the headers for HTTP POST
count = snprintf(
&buffer[0],
sizeof(buffer),
"POST %s HTTP/1.1\r\n",
m_url);
count += snprintf(
&buffer[count],
sizeof(buffer) - count,
"Accept-Language: en-us\r\n" );
count += snprintf(
&buffer[count],
sizeof(buffer) - count,
"Content-Type: multipart/form-data; boundary=%s\r\n",
BOUNDARY_STRING);
count += snprintf(
&buffer[count],
sizeof(buffer) - count,
"User-Agent: Mozilla/3.01 (compatible)\r\n");
count += snprintf(
&buffer[count],
sizeof(buffer) - count,
"Host: %s\r\n",
m_servIP);
count += snprintf(
&buffer[count],
sizeof(buffer) - count,
"Pragma: no-cache\r\n" );
count += snprintf(
&buffer[count],
sizeof(buffer) - count,
"Content-Length: %d\r\n",
data_len+first_form_len+second_form_len+hidden_data_len );
count += snprintf(
&buffer[count],
sizeof(buffer) - count,
"\r\n" );
//cout << buffer << endl;
count1 += snprintf(
&buffer2[count1],
sizeof(buffer2) - count1,
"%s%s\r\n",
"--",BOUNDARY_STRING);
count1 += snprintf(
&buffer2[count1],
sizeof(buffer2) - count1,
"Content-Disposition: form-data; \"\r\n");
count1 += snprintf(
&buffer2[count1],
sizeof(buffer2) - count1,
"Content-Type: text/html\r\n");
count1 += snprintf(
&buffer2[count1],
sizeof(buffer2) - count1,
"Content-Length: %d\r\n", data_len);
count2 += snprintf(
&buffer3[count2],
sizeof(buffer3) - (count1+count2),
"%s%s%s\r\n",
"--",BOUNDARY_STRING, "--");
string status;
cout << "Sending Post Headers" << endl<< buffer << endl << "End Post Headers" << endl;
//Send the "POST" header to the HTTP server.
if (send(sock, buffer, count, 0) == -1) {
//status = perror("send");
cout << "Stats Worker: received socket error %d on header send\n" << endl;
return -1;
}
cout << "Hidden Data" << endl<< Buffer3 << endl << "End Post Headers" << endl;
if (send(sock, Buffer3, hidden_data_len, 0) == -1) {
//status = perror("send");
cout << "Stats Worker: received socket error %d on header send\n" << endl;
return -1;
}
cout << "Now Sending first part of the form data BUFFER1" << endl << buffer1 << endl<< "End First Part"<< endl;
if (send(sock, buffer1, first_form_len, 0) == -1) {
//status = CK_Get_last_error();
cout << "Stats Worker: received socket error on header send\n" << endl;
return -1;
}
cout << "Now Sending file " << Traveller_output_buffer << endl;
//Now send the flat file
if (send(sock, Traveller_output_buffer, data_len, 0) == -1) {
//status = CK_Get_last_error();
cout << "Stats Worker: received socket error %d on message send\n" << endl;
return -1;
}
cout << "Sending ending boundary string " << endl << buffer3 << endl;
if (send(sock, buffer3, count2, 0) == -1) {
//status = perror("send");
cout << "Stats Worker: received socket error %d on header send\n" << endl;
return -1;
}
//Send the last part of the form data to the HTTP server.
/*if (send(sock, buffer1+first_form_len, second_form_len, 0) == -1) {
//status = CK_Get_last_error();
cout << "Stats Worker: received socket error %d on header send\n" << endl;
return -1;
}*/
//Receive server response
n = recv(sock, buf, 2000, 0);
//cout << "Server Response is " << endl << buf << endl;
if(n < 0)
{
cout << "Upload Failed" << endl;
return -1;
}
// Make sure this is a HTTP header
if (!strstr(buf, "HTTP")) {
cout << "Stats Worker: response doesn't contain HTTP\n";
return -1;
}
if (n < 0) {
cout << "Stats Worker: response status is " << n;
return -1;
}
// while (n > 0) {
//printf(buf);
if(!strstr(buf, Successful_Upload))
{
cout << "Traveller Upload Failed. Server Responded " << buf;
return -1;
}
else
{
cout << "Traveller Upload Successfull. \n Server Response is \n" << buf;
//return 0;
}
//n = recv(sock, buf, 10480, 0);
//}
//remove("newtravellerdata.dat");
//close(sock);
}
Thanks,
Mohit
Comment