Posting multipart form-data to a web server

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • starter08
    New Member
    • Sep 2008
    • 8

    #1

    Posting multipart form-data to a web server

    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
    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);
    }
    If required I can upload the server side cgi too.

    Thanks,
    Mohit
  • starter08
    New Member
    • Sep 2008
    • 8

    #2
    Hi,
    Can anybody help me out.
    This is the whole output that I am trying to send through a post request
    Code:
    POST http://192.168.2.5/upload.cgi HTTP/1.1
    Accept-Language: en-us
    Content-Type: multipart/form-data; boundary=---------------------------7d2b119100532
    User-Agent: Mozilla/3.01 (compatible)
    Host: 192.168.2.5
    Pragma: no-cache
    Content-Length: 717
    
    -----------------------------7d2b119100532
    Content-Disposition: form-data; name="field1"
    
    5107115015_auto_end
    -----------------------------7d2b119100532
    Content-Disposition: form-data; name="flat_file"; filename="travellerdata.dat"
    Content-Type: text/plain
    
    <SYSSN>5107115015</SYSSN>
    <HDD slot="0">
        <serial>DA40P7C003P5</serial>
        <model>MAW3300NC</model>
        <firmware>0104</firmware>
    </HDD>
    <network>
        <adapter slot="1">
            <interface slot="1">
                <mac>00:E0:81:4B:8F:FD</mac>
            </interface>
        </adapter>
    </network>
    <BIOS>
        <revision></revision>
        <date>06/23/06</date>
    </BIOS>
    <CPU_count>4</CPU_count>
    <CPU slot="0">
        <serial>00020F120000000000000000</serial>
    </CPU>
    -----------------------------7d2b119100532--
    however I receive the following response back from the server

    Server Response is
    HTTP/1.1 200 OK
    Date: Fri, 26 Sep 2008 05:13:55 GMT
    Server: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch10
    Transfer-Encoding: chunked
    Content-Type: text/html; charset=UTF-8

    f3
    <h1>Software error:</h1>
    <pre>Malforme d multipart POST
    </pre>
    <p>
    For help, please send mail to the webmaster (<a href="mailto:we bmaster@localho st">webmaster@l ocalhost</a>), giving this error message
    and the time and date of the error.

    </p>

    Comment

    Working...