Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 187 lines (139 sloc) 3.69 KB
#ifndef com_sleepless_net_http_httpgetrequest_h
#define com_sleepless_net_http_httpgetrequest_h
// Copyright 1998-2002
// Sleepless Software Inc.
// All Rights Reserved
/*
XXX generify this and put it somewhere else.
This header defines a struct called HTTPGetRequest
that performs HTTP GET transactions under win32.
***** THIS CODE IS WINDOWS SPECIFIC. ******
Supports HTTP and HTTPS (secure) protocols.
The constructor actually performs the initial request after
which calls to read() are done to receive the content.
There is a getHeader() call to retrieve response headers.
(( see code for details ))
*/
#ifdef WIN32
#include <windows.h>
#include <wininet.h>
#include <stdlib.h>
struct HTTPGetRequest
{
HINTERNET h;
HINTERNET hc;
HINTERNET hr;
char buf[1000];
bool failed;
long contentLength;
long leftToRead;
HTTPGetRequest(const char *host, int port, const char *path, bool ssl, bool reload, bool cacheIt)
{
static const char *acceptTypes[] = { "*/*", 0 };
failed = false;
contentLength = 0;
h = InternetOpen( "Sleepless Software Inc.", INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0);
if(h == NULL)
{
failed = true;
return;
}
hc = InternetConnect(h, host, port, "Sleepless Software Inc.", "Sleepless Software Inc.", INTERNET_SERVICE_HTTP, 0, 0);
if(hc == NULL)
{
InternetCloseHandle(h);
failed = true;
return;
}
hr = HttpOpenRequest( hc, "GET", path, "HTTP/1.0", NULL, acceptTypes, (reload ? INTERNET_FLAG_RELOAD : 0) | (cacheIt ? INTERNET_FLAG_DONT_CACHE : 0) | INTERNET_FLAG_RAW_DATA | (ssl ? INTERNET_FLAG_SECURE : 0) | INTERNET_FLAG_EXISTING_CONNECT, NULL);
if(hr == NULL)
{
InternetCloseHandle(hc);
InternetCloseHandle(h);
failed = true;
return;
}
if( ! HttpSendRequest( hr, NULL, 0, NULL, 0) )
{
InternetCloseHandle(hr);
InternetCloseHandle(hc);
InternetCloseHandle(h);
failed = true;
return;
}
unsigned long sz = sizeof(buf);
if(!HttpQueryInfo(hr, HTTP_QUERY_STATUS_CODE, buf, &sz, NULL))
{
InternetCloseHandle(hr);
InternetCloseHandle(hc);
InternetCloseHandle(h);
failed = true;
return;
}
int rc = atoi(buf);
if(rc < 200 || rc > 299)
{
InternetCloseHandle(hr);
InternetCloseHandle(hc);
InternetCloseHandle(h);
failed = true;
return;
}
const char *cl = getHeader("Content-Length");
contentLength = cl ? atol(cl) : 0;
leftToRead = contentLength;
}
~HTTPGetRequest()
{
if(!failed)
{
InternetCloseHandle(hr);
InternetCloseHandle(hc);
InternetCloseHandle(h);
}
}
// Returns 1 thru len inclusive if data was read.
// Returns 0 when no more data is left to read
// Take a look at 'failed' to differentiate between a normal
// EOF and an error.
// WARNING: I've noticed that if I fetch a file that is, say
// 45 bytes long ... on win95, it strangely returns 47 bytes
// read. This makes no sense, and of course fucks me all up.
// So instead of relying on the system to return an appropriately
// short read on EOF, I note content-length in the constructor,
// and track how many bytes are read on each call so that if
// I reach the end of the CONTENT-LENGTH, I return a short read,
// then 0 on the next call.
unsigned long read(char *b, int l)
{
if(failed)
return 0;
if(leftToRead == 0)
return 0;
if(leftToRead < l)
l = leftToRead;
unsigned long r;
if(!InternetReadFile(hr, b, l, &r))
{
failed = true;
leftToRead = 0;
}
else
{
leftToRead -= r;
}
return r;
}
const char *getHeader(const char *hdr)
{
if(failed)
return NULL;
strncpy(buf, hdr, sizeof(buf));
unsigned long sz = sizeof(buf);
if(!HttpQueryInfo(hr, HTTP_QUERY_CUSTOM, buf, &sz, NULL))
return NULL;
return buf;
}
};
#endif
#endif