I am one of the many people trying to grasp something new in this forum. I come here, because it seems to frequented by C++ experts, who actually try to respond.
I am trying to learn how to program an HTTP protocol based text file download. I have searched far and wide on the internet, and find both commercial and non-commercial code to provide internet functionality. I have not found a single, Borland Builder based, windows socket and http tutorial.
I did download one of the free, non-commercial files, and it did compile and run on Borland Builder 6.0 with just a few changes. I believe it has a socket, because the RichText box control I am using fills with various obscure facts about my internet service provider (including its usual $9.95 per month advertisement), all in text, when I activate the code that was said to perform an HTTP based POST. I think that means that the code was able to access a socket. I'm not as sure that it was able to create the socket, as I already had internet explorer opened to a web site and was connected.
IF YOU'VE READ THIS FAR, then perhaps I should note that what I ultimately need to do is to access a password protected directory, and download a text file using http protocol. I was told this was both possible and none too difficult. (I was at my limits getting the file I downloaded to compile under Borland Builder.) I did search for and purchase multiple texts on internet programming, but all via mail. The local bookstores and college library have nothing in them describing C++ programming of HTTP commands, I've spent days looking before I came here. I am attaching some code. It is supposed to accomplish an internet POST. I understand that is useful for chat rooms and a few other things, but not for my needs at present. To be perfectly straightforward, much of what this code does is Greek to me. I downloaded it to see if it could be made to work, as a roadmap to a means by which to get a socket connection. Step two is trying to figure out how to convert the POST function to a GET function that will download a text file from a password protected directory. (I honestly don't know, in the context of this code, what it is supposed to return, or why I received the info I did from an internet service provider whose url I wasn't trying to use.)
I'll post the code I downloaded. If anyone can get me to the point where this code will enable me to access a password protected directory, we'll call it:
"http://mysite.hostserver.com/secret"
with user name: myname
and password: mypassword,
and download file: mytextfile.txt using http,
that would be, as the waitress on the television commercial says, "great".
The code I was using is based upon Windows sockets and winsock2.h. I don't want to change this. I just want it to work. Any help would be much appreciated.
BORLAND BUILDER 6.0 CODE FOLLOWS:
/*
* http_post.cpp
*
* by Uday Chitragar - 2004/Dec/01
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any
* damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and
* redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must
* not claim that you wrote the original software. If you use this
* software in a product, an acknowledgment in the product documentation
* would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and
* must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
* */
/*
* Notes:
* This source demonstrates sending HTTP POST request to webserver from C++
* This uses sockets hence can be compiled on Linux, UNIX, Win
*/
//#define LINUX_OS
#define WIN_OS
#define _DEBUG_PRINT(X) /* X */
//For commn
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
//#ifdef LINUX_OS
// #include <netdb.h>
//#endif
//#ifdef WIN_OS
// #include <Winsock2.h>
//#endif
#define SEND_RQ(MSG) \
/*cout<<send_str;*/ \
send(sock,MSG,strlen(MSG),0);
using namespace std;
//<exe> hostname api parameters
int request (char* hostname, char* api, char* parameters, string& message)
{
#ifdef WIN_OS
{
WSADATA WsaData;
WSAStartup (0x0101, &WsaData);
}
#endif
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
sockaddr_in sin;
int sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
return -100;
}
sin.sin_family = AF_INET;
sin.sin_port = htons( (unsigned short)80);
struct hostent * host_addr = gethostbyname(hostname);
if(host_addr==NULL) {
_DEBUG_PRINT( cout<<"Unable to locate host"<<endl );
return -103;
}
sin.sin_addr.s_addr = *((int*)*host_addr->h_addr_list) ;
_DEBUG_PRINT( cout<<"Port :"<<sin.sin_port<<", Address : "<< sin.sin_addr.s_addr<<endl);
if( connect (sock,(const struct sockaddr *)&sin, sizeof(sockaddr_in) ) == -1 ) {
_DEBUG_PRINT( cout<<"connect failed"<<endl ) ;
return -101;
}
string send_str;
SEND_RQ("POST ");
SEND_RQ(api);
SEND_RQ(" HTTP/1.0\r\n");
SEND_RQ("Accept: */*\r\n");
SEND_RQ("User-Agent: Mozilla/4.0\r\n");
char content_header[100];
sprintf(content_header,"Content-Length: %d\r\n",strlen(parameters));
SEND_RQ(content_header);
SEND_RQ("Accept-Language: en-us\r\n");
SEND_RQ("Accept-Encoding: gzip, deflate\r\n");
SEND_RQ("Host: ");
SEND_RQ("hostname");
SEND_RQ("\r\n");
SEND_RQ("Content-Type: application/x-www-form-urlencoded\r\n");
//If you need to send a basic authorization
//NOTE: IS THIS TO GET
// PAST YOUR OWN SITE'S ADMINISTRATOR PASSWORD, OR THE
// DIRECTORY PASSWORD? I NEED TO GET PAST MY DIRECTORY
// PROTECTING PASSWORD.
//(USING NON-PASSWORD PROTECTED DIRECTORY
// ISN'T AN OPTION).
//string Auth = "mysite:mypassword";
//string AuthInfo = Auth;
//Figureout a way to encode test into base64 ! WHAT????
//string AuthInfo = base64_encode(reinterpret_cast<const unsigned char*>(Auth.c_str()),Auth.length());
//string sPassReq = "Authorization: Basic " + AuthInfo;
//SEND_RQ(sPassReq.c_str());
SEND_RQ("\r\n");
SEND_RQ("\r\n");
SEND_RQ(parameters);
SEND_RQ("\r\n");
_DEBUG_PRINT(cout<<"####HEADER####"<<endl);
char c1[1];
int l,line_length;
bool loop = true;
bool bHeader = false;
while(loop) {
l = recv(sock, c1, 1, 0);
if(l<0) loop = false;
if(c1[0]=='\n') {
if(line_length == 0) loop = false;
line_length = 0;
if(message.find("200") != string::npos)
bHeader = true;
}
else if(c1[0]!='\r') line_length++;
_DEBUG_PRINT( cout<<c1[0]);
message += c1[0];
}
message="";
if(bHeader) {
_DEBUG_PRINT( cout<<"####BODY####"<<endl) ;
char p[1024];
while((l = recv(sock,p,1023,0)) > 0) {
_DEBUG_PRINT( cout.write(p,l)) ;
p[l] = '\0';
message += p;
}
_DEBUG_PRINT( cout << message.c_str());
} else {
return -102;
}
#ifdef WIN_OS
WSACleanup( );
#endif
return 0;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
string message;
char* mysite = "www.netzero.com";
char* postapi = "/post_url.pl";
char* myparams = "search=hello&date=todat";
//Following line originally used "string& message". I don't know what
//that was supposed to accomplish, but what follows
//was what I was able to get to compile, with "string message" instead.
int errornumberreturned = request(mysite, postapi, myparams, message);
const char* mymessage = message.c_str();
RichEdit1->Text= mymessage;
RichEdit2->Text = errornumberreturned;
//errornumberreturned was 0 -> never got to functions to return error code??
// message contains response! WELL, it contained a response.
}
//---------------------------------------------------------------------------