2012-04-15 03:40:35 +00:00
|
|
|
#pragma optimize 79
|
2012-04-25 03:54:12 +00:00
|
|
|
#pragma noroot
|
2012-04-15 03:40:35 +00:00
|
|
|
|
2012-03-09 02:15:46 +00:00
|
|
|
#include <Memory.h>
|
2012-04-15 03:40:35 +00:00
|
|
|
#include <MiscTool.h>
|
2012-03-09 02:15:46 +00:00
|
|
|
#include <tcpip.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2012-03-11 22:48:45 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2012-04-15 04:08:09 +00:00
|
|
|
#include <errno.h>
|
2012-04-10 04:21:33 +00:00
|
|
|
|
2012-03-12 02:44:29 +00:00
|
|
|
#include <unistd.h>
|
2012-03-09 02:15:46 +00:00
|
|
|
|
2012-04-28 01:19:38 +00:00
|
|
|
#include "url.h"
|
|
|
|
#include "connection.h"
|
|
|
|
#include "readline2.h"
|
|
|
|
#include "prototypes.h"
|
2012-04-28 03:36:25 +00:00
|
|
|
#include "flags.h"
|
2012-04-28 01:19:38 +00:00
|
|
|
|
2012-04-25 03:54:12 +00:00
|
|
|
#include "s16debug.h"
|
|
|
|
|
|
|
|
|
2012-04-16 22:38:25 +00:00
|
|
|
extern int setfiletype(const char *filename);
|
|
|
|
|
2012-03-09 02:15:46 +00:00
|
|
|
/*
|
|
|
|
* connect gopher.floodgap.com:70
|
|
|
|
* send path
|
|
|
|
* read output.
|
|
|
|
* text -- ends with . <CR><LF>
|
|
|
|
* bin -- ends when connection is closed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-04-25 03:54:12 +00:00
|
|
|
static int gopher_text(Word ipid, FILE *file)
|
2012-03-11 22:48:45 +00:00
|
|
|
{
|
|
|
|
// text \r\n
|
|
|
|
// ...
|
|
|
|
// . \r\n
|
|
|
|
// any leading '.' must be doubled.
|
|
|
|
|
2012-04-06 02:52:09 +00:00
|
|
|
Word eof = 0;
|
2012-04-10 04:21:33 +00:00
|
|
|
int rv = 0;
|
2012-04-15 04:08:09 +00:00
|
|
|
Word lastTerm = 0;
|
2012-04-10 04:21:33 +00:00
|
|
|
|
|
|
|
TCPIPPoll();
|
2012-03-12 02:44:29 +00:00
|
|
|
|
2012-04-06 02:52:09 +00:00
|
|
|
for(;;)
|
|
|
|
{
|
2012-03-11 22:48:45 +00:00
|
|
|
Word count;
|
2012-04-06 02:52:09 +00:00
|
|
|
Handle h;
|
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
rlBuffer rb;
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
rv = ReadLine2(ipid, &rb);
|
2012-04-07 00:13:05 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
h = rb.bufferHandle;
|
|
|
|
count = rb.bufferSize;
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
if (rv < 0) break; // eof
|
|
|
|
if (rv == 0) // no data available (yet)
|
2012-04-06 02:52:09 +00:00
|
|
|
{
|
2012-04-10 04:21:33 +00:00
|
|
|
TCPIPPoll();
|
|
|
|
continue;
|
2012-04-06 02:52:09 +00:00
|
|
|
}
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
if (!rb.moreFlag) TCPIPPoll();
|
|
|
|
|
|
|
|
if (count == 0)
|
2012-04-07 00:13:05 +00:00
|
|
|
{
|
2012-04-10 04:21:33 +00:00
|
|
|
DisposeHandle(h);
|
|
|
|
if (rb.terminator)
|
|
|
|
{
|
2012-04-15 04:08:09 +00:00
|
|
|
if (lastTerm == '\r' && rb.terminator == '\n')
|
|
|
|
{
|
2012-04-25 03:54:12 +00:00
|
|
|
lastTerm = TERMINATOR_CR_LF;
|
2012-04-15 04:08:09 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
fputc('\r', file);
|
2012-04-10 04:21:33 +00:00
|
|
|
}
|
|
|
|
|
2012-04-15 04:08:09 +00:00
|
|
|
lastTerm = rb.terminator;
|
2012-04-10 04:21:33 +00:00
|
|
|
continue;
|
2012-04-07 00:13:05 +00:00
|
|
|
}
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-06 02:52:09 +00:00
|
|
|
if (count)
|
2012-03-11 22:48:45 +00:00
|
|
|
{
|
2012-04-06 02:52:09 +00:00
|
|
|
char *cp;
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-07 00:13:05 +00:00
|
|
|
HLock(h);
|
2012-04-06 02:52:09 +00:00
|
|
|
cp = *((char **)h);
|
|
|
|
|
|
|
|
// .. -> .
|
|
|
|
// . \r\n -> eof
|
|
|
|
|
|
|
|
if (*cp == '.')
|
2012-03-11 22:48:45 +00:00
|
|
|
{
|
2012-04-06 02:52:09 +00:00
|
|
|
if (count == 1)
|
|
|
|
{
|
|
|
|
DisposeHandle(h);
|
|
|
|
eof = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp++;
|
|
|
|
count--;
|
|
|
|
}
|
2012-04-10 04:21:33 +00:00
|
|
|
|
2012-04-06 02:52:09 +00:00
|
|
|
fwrite(cp, 1, count, file);
|
|
|
|
fputc('\r', file);
|
2012-03-11 22:48:45 +00:00
|
|
|
}
|
2012-04-06 02:52:09 +00:00
|
|
|
|
|
|
|
DisposeHandle(h);
|
2012-03-11 22:48:45 +00:00
|
|
|
}
|
2012-04-06 02:52:09 +00:00
|
|
|
|
|
|
|
if (!eof)
|
2012-03-12 02:44:29 +00:00
|
|
|
fprintf(stderr, "Warning: eof not found.\n");
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
return eof ? 0 : -1;
|
2012-03-11 22:48:45 +00:00
|
|
|
}
|
|
|
|
|
2012-04-25 03:54:12 +00:00
|
|
|
static int gopher_dir(Word ipid, FILE *file)
|
2012-03-12 02:44:29 +00:00
|
|
|
{
|
|
|
|
Word eof = 0;
|
2012-04-10 04:21:33 +00:00
|
|
|
int rv = 0;
|
2012-03-12 02:44:29 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
TCPIPPoll();
|
2012-03-12 02:44:29 +00:00
|
|
|
|
2012-04-15 04:08:09 +00:00
|
|
|
|
|
|
|
// blank lines are ignored, so no need to check for terminator split.
|
|
|
|
|
2012-03-12 02:44:29 +00:00
|
|
|
for(;;)
|
|
|
|
{
|
2012-04-10 04:21:33 +00:00
|
|
|
rlBuffer rb;
|
2012-03-12 02:44:29 +00:00
|
|
|
Word count;
|
|
|
|
Handle h;
|
|
|
|
|
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
rv = ReadLine2(ipid, &rb);
|
2012-03-12 02:44:29 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
h = rb.bufferHandle;
|
|
|
|
count = rb.bufferSize;
|
2012-03-12 02:44:29 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
if (rv < 0) break;
|
|
|
|
if (rv == 0)
|
2012-03-12 02:44:29 +00:00
|
|
|
{
|
2012-04-10 04:21:33 +00:00
|
|
|
TCPIPPoll();
|
|
|
|
continue;
|
2012-03-12 02:44:29 +00:00
|
|
|
}
|
2012-04-10 04:21:33 +00:00
|
|
|
if (!rb.moreFlag) TCPIPPoll();
|
|
|
|
|
2012-03-12 02:44:29 +00:00
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
if (!count)
|
2012-04-06 02:52:09 +00:00
|
|
|
{
|
2012-04-10 04:21:33 +00:00
|
|
|
// blank line?
|
|
|
|
continue;
|
2012-04-06 02:52:09 +00:00
|
|
|
}
|
2012-03-12 02:44:29 +00:00
|
|
|
|
|
|
|
if (count)
|
|
|
|
{
|
|
|
|
|
|
|
|
Word tabs[4];
|
|
|
|
unsigned i,j;
|
|
|
|
char type;
|
2012-04-07 00:13:05 +00:00
|
|
|
char *buffer;
|
|
|
|
|
|
|
|
HLock(h);
|
|
|
|
buffer = *((char **)h);
|
2012-03-12 02:44:29 +00:00
|
|
|
|
|
|
|
type = *buffer;
|
|
|
|
++buffer;
|
|
|
|
--count;
|
|
|
|
|
|
|
|
if (type == '.' && count == 0)
|
|
|
|
{
|
|
|
|
eof = 1;
|
|
|
|
DisposeHandle(h);
|
|
|
|
break;
|
|
|
|
}
|
2012-04-10 04:21:33 +00:00
|
|
|
|
2012-03-12 02:44:29 +00:00
|
|
|
// format is [type][name] \t [path] \t [server] \t [port]
|
|
|
|
j = 1;
|
|
|
|
tabs[0] = 0;
|
|
|
|
tabs[1] = tabs[2] = tabs[3] = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
if (buffer[i] == '\t')
|
|
|
|
{
|
|
|
|
tabs[j++] = i;
|
|
|
|
buffer[i] = 0;
|
|
|
|
if (j == 4) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 'i' is info record.
|
|
|
|
if (type == 'i')
|
|
|
|
{
|
|
|
|
if (tabs[1] == -1)
|
2012-04-06 02:52:09 +00:00
|
|
|
fwrite(buffer, 1, count, file);
|
|
|
|
else
|
|
|
|
fputs(buffer, file);
|
|
|
|
|
|
|
|
fputc('\r', file);
|
2012-03-12 02:44:29 +00:00
|
|
|
}
|
|
|
|
else if (j == 4) // all the tabs.
|
|
|
|
{
|
|
|
|
int port = 0;
|
|
|
|
// description
|
|
|
|
// file name
|
|
|
|
// server
|
|
|
|
// port
|
|
|
|
for (i = tabs[3] + 1; i < count; ++i)
|
|
|
|
{
|
|
|
|
char c = buffer[i];
|
|
|
|
if (c >= '0' && c <= '9') port = port * 10 + c - '0';
|
|
|
|
}
|
2012-04-10 04:21:33 +00:00
|
|
|
|
2012-03-12 02:44:29 +00:00
|
|
|
if (port == 70)
|
|
|
|
{
|
2012-04-07 00:13:05 +00:00
|
|
|
fprintf(file, "[%s/%c%s] %s\r",
|
2012-03-12 02:44:29 +00:00
|
|
|
buffer + 1 + tabs[2], // server
|
|
|
|
type, // type
|
2012-04-07 00:13:05 +00:00
|
|
|
buffer + 1 + tabs[1], // file name
|
|
|
|
buffer // description
|
2012-03-12 02:44:29 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-04-07 00:13:05 +00:00
|
|
|
fprintf(file, "[%s:%u/%c%s] %s\r",
|
2012-03-12 02:44:29 +00:00
|
|
|
buffer + 1 + tabs[2], // server
|
|
|
|
port, // port
|
|
|
|
type, // type
|
2012-04-07 00:13:05 +00:00
|
|
|
buffer + 1 + tabs[1], // file name
|
|
|
|
buffer // description
|
2012-03-12 02:44:29 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
DisposeHandle(h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eof)
|
|
|
|
fprintf(stderr, "Warning: eof not found.\n");
|
|
|
|
|
2012-04-10 04:21:33 +00:00
|
|
|
return eof ? 0 : -1;
|
2012-03-12 02:44:29 +00:00
|
|
|
}
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-28 03:36:25 +00:00
|
|
|
int do_gopher(const char *url, URLComponents *components)
|
2012-03-09 02:15:46 +00:00
|
|
|
{
|
2012-04-28 01:19:38 +00:00
|
|
|
Connection connection;
|
2012-03-09 02:15:46 +00:00
|
|
|
char *host;
|
2012-04-28 03:36:25 +00:00
|
|
|
char *path;
|
2012-03-11 22:48:45 +00:00
|
|
|
char type;
|
2012-04-28 01:19:38 +00:00
|
|
|
int ok;
|
2012-04-28 03:36:25 +00:00
|
|
|
|
|
|
|
FILE *file;
|
|
|
|
char *filename;
|
|
|
|
|
|
|
|
file = stdout;
|
2012-04-28 01:19:38 +00:00
|
|
|
|
|
|
|
|
2012-04-15 04:08:09 +00:00
|
|
|
if (!components->portNumber) components->portNumber = 70;
|
|
|
|
|
2012-04-28 01:19:38 +00:00
|
|
|
host = URLComponentGetCMalloc(url, components, URLComponentHost);
|
2012-04-28 03:36:25 +00:00
|
|
|
path = URLComponentGetCMalloc(url, components, URLComponentPath);
|
2012-04-28 01:19:38 +00:00
|
|
|
if (!host)
|
2012-04-15 04:08:09 +00:00
|
|
|
{
|
2012-04-28 01:19:38 +00:00
|
|
|
fprintf(stderr, "URL `%s': no host.", url);
|
2012-04-28 03:36:25 +00:00
|
|
|
free(path);
|
2012-04-28 01:19:38 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-03-11 22:48:45 +00:00
|
|
|
|
2012-04-28 03:36:25 +00:00
|
|
|
if (path && components->path.length <= 2)
|
|
|
|
{
|
|
|
|
free(path);
|
|
|
|
path = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// open the file.
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "-O flag cannot be used with this URL.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
filename = strrchr(path + 2, '/');
|
|
|
|
if (filename) // *filename == '/'
|
|
|
|
{
|
|
|
|
filename++;
|
|
|
|
if (!filename[0])
|
|
|
|
{
|
|
|
|
// path/ ?
|
|
|
|
fprintf(stderr, "-O flag cannot be used with this URL.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
filename = path + 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
setfiletype(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-28 01:19:38 +00:00
|
|
|
ok = ConnectLoop(host, components->portNumber, &connection);
|
|
|
|
|
|
|
|
if (!ok)
|
2012-03-09 02:15:46 +00:00
|
|
|
{
|
|
|
|
free(host);
|
2012-04-28 03:36:25 +00:00
|
|
|
free(path);
|
|
|
|
if (file != stdout) fclose(file);
|
2012-04-28 01:19:38 +00:00
|
|
|
return -1;
|
2012-03-09 02:15:46 +00:00
|
|
|
}
|
|
|
|
|
2012-04-28 01:19:38 +00:00
|
|
|
|
2012-03-11 22:48:45 +00:00
|
|
|
// connected....
|
2012-03-09 02:15:46 +00:00
|
|
|
|
2012-03-11 22:48:45 +00:00
|
|
|
// path is /[type][resource]
|
|
|
|
// where [type] is 1 char and the leading / is ignored.
|
|
|
|
|
2012-04-28 03:36:25 +00:00
|
|
|
if (path)
|
2012-03-09 02:15:46 +00:00
|
|
|
{
|
2012-04-28 03:36:25 +00:00
|
|
|
// path[0] = '/'
|
|
|
|
// path[1] = type
|
|
|
|
type = path[1];
|
2012-03-11 22:48:45 +00:00
|
|
|
TCPIPWriteTCP(
|
2012-04-28 01:19:38 +00:00
|
|
|
connection.ipid,
|
2012-04-28 03:36:25 +00:00
|
|
|
path + 2,
|
2012-04-15 04:08:09 +00:00
|
|
|
components->path.length - 2,
|
2012-04-28 03:36:25 +00:00
|
|
|
false,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
type = 1;
|
2012-03-09 02:15:46 +00:00
|
|
|
}
|
2012-03-11 22:48:45 +00:00
|
|
|
//
|
2012-04-28 03:36:25 +00:00
|
|
|
TCPIPWriteTCP(connection.ipid, "\r\n", 2, true, false);
|
|
|
|
|
|
|
|
|
2012-03-09 02:15:46 +00:00
|
|
|
|
2012-03-11 22:48:45 +00:00
|
|
|
// 5 and 9 are binary, 1 is dir, all others text.
|
2012-03-09 02:15:46 +00:00
|
|
|
|
2012-03-12 02:44:29 +00:00
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case '1':
|
2012-04-28 01:19:38 +00:00
|
|
|
gopher_dir(connection.ipid, file);
|
2012-03-12 02:44:29 +00:00
|
|
|
break;
|
|
|
|
case '5':
|
|
|
|
case '9':
|
2012-04-15 04:08:09 +00:00
|
|
|
fsetbinary(file);
|
2012-04-28 01:19:38 +00:00
|
|
|
ok = read_binary(connection.ipid, file);
|
2012-03-12 02:44:29 +00:00
|
|
|
break;
|
|
|
|
default:
|
2012-04-28 01:19:38 +00:00
|
|
|
ok = gopher_text(connection.ipid, file);
|
2012-03-12 02:44:29 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-03-09 02:15:46 +00:00
|
|
|
|
2012-03-12 02:44:29 +00:00
|
|
|
fflush(file);
|
2012-04-28 03:36:25 +00:00
|
|
|
if (file != stdout) fclose(file);
|
2012-03-09 02:15:46 +00:00
|
|
|
|
2012-04-28 01:19:38 +00:00
|
|
|
CloseLoop(&connection);
|
|
|
|
free(host);
|
2012-04-28 03:36:25 +00:00
|
|
|
free(path);
|
|
|
|
|
2012-04-28 01:19:38 +00:00
|
|
|
return 0;
|
2012-03-11 22:48:45 +00:00
|
|
|
}
|
2012-03-09 02:15:46 +00:00
|
|
|
|
|
|
|
|
2012-04-15 04:08:09 +00:00
|
|
|
|
|
|
|
|
2012-03-09 02:15:46 +00:00
|
|
|
|