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
/
gopherd
/
waisgopher.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-28
|
17KB
|
688 lines
/* Wais to gopher gateway code.
Paul Lindner, March 1992
<lindner@boombox.micro.umn.edu>
*/
/* WIDE AREA INFORMATION SERVER SOFTWARE:
No guarantees or restrictions. See the readme file for the full standard
disclaimer.
Brewster@think.com
*/
#if defined(WAISSEARCH) /*** Only compile this if we have WAIS ***/
#include <ctype.h>
#include <string.h>
#include <ui.h>
#include <docid.h>
#define MAIN
#include "wais.h"
#define WAISSEARCH_DATE "Fri Sep 13 1991"
#include "gopherd.h"
/**** Needed by wais-8-b5... Ick... ***/
char *sdir=NULL;
char *cdir=NULL;
/**** Used by something in the source reading routines. ***/
void
PrintStatus(str)
char * str;
{
return;
}
void find_value(source, key, value, value_size)
char *source, *key, *value;
int value_size;
{
char ch;
long position = 0; /* position in value */
char *pos =strstr(source, key); /* address into source */
value[0] = '\0'; /* initialize to nothing */
if(NULL == pos)
return;
pos = pos + strlen(key);
ch = *pos;
/* skip leading quotes and spaces */
while((ch == '\"') || (ch == ' ')) {
pos++; ch = *pos;
}
for(position = 0; pos < source + strlen(source); pos++){
if((ch = *pos) == ' ') {
value[position] = '\0';
return;
}
value[position] = ch;
position++;
if(position >= value_size){
value[value_size - 1] = '\0';
return;
}
}
value[position] = '\0';
}
/****/
void ZapTabs(in)
char *in;
{
/** replace tabs with a space... **/
while (*in != '\0') {
if (*in == '\t')
*in = ' ';
in ++;
}
}
/*** Modified from ../ir/ui.c to add \r\n at the ends of the line... ***/
void
Mydisplay_text_record_completely(record,quote_string_quotes, sockfd)
WAISDocumentText *record;
boolean quote_string_quotes;
{
long count;
long ch;
char output[512];
int outputptr = 0;
for(count = 0; count < record->DocumentText->size; count++){
ch = (unsigned char)record->DocumentText->bytes[count];
if(27 == ch){
/* then we have an escape code */
/* if the next letter is '(' or ')', then ignore two letters */
if('(' == record->DocumentText->bytes[count + 1] ||
')' == record->DocumentText->bytes[count + 1])
count += 1; /* it is a term marker */
else count += 4; /* it is a paragraph marker */
}
else if (ch == '\t') /* a TAB! */
output[outputptr++] = ch;
else if (isprint(ch)){
if(quote_string_quotes && ch == '"') {
output[outputptr++] = '/';
output[outputptr++] = '/';
}
output[outputptr++] = ch;
}
else if (ch == '\n' || ch == '\r') {
output[outputptr++] = '\r';
output[outputptr++] = '\n';
}
if (outputptr >500) {
output[outputptr++] = '\0';
writestring(sockfd, output);
outputptr = 0;
}
}
/*** Write out the rest of the buffer... ***/
output[outputptr++] = '\0';
writestring(sockfd, output);
}
/* modified from Jonny G's version in ui/question.c */
void showDiags(d)
diagnosticRecord **d;
{
long i;
for (i = 0; d[i] != NULL; i++) {
if (d[i]->ADDINFO != NULL) {
printf("Code: %s, %s\n", d[i]->DIAG, d[i] ->ADDINFO);
}
}
}
int
acceptable(foo)
char foo;
{
if (foo == '\t' || foo == '\r' || foo == '\n' || foo == '\0')
return(0);
else if (!isprint(foo))
return(0);
else
return(1);
}
static char * hex = "0123456789ABCDEF";
/*
* DocId_to_Gopher transforms a docid into a character string suitable for
* transmission
*/
char *DocId_to_Gopher(docid, docsize)
any *docid;
int docsize;
{
static char GopherString[512];
char *q = GopherString;
char *p;
int l, i;
/** First lets stick on the size of the document first **/
sprintf(GopherString, "%d", docsize);
q += strlen(GopherString);
*q++ = ':';
for (p=docid->bytes; (p < docid->bytes + docid->size) && q<&GopherString[512];) {
if (*p >= 10) {
; /* Bad thing happened, can't understand docid, punt */
return(NULL);
}
*q++ = (*p++) + '0'; /* Record Type */
*q++ = '='; /* Seperate */
l = *p++; /* Length */
for (i=0; i<l; i++, p++) {
if (acceptable(*p)==0) {
*q++ = '%';
*q++ = hex[(*p) >> 4];
*q++ = hex[(*p) & 15];
}
else *q++ = *p;
}
*q++ = ';';
}
*q++ = 0;
return(GopherString);
}
/*
* Gstring is a name produced by DocID_to_Gopher
*/
any *Gopher_to_DocId(Gstring, DocSize)
char *Gstring;
int *DocSize;
{
static any docid;
char *outptr;
char *inptr;
char *sor;
char *eqptr;
char *semiptr;
int size;
/* Strip off the Document size first.... */
inptr = strchr(Gstring, ':');
if (inptr == NULL)
return;
*DocSize = atoi(Gstring);
Gstring = inptr +1;
for (size=0, inptr=Gstring; *inptr; inptr++) {
size ++;
if (*inptr == ';')
size--;
else if (*inptr == '%')
size -=2;
}
docid.size = size;
docid.bytes = (char *) malloc(docid.size);
outptr = docid.bytes;
for (inptr = Gstring; *inptr;) {
*outptr++ = *inptr++ - '0'; /* Record Type */
eqptr = strchr(inptr, '=');
if (!eqptr)
return(0);
semiptr = strchr(inptr, ';');
if (!semiptr)
return(0);
sor = outptr;
outptr++;
for (inptr = eqptr+1; *inptr!=';' ; ) {
if (*inptr == '%') {
char c;
unsigned int b;
inptr++;
c = *inptr++;
b = from_hex(c);
c = *inptr++;
if (!c) break;
*outptr++ = (b<<4) + from_hex(c);
} else {
*outptr++ = *inptr++;
}
}
*sor = (outptr-sor-1);
inptr++;
}
return(&docid);
}
/*-----------------------------------------------------------------*/
/* modified from tracy shen's version in wutil.c
* displays either a text record of a set of headlines.
*/
void
display_search_response(response, hostname, port, dbname, SourceName, sockfd)
SearchResponseAPDU *response;
char *hostname, *port, *dbname, *SourceName;
int sockfd;
{
WAISSearchResponse *info;
long i, k;
struct sockaddr_in serv_addr;
int length = sizeof(serv_addr);
GopherObj *gs = NULL;
GopherDirObj *gd = NULL;
char gopherpath[1024];
gs = GSnew();
gd = GDnew(64);
if ( response->DatabaseDiagnosticRecords != 0 ) {
info = (WAISSearchResponse *)response->DatabaseDiagnosticRecords;
i =0;
if (info->Diagnostics != NULL)
showDiags(info->Diagnostics);
if ( info->DocHeaders != 0 ) {
k =0;
while (info->DocHeaders[k] != 0 ) {
i++;
ZapCRLF(info->DocHeaders[k]->Headline);
ZapTabs(info->DocHeaders[k]->Headline);
GSinit(gs);
GSsetType(gs, '0');
GSsetTitle(gs, info->DocHeaders[k]->Headline);
sprintf(gopherpath, "waisdocid:%s:%s",
SourceName,
DocId_to_Gopher(info->DocHeaders[k]->DocumentID,
info->DocHeaders[k]->DocumentLength));
GSsetPath(gs, gopherpath);
GSsetHost(gs, Zehostname);
GSsetPort(gs, GopherPort);
GDaddGS(gd, gs);
k++;
}
GDtoNet(gd, sockfd);
writestring(sockfd, ".\r\n");
}
if ( info->Text != 0 ) {
k =0;
while ((info->Text[k] != 0) ) {
i++;
printf("\n Text record %2d, ", i);
Mydisplay_text_record_completely( info->Text[k++], false, sockfd);
}
}
}
}
#define MAX_KEYWORDS_LENGTH 1000
#define MAX_SERVER_LENGTH 1000
#define MAX_DATABASE_LENGTH 1000
#define MAX_SERVICE_LENGTH 1000
#define MAXDOCS 40
/******************************************************************/
void SearchRemoteWAIS(sockfd, inputline)
int sockfd;
char *inputline;
{
char* request_message = NULL; /* arbitrary message limit */
char* response_message = NULL; /* arbitrary message limit */
long request_buffer_length; /* how of the request is left */
SearchResponseAPDU *query_response;
SearchResponseAPDU *retrieval_response;
WAISSearchResponse *query_info, *retrieval_info;
char server_name[MAX_SERVER_LENGTH + 1];
char service[MAX_SERVICE_LENGTH + 1];
char database[MAX_DATABASE_LENGTH + 1];
long count;
FILE *connection;
char *keywords;
FILE *Dotsrcfile;
char *SourceName;
char *WaisGatePort=NULL;
Source Moo;
char *cp;
server_name[0] = '\0'; /* null it out */
database[0] = '\0'; /* null it out */
service[0] = '\0'; /* null it out */
/**
** Next load up the name of the source...
*/
cp = strchr(inputline, '\t');
keywords = cp + 1;
if (cp == NULL) {
/** An error occured, probably old client software... **/
writestring(sockfd, ".\r\n");
} else
*cp = '\0';
SourceName= inputline;
Moo = (Source)malloc(sizeof(_Source));
Dotsrcfile = rfopen(SourceName, "r");
if (Dotsrcfile == NULL) {
char tmpstr[256];
sprintf(tmpstr, "File '%s' does not exist", SourceName);
Abortoutput(sockfd, tmpstr), exit(-1);
}
ReadSource(Moo, Dotsrcfile);
strcpy(server_name, Moo->server);
strcpy(database, Moo->database);
strcpy(service, Moo->service);
if (server_name[0] == 0)
connection = NULL;
else if ((connection=connect_to_server(server_name,atoi(service))) == NULL)
{
char Errorstr[256];
sprintf(Errorstr,"Error openning connection to %s via service %s.",
server_name, service);
Abortoutput(sockfd, Errorstr);
exit(-1);
}
request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
{
char userInfo[256];
sprintf(userInfo, "waisgopher %s, from host: %s", VERSION, Zehostname);
init_connection(request_message, response_message,
MAX_MESSAGE_LEN,
connection,
userInfo);
}
request_buffer_length = MAX_MESSAGE_LEN; /* how of the request is left */
if(NULL ==
generate_search_apdu(request_message + HEADER_LENGTH,
&request_buffer_length,
keywords, database, NULL, MAXDOCS))
Abortoutput(sockfd, "request too large");
if(0 ==
interpret_message(request_message,
MAX_MESSAGE_LEN - request_buffer_length,
response_message,
MAX_MESSAGE_LEN,
connection,
false /* true verbose */
)) { /* perhaps the server shut down on us, let's see: */
if ( connection != NULL) {
fclose(connection);
if ((connection=connect_to_server(server_name,atoi(service))) == NULL)
{
char Errorstr[256];
sprintf(Errorstr, "Error openning connection to %s via service %s.\n",
server_name, service);
Abortoutput(sockfd, Errorstr);
}
if(0 ==
interpret_message(request_message,
MAX_MESSAGE_LEN - request_buffer_length,
response_message,
MAX_MESSAGE_LEN,
connection,
false /* true verbose */
))
Abortoutput(sockfd, "really couldn't deliver message");
}
else
Abortoutput("returned message too large");
}
readSearchResponseAPDU(&query_response, response_message + HEADER_LENGTH);
display_search_response(query_response, server_name, service, database, SourceName, sockfd);
freeWAISSearchResponse(query_response->DatabaseDiagnosticRecords);
freeSearchResponseAPDU( query_response);
/*** close it down ***/
close_connection(connection);
s_free(request_message);
s_free(response_message);
}
/*******************************************************/
void
Fetchdocid(sockfd, inputline)
int sockfd;
char *inputline;
{
any *docid;
int DocLen;
int count;
char* request_message = NULL; /* arbitrary message limit */
char* response_message = NULL; /* arbitrary message limit */
long request_buffer_length; /* how of the request is left */
char server_name[MAX_SERVER_LENGTH + 1];
char service[MAX_SERVICE_LENGTH + 1];
char database[MAX_DATABASE_LENGTH + 1];
SearchResponseAPDU *retrieval_response;
FILE *connection;
char *SourceName;
char *WaisGatePort=NULL;
Source Moo;
char *DocIdString;
FILE *Dotsrcfile;
server_name[0] = '\0'; /* null it out */
database[0] = '\0'; /* null it out */
service[0] = '\0'; /* null it out */
DocIdString = strchr(inputline, ':');
if (DocIdString == NULL) {
Abortoutput(sockfd, "Malformed docid");
return;
}
else {
*DocIdString = '\0';
DocIdString++;
}
SourceName = inputline;
Moo = (Source)malloc(sizeof(_Source));
Dotsrcfile = rfopen(SourceName, "r");
if (Dotsrcfile == NULL) {
char tempstr[256];
sprintf(tempstr, "File '%s' does not exist", SourceName);
Abortoutput(sockfd, tempstr);
exit(-1);
}
ReadSource(Moo, Dotsrcfile);
strcpy(server_name, Moo->server);
strcpy(database, Moo->database);
strcpy(service, Moo->service);
if (server_name[0] == 0)
connection = NULL;
else if ((connection=connect_to_server(server_name,atoi(service))) == NULL)
{
char Errorstr[256];
sprintf(Errorstr,"Error openning connection to %s via service %s.",
server_name, service);
Abortoutput(sockfd, Errorstr);
return;
}
request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
docid = Gopher_to_DocId(DocIdString, &DocLen);
/*** First let's transform the first word into a docid ***/
/*** What we need from net: DocumentLength, Types: (TEXT!), docid, **/
for(count = 0;
count * CHARS_PER_PAGE <
DocLen;
count++){
char *type;
/* if(query_info->DocHeaders[1]->Types == NULL)*/
type = s_strdup("TEXT");
/* else
type = s_strdup(query_info->DocHeaders[1]->Types[0]);*/
request_buffer_length = MAX_MESSAGE_LEN; /* how of the request is left */
if(0 ==
generate_retrieval_apdu(request_message + HEADER_LENGTH,
&request_buffer_length,
docid,
CT_byte,
count * CHARS_PER_PAGE,
MIN((count + 1) * CHARS_PER_PAGE,
DocLen),
type,
database
))
panic("request too long");
if(0 ==
interpret_message(request_message,
MAX_MESSAGE_LEN - request_buffer_length,
response_message,
MAX_MESSAGE_LEN,
connection,
false /* true verbose */
)) { /* perhaps the server shut down on us, let's see: */
if ( connection != NULL) {
fclose(connection);
if ((connection=connect_to_server(server_name,atoi(service))) == NULL)
{
fprintf (stderr, "Error openning connection to %s via service %s.\n",
server_name, service);
exit(-1);
}
if(0 ==
interpret_message(request_message,
MAX_MESSAGE_LEN - request_buffer_length,
response_message,
MAX_MESSAGE_LEN,
connection,
false /* true verbose */
))
panic("really couldn't deliver message");
}
else
panic("returned message too large");
}
readSearchResponseAPDU(&retrieval_response,
response_message + HEADER_LENGTH);
/* display_search_response(retrieval_response); the general thing */
if(NULL == ((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text){
display_search_response(retrieval_response);
panic("No text was returned");
}
Mydisplay_text_record_completely
(((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[0], false, sockfd);
}
freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
freeSearchResponseAPDU( retrieval_response);
/*** close it down ***/
close_connection(connection);
s_free(request_message);
s_free(response_message);
writestring(sockfd, ".\r\n");
}
#else /* defined(WAISSEARCH) */
void
SearchRemoteWAIS(sockfd, selstr)
int sockfd;
char *selstr;
{
Abortoutput(sockfd, "No wais stuff in the server!!");
}
void
Fetchdocid(sockfd, selstr)
int sockfd;
char *selstr;
{
Abortoutput(sockfd, "No wais stuff in the server!!");
}
#endif