Sending a file to HTTP server via a multi-part flat form

Hi,
I need to send a flat file to http server. The file that needs to be sent is an xml file which is created by another routine. FTP is not an option, I have to send it to an http server via a multi-part form.
Appreciate any help in this regards.
So far I have this code, but getting this error in apache2 logs

"[error] [client 192.168.2.20] Attempt to serve directory: /usr/local/sam/web/"

code snippet for sending the file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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;
	
	unsigned data_len;
	servIP = "192.168.2.20";
	echoServPort = 80;
	url = "http://something.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;

	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,"--" );

	// 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;
	}

    //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);
        }
	

close(sock);
}


Really appreciate any help

Thanks
Having a scoot around with google, this appears to be a server configuration error - but beyond that I can't really say.
I see lots of hits about missing default page(s) like missing default.html or index.html, etc..
There seem to be a few reasons why this error can be logged - which may be nothing to do with your code.
Is SCP an option?

Because you are looking at a whole raft of security related issues by doing this via an HTTP request through to a server-side object.
Hi,
This is a part of a secure proprietary kernel so I am not worried about the security issues as those will already be taken care of.
I realized that there was no index file in the document root servred by apache so the earlier apache error, that is fixed.
However not I get the following response from the server
1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Date: Thu, 04 Sep 2008 02:45:23 GMT
Server: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch10
X-Powered-By: PHP/5.2.0-8+etch10
Content-Length: 28
Connection: close
Content-Type: text/html; charset=UTF-8

Segmentation fault

I am not sure why segmentation fault is occuring, though the http response is ok however the file is not uploaded to the webserver. Also I am not sure about the Content-Length given in the response from the server, is that the length of data server sent ? could segementation fault be because of this?

Appreciate any help.
Segmentation Fault indicates that apache has suffered a buffer-overflow.

Content Length should be the number of bytes you are sending within the POST request. Not including the header.
Hi,
Ok I resolved the segmentation fault error, however still the file is not uploaded to the server.
Do I also need some script on the server side to receive the file and write it to a directory or the file should be uploaded to the default web directory ?

Appreciate any help.
Thanks
You need a server-side script. Again, I don't know why you just don't use SCP
Last edited on
Hi,
Thanks for the reply. I cannot use scp because the server where we need to send the file will only accept http requests nothing else.

Thanks for the reply again.
If this is a web-hosting account your trying to upload the file to. I'd check to see if the server can handle what your trying to do. Alot of places have their configurations for PHP/.NET set so you can't upload a file.

Edit: How are you going to upload your server-side code when you can't FTP or SCP?
Last edited on
Hi,
We have full control over the server and can put the server-side code on the server, however nothing is accessible to anybody except http requests over the net.
I tried writing server side code however we cannot bind port 80 as it is a well known port.
The php config allows uploading of files and the size of the file is also set so that the file I am trying to upload will not have any problems regarding the size.

For sending the file I open it in binary mode for reading and then send the content of the files to the server, is that the right way to send the file.
1
2
3
4
5
6
7
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;
	}

in the code above Traveller_output_buffer, has the contents of the file.
Appreciate your help.
Thanks,
So you want other people to be able to upload files? Why not just have them do it through a web-form?
Topic archived. No new replies allowed.