home *** CD-ROM | disk | FTP | other *** search
/ Internet Publisher's Toolbox 2.0 / Internet Publisher's Toolbox.iso / internet / ntserver / wtsource / waislook.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-22  |  14.3 KB  |  473 lines

  1. /*
  2.  *  waislook.c
  3.  *
  4.  *  WAIS search driver.  Based on John Franks' WAISGN program.
  5.  *
  6.  *  (C) Copyright 1994 The University Court of the University of Edinburgh
  7.  *  (C) Copyright 1994 John Franks
  8.  *
  9.  *  Author:  Chris Adie <C.J.Adie@ed.ac.uk> 
  10.  *
  11.  */
  12.  
  13. /******************************************************************************/
  14. /* INCLUDE FILES                                                              */
  15. /******************************************************************************/
  16.  
  17. #include <stdio.h>
  18. #include <io.h>
  19. #include <ctype.h>
  20. #include <string.h>
  21. #include <math.h>
  22. #include "cutil.h"   
  23. #include "irext.h"
  24. #include "irsearch.h"
  25. #include "docid.h"
  26. #include "irtfiles.h"
  27. #include "waisgn.h"
  28. #include "version.h"
  29.  
  30. /******************************************************************************/
  31. /* CONSTANT DEFINITIONS                                                       */
  32. /******************************************************************************/
  33.  
  34. /* This section deliberately left blank */
  35.  
  36. /******************************************************************************/
  37. /* MACRO FUNCTION DEFINITIONS                                                 */
  38. /******************************************************************************/
  39.  
  40.  
  41. /******************************************************************************/
  42. /* TYPE DEFINITIONS                                                           */
  43. /******************************************************************************/
  44.  
  45. /* This section deliberately left blank */
  46.  
  47. /******************************************************************************/
  48. /* GLOBAL VARIABLES AND FUNCTIONS IMPORTED                                    */
  49. /******************************************************************************/
  50.  
  51. /* The following are defined in irsearch.c */
  52. extern boolean search_for_words(char *words,database *db,long doc_id,char *words_used);
  53. extern long next_best_hit(hit *besthit,database *db);
  54. extern char FileTypeFromTable(char *FileName);
  55.  
  56. /******************************************************************************/
  57. /* GLOBAL VARIABLES EXPORTED                                                  */
  58. /******************************************************************************/
  59.  
  60. /* char *log_file_name = NULL; */
  61.  
  62. /******************************************************************************/
  63. /* VARIABLES PRIVATE TO THIS FILE                                             */
  64. /******************************************************************************/
  65.  
  66. static char     host[MIDLEN] = "";
  67. static char     dbname[MIDLEN] = "index";
  68. static char     gntype[SMALLLEN] = "7w";
  69. static char     words[MAXLEN] = "";
  70. static char     gntitle[MAXLEN] = "";
  71. static char     port[SMALLLEN] = "";
  72. static char     virtpath[MAXLEN] = "";
  73.  
  74. static FILE *dfp = stderr;
  75.  
  76. static FILE *logfile = NULL;
  77.  
  78. static enum {interactive, http, gopher} mode = interactive;
  79.  
  80. static int    usedir = FALSE;
  81. static int    userange = FALSE;
  82. static int    is0h = FALSE;
  83. static int    debug = FALSE;
  84.  
  85. static double MaxRawScore = 0.0;
  86.  
  87. /******************************************************************************/
  88. /* FUNCTIONS PRIVATE TO THIS FILE                                             */
  89. /******************************************************************************/
  90.  
  91. /*
  92.  *  Change backslashes in the path to forward slashes, and then apply the URL
  93.  *  character escaping rules.
  94.  */
  95. static void EscapeURL(char *path) {
  96. char   *cp;
  97. char   *cp2;
  98. char   buf[BUFSIZE];
  99.  
  100.     /* Change backslashes to forward slashes */
  101.     cp = path;
  102.     while (*cp) {
  103.         if (*cp=='\\') {
  104.             *cp = '/';
  105.         }
  106.         cp++;
  107.     }
  108.     /* Apply character escaping rules */
  109.     cp = path;
  110.     cp2 = buf;
  111.     while ( *cp ) {
  112.         switch (*cp) {
  113.         case ',':
  114.         case ';':
  115.         case '"':
  116.         case '\'':
  117.         case '&':
  118.         case '=':
  119.         case '(':
  120.         case ')':
  121.         case '{':
  122.         case '}':
  123.         case '%':
  124.         case ' ':
  125.             sprintf( cp2, "%%%X", (int) *cp);
  126.             cp2 += 3;
  127.             cp++;
  128.             break;
  129.         default:
  130.             *cp2++ = *cp++;
  131.         }
  132.     }
  133.     *cp2 = '\0';
  134.     strcpy(path,buf);
  135. }
  136.  
  137.  
  138. /*
  139.  *  For a particular match, produce output according to the selected protocol.
  140.  */
  141. static void doline(hit * match) {
  142. int score;
  143. int size;
  144. char    *cp,
  145.         *relpath,
  146.         type1,
  147.         typebuf[MIDLEN],
  148.         pathbuf[MAXLEN],
  149.         relpathbuf[MAXLEN],
  150.         name[MAXLEN];
  151.  
  152.     strcpy( pathbuf, match->filename);
  153.     relpath = pathbuf;
  154.  
  155.     strcpy( relpathbuf, relpath);
  156.  
  157.     strcpy( name, match->headline);
  158.     cp = name;
  159.     while ( *cp) {
  160.         if ( isspace(*cp))
  161.             *cp = ' ';
  162.         cp++;
  163.     }
  164.  
  165.     if (MaxRawScore>0.0) {
  166.         score = (int)((match->weight / MaxRawScore) * 1000.0);
  167.     } else {
  168.         score = 0;
  169.     }
  170.  
  171.     size = match->end_character-match->start_character;
  172.  
  173.         if ( userange) {
  174.             type1 = '0';
  175.             sprintf( typebuf, "R%ld-%ld-%range",
  176.                 match->start_character, match->end_character);
  177.         }
  178.  
  179.         else if ( *(match->type) == 'D') {  /* DVI type */
  180.             type1 = '9';
  181.             strcpy( typebuf, "9");
  182.         }
  183.         else if ( is0h) {  /* 0h type */
  184.             type1 = '0';
  185.             strcpy( typebuf, "0h");
  186.         }
  187.         else if ( usedir) {  /* Return directory containing file */
  188.             type1 = '1';
  189.             strcpy( typebuf, "1");
  190.         }
  191.         else {
  192.             type1 = '0';
  193.             strcpy( typebuf, "0");
  194.             if (mode==gopher) {
  195.                 type1 = FileTypeFromTable(relpathbuf);
  196.                 typebuf[0] = type1;
  197.                 typebuf[1] = '\0';
  198.             }            
  199.         }
  200.  
  201.     if (mode==http) {
  202.         EscapeURL(relpathbuf);
  203.         printf("<li> <a href=\"http://%s:%s", host, port);
  204.         if (virtpath[0]!='\0') {
  205.             printf("/%s",virtpath);
  206.         }
  207.         printf("/%s\">%s</a><BR>(Score=%d, Size=%d)\n", relpathbuf, name, score, size);
  208.     } else
  209.     if (mode==gopher) {
  210.         printf("%c%s\t%s\\%s\t%s\t%s\r\n",type1, name, typebuf, relpathbuf, host, port);
  211.     } else {
  212.         printf("%s %s\n",relpathbuf,name);
  213.     }
  214. }
  215.  
  216.  
  217.  
  218. int senderr(char *msg) {
  219.     if (mode==http) {
  220.         printf( "<HEAD> <TITLE>%s</TITLE> </HEAD>\n", msg);
  221.         printf( "<BODY><HR><H2>%s</H2>\n", msg );
  222.         printf( "Sorry, an error has occurred in");
  223.         printf( " the WAIS index search.\n<HR></BODY>\n");
  224.     } else
  225.     if (mode==gopher) {
  226.         printf( "3Server error: %s\t\terror.host\t0\r\n.\r\n", msg);
  227.     } else {
  228.         printf("An error has occurred in the search: %s\n",msg);
  229.     }
  230.     return 0;
  231. }
  232.  
  233.  
  234. static void httpintro(void) {
  235.     printf( "<HEAD> <TITLE>%s</TITLE> </HEAD>\n", gntitle);
  236.     printf( "<BODY><HR><H2>%s</H2>\n", gntitle);
  237.     printf( "The following items were returned as matches\n");
  238.     printf( "for <B>`%s'</B> by the WAIS index search.\n", words);
  239.     printf( "They are ordered with the best matches first.\n");
  240.     printf( "<P>\n<UL>\n", words);
  241. }
  242.  
  243.  
  244. static void toobad(char *CatalogURL) {
  245.     printf( "<HEAD> <TITLE>%s</TITLE> </HEAD>\n", gntitle);
  246.     printf( "<BODY><HR><H2>%s</H2>\n", gntitle);
  247.     printf( "Sorry, no matches for <B>`%s'</B> were returned\n", words);
  248.     printf( "by the WAIS index search.  You may try again with\n");
  249.     printf( "different search terms.\n <ISINDEX> \n");
  250.     printf( "<p>The <a href=\"%s\">catalog of this WAIS database</a>\n",CatalogURL);
  251.     printf( "may be helpful.</BODY>\n");
  252. }
  253.  
  254. /*
  255.  * This function is based very loosely on a function of the same
  256.  * name in Don Gilbert's Go_Ask_WAIS utility.  I am very grateful
  257.  * for the help in dealing with WAIS that his routine has provided
  258.  * provided and for his kind permission to use it here.  Any errors are
  259.  * mine and not Don's.  JMF
  260.  */
  261. static void AskWais(char *SearchWords,int maxhits) {
  262. database        *db;
  263. long            i;
  264. query_parameter_type    parameters;
  265. boolean         searchResult;
  266. hit             theHit;
  267. char            CatalogURL[MAXLEN];
  268. char            *p;
  269.           
  270.     if ( debug)
  271.         fprintf( dfp, "Opening data base %s\n", dbname);
  272.     strcpy(CatalogURL, dbname);
  273.     strcat(CatalogURL, dictionary_ext);
  274.     if (_access(CatalogURL, 0) == -1) {
  275.         senderr( "The database does not exist\n");
  276.         exit( 2);
  277.     }    
  278.     if ( (db = openDatabase(dbname, false, true)) == (database *) NULL) {
  279.         senderr( "Failed to open database\n");
  280.         exit( 2);
  281.     }
  282.  
  283.     parameters.max_hit_retrieved = ((maxhits > 0) ? maxhits : 256);
  284.     set_query_parameter(SET_MAX_RETRIEVED_MASK, ¶meters);
  285.     searchResult = search_for_words(SearchWords, db, 0, NULL);
  286.  
  287.     /* Initialise the maximum raw hit weight */
  288.     MaxRawScore = 0.0;
  289.     
  290.     if (searchResult == true) {
  291.         finished_search_word(db);
  292.         if ( debug)
  293.             fprintf( dfp, "Dbase search successful\n");
  294.  
  295.         if (next_best_hit(&theHit, db) != 0) {
  296.             if ( debug)
  297.                 fprintf( dfp, "Headline = %s\n",
  298.                     theHit.headline);
  299.             if (mode==http) {
  300.                 /* Generate the (relative) URL of the catalog. */
  301.                 p = strrchr(dbname,'\\');
  302.                 if (p==NULL) p = dbname; else p++;
  303.                 strncpy(CatalogURL,p,sizeof(CatalogURL));
  304.                 strncat(CatalogURL,".cat",sizeof(CatalogURL));
  305.                 EscapeURL(CatalogURL);
  306.                 toobad(CatalogURL);
  307.             } else
  308.             if (mode==gopher) {
  309.                 printf( ".\r\n");
  310.             } else {
  311.                 printf("No match found\n");
  312.             }
  313.             finished_best_hit(db);
  314.             closeDatabase(db);
  315.             return;
  316.         }
  317.  
  318.         if (mode==http) {
  319.             httpintro();
  320.         }
  321.  
  322.         i = 1;
  323.         do {
  324.             if (theHit.weight > 0) {
  325.                 if (MaxRawScore<=0.0) {
  326.                     MaxRawScore = theHit.weight;
  327.                 }
  328.                 doline(&theHit);
  329.             }
  330.             i++;
  331.         } while ( i < parameters.max_hit_retrieved  && 
  332.             (next_best_hit(&theHit, db) == 0));
  333.  
  334.         if (mode==http) {
  335.             printf( "</ul>\n<P>You may repeat your search with\n");
  336.             printf( "a new search term. <P> <ISINDEX></BODY>\n");
  337.         }
  338.     } else {
  339.         senderr( "The database search failed.");
  340.         exit( 2);
  341.     }
  342.     finished_best_hit(db);
  343.     closeDatabase(db);
  344.     return;
  345. }
  346.  
  347.  
  348. /******************************************************************************/
  349. /* GLOBAL FUNCTIONS EXPORTED                                                  */
  350. /******************************************************************************/
  351.  
  352. /*
  353.  *  The main program.
  354.  */
  355. int main(int argc,char *argv[]) {
  356. char *cp;
  357. int i;
  358.     
  359.     if (argc<=1) {
  360.         /* No arguments */
  361.         printf("Usage: %s [-d dbname] [-h host] [-p port] [-debug]\n",argv[0]);
  362.         printf("       [-http|-gopher] [-t title] [-q virtpath] [-v] search words ...\n");
  363.         exit(0);
  364.     }
  365.  
  366.     /* Collect the arguments */
  367.     for (i=1;i<argc;i++) {        
  368.  
  369.         if (strcmp(argv[i],"-debug")==0) {
  370.             debug = TRUE;
  371.         } else
  372.         if (strcmp(argv[i],"-h")==0) {
  373.             strncpy(host,argv[++i],sizeof(host));
  374.         } else
  375.         if (strcmp(argv[i],"-p")==0) {
  376.             strncpy(port,argv[++i],sizeof(port));
  377.         } else
  378.         if (strcmp(argv[i],"-d")==0) {
  379.             strncpy(dbname,argv[++i],sizeof(dbname));
  380.             /* Strip off trailing extension if any */
  381.             cp = strrchr(dbname,'\\');
  382.             if (cp==NULL) {
  383.                 cp = dbname;
  384.             }
  385.             cp = strrchr(cp,'.');
  386.             if (cp!=NULL) {
  387.                 *cp = '\0';
  388.             }
  389.         } else
  390.         if (strcmp(argv[i],"-t")==0) {
  391.             strncpy(gntitle,argv[++i],sizeof(gntitle));
  392.         } else
  393.         if (strcmp(argv[i],"-v")==0) {
  394. #ifdef WIN32
  395.             printf("%s\n",VERWIN32);
  396.             if (argc == 2)
  397.               exit(0);
  398. #endif
  399.         } else
  400.         if (strcmp(argv[i],"-http")==0) {
  401.             mode = http;
  402.         } else
  403.         if (strcmp(argv[i],"-gopher")==0) {
  404.             mode = gopher;
  405.         } else
  406.         if (strcmp(argv[i],"-q")==0) {
  407.             strncpy(virtpath,argv[++i],sizeof(virtpath));
  408.         } else
  409.         if (argv[i][0]=='-') {
  410.             printf("Unknown option %s\n",argv[i]);
  411.             exit(0);
  412.         } else {
  413.             /* Remaining arguments are the words to search for. */
  414.             *words =  '\0';
  415.             while( i < argc) {
  416.                 strncat(words, argv[i], sizeof(words));
  417.                 if ( i < argc - 1 ) {
  418.                     /* Single space between words */
  419.                     strncat(words, " ",sizeof(words));
  420.                 }
  421.                 i++;
  422.             }
  423.         }
  424.  
  425.     }
  426.  
  427.     if ( debug) {
  428.         fprintf( dfp, "Database: %s\n", dbname);
  429.         if (*host) fprintf( dfp, "Host: %s\n", host);
  430.         if (*port) fprintf( dfp, "Port: %s\n", port);
  431.         fprintf( dfp, "Type: %s\n", gntype);
  432.         if (*gntitle) fprintf( dfp, "Title: %s\n", gntitle);
  433.         switch (mode) {
  434.             case interactive: cp = "interactive"; break;
  435.             case http: cp = "http"; break;
  436.             case gopher: cp = "gopher"; break;
  437.             default: cp = "unknown";
  438.         }
  439.         fprintf( dfp, "Protocol: %s\n", cp);
  440.         fprintf( dfp, "Search term: %s\n", words);
  441.     }
  442.  
  443.     /*
  444.      * gntype is "7w", "7wr", or "7wh" according to whether 
  445.      * it is plain text, a range, or type 0h.
  446.      * If "7w" has a 'd' appended it means that instead
  447.      * of returning the selector of the file matched, the selector of
  448.      * the directory containing it should be returned.  It can also
  449.      * be "7wd" indicating that the search should return
  450.      * the directory containing the matching item rather than the
  451.      * item itself.
  452.      */
  453.  
  454.     switch ( gntype[2]) {
  455.     case 'd':
  456.         usedir = TRUE;
  457.         break;
  458.     case 'r':
  459.         userange = TRUE;
  460.         break;
  461.     case 'h':
  462.         is0h = TRUE;
  463.         break;
  464.     }
  465.  
  466.     AskWais( words, MAXHITS_RETURNED);
  467.  
  468.     return 0;
  469. }
  470.  
  471.  
  472.  
  473.