HTWSRC.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:11k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /*        HTWSRC.c
  2. ** PARSE WAIS SOURCE FILE
  3. **
  4. ** (c) COPYRIGHT MIT 1995.
  5. ** Please first read the full copyright statement in the file COPYRIGH.
  6. **
  7. ** This module parses a stream with WAIS source file
  8. ** format information on it and creates a structured stream.
  9. ** That structured stream is then converted into whatever.
  10. **
  11. ** 3 Jun 93 Bug fix: Won't crash if no description
  12. ** 8 Jul 94  FM Insulate free() from _free structure element.
  13. */
  14. /* Library include files */
  15. #include "tcp.h"
  16. #include "HTUtils.h"
  17. #include "HTString.h"
  18. #include "HTMLPDTD.h"
  19. #include "HTMLGen.h"
  20. #include "HTParse.h"
  21. #include "HTReqMan.h"
  22. #include "HTProxy.h"
  23. #include "HTWSRC.h"  /* Implemented here */
  24. #define BIG 10000 /* Arbitrary limit to value length */
  25. #define PARAM_MAX BIG
  26. #define CACHE_PERIOD (7*86400) /* Time to keep .src file in seconds */
  27. #define HEX_ESCAPE '%'
  28. struct _HTStructured {
  29. CONST HTStructuredClass * isa;
  30. /* ... */
  31. };
  32. #define PUTC(c) (*me->target->isa->put_character)(me->target, c)
  33. #define PUTS(s) (*me->target->isa->put_string)(me->target, s)
  34. #define START(e) (*me->target->isa->start_element)(me->target, e, 0, 0)
  35. #define END(e) (*me->target->isa->end_element)(me->target, e)
  36. /* Here are the parameters which can be specified in a  source file
  37. */
  38. PRIVATE CONST char* par_name[] = {
  39. "version", 
  40. "ip-address",
  41. #define PAR_IP_NAME 2
  42. "ip-name", 
  43. #define PAR_TCP_PORT 3
  44. "tcp-port", 
  45. #define PAR_DATABASE_NAME 4
  46. "database-name",
  47. #define PAR_COST 5
  48. "cost", 
  49. #define PAR_COST_UNIT 6
  50. "cost-unit", 
  51. #define PAR_FREE 7
  52. "free",
  53. #define PAR_MAINTAINER 8
  54. "maintainer", 
  55. #define PAR_DESCRIPTION 9
  56. "description",
  57. "keyword-list", 
  58. "source",
  59. #define PAR_UNKNOWN 12
  60. "unknown",
  61. 0, /* Terminate list */
  62. #define PAR_COUNT 13
  63. } ;
  64. #if 0
  65. PRIVATE  CONST char * hex = "0123456789ABCDEF";
  66. #endif
  67. enum tokenstate { beginning, before_tag, colon, before_value,
  68. value, bracketed_value, quoted_value, escape_in_quoted, done };
  69. /* Stream Object
  70. ** ------------
  71. **
  72. ** The target is the structured stream down which the
  73. ** parsed results will go.
  74. **
  75. ** all the static stuff below should go in here to make it reentrant
  76. */
  77. struct _HTStream {
  78. CONST HTStreamClass * isa;
  79. HTStructured * target;
  80. HTRequest * request;
  81. char * par_value[PAR_COUNT];
  82. enum tokenstate  state;
  83. char  param[BIG+1];
  84. int param_number;
  85. int param_count;
  86. };
  87. #if 0
  88. /* Decode one hex character
  89. */
  90. PRIVATE char from_hex (char c)
  91. {
  92.     return    (c>='0')&&(c<='9') ? c-'0'
  93. : (c>='A')&&(c<='F') ? c-'A'+10
  94. : (c>='a')&&(c<='f') ? c-'a'+10
  95. :        0;
  96. }
  97. #endif
  98. /* State machine
  99. ** -------------
  100. **
  101. ** On entry,
  102. ** me->state is a valid state (see WSRC_init)
  103. ** c is the next character
  104. ** On exit,
  105. **  returns 1 Done with file
  106. ** 0 Continue. me->state is updated if necessary.
  107. ** -1 Syntax error error
  108. */
  109. /* Treat One Character
  110. ** -------------------
  111. */
  112. PRIVATE int WSRCParser_put_character (HTStream* me, char c)
  113. {
  114.     switch (me->state) {
  115.     case beginning:
  116.         if (c=='(') me->state = before_tag;
  117. break;
  118.     case before_tag:
  119.         if (c==')') {
  120.     me->state = done;
  121.     return HT_OK; /* Done with input file */
  122. } else if (c==':') {
  123.     me->param_count = 0;
  124.     me->state = colon;
  125. } /* Ignore other text */
  126. break;
  127.     case colon:
  128.         if (WHITE(c)) {
  129.     me->param[me->param_count++] = 0; /* Terminate */
  130.     for(me->param_number = 0; par_name[me->param_number]; me->param_number++) {
  131. if (0==strcmp(par_name[me->param_number], me->param)) {
  132.     break;
  133. }
  134.     }
  135.     if (!par_name[me->param_number]) { /* Unknown field */
  136.         if (WWWTRACE) TTYPrint(TDEST,
  137.     "HTWSRC: Unknown field `%s' in source filen",
  138.     me->param);
  139. me->param_number = PAR_UNKNOWN;
  140. me->state = before_value; /* Could be better ignore */
  141. return HT_OK;
  142.     }
  143.     me->state = before_value;
  144. } else {
  145.     if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  146. }
  147. break;
  148.     case before_value:
  149.         if (c==')') {
  150.     me->state = done;
  151.     return HT_OK; /* Done with input file */
  152. }
  153. if (WHITE(c)) return HT_OK; /* Skip white space */
  154. me->param_count = 0;
  155. if (c=='"') {
  156.     me->state = quoted_value;
  157.     break;
  158. }
  159. me->state = (c=='"') ? quoted_value : 
  160.     (c=='(') ? bracketed_value : value;
  161. me->param[me->param_count++] = c; /* Don't miss first character */
  162. break;
  163.     case value:
  164.         if (WHITE(c)) {
  165.     me->param[me->param_count] = 0;
  166.     StrAllocCopy(me->par_value[me->param_number], me->param);
  167.     me->state = before_tag;
  168. } else {
  169.     if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  170. }
  171. break;
  172.     case bracketed_value:
  173.         if (c==')') {
  174.     me->param[me->param_count] = 0;
  175.     StrAllocCopy(me->par_value[me->param_number], me->param);
  176.     me->state = before_tag;
  177.     break;
  178. }
  179.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  180. break;
  181.     case quoted_value:
  182.         if (c=='"') {
  183.     me->param[me->param_count] = 0;
  184.     StrAllocCopy(me->par_value[me->param_number], me->param);
  185.     me->state = before_tag;
  186.     break;
  187. }
  188. if (c=='\') { /* Ignore escape but switch state */
  189.     me->state = escape_in_quoted;
  190.     break;
  191. }
  192. /* Fall through! */
  193.     case escape_in_quoted:
  194.         if (me->param_count < PARAM_MAX)  me->param[me->param_count++] = c;
  195. break;
  196.     case done: /* Ignore anything after EOF */
  197. return HT_OK;
  198.     } /* switch me->state */
  199.     return HT_OK;
  200. }
  201. /* Open Cache file
  202. ** ===============
  203. **
  204. **   Bugs: Maybe for filesystem-challenged platforms (MSDOS for example) we
  205. **   should make a hash code for the filename.
  206. */
  207. #ifdef CACHE_FILE_PREFIX
  208. PRIVATE BOOL write_cache (HTStream * me)
  209. {
  210.     FILE * fp;
  211.     char cache_file_name[256];
  212.     char * www_database;
  213.     if (!me->par_value[PAR_DATABASE_NAME]
  214.      || !me->par_value[PAR_IP_NAME]
  215. ) return NO;
  216.     
  217.     www_database = HTEscape(me->par_value[PAR_DATABASE_NAME], URL_XALPHAS);
  218.     sprintf(cache_file_name, "%sWSRC-%s:%s:%.100s.txt",
  219.      CACHE_FILE_PREFIX,
  220. me->par_value[PAR_IP_NAME],
  221. me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT] : "210",
  222. www_database);
  223.     HT_FREE(www_database);
  224.     fp = fopen(cache_file_name, "wb");
  225.     if (!fp) return NO;
  226.     
  227.     if (me->par_value[PAR_DESCRIPTION])
  228.         fputs(me->par_value[PAR_DESCRIPTION], fp);
  229.     else 
  230.         fputs("Description not availablen", fp);
  231.     fclose(fp);
  232.     return YES;
  233. }
  234. #endif
  235. /* Output equivalent HTML
  236. ** ----------------------
  237. **
  238. */
  239. void give_parameter (HTStream * me, int p)
  240. {
  241.     PUTS(par_name[p]);
  242.     if (me->par_value[p]) {
  243. PUTS(": ");
  244. PUTS(me->par_value[p]);
  245. PUTS("; ");
  246.     } else {
  247.         PUTS(" NOT GIVEN in source file; ");
  248.     }
  249. }
  250. /* Generate Outout
  251. ** ===============
  252. */
  253. PRIVATE void WSRC_gen_html (HTStream * me, BOOL source_file)
  254. {
  255.     if (me->par_value[PAR_DATABASE_NAME]) {
  256. char * shortname = NULL;
  257. int l;
  258. StrAllocCopy(shortname, me->par_value[PAR_DATABASE_NAME]);
  259. l = strlen(shortname);
  260. if ( l > 4 && !strcasecomp(shortname + l -4, ".src")) {
  261.     shortname[l-4] = 0; /* Chop of .src -- boring! */
  262. }
  263. START(HTML_TITLE);
  264. PUTS(shortname);
  265. PUTS(source_file ? " WAIS source file" : " index");
  266. END(HTML_TITLE);
  267.     
  268. START(HTML_H1);
  269. PUTS(shortname);
  270. PUTS(source_file ? " description" : " index");
  271. END(HTML_H1);
  272. HT_FREE(shortname);   /* memleak, henrik */
  273.     }
  274.     
  275.     START(HTML_DL); /* Definition list of details */
  276.     
  277.     if (source_file) {
  278. START(HTML_DT);
  279. PUTS("Access link");
  280. START(HTML_DD);
  281. if (me->par_value[PAR_IP_NAME] &&
  282.     me->par_value[PAR_DATABASE_NAME]) {
  283.     char WSRC_address[256];
  284.     char *addr = HTAnchor_address((HTAnchor*) me->request->anchor);
  285.     char *gate = HTGateway_find(addr);
  286.     char *www_database = HTEscape(me->par_value[PAR_DATABASE_NAME],
  287.   URL_XALPHAS);
  288.     if (!gate) {
  289. sprintf(WSRC_address, "wais://%s%s%s/%s",
  290. me->par_value[PAR_IP_NAME],
  291. me->par_value[PAR_TCP_PORT] ? ":" : "",
  292. me->par_value[PAR_TCP_PORT] ?
  293. me->par_value[PAR_TCP_PORT] :"", www_database);
  294. HTStartAnchor(me->target, NULL, WSRC_address);
  295. PUTS("Direct access");
  296. END(HTML_A);
  297.     } else {
  298. sprintf(WSRC_address, "%s%s%s%s/%s",
  299. gate,
  300. me->par_value[PAR_IP_NAME],
  301. me->par_value[PAR_TCP_PORT] ? ":" : "",
  302. me->par_value[PAR_TCP_PORT] ?
  303. me->par_value[PAR_TCP_PORT] : "",
  304. www_database);
  305. HTStartAnchor(me->target, NULL, WSRC_address);
  306. PUTS("Through a gateway");
  307. END(HTML_A);
  308.     }
  309.     HT_FREE(gate);
  310.     HT_FREE(addr);
  311.     HT_FREE(www_database);
  312.     
  313. } else {
  314.     give_parameter(me, PAR_IP_NAME);
  315.     give_parameter(me, PAR_DATABASE_NAME);
  316. }
  317.     
  318.     } /* end if source_file */
  319.     
  320.     if (me->par_value[PAR_MAINTAINER]) {
  321. START(HTML_DT);
  322. PUTS("Maintainer");
  323. START(HTML_DD);
  324. PUTS(me->par_value[PAR_MAINTAINER]);
  325.     }
  326.     if (me->par_value[PAR_IP_NAME]) {
  327.      START(HTML_DT);
  328.      PUTS("Host");
  329.      START(HTML_DD);
  330.      PUTS(me->par_value[PAR_IP_NAME]);
  331.     }
  332.     
  333.     END(HTML_DL);
  334.     if (me->par_value[PAR_DESCRIPTION]) {
  335. START(HTML_PRE); /* Preformatted description */
  336. PUTS(me->par_value[PAR_DESCRIPTION]);
  337. END(HTML_PRE);
  338.     }
  339.     
  340.     (*me->target->isa->_free)(me->target);
  341.     
  342.     return;
  343. } /* generate html */
  344. PRIVATE int WSRCParser_put_string (HTStream * context, CONST char* s)
  345. {
  346.     while (*s)
  347.         WSRCParser_put_character(context, *s++);
  348.     return HT_OK;
  349. }
  350. PRIVATE int WSRCParser_write (HTStream *  context,
  351.    CONST char*  b,
  352.    int l)
  353. {
  354.     while (l-- > 0)
  355. WSRCParser_put_character(context, *b++);
  356.     return HT_OK;
  357. }
  358. PRIVATE int WSRCParser_flush (HTStream * me)
  359. {
  360.     return HT_OK;
  361. }
  362. PRIVATE int WSRCParser_free (HTStream * me)
  363. {
  364.     WSRC_gen_html(me, YES);
  365. #ifdef CACHE_FILE_PREFIX
  366.     write_cache(me);
  367. #endif
  368.     {
  369. int p;
  370. for(p=0; par_name[p]; p++) { /* Clear out old values */
  371.     if (me->par_value[p]) {
  372. HT_FREE(me->par_value[p]);
  373.     }
  374. }
  375.     }
  376.     HT_FREE(me);
  377.     return HT_OK;
  378. }
  379. PRIVATE int WSRCParser_abort (HTStream * me, HTList * e)
  380. {
  381.     WSRCParser_free(me);
  382.     return HT_ERROR;
  383. }
  384. /* Stream subclass -- method routines
  385. ** ---------------
  386. */
  387. HTStreamClass WSRCParserClass = {
  388. "WSRCParser",
  389. WSRCParser_flush,
  390. WSRCParser_free,
  391. WSRCParser_abort,
  392. WSRCParser_put_character,
  393.   WSRCParser_put_string,
  394. WSRCParser_write
  395. };
  396. /* Converter from WAIS Source to whatever
  397. ** --------------------------------------
  398. */
  399. PUBLIC HTStream* HTWSRCConvert (HTRequest * request,
  400. void * param,
  401. HTFormat input_format,
  402. HTFormat output_format,
  403. HTStream * output_stream)
  404. {
  405.     HTStream * me;
  406.     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
  407.         HT_OUTOFMEM("HTWSRCConvert");
  408.     me->isa = &WSRCParserClass;
  409.     me->target = HTMLGenerator(request, param, input_format, output_format,
  410.        output_stream);
  411.     me->request = request;
  412.     me->state = beginning;
  413.     return me;
  414. }