home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************
- * $Author: lindner $
- * $Revision: 1.1 $
- * $Date: 1992/12/10 23:13:27 $
- * $Source: /home/mudhoney/GopherSrc/release1.11/gopherd/RCS/waisgopher.c,v $
- * $Status: $
- *
- * Paul Lindner, University of Minnesota CIS.
- *
- * Copyright 1991, 1992 by the Regents of the University of Minnesota
- * see the file "Copyright" in the distribution for conditions of use.
- *********************************************************************
- * MODULE: waisgopher.c
- * Routines to translate from gopher protocol to wais protocol
- *********************************************************************
- * Revision History:
- * $Log: waisgopher.c,v $
- * Revision 1.1 1992/12/10 23:13:27 lindner
- * gopher 1.1 release
- *
- *
- *********************************************************************/
-
-
- /* 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 "gopherd.h"
-
- #if defined(_AIX)
- #define ANSI_LIKE
- #endif
-
- #include <ctype.h>
- #include <ui.h>
- #include <docid.h>
-
- #define MAIN
- #define sockets_h
- #include "wais.h"
-
- #define WAISSEARCH_DATE "Fri Sep 13 1991"
-
-
- /**** 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 ++;
- }
- }
-
- void
- Send_binary_record(record, sockfd)
- WAISDocumentText *record;
- int sockfd;
- {
- long count;
- long ch;
- char output[512];
- int outputptr = 0;
-
- writen(sockfd, record->DocumentText->bytes, record->DocumentText->size);
- }
-
-
- /*** 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;
- int sockfd;
- {
- long count;
- unsigned char ch;
- unsigned char output[512];
- int outputptr = 0;
-
- for(count = 0; count < record->DocumentText->size; count++){
-
- ch = (unsigned char)record->DocumentText->bytes[count];
-
- switch (ch) {
-
- case 27:
- /* 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 */
- break;
- case '\t':
- output[outputptr++] = ch;
- break;
- case '\r':
- if ('\n' == record->DocumentText->bytes[count + 1])
- break;
- case '\n':
- if (DEBUG) printf("Got a return\n");
- output[outputptr++] = '\r';
- output[outputptr++] = '\n';
- break;
- default:
- if (isprint(ch)){
- if(quote_string_quotes && ch == '"') {
- output[outputptr++] = '/';
- output[outputptr++] = '/';
- }
- output[outputptr++] = ch;
- }
- }
-
- 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);
-
- GSsetTitle(gs, info->DocHeaders[k]->Headline);
-
- sprintf(gopherpath, "waisdocid:%s:%s:%s",
- SourceName,
- info->DocHeaders[k]->Types[0],
- DocId_to_Gopher(info->DocHeaders[k]->DocumentID,
- info->DocHeaders[k]->DocumentLength));
- GSsetPath(gs, gopherpath);
- GSsetHost(gs, Zehostname);
- GSsetPort(gs, GopherPort);
-
- if (strcmp(info->DocHeaders[k]->Types[0], "TEXT") == 0) {
- GSsetType(gs, A_FILE);
- }
- else if (strcmp(info->DocHeaders[k]->Types[0],"GIF")==0) {
- GSsetType(gs, A_GIF);
- }
- else if (strcmp(info->DocHeaders[k]->Types[0],"PICT")==0) {
- GSsetType(gs, A_IMAGE);
- }
- else if (strcmp(info->DocHeaders[k]->Types[0],"WSRC")==0) {
- GSsetType(gs, A_INDEX);
- }
- else
- GSsetType(gs, A_UNIXBIN);
-
- 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);
- }
- }
- }
- }
-
-
- /*** Find server, database, and service
- *** This routine recognizes the hack where the filename is
- *** (server database service)
- ***/
- MyReadSource(Moo, filename, sockfd)
- Source Moo;
- char *filename;
- int sockfd;
- {
- FILE *dotsrc;
- char *cp;
- if (filename == NULL)
- Abortoutput(sockfd, "No Filename!");
-
- if (*filename == '(' && filename[strlen(filename)-1] == ')') {
- cp = strchr(filename, ' ');
- if (cp==NULL)
- Abortoutput(sockfd, "malformed filename");
- *cp = '\0';
- strcpy(Moo->server, filename+1);
- *cp = ' ';
-
- filename = cp+1;
- cp = strchr(filename, ' ');
- if (cp==NULL)
- Abortoutput(sockfd, "malformed filename");
- *cp = '\0';
- strcpy(Moo->database, filename);
- *cp = ' ';
-
- filename = cp +1;
- filename[strlen(filename)] = '\0';
- strcpy(Moo->service, filename);
- }
- else {
- dotsrc = rfopen(filename, "r");
- if (dotsrc == NULL) {
- char tmpstr[256];
- sprintf(tmpstr, "File '%s' does not exist", filename);
- Abortoutput(sockfd, tmpstr), exit(-1);
- }
-
- ReadSource(Moo, dotsrc);
- fclose(dotsrc);
- }
- }
-
-
-
-
-
-
- #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));
- bzero(Moo, sizeof(_Source));
-
- MyReadSource(Moo, SourceName, sockfd);
- 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(sockfd, "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;
- char *type;
- char *searchwords;
-
- 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++;
- type = DocIdString;
- DocIdString = strchr(type, ':') + 1;
- searchwords = strrchr(DocIdString, '\t');
- if (searchwords != NULL) {
- *(searchwords) = '\0';
- searchwords++;
- }
- }
-
- SourceName = inputline;
-
- Moo = (Source)malloc(sizeof(_Source));
- bzero(Moo, sizeof(_Source));
-
- MyReadSource(Moo, SourceName);
-
- 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++){
-
- 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");
- }
-
- if (strncmp(type, "TEXT", 4) == 0) {
- int k;
- k = 0;
- if (DEBUG) printf("Displaying text\n");
- while (((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[k] != 0) {
- Mydisplay_text_record_completely
- (((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[k++], false, sockfd);
- }
- writestring(sockfd, ".\r\n");
-
- }
- else if (strncmp(type, "WSRC", 4) == 0) {
- char searchline[512];
- char tempfile[64];
- int tempdotsrc;
- Source Moo;
- FILE *Dotsrcfile;
- int k;
-
- /*** It's a search! **/
- if (DEBUG) printf("Searching!\n");
-
- /*** Dump out the contents of the text record on the server ***/
- /*** then call SearchRemoteWAIS(), then delete file ***/
- rchdir("/");
- mkdir("tmp",0755);
- sprintf(tempfile, "/tmp/waissearch.%d", getpid());
- tempdotsrc = ropen(tempfile, O_RDWR|O_CREAT,0755);
- if (tempdotsrc < 0) {
- writestring(sockfd, "3couldn't make temp file\r\n.\r\n");
- return;
- }
- Mydisplay_text_record_completely
- (((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[0], false, tempdotsrc);
- close(tempdotsrc);
-
- Moo = (Source) malloc(sizeof(_Source));
- bzero(Moo, sizeof(_Source));
-
- MyReadSource(Moo, tempfile);
-
- sprintf(searchline, "(%s %s %s)\t%s", Moo->server, Moo->database, Moo->service, searchwords);
-
- if (DEBUG) printf("%s\n", searchline);
- rchdir("/");
- SearchRemoteWAIS(sockfd, searchline);
-
- /* unlink(tempfile);*/
- }
- else {
- int recs =0;
-
- if (DEBUG) printf("Displaying Binary\n");
- while (1) {
- if (((WAISSearchResponse*)retrieval_response->DatabaseDiagnosticRecords)->Text[recs] == NULL)
- break;
- Send_binary_record(((WAISSearchResponse *)retrieval_response->DatabaseDiagnosticRecords)->Text[recs++], sockfd);
- }
- }
- }
-
- freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
- freeSearchResponseAPDU( retrieval_response);
-
- /*** close it down ***/
-
- close_connection(connection);
-
- s_free(request_message);
- s_free(response_message);
-
- }
-
- #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
-