Thread: uploading file to http server via multipart form data

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    10

    uploading file to http server via multipart form data

    Hi,
    I have written a code which generates an xml file, now I need to send this xml file to a http server, using multipart form data in C++.
    the code is
    Code:
    #include <string>
    #include <iostream>
    #include <fstream>
    #include <ostream>
    #include <stdio.h>        /* for printf() and fprintf() */
    #include <sys/socket.h>   /* for socket(), connect(), send(), and recv() */
    #include <arpa/inet.h>    /* for sockaddr_in and inet_addr() */
    #include <stdlib.h>       /* for atoi() */
    #include <string.h>       /* for memset() */
    #include <unistd.h>       /* for close() */
    #define RCVBUFSIZE 32     /* Size of receive buffer */
    #define RESPONSE_LEN    10240
    #define SUCCESS_MSG     "Upload Successful"
    #define FAILURE_MSG     "Upload Failure"
    //Some random sequence of char's that won't appear in the file
    #define BOUNDARY_STRING "---------------------------7d2b119100532" 
    #define	COMPANY_NAME "Some Company";
     #define PRODUCT_NAME "Some Product";
    #define  MAJOR_VERSION "123456"
    #define  MINOR_VERSION "23.44";
    #define  PATCH_VERSION "p1.1";
    #define  RELEASE_VERSION "r1.2";
    
    char response[RESPONSE_LEN+1];
    char buffer[2048];
    char buffer1[2048];
    
    using namespace std;
    static char* xml_serial="serial";
    static char* xml_slot="slot";
    
    static char* xml_system_serial="SYSSN";
    static char* xml_birth_edition="edition";
    
    static char* xml_hdd="HDD";
    static char* xml_model="model";
    static char* xml_firmware="firmware";
    
    static char* xml_network="network";
    static char* xml_adapter="adapter";
    static char* xml_interface="interface";
    static char* xml_mac="mac";
    
    static char* xml_bios="BIOS";
    static char* xml_revision="revision";
    static char* xml_date="date";
    
    static char* xml_cpu="CPU";
    static char* xml_cpu_count="CPU_count";
    
    static char* xml_public_key="public_key";
    
    //Data static for testing needs to be replaced by functions which get the actual data for the xml file
    
    static char* syssn_no = "5107115015";
    static char* hdd_slot0 = "0";
    static char* hdd_serial0= "DA40P7C003P5";
    static char* hdd_model0 = "MAW3300NC";
    static char* hdd_firmware0 = "0104";
    static char* hdd_slot1 = "1";
    static char* hdd_serial1 = "DA40P7C004MG";
    static char* hdd_model1 = "MAW3300NC";
    static char* hdd_firmware1 = "0104";
    static char* network_adapter_slot = "1";
    static char* network_interface_slot = "1";
    static char* network_mac = "00:E0:81:4B:8F:FD";
    static char* bios_revision = "";
    static char* bios_date = "06/23/06";
    static char* cpu_count = "4";
    static char* cpu_slot="0";
    static char* cpu_serial = "00020F120000000000000000";
    char *servlP = "192.168.2.20";
    
    unsigned indent;
    void Indent(unsigned m_indent, std::ofstream& m_output)
    	{
    		for(unsigned i=0;i<m_indent;i++)
    		{
    			m_output << " ";
    		}
    	}
    	
    void create_opening_tag(std::ofstream& ostrFile, string tag_name, unsigned indent=0, bool m_tag_on_seperate_line=false)
    {
    	ostrFile << "<";
    	ostrFile << tag_name;
    	ostrFile << ">";
    	if(m_tag_on_seperate_line)
    	ostrFile << "\n";
    	//outFile.close();	
    }
    
    
    void create_closing_tag(std::ofstream& ostrFile, string tag_name, bool m_tag_on_seperate_line=false, unsigned indent=0)
    {
    		if(indent)
    		 {
    		  Indent(indent, ostrFile);
    	 	  }
    		ostrFile << "</";
    		ostrFile << tag_name;
    		ostrFile << ">";
    		ostrFile << "\n";
    		//ostrFile.close();
    }
    void add_Data(std::ofstream& ostrFile, string tag_name, string tag_data, bool closing_tag=false, unsigned indent=0)
    {
    	if(indent)
    	 {
    		Indent(indent, ostrFile);
    	 }
    	ostrFile << "<";
    	ostrFile << tag_name;
    	ostrFile << ">";
    	ostrFile << tag_data;
    	if(closing_tag)
    	 {
    		create_closing_tag(ostrFile, tag_name, true, indent=0);
    	 }
    }
    
    void add_Attribute(std::ofstream& ostrFile, string tag_name, string attribute_name, string attribute_value, bool tag_on_seperate_line=false, unsigned indent=0)
    {
    	if(indent)
    	 {
    		Indent(indent, ostrFile);
    	 }
    	ostrFile << "<";
    	ostrFile << tag_name;
    	ostrFile << " ";
    	ostrFile << attribute_name;
    	ostrFile << "=";
    	ostrFile << "\"";
    	ostrFile << attribute_value;
    	ostrFile << "\"";
    	ostrFile << ">";
    	ostrFile << "\n";
    	
    }
    void hdd_traveller(std::ofstream& ostrFile, string slot, string serial, string model, string firmware)
    {
    	add_Attribute(ostrFile, xml_hdd, xml_slot, hdd_slot0, false, indent);
    	add_Data(ostrFile, xml_serial, hdd_serial0, true, indent+4);
    	add_Data(ostrFile, xml_model,hdd_model0, true, indent+4);
    	add_Data(ostrFile, xml_firmware, hdd_firmware0, true, indent+4);
    	create_closing_tag(ostrFile, xml_hdd, true, indent);
    }
    void network_traveller(std::ofstream& ostrFile, string slot, string interface, string mac, string adapter)
    {
    	create_opening_tag(ostrFile, xml_network, indent=0, true);
    	add_Attribute(ostrFile, xml_adapter, xml_slot, network_adapter_slot, false, indent+4);
    	add_Attribute(ostrFile, xml_interface, xml_slot, network_interface_slot, false, indent+8);
    	add_Data(ostrFile, xml_mac, network_mac, true, indent+12);
    	create_closing_tag(ostrFile, xml_interface, false, indent+8);
    	create_closing_tag(ostrFile, xml_adapter, false, indent+4);
    	create_closing_tag(ostrFile, xml_network, false, indent);
    }
    void bios_traveller(std::ofstream& ostrFile, string bios, string revision, string bios_date)
    {
    	create_opening_tag(ostrFile, xml_bios, indent, true);
    	add_Data(ostrFile, xml_revision, bios_revision, true, indent+4);
    	add_Data(ostrFile, xml_date, bios_date, true, indent+4);
    	create_closing_tag(ostrFile, xml_bios, false, indent);
    }
    void cpu_traveller(std::ofstream& ostrFile, string slot, string cpu_count, string cpu, string serial)
    {
    	add_Data(ostrFile, xml_cpu_count, cpu_count, true, indent);
    	add_Attribute(ostrFile, xml_cpu, xml_slot, cpu_slot, false, indent);
    	add_Data(ostrFile, xml_serial, cpu_serial, true, indent+4);
    	create_closing_tag(ostrFile, xml_cpu, false, indent);
    }
    int Send_to_DB_via_HTTP(string filename)
    {
     	int sock;                          /*  Socket descriptor */
        	struct sockaddr_in echoServAddr;   /*  server address */
        	unsigned short echoServPort;       /*  server port */
        	char *servIP;                      /*  Server IP address (dotted quad) */
    	char *url;
        	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;
    	unsigned 		    count = 0;
    	char* Traveller_output_buffer;
    	FILE * pFile;
    	long lSize;
    	size_t result;
    	char* buf;
    	pFile = fopen ( filename.c_str(), "rb" );
    	// obtain file size:
      	fseek (pFile , 0 , SEEK_END);
      	lSize = ftell (pFile);
      	rewind (pFile);
    	// allocate memory to contain the whole file:
      	Traveller_output_buffer = (char*) malloc (sizeof(char)*lSize);
      	if (Traveller_output_buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
    	
      	// copy the file into the buffer:
      	result = fread (Traveller_output_buffer,1,lSize,pFile);
    
    	//ifstream file_to_send;
    	
    	//string readline;
    	unsigned data_len;
    	servIP = "192.168.2.20";
    	echoServPort = 80;
    	url = "http://leisure.dyndns.org";
    	data_len = sizeof(char)*lSize;
    	/* 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         = AF_INET;              /* Internet address family */
    	echoServAddr.sin_addr.s_addr = inet_addr(servlP);       /* Server IP address */
    	echoServAddr.sin_port           = htons(echoServPort); /* Server port */
    	/* Establish the connection to the echo server */
    	if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
         	 cout<< "Error Connecting to " << servIP << endl;
    	else
    	 cout << "Connection Successfull to " << servIP << endl;
    	//Read File Data
    	//file_to_send.open(filename.c_str());
    	//while(getline(file_to_send, readline))
                  // {
                     // Traveller_output_buffer += readline;
                     //}
    	first_form_len += snprintf(
                            &buffer1[first_form_len],
                            sizeof(buffer1) - first_form_len,
                            "Content-Disposition: form-data; name=\"flat_file\"; filename=\"new.dat\"\r\n" );
    	
    	first_form_len += snprintf(
                            &buffer1[first_form_len],
                            sizeof(buffer1) - first_form_len,
                            "Content-Type: text/plain\r\n\r\n" );
    	cout << first_form_len << endl;
    	//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 );
    	second_form_len += snprintf(
                            &buffer1[(first_form_len+second_form_len)],
                            sizeof(buffer1) - (first_form_len+second_form_len),
                            "Content-Disposition: form-data; name=\"filename\"\r\n\r\n%s_auto_end\r\n",
    						syssn_no );
    	//End of multi-part form
        	second_form_len += snprintf(
                            &buffer1[(first_form_len+second_form_len)],
                            sizeof(buffer1) - (first_form_len+second_form_len),
                            "%s%s%s\r\n",
                            "--",BOUNDARY_STRING,"--" );
    	cout << second_form_len << endl;
    	// Put together the headers for HTTP POST
        	count = snprintf(
                           &buffer[0],
                           sizeof(buffer),
                           "POST %s HTTP/1.0\r\n",
                           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;  %s-%s/%d.%d.%02d r%d)\r\n");
        	count += snprintf(
                            &buffer[count],
                            sizeof(buffer) - count,
                            "Host: %s\r\n",
                            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 );
        	count += snprintf(
                            &buffer[count],
                            sizeof(buffer) - count,
                            "\r\n" );
    	cout << buffer1 << endl;
    	string status;
    	//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;
    	}
    	else
    	{
    		cout << "data Sent" << endl;
    	}
    	
    	//Send the first part of the form data to the HTTP server.
    	if (send(sock, buffer1, first_form_len, 0) == -1) {
    		
    		//status = CK_Get_last_error();
    		cout << "Stats Worker: received socket error %d on header send\n" << endl;
    		return -1;
    	}
    	cout << "Sending this data "<< buffer1 << 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;
    	}
    
    
    	//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;
    	}
    	else
    	{
    		cout << "Data has been Sent Successfully" << endl;
    	}
    	int n = recv(sock, buf, sizeof(buf), 0);
            while (n > 0) {
                printf(buf);
                n = recv(sock, buf, sizeof(buf), 0);
            }
    	/* Determine input length */
    	/*echoStringLen = strlen(echoString) ;
    	printf("Sending HTTP Request");
    	printf(echoString);*/
    	/* Send GET REQUEST to the server*/
    	/*if (send(sock, echoString, echoStringLen, 0) != echoStringLen)
         	 DieWithError("send() sent a different number of bytes than expected");
    	else
    	 printf("Successfully sent the request");
    
            char buf[1000];    */  /* buffer for data from the server     */
    
            /* Repeatedly read data from socket and write to user's screen. */
    
            /*int n = recv(sock, buf, sizeof(buf), 0);
            while (n > 0) {
                printf(buf);
                n = recv(sock, buf, sizeof(buf), 0);
            }*/
    
    close(sock);
    }
    int main()
    {
    	//unsigned indent;
    	string dataFile = "new.dat";
    	//ofstream outfile (dataFile.c_str(),ios::app);
    	//create_opening_tag(outfile, xml_system_serial, system_serial_number, indent+2);
    	//add_Data(outfile, xml_system_serial, syssn_no, false);
    	//create_closing_tag(outfile, xml_system_serial, false, indent);
    	//hdd_traveller(outfile, xml_slot, xml_serial, xml_model, xml_firmware);
    	//network_traveller(outfile, xml_slot, xml_interface, xml_mac, xml_adapter);
    	//bios_traveller(outfile, xml_bios, xml_revision,xml_date);
    	//cpu_traveller(outfile, xml_slot, xml_cpu_count, xml_cpu, xml_serial);
    	//outfile.close();
    	Send_to_DB_via_HTTP(dataFile);
    	
    	
    	
    	//return 0;
    	exit(0);;
    }
    However the file is not uploaded and I keep getting the following errors
    Code:
    [error] [client 192.168.2.20] Attempt to serve directory: /usr/local/username/web/
    in apache2 error logs.
    Appreciate if anybody can point me in the right direction.

    Thanks,
    dynamo

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Use a network sniffer to figure out what you're actually sending. Then figure out what the Apache error means in relation to that.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  2. Encryption program
    By zeiffelz in forum C Programming
    Replies: 1
    Last Post: 06-15-2005, 03:39 AM
  3. Editing a data file
    By Strait in forum C++ Programming
    Replies: 7
    Last Post: 02-05-2005, 04:21 PM
  4. Possible circular definition with singleton objects
    By techrolla in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2004, 10:46 AM
  5. spell check in C using a dictionary file
    By goron350 in forum C Programming
    Replies: 10
    Last Post: 11-25-2004, 06:44 PM