home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / WINWAIS / IR / UI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-07  |  13.6 KB  |  511 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.
  4.  
  5.    Brewster@think.com
  6. */
  7.  
  8. #include <ctype.h>
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <dos.h>
  12.  
  13. #include "ui.h"
  14. #include "sockets.h"
  15.  
  16. #define MAX_TEXT_LENGTH 120
  17.  
  18. extern char db_path[255];
  19. extern int recv_bufsize;
  20. extern int send_bufsize;
  21.  
  22. /* returns a pointer in the buffer of the first free byte.
  23.    if it overflows, then NULL is returned
  24. */
  25.  
  26. char * generate_search_apdu(buff, buff_len, seed_words, database_name,
  27.                             docobjs, maxDocsRetrieved)
  28. char* buff;     /* buffer to hold the apdu */
  29. long *buff_len;    /* length of the buffer changed to reflect new data written */
  30. char *seed_words;    /* string of the seed words */
  31. char *database_name;
  32. DocObj** docobjs;
  33. long maxDocsRetrieved;
  34. {
  35.     /* local variables */
  36.  
  37.     SearchAPDU *search3;
  38.     char  *end_ptr;
  39.     static char *database_names[2] = {
  40.         "", 0            };
  41.     any refID;
  42.     WAISSearch *query;
  43.     refID.size = 1L;
  44.     refID.bytes = "3";
  45.  
  46.     database_names[0] = database_name;
  47.  
  48.     query = makeWAISSearch(seed_words,
  49.       docobjs,                         /* DocObjsPtr */
  50.       0L,
  51.       1L,                              /* DateFactor */
  52.       0L,                              /* BeginDateRange */
  53.       0L,                              /* EndDateRange */
  54.       maxDocsRetrieved);
  55.  
  56.     search3 = makeSearchAPDU(30L,
  57.       5000L, /* should be large */
  58.       30L,
  59.       1L,                              /* replace indicator */
  60.       (long)NULL,                      /* result set name */
  61.       database_names,                  /* database name */
  62.       (long)QT_RelevanceFeedbackQuery, /* query_type */
  63.       0L,                              /* element name */
  64.       (long)NULL,                      /* reference ID */
  65.       query);
  66.  
  67.     end_ptr = writeSearchAPDU(search3, buff, buff_len);
  68.  
  69.     CSTFreeWAISSearch(query);
  70.     freeSearchAPDU(search3);
  71.     return(end_ptr);
  72. }
  73.  
  74.  
  75. /* returns a pointer into the buffer of the next free byte.
  76.    if it overflowed, then NULL is returned
  77.  */
  78.  
  79. char *
  80. generate_retrieval_apdu(buff,
  81. buff_len,
  82. docID,
  83. chunk_type,
  84. start,
  85. end,
  86. type,
  87. database_name)
  88. char *buff;
  89. long *buff_len;    /* length of the buffer changed to reflect new data written */
  90. any *docID;
  91. long chunk_type;
  92. long start;
  93. long end;
  94. char *type;
  95. char *database_name;
  96. {
  97.     SearchAPDU *search;
  98.     char  *end_ptr;
  99.  
  100.     static char *database_names[2];
  101.     static char *element_names[3];
  102.     any refID;
  103.  
  104.     DocObj *DocObjs[2];
  105.     any *query;                 /* changed from char* by brewster */
  106.  
  107.     if(NULL == type)
  108.         type = s_strdup("TEXT");
  109.  
  110.     database_names[0] = database_name;
  111.     database_names[1] = NULL;
  112.  
  113.     element_names[0] = " ";
  114.     element_names[1] = ES_DocumentText;
  115.     element_names[2] = NULL;
  116.  
  117.     refID.size = 1L;
  118.     refID.bytes = "3";
  119.  
  120.     switch(chunk_type){
  121.     case CT_line:
  122.         DocObjs[0] = makeDocObjUsingLines(docID, type, start, end);
  123.         break;
  124.     case CT_byte:
  125.         DocObjs[0] = makeDocObjUsingBytes(docID, type, start, end);
  126.         break;
  127.     }
  128.     DocObjs[1] = NULL;
  129.  
  130.     query = makeWAISTextQuery(DocObjs);
  131.  
  132.     search = makeSearchAPDU( 10L, 16L, 15L,
  133.       1L,  /* replace indicator */
  134.       "FOO", /* result set name */
  135.       database_names, /* database name */
  136.       QT_TextRetrievalQuery, /* query_type */
  137.       element_names, /* element name */
  138.       &refID, /* reference ID */
  139.       query);
  140.  
  141.     end_ptr = writeSearchAPDU(search, buff, buff_len);
  142.     CSTFreeWAISTextQuery(query);
  143.     freeSearchAPDU(search);
  144.     return(end_ptr);
  145. }
  146.  
  147. static boolean isnumber _AP((char* string));
  148.  
  149. static boolean isnumber(string)
  150. char *string;
  151. {
  152.     long count;
  153.     for(count = 0L; count < strlen(string); count++){
  154.         if(!isdigit(string[count])){
  155.             return(false);
  156.         }
  157.     }
  158.     return(true);
  159. }
  160.  
  161.  
  162. /* this will negotiate with server, and returs the maximum buffer size
  163.    the server can handle.
  164. */
  165.  
  166. long init_connection(inBuffer, outBuffer, bufferSize, connection)
  167. char *inBuffer, *outBuffer;
  168. long bufferSize;
  169. SOCKET connection;
  170. {
  171.     InitAPDU* init = NULL;
  172.     InitResponseAPDU* reply = NULL;
  173.     long result;
  174.     /* construct an init */
  175.     init = makeInitAPDU(true,false,false,false,false,bufferSize,bufferSize,
  176.     NULL,defaultImplementationID(),
  177.     defaultImplementationName(),
  178.     defaultImplementationVersion(),NULL,NULL);
  179.     /* write it to the buffer */
  180.     result = (long)(writeInitAPDU(init,inBuffer+HEADER_LENGTH,(long *)&bufferSize) - inBuffer);
  181.     if(result < 0L){
  182.         freeInitAPDU(init);
  183.         return(-1L);
  184.     }
  185.     if (0 == interpret_message(inBuffer,
  186.                           (long)(result - HEADER_LENGTH),
  187.                           outBuffer,
  188.                           bufferSize,
  189.                           connection,
  190.                           false))     /* true verbose */
  191.     {
  192.         /* error making a connection */
  193.         return (-1L);
  194.     }
  195.     if (readInitResponseAPDU(&reply,outBuffer + HEADER_LENGTH) == NULL){
  196.         freeWAISInitResponse((WAISInitResponse*)reply->UserInformationField);
  197.         freeInitResponseAPDU(reply);
  198.         return(-1L);
  199.     }
  200.     if (reply->Result == false)
  201.     {                           /* the server declined service */
  202.         freeWAISInitResponse((WAISInitResponse*)reply->UserInformationField);
  203.         freeInitResponseAPDU(reply);
  204.         return(-1L);
  205.     }
  206.     else                                /* we got a response back */
  207.     {
  208.         result = reply->MaximumRecordSize;
  209.         freeWAISInitResponse((WAISInitResponse*)reply->UserInformationField);
  210.         freeInitResponseAPDU(reply);
  211.         return(result);
  212.     }
  213. }
  214.  
  215. /* this is a safe version of unix 'read' it does all the checking
  216.  * and looping necessary
  217.  * to those trying to modify the transport code to use non-UNIX streams:
  218.  *  This is the function to modify!
  219.  */
  220.  
  221. long read_from_stream(d,buf,nbytes)
  222. SOCKET d;                          /* this is the stream */
  223. char *buf;
  224. long nbytes;
  225. {
  226.  
  227.     int didRead, max;
  228.     int status;
  229.     
  230.     long totalRead = 0;
  231.     unsigned long toRead = nbytes;
  232.  
  233.     while(toRead > 0)
  234.     {
  235.       didRead = 0;
  236.       max = toRead < recv_bufsize ? toRead : recv_bufsize;
  237.           
  238.       if (SOCKET_ERROR == (didRead = recv(d, buf, max, 0)))
  239.       {
  240.         msgbox("RECV Error: %d");
  241.         return(-1);
  242.       }  
  243.       
  244.       buf[didRead] = '\0';
  245.       toRead -= didRead;
  246.       buf += didRead;
  247.       totalRead += didRead;
  248.     }
  249.  
  250.     if(totalRead != nbytes)     /* we overread for some reason */
  251.         return(- totalRead);    /* bad news */
  252.  
  253.     return(totalRead);
  254. }
  255.  
  256. /* returns the length of the response, 0 if an error */
  257.  
  258. long
  259. transport_message(connection, request_message, request_length, response_message, response_buffer_length)
  260. SOCKET connection;
  261. char *request_message;
  262. long request_length;
  263. char *response_message;
  264. long response_buffer_length;
  265. {
  266.  
  267.     WAISMessage header;
  268.     long response_length;
  269.     int didSend, max;
  270.     char bf[20];
  271.     FILE *fp;
  272.  
  273.     int status;
  274.  
  275.     long toSend = request_length + HEADER_LENGTH;
  276.     long totalSend = 0;
  277.     
  278.     /* Write out message. Read back header. Figure out response length. */
  279.       
  280.     while (toSend > 0)
  281.     {
  282.       max = toSend < send_bufsize ? toSend : send_bufsize;
  283.       if (SOCKET_ERROR == (didSend = send(connection, request_message, max, 0)))
  284.       {
  285.         msgbox("SEND Error: %d");
  286.         return(0L);
  287.       }
  288.       toSend -= didSend;
  289.       request_message += didSend;
  290.       totalSend += didSend;
  291.     }
  292.       
  293.     if (request_length + HEADER_LENGTH != totalSend)
  294.       return 0L;
  295.  
  296.     /* read for the first '0' */
  297.     
  298.     while(1)
  299.     {    
  300.       if(0L > read_from_stream(connection, response_message, 1L))
  301.         return 0L;
  302.       if('0' == response_message[0])
  303.         break;
  304.     }
  305.  
  306.     if(0L > read_from_stream(connection,
  307.                              response_message + 1,
  308.                              (long)(HEADER_LENGTH - 1L)))
  309.       return 0L;
  310.       
  311.     readWAISPacketHeader(response_message, &header);
  312.     {
  313.       char length_array[11];
  314.       strncpy(length_array, header.msg_len, 10);
  315.       length_array[10] = '\0';
  316.       response_length = atol(length_array);
  317.       if(response_length > response_buffer_length)
  318.       {       
  319.         /* we got a message that is too long, 
  320.            therefore empty the message out,
  321.            and return 0 
  322.         */
  323.         long i;
  324.         for(i = 0L; i < response_length; i++)
  325.         {      
  326.           read_from_stream(connection,
  327.                            response_message + HEADER_LENGTH,
  328.                            1L);
  329.         }
  330.         return(0L);
  331.       }
  332.     }
  333.       
  334.     if(0L > read_from_stream(connection,
  335.                             response_message + HEADER_LENGTH,
  336.                             response_length))
  337.       return 0L;
  338.     
  339.     return(response_length);
  340. }
  341.  
  342. /* returns the number of bytes writeen.  0 if an error */
  343. long
  344. interpret_message(request_message,request_length, response_message, response_buffer_length, connection, verbose)
  345. char *request_message;
  346. long request_length; /* length of the buffer */
  347. char *response_message;
  348. long response_buffer_length;
  349. SOCKET connection;
  350. boolean verbose;
  351. {
  352.     long response_length;
  353.  
  354.     writeWAISPacketHeader(request_message,
  355.                           request_length,
  356.                           (long)'z',            /* Z39.50 */
  357.                           "wais      ",         /* server name */
  358.                           (long)NO_COMPRESSION, /* no compression */
  359.                           (long)NO_ENCODING,
  360.                           (long)HEADER_VERSION);
  361.  
  362.     if(connection != NULL) 
  363.     {
  364.       if(0L == (response_length = transport_message(connection, 
  365.                                                     request_message,
  366.                                                     request_length,
  367.                                                     response_message,
  368.                                                     response_buffer_length)))
  369.         return(0L);
  370.     }
  371.     else
  372.     {
  373.         return(0L);
  374.     }
  375.     
  376.     return(response_length);
  377. }
  378.  
  379. /* this closes the connection to the socket.
  380.  * the mythology is that this is cleaner than exiting
  381.  */
  382.  
  383. long close_connection(connection)
  384. SOCKET connection;
  385. {
  386. //    if(connection != NULL)
  387. //    {
  388. //      sock_close(connection);
  389. //      return(-1L);
  390. //    }
  391.  
  392.     return(0L);
  393. }
  394.  
  395.  
  396. save_text_record_completely(record,quote_string_quotes,fp,entry_no)
  397. WAISDocumentText *record;
  398. boolean quote_string_quotes;
  399. FILE *fp;
  400. long entry_no;
  401. {
  402.  
  403.     static long lcnt;
  404.     long count;
  405.  
  406.     if (entry_no == 0)
  407.       lcnt = 0;
  408.  
  409.     for(count = 0L; count < record->DocumentText->size; count++){
  410.  
  411.         unsigned char ch = (unsigned char)record->DocumentText->bytes[count];
  412.         if(27 == ch)
  413.         {
  414.             if('(' == record->DocumentText->bytes[count + 1L] ||
  415.                 ')' == record->DocumentText->bytes[count + 1L])
  416.                 count += 1L;             /* it is a term marker */
  417.             else count += 4L;          /* it is a paragraph marker */
  418.         }
  419.         else if (ch == '\t') /* a TAB! */
  420.         {
  421.             putc(0x20, fp);    /* change it to a space */
  422.             lcnt++;
  423.         }
  424.         else if (isprint(ch))
  425.         {
  426.             if(quote_string_quotes && ch == '"')
  427.             {
  428.                 putc('\\', fp);
  429.                 lcnt++;
  430.             }
  431.             putc(ch, fp);
  432.             lcnt++;
  433.         }
  434.         else if (ch == '\n' || ch == '\r')
  435.         {
  436.           lcnt = lcnt % MAX_TEXT_LENGTH;
  437.           for ( ; lcnt < MAX_TEXT_LENGTH; lcnt++)
  438.             putc(0x20,fp);
  439.           lcnt = 0;
  440.         }
  441.     }
  442. }
  443.  
  444. save_binary_record_completely(record,fp)
  445. WAISDocumentText *record;
  446. FILE *fp;
  447. {
  448.  
  449.     long count;
  450.     
  451.     for(count = 0L; count < record->DocumentText->size; count++)
  452.     {
  453.       putc((unsigned char)record->DocumentText->bytes[count],fp);
  454.     }
  455. }
  456.  
  457. /* modifies the string to exclude all seeker codes. sets length to
  458.    the new length. */
  459.  
  460. char *delete_seeker_codes(string,length)
  461. char *string;
  462. long *length;
  463. {
  464.     long original_count; /* index into the original string */
  465.     long new_count = 0L; /* index into the collapsed string */
  466.     for(original_count = 0L; original_count < *length; original_count++){
  467.         if(27 == string[original_count]){
  468.             /* then we have an escape code */
  469.             /* if the next letter is '(' or ')', then ignore two letters */
  470.             if('(' == string[original_count + 1] ||
  471.                 ')' == string[original_count + 1])
  472.                 original_count += 1;    /* it is a term marker */
  473.             else original_count += 4; /* it is a paragraph marker */
  474.         }
  475.         else string[new_count++] = string[original_count];
  476.     }
  477.     *length = new_count;
  478.     return(string);
  479. }
  480.  
  481. /* returns a pointer to a string with good stuff */
  482.  
  483. char *trim_junk(headline)
  484. char *headline;
  485. {
  486.     long length = strlen(headline) + 1; /* include the trailing null */
  487.     long i;
  488.     headline = delete_seeker_codes(headline, &length);
  489.     /* delete leading spaces */
  490.     for(i=0L; i < strlen(headline); i++){
  491.         if(isprint(headline[i])){
  492.             break;
  493.         }
  494.     }
  495.     
  496.     headline = headline + i;
  497.     
  498.     /* delete trailing stuff */
  499.     if (strlen(headline) > 0)
  500.     {
  501.       for(i=strlen(headline) - 1 ; i > 0; i--)
  502.       {
  503.         if(isprint(headline[i]))
  504.           break;
  505.         headline[i] = '\0';
  506.       }
  507.     }
  508.     return(headline);
  509. }
  510.  
  511.