gopher/http.c

260 lines
4.5 KiB
C
Raw Normal View History

2012-04-28 01:19:00 +00:00
/*
* HTTP 1.0
*
* request:
* verb url version CR LF
* header CR LF *
* CR LF
*
* response:
* status CR LF
* header CR LF *
* CR LF
* data
*/
#pragma optimize 79
#pragma noroot
#include <TCPIP.h>
#include <MiscTool.h>
#include <Memory.h>
#include <stdlib.h>
2012-04-28 04:58:13 +00:00
#include <stdio.h>
#include <string.h>
#include <errno.h>
2012-04-28 01:19:00 +00:00
#include "url.h"
#include "connection.h"
#include "prototypes.h"
#include "dictionary.h"
2012-04-28 04:36:03 +00:00
#include "flags.h"
static int do_http_0_9(
const char *url,
URLComponents *components,
Word ipid,
FILE *file,
const char *filename)
2012-04-28 01:19:00 +00:00
{
2012-04-28 04:58:13 +00:00
int ok;
char *cp;
int length;
2012-04-28 04:36:03 +00:00
TCPIPWriteTCP(ipid, "GET ", 4, false, false);
2012-04-28 01:19:00 +00:00
2012-04-28 04:58:13 +00:00
length = components->pathAndQuery.length;
cp = url + components->pathAndQuery.location;
if (!length)
2012-04-28 01:19:00 +00:00
{
2012-04-28 04:58:13 +00:00
length = 1;
cp = "/";
2012-04-28 01:19:00 +00:00
}
2012-04-28 04:58:13 +00:00
TCPIPWriteTCP(ipid, cp, length, false, false);
2012-04-28 04:36:03 +00:00
TCPIPWriteTCP(ipid, "\r\n", 2, true, false);
ok = read_binary(ipid, file);
return 0;
}
2012-04-28 01:19:00 +00:00
2012-04-28 04:36:03 +00:00
static int do_http_1_1(
const char *url,
URLComponents *components,
Word ipid,
FILE *file,
const char *filename)
{
Handle dict;
DictionaryEnumerator e;
Word cookie;
2012-04-28 04:58:13 +00:00
int ok;
2012-04-28 04:36:03 +00:00
char *cp;
int length;
2012-04-28 01:19:00 +00:00
// html headers.
// (not really needed until 1.1)
dict = DictionaryCreate(MMStartUp(), 2048);
2012-04-28 04:36:03 +00:00
length = components->host.length;
cp = url + components->host.location;
DictionaryAdd(dict, "Host", 4, cp, length, false);
2012-04-28 01:19:00 +00:00
DictionaryAdd(dict, "Connection", 10, "close", 5, false);
// connected....
// send the request.
2012-04-28 04:36:03 +00:00
// GET path HTTP/version\r\n
2012-04-28 04:58:13 +00:00
TCPIPWriteTCP(ipid, "GET ", 4, false, false);
2012-04-28 01:19:00 +00:00
2012-04-28 04:36:03 +00:00
length = components->pathAndQuery.length;
cp = url + components->pathAndQuery.location;
2012-04-28 04:58:13 +00:00
if (!length)
2012-04-28 01:19:00 +00:00
{
2012-04-28 04:58:13 +00:00
length = 1;
cp = "/";
2012-04-28 01:19:00 +00:00
}
2012-04-28 04:58:13 +00:00
TCPIPWriteTCP(ipid, cp, length, false, false);
2012-04-28 04:36:03 +00:00
if (flags._0)
{
2012-04-28 04:58:13 +00:00
TCPIPWriteTCP(ipid, " HTTP/1.0\r\n", 11, false, false);
2012-04-28 04:36:03 +00:00
}
else
{
2012-04-28 04:58:13 +00:00
TCPIPWriteTCP(ipid, " HTTP/1.1\r\n", 11, false, false);
2012-04-28 04:36:03 +00:00
}
2012-04-28 01:19:00 +00:00
// send the headers.
2012-04-28 04:36:03 +00:00
cookie = 0;
while ((cookie = DictionaryEnumerate(dict, &e, cookie)))
2012-04-28 01:19:00 +00:00
{
2012-04-28 04:36:03 +00:00
if (!e.keySize) continue;
2012-04-28 01:19:00 +00:00
2012-04-28 04:58:13 +00:00
TCPIPWriteTCP(ipid, e.key, e.keySize, false, false);
TCPIPWriteTCP(ipid, ": ", 2, false, false);
TCPIPWriteTCP(ipid, e.value, e.valueSize, false, false);
TCPIPWriteTCP(ipid, "\r\n", 2, false, false);
2012-04-28 01:19:00 +00:00
}
2012-04-28 04:36:03 +00:00
2012-04-28 01:19:00 +00:00
// end headers and push.
2012-04-28 04:58:13 +00:00
TCPIPWriteTCP(ipid, "\r\n", 2, true, false);
2012-04-28 01:19:00 +00:00
2012-04-28 04:36:03 +00:00
DisposeHandle(dict);
dict = NULL;
2012-04-28 01:19:00 +00:00
2012-04-28 04:58:13 +00:00
ok = read_binary(ipid, file);
2012-04-28 04:36:03 +00:00
return 0;
}
2012-04-28 01:19:00 +00:00
2012-04-28 04:36:03 +00:00
int do_http(const char *url, URLComponents *components)
{
char *host;
char *path;
char *filename;
Connection connection;
int ok;
2012-04-28 04:58:13 +00:00
FILE *file;
2012-04-28 04:36:03 +00:00
file = stdout;
if (!components->portNumber) components->portNumber = 80;
2012-04-28 01:19:00 +00:00
2012-04-28 04:36:03 +00:00
host = URLComponentGetCMalloc(url, components, URLComponentHost);
path = URLComponentGetCMalloc(url, components, URLComponentPath);
if (!host)
{
fprintf(stderr, "URL `%s': no host.", url);
free(path);
return -1;
}
// outfile.
filename = NULL;
if (flags._o)
{
filename = flags._o;
if (filename && !filename[0])
filename = NULL;
if (filename && filename[0] == '-' && !filename[1])
filename = NULL;
}
if (flags._O)
{
if (path)
{
// path starts with /.
filename = strrchr(path + 1, '/');
if (filename) // *filename == '/'
{
filename++;
}
else
{
filename = path + 1;
}
}
if (!filename || !filename[0])
{
// path/ ?
fprintf(stderr, "-O flag cannot be used with this URL.\n");
free(host);
free(path);
return -1;
}
}
if (filename)
{
file = fopen(filename, "w");
if (!file)
{
fprintf(stderr, "Unable to to open file ``%s'': %s\n",
filename, strerror(errno));
free(host);
free(path);
return -1;
}
// should set from mime type?
setfiletype(filename);
}
ok = ConnectLoop(host, components->portNumber, &connection);
if (!ok)
{
free(host);
free(path);
fclose(file);
return -1;
}
if (flags._9)
{
ok = do_http_0_9(url, components, connection.ipid, file, filename);
}
else
{
ok = do_http_1_1(url, components, connection.ipid, file, filename);
}
fflush(file);
if (file != stdout) fclose(file);
2012-04-28 01:19:00 +00:00
CloseLoop(&connection);
2012-04-28 04:36:03 +00:00
free(host);
free(path);
2012-04-28 01:19:00 +00:00
return 0;
}