home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.muug.mb.ca
/
2014.06.ftp.muug.mb.ca.tar
/
ftp.muug.mb.ca
/
pub
/
src
/
gopher
/
gopher1.01
/
object
/
GSgopherobj.c
< prev
next >
Wrap
Text File
|
1992-06-11
|
9KB
|
438 lines
/*
* This is a crude attempt at doing some object-based programming in C
*/
#include "GSgopherobj.h"
#if defined(mips) /*** Gross hack, yuck! ***/
#define _SIZE_T
#endif
#include <string.h>
#include <stdio.h>
extern int DEBUG;
/*
* These are needed for GSconnect(). Ick.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/file.h>
#ifndef hpux
#include <arpa/inet.h>
#endif
#include <netdb.h>
#include "Malloc.h"
/*
* Make a new gopherstruct... Should reuse destroyed GopherObjs...
*/
GopherObj *
GSnew()
{
GopherObj *temp;
temp = (GopherObj *) malloc(sizeof(GopherObj));
temp->Selstr = STRnew();
temp->Title = STRnew();
temp->Host = STRnew();
GSinit(temp);
return(temp);
}
void
GSdestroy(gs)
GopherObj *gs;
{
STRdestroy(gs->Selstr);
STRdestroy(gs->Title);
STRdestroy(gs->Host);
free(gs);
}
/*
* Clear out all the crud
*/
void
GSinit(gs)
GopherObj *gs;
{
GSsetType(gs, '\0');
STRinit(gs->Title);
STRinit(gs->Selstr);
STRinit(gs->Host);
gs->iPort = 0;
gs->iItemnum = 0;
GSsetWeight(gs, 0);
}
void
GStoNet(gs, sockfd)
GopherObj *gs;
int sockfd;
{
static char buf[1024];
buf[0] = GSgetType(gs);
if (GSgetWeight(gs) == 0)
sprintf(buf + 1, "%s\t%s\t%s\t%d\r\n",
GSgetTitle(gs),
GSgetPath(gs),
GSgetHost(gs),
GSgetPort(gs));
else
sprintf(buf + 1, "%s\t%s\t%s\t%d\t%d\r\n",
GSgetTitle(gs),
GSgetPath(gs),
GSgetHost(gs),
GSgetPort(gs),
GSgetWeight(gs));
writestring(sockfd, buf);
if (DEBUG)
fprintf(stderr, buf);
}
void
GStoNetHTML(gs, sockfd)
GopherObj *gs;
int sockfd;
{
static char buf[1024];
static char pathbuf[1024];
char *cp, *cpout;
buf[0] = '\0';
pathbuf[0] = '\0';
/** Convert Path so that spaces are %20 **/
Tohexstr(GSgetPath(gs), pathbuf);
sprintf(buf, "<A HREF=http://%s:%d/%s>%s</A>",
GSgetHost(gs),
GSgetPort(gs),
pathbuf,
GSgetTitle(gs));
writestring(sockfd, buf);
if (DEBUG)
fprintf(stderr, "HTML: %s", buf);
if (GSgetWeight(gs) != 0) {
sprintf(buf, "Score: %d\r\n", GSgetWeight(gs));
writestring(sockfd, buf);
}
else
writestring(sockfd, "\r\n");
}
/*
* Fill in a GopherObj, given an HREF= link from a WWW anchor..
* So far only works with http
*/
void
GSfromHREF(gs, href)
GopherObj *gs;
char *href;
{
char *cp;
char *host;
char *port;
char path[1024];
if (strncasecmp(href, "http://", 7)==0) {
host = href +7;
cp = strchr(href+7, '/');
if (cp == NULL)
return;
*cp = '\0';
strcpy(path, "GET ");
strcat(path, cp+1);
GSsetPath(gs, path);
GSsetType(gs, 'h');
GSsetPath(gs, path);
cp = strchr(host, ':');
if (cp==NULL)
GSsetPort(gs, 80); /** default WWW port **/
else
GSsetPort(gs, atoi(cp+1));
*cp = '\0';
GSsetHost(gs, host);
}
}
extern int readfield();
extern int readline();
int
GSfromNet(gs, sockfd)
GopherObj *gs;
int sockfd;
{
char *cPtr = NULL;
char foo[1024];
if (readfield(sockfd, foo, 1024)<= 0) {
/* EOF or error */
return(-1);
}
GSsetType(gs, foo[0]);
/** Get the kind of file from the first character **/
/** Filter out files that we can't deal with **/
switch (GSgetType(gs)) {
case A_FILE:
case A_DIRECTORY:
case A_MACHEX:
case A_PCHEX:
case A_CSO:
case A_INDEX:
case A_TELNET:
case A_SOUND:
case A_UNIXBIN:
case A_HTML:
case A_TN3270:
case A_MIME:
/* case A_EVENT:
case A_CALENDAR: not ready for prime time yet */
break;
case A_EOI:
return(1);
default:
return(-1);
}
/** Suck off the User Displayable name **/
GSsetTitle(gs, foo+1);
/** Suck off the Pathname **/
if (readfield(sockfd, foo, 1024) == 0)
return(-1);
GSsetPath(gs, foo);
/** Suck off the hostname **/
if (readfield(sockfd, foo, 1024) == 0)
return(-1);
GSsetHost(gs, foo);
if (readline(sockfd, foo, 1024)==0)
return(-1);
GSsetPort(gs, 0);
/** Get the port number **/
GSsetPort(gs, atoi(foo));
return(0);
}
/** Copy a GopherObj ***/
void
GScpy(dest, orig)
GopherObj *dest, *orig;
{
dest->sFileType = orig->sFileType;
dest->iPort = orig->iPort;
dest->iItemnum = orig->iItemnum;
GSsetTitle(dest, GSgetTitle(orig));
GSsetPath(dest, GSgetPath(orig));
GSsetHost(dest, GSgetHost(orig));
}
/** Compare two GopherObjs ***/
int
GScmp(gs1, gs2)
GopherObj *gs1, *gs2;
{
if (GSgetTitle(gs1) == NULL)
return(1);
if (GSgetTitle(gs2) == NULL)
return(-1);
return(strcmp(GSgetTitle(gs1), GSgetTitle(gs2)));
}
/* GSconnect performs a connection to socket 'service' on host
* 'host'. Host can be a hostname or ip-address. If 'host' is null, the
* local host is assumed. The parameter full_hostname will, on return,
* contain the expanded hostname (if possible). Note that full_hostname is a
* pointer to a char *, and is allocated by connect_to_gopher()
*
* Errors:
*
* -1 get service failed
*
* -2 get host failed
*
* -3 socket call failed
*
* -4 connect call failed
*/
int
GSconnect(gs)
GopherObj *gs;
{
struct sockaddr_in Server;
char sBuf[16];
struct hostent *HostPtr;
int iSock = 0;
if ((Server.sin_addr.s_addr = inet_addr(GSgetHost(gs))) == -1) {
if (HostPtr = gethostbyname(GSgetHost(gs))) {
bzero((char *) &Server, sizeof(Server));
bcopy(HostPtr->h_addr, (char *) &Server.sin_addr, HostPtr->h_length);
Server.sin_family = HostPtr->h_addrtype;
} else
return (-2);
} else
Server.sin_family = AF_INET;
Server.sin_port = (unsigned short) htons(GSgetPort(gs));
if ((iSock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return (-3);
setsockopt(iSock, SOL_SOCKET, ~SO_LINGER, 0, 0);
setsockopt(iSock, SOL_SOCKET, SO_REUSEADDR, 0, 0);
setsockopt(iSock, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
if (connect(iSock, (struct sockaddr *) &Server, sizeof(Server)) < 0) {
close(iSock);
return (-4);
}
return(iSock);
}
/*
* GSfromLink takes an open file descriptor and starts reading from it.
* It keeps going until it findsL
* enough fields for a gopherobj
* no data left
*
* returns 0 with success, -1 on an error.
*/
#define G_PATH (1<<0)
#define G_TYPE (1<<1)
#define G_NAME (1<<2)
#define G_PORT (1<<3)
#define G_HOST (1<<4)
#define G_ALL (G_PATH | G_TYPE | G_NAME | G_PORT | G_HOST)
int
GSfromLink(gs, fd, host, port)
GopherObj *gs;
int fd;
char *host;
int port;
{
int doneflags = 0;
char buf[1024];
while ((doneflags != G_ALL) && readline(fd, buf, 1024)) {
if (buf[0] == '#')
continue; /* comment */
ZapCRLF(buf);
if (strncmp(buf, "Type=", 5)==0) {
GSsetType(gs, buf[5]);
doneflags |= G_TYPE;
}
if (strncmp(buf, "Name=", 5)==0) {
GSsetTitle(gs, buf+5);
doneflags |= G_NAME;
}
if (strncmp(buf, "Path=", 5)==0) {
GSsetPath(gs, buf+5);
doneflags |= G_PATH;
}
if (strncmp(buf, "Host=", 5)==0) {
if (buf[5] == '+' && buf[6] == '\0')
GSsetHost(gs, host);
else
GSsetHost(gs, buf+5);
doneflags |= G_HOST;
}
if (strncmp(buf, "Port=", 5)==0) {
if (buf[5] == '+' && buf[6] == '\0')
GSsetPort(gs, port);
else
GSsetPort(gs, atoi(buf+5));
doneflags |= G_PORT;
}
if (strncmp(buf, "Numb=", 5)==0)
GSsetNum(gs, atoi(buf+5));
}
return ((doneflags == G_ALL) ? 0 : -1); /* 0 == success */
}
void
GStoLink(gs, fd)
GopherObj *gs;
int fd;
{
char gtype[2];
char portnum[16];
gtype[0] = GSgetType(gs);
gtype[1] = '\0';
writestring(fd, "#");
writestring(fd, "\nType=");
writestring(fd, gtype);
writestring(fd, "\nName=");
writestring(fd, GSgetTitle(gs));
writestring(fd, "\nPath=");
writestring(fd, GSgetPath(gs));
writestring(fd, "\nHost=");
writestring(fd, GSgetHost(gs));
writestring(fd, "\nPort=");
sprintf(portnum, "%d", GSgetPort(gs));
writestring(fd, portnum);
writestring(fd, "\n");
}