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

浏览器

开发平台:

Unix_Linux

  1. /*      HTAccess.c
  2. ** ACCESS MANAGER
  3. **
  4. ** (c) COPYRIGHT MIT 1995.
  5. ** Please first read the full copyright statement in the file COPYRIGH.
  6. **
  7. ** Authors
  8. ** TBL Tim Berners-Lee timbl@w3.org
  9. ** JFG Jean-Francois Groff jfg@dxcern.cern.ch
  10. ** DD Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
  11. ** History
  12. **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
  13. ** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
  14. **  6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
  15. ** 17 Dec 92 Tn3270 added, bug fix. DD
  16. **  4 Feb 93 Access registration, Search escapes bad chars TBL
  17. **   PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
  18. ** 28 May 93 WAIS gateway explicit if no WAIS library linked in.
  19. **    Dec 93 Bug change around, more reentrant, etc
  20. ** 09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
  21. **  8 Jul 94 Insulate HT_FREE();
  22. **    Sep 95 Rewritten, HFN
  23. */
  24. #if !defined(HT_DIRECT_WAIS) && !defined(HT_DEFAULT_WAIS_GATEWAY)
  25. #define HT_DEFAULT_WAIS_GATEWAY "http://www.w3.org:8001/"
  26. #endif
  27. /* Library include files */
  28. #include "WWWLib.h"
  29. #include "HTReqMan.h"
  30. #include "HTAccess.h"  /* Implemented here */
  31. #ifndef VC
  32. #define VC "unknown"
  33. #endif
  34. PRIVATE char * HTAppName = NULL;   /* Application name: please supply */
  35. PRIVATE char * HTAppVersion = NULL;    /* Application version: please supply */
  36. PRIVATE char * HTLibName = "libwww";
  37. PRIVATE char * HTLibVersion = VC;
  38. PRIVATE BOOL   HTSecure = NO;  /* Can we access local file system? */
  39. #define PUTBLOCK(b, l) (*target->isa->put_block)(target, b, l)
  40. struct _HTStream {
  41.     HTStreamClass * isa;
  42. };
  43. /* --------------------------------------------------------------------------*/
  44. /*            Initialization and Termination of the Library      */
  45. /* --------------------------------------------------------------------------*/
  46. /* Information about the Application
  47. ** ---------------------------------
  48. */
  49. PUBLIC CONST char * HTLib_appName (void)
  50. {
  51.     return HTAppName ? HTAppName : "UNKNOWN";
  52. }
  53. PUBLIC CONST char * HTLib_appVersion (void)
  54. {
  55.     return HTAppVersion ? HTAppVersion : "0.0";
  56. }
  57. /* Information about libwww
  58. ** ------------------------
  59. */
  60. PUBLIC CONST char * HTLib_name (void)
  61. {
  62.     return HTLibName ? HTLibName : "UNKNOWN";
  63. }
  64. PUBLIC CONST char * HTLib_version (void)
  65. {
  66.     return HTLibVersion ? HTLibVersion : "0.0";
  67. }
  68. /* Access Local File System
  69. ** ------------------------
  70. ** In this mode we do not tough the local file system at all
  71. */
  72. PUBLIC BOOL HTLib_secure (void)
  73. {
  74.     return HTSecure;
  75. }
  76. PUBLIC void HTLib_setSecure (BOOL mode)
  77. {
  78.     HTSecure = mode;
  79. }
  80. /*      HTLibInit
  81. **
  82. ** This function initiates the Library and it MUST be called when
  83. ** starting up an application. See also HTLibTerminate()
  84. */
  85. PUBLIC BOOL HTLibInit (CONST char * AppName, CONST char * AppVersion)
  86. {
  87. #ifdef WWW_WIN_ASYNC
  88.     /*
  89.     ** We are here starting a hidden window to take care of events from
  90.     **  the async select() call in the async version of the event loop in
  91.     ** the Internal event manager (HTEvntrg.c)
  92.     */
  93.     HWND htSocketWin;
  94.     static char className[] = "AsyncWindowClass";
  95.     WNDCLASS wc;
  96.     OSVERSIONINFO osInfo;
  97.     
  98.     wc.style=0;
  99.     wc.lpfnWndProc=(WNDPROC)AsyncWindowProc;
  100.     wc.cbClsExtra=0;
  101.     wc.cbWndExtra=0;
  102.     wc.hIcon=0;
  103.     wc.hCursor=0;
  104.     wc.hbrBackground=0;
  105.     wc.lpszMenuName=(LPSTR)0;
  106.     wc.lpszClassName=className;
  107.     osInfo.dwOSVersionInfoSize = sizeof(osInfo);
  108.     GetVersionEx(&osInfo);
  109.     if (osInfo.dwPlatformId == VER_PLATFORM_WIN32s || osInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  110. wc.hInstance=GetModuleHandle(NULL); /* 95 and non threaded platforms */
  111.     else
  112. wc.hInstance=GetCurrentProcess(); /* NT and hopefully everything following */
  113. #endif /* WWW_WIN_ASYNC */
  114. #if WWWTRACE_MODE == WWWTRACE_FILE   /* Open trace file */
  115.     if ((TDEST = fopen(HT_TRACE_FILE, "a")) != NULL) {
  116. if (setvbuf(TDEST, NULL, _IOLBF, 0) < 0) {  /* Change to line buffer */
  117.     TTYPrint(TDEST, "WWWLibInit.. Can't initialize TRACE buffer - no TRACEn");
  118.     fclose(TDEST);
  119.     TDEST = NULL;
  120.     WWW_TraceFlag = 0;
  121. }
  122.     } else
  123. WWW_TraceFlag = 0;
  124. #endif /* WWWTRACE_FILE */
  125.     if (WWWTRACE)
  126. TTYPrint(TDEST, "WWWLibInit.. INITIALIZING LIBRARY OF COMMON CODEn");
  127.     /* Set the application name and version */
  128.     if (AppName) {
  129. char *ptr;
  130. StrAllocCopy(HTAppName, AppName);
  131. ptr = HTAppName;
  132. while (*ptr) {
  133.     if (WHITE(*ptr)) *ptr = '_';
  134.     ptr++;
  135. }
  136.     }
  137.     if (AppVersion) {
  138. char *ptr;
  139. StrAllocCopy(HTAppVersion, AppVersion);
  140. ptr = HTAppVersion;
  141. while (*ptr) {
  142.     if (WHITE(*ptr)) *ptr = '_';
  143.     ptr++;
  144. }
  145.     }
  146.     HTBind_init();       /* Initialize bindings */
  147. #ifdef WWWLIB_SIG
  148.     /* On Solaris (and others?) we get a BROKEN PIPE signal when connecting
  149.     ** to a port where we should get `connection refused'. We ignore this 
  150.     ** using the following function call
  151.     */
  152.     HTSetSignal();    /* Set signals in library */
  153. #endif
  154. #ifdef WWW_WIN_ASYNC
  155.     if (!RegisterClass(&wc)) {
  156.      TTYPrint(TDEST, "HTEvent_Loop.. Can't RegisterClass "%s"n", className);
  157.     return NO;
  158.     }
  159.     if (!(htSocketWin = CreateWindow(className, "WWW_WIN_ASYNC", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, 
  160.                                      CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, wc.hInstance,0))) {
  161. char space[50];
  162.         TTYPrint(TDEST, "HTEvent_Loop.. Can't CreateWindow "WWW_WIN_ASYNC" - error:");
  163. sprintf(space, "%ldn", GetLastError());
  164. TTYPrint(TDEST, space);
  165.      return NO;
  166.     }
  167.     HTEvent_setWinHandle (htSocketWin, WM_USER);     /* use first available message since app uses none */
  168. #endif /* WWW_WIN_ASYNC */
  169. #ifdef _WINSOCKAPI_
  170.     /*
  171.     ** Initialise WinSock DLL. This must also be shut down! PMH
  172.     */
  173.     {
  174.         WSADATA            wsadata;
  175. if (WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata)) {
  176.     if (WWWTRACE)
  177. TTYPrint(TDEST, "WWWLibInit.. Can't initialize WinSocn");
  178.             WSACleanup();
  179.             return NO;
  180.         }
  181.         if (wsadata.wVersion < MINIMUM_WINSOCK_VERSION) {
  182.             if (WWWTRACE)
  183. TTYPrint(TDEST, "WWWLibInit.. Bad version of WinSocn");
  184.             WSACleanup();
  185.             return NO;
  186.         }
  187.     }
  188. #endif /* _WINSOCKAPI_ */
  189. #ifndef NO_TIMEGM
  190.     HTGetTimeZoneOffset();    /* Find offset from GMT if using mktime() */
  191. #endif
  192.     HTTmp_setRoot(NULL);      /* Set up default tmp directory */
  193.     return YES;
  194. }
  195. /* HTLibTerminate
  196. ** --------------
  197. ** This function frees memory kept by the Library and should be called
  198. ** before exit of an application (if you are on a PC platform)
  199. */
  200. PUBLIC BOOL HTLibTerminate (void)
  201. {
  202.     if (WWWTRACE)
  203. TTYPrint(TDEST, "WWWLibTerm.. Cleaning up LIBRARY OF COMMON CODEn");
  204.     HTAtom_deleteAll();  /* Remove the atoms */
  205.     HTDNS_deleteAll(); /* Remove the DNS host cache */
  206.     HTAnchor_deleteAll(NULL); /* Delete anchors and drop hyperdocs */
  207.     HTProtocol_deleteAll();  /* Remove bindings between access and protocols */
  208.     HTBind_deleteAll();     /* Remove bindings between suffixes, media types */
  209.     HTFreeHostName();     /* Free up some internal strings */
  210.     HTFreeMailAddress();
  211.     HTTmp_freeRoot();
  212. #ifdef _WINSOCKAPI_
  213.     WSACleanup();
  214. #endif
  215. #ifdef WWW_WIN_ASYNC
  216.     DestroyWindow(HTEvent_getWinHandle(0));
  217. #endif
  218. #if WWWTRACE_MODE == WWWTRACE_FILE  /* Close trace file */
  219.     if (TDEST) {
  220. fclose(TDEST);
  221. TDEST = NULL;
  222. WWW_TraceFlag = 0;
  223.     }
  224. #endif /* WWWTRACE_FILE */
  225.     return YES;
  226. }
  227. /* --------------------------------------------------------------------------*/
  228. /*             Load Access functions      */
  229. /* --------------------------------------------------------------------------*/
  230. /* Request a document
  231. ** -----------------
  232. ** Private version that requests a document from the request manager
  233. ** Returns YES if request accepted, else NO
  234. */
  235. PRIVATE BOOL HTLoadDocument (HTRequest * request, BOOL recursive)
  236. {
  237.     if (PROT_TRACE) {
  238. HTParentAnchor *anchor = HTRequest_anchor(request);
  239. char * full_address = HTAnchor_address((HTAnchor *) anchor);
  240. TTYPrint(TDEST, "HTAccess.... Accessing document %sn", full_address);
  241. HT_FREE(full_address);
  242.     }
  243.     return HTLoad(request, recursive);
  244. }
  245. /* Request a document from absolute name
  246. ** -------------------------------------
  247. ** Request a document referencd by an absolute URL.
  248. ** Returns YES if request accepted, else NO
  249. */
  250. PUBLIC BOOL HTLoadAbsolute (CONST char * url, HTRequest* request)
  251. {
  252.     if (url && request) {
  253. HTAnchor * anchor = HTAnchor_findAddress(url);
  254. HTRequest_setAnchor(request, anchor);
  255. return HTLoadDocument(request, NO);
  256.     }
  257.     return NO;
  258. }
  259. /* Request a document from absolute name to stream
  260. ** -----------------------------------------------
  261. ** Request a document referencd by an absolute URL and sending the data
  262. ** down a stream. This is _excactly_ the same as HTLoadAbsolute as
  263. ** the ourputstream is specified using the function
  264. ** HTRequest_setOutputStream(). 'filter' is ignored!
  265. ** Returns YES if request accepted, else NO
  266. */
  267. PUBLIC BOOL HTLoadToStream (CONST char * url, BOOL filter, HTRequest *request)
  268. {
  269.     return HTLoadAbsolute(url, request);
  270. }
  271. /* Request a document from relative name
  272. ** -------------------------------------
  273. ** Request a document referenced by a relative URL. The relative URL is 
  274. ** made absolute by resolving it relative to the address of the 'base' 
  275. ** anchor.
  276. ** Returns YES if request accepted, else NO
  277. */
  278. PUBLIC BOOL HTLoadRelative (CONST char *  relative,
  279.     HTParentAnchor * base,
  280.     HTRequest * request)
  281. {
  282.     BOOL status = NO;
  283.     if (relative && base && request) {
  284. char * rel = NULL;
  285. char * full_url = NULL;
  286. char * base_url = HTAnchor_address((HTAnchor *) base);
  287. StrAllocCopy(rel, relative);
  288. full_url = HTParse(HTStrip(rel), base_url,
  289.  PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
  290. status = HTLoadAbsolute(full_url, request);
  291. HT_FREE(rel);
  292. HT_FREE(full_url);
  293. HT_FREE(base_url);
  294.     }
  295.     return status;
  296. }
  297. /* Request an anchor
  298. ** -----------------
  299. ** Request the document referenced by the anchor
  300. ** Returns YES if request accepted, else NO
  301. */
  302. PUBLIC BOOL HTLoadAnchor (HTAnchor * anchor, HTRequest * request)
  303. {
  304.     if (anchor && request) {
  305. HTRequest_setAnchor(request, anchor);
  306. return HTLoadDocument(request, NO);
  307.     }
  308.     return NO;
  309. }
  310. /* Request an anchor
  311. ** -----------------
  312. ** Same as HTLoadAnchor but any information in the Error Stack in the 
  313. ** request object is kept, so that any error messages in one 
  314. ** This function is almost identical to HTLoadAnchor, but it doesn't
  315. ** clear the error stack so that the information in there is kept.
  316. ** Returns YES if request accepted, else NO
  317. */
  318. PUBLIC BOOL HTLoadAnchorRecursive (HTAnchor * anchor, HTRequest * request)
  319. {
  320.     if (anchor && request) {
  321. HTRequest_setAnchor(request, anchor);
  322.         return HTLoadDocument(request, YES);
  323.     }
  324.     return NO;
  325. }
  326. /* Search an Anchor
  327. ** ----------------
  328. ** Performs a keyword search on word given by the user. Adds the keyword
  329. ** to the end of the current address and attempts to open the new address.
  330. ** The list of keywords must be a space-separated list and spaces will
  331. ** be converted to '+' before the request is issued.
  332. ** Search can also be performed by HTLoadAbsolute() etc.
  333. ** Returns YES if request accepted, else NO
  334. */
  335. PUBLIC BOOL HTSearch (CONST char * keywords,
  336.       HTParentAnchor *  base,
  337.       HTRequest *  request)
  338. {
  339.     BOOL status = NO;
  340.     if (keywords && base && request) {
  341. char *base_url = HTAnchor_address((HTAnchor *) base);
  342. if (*keywords) {
  343.     char *plus;
  344.     StrAllocCat(base_url, "?");
  345.     StrAllocCat(base_url, keywords);
  346.     plus = strchr(base_url, '?');
  347.     while (*plus) {
  348. if (*plus == ' ') *plus = '+';
  349. plus++;
  350.     }
  351. }
  352. status = HTLoadAbsolute(base_url, request);
  353. HT_FREE(base_url);
  354.     }
  355.     return status;
  356. }
  357. /* Search a document from absolute name
  358. ** ------------------------------------
  359. ** Request a document referencd by an absolute URL appended with the
  360. ** keywords given. The URL can NOT contain any fragment identifier!
  361. ** The list of keywords must be a space-separated list and spaces will
  362. ** be converted to '+' before the request is issued.
  363. ** Returns YES if request accepted, else NO
  364. */
  365. PUBLIC BOOL HTSearchAbsolute (CONST char * keywords,
  366.       CONST char * url,
  367.       HTRequest * request)
  368. {
  369.     if (url && request) {
  370. HTAnchor * anchor = HTAnchor_findAddress(url);
  371. return HTSearch(keywords, HTAnchor_parent(anchor), request);
  372.     }
  373.     return NO;
  374. }
  375. /* --------------------------------------------------------------------------*/
  376. /* Post Access Functions       */
  377. /* --------------------------------------------------------------------------*/
  378. /* Copy an anchor
  379. ** --------------
  380. ** Fetch the URL (possibly local file URL) and send it using either PUT
  381. ** or POST to the remote destination using HTTP. The caller can decide the
  382. ** exact method used and which HTTP header fields to transmit by setting
  383. ** the user fields in the request structure.
  384. ** If posting to NNTP then we can't dispatch at this level but must pass
  385. ** the source anchor to the news module that then takes all the refs
  386. ** to NNTP and puts into the "newsgroups" header
  387. ** Returns YES if request accepted, else NO
  388. */
  389. PUBLIC BOOL HTCopyAnchor (HTAnchor * src_anchor, HTRequest * main_dest)
  390.     HTRequest * src_req;
  391.     HTList * cur;
  392.     if (!src_anchor || !main_dest) {
  393. if (WWWTRACE) TTYPrint(TDEST, "Copy........ BAD ARGUMENTn");
  394. return NO;
  395.     }
  396.     /* Set the source anchor */
  397.     main_dest->source_anchor = HTAnchor_parent(src_anchor);
  398.     /* Build the POST web if not already there */
  399.     if (!main_dest->source) {
  400. src_req = HTRequest_dupInternal(main_dest);   /* Get a duplicate */
  401. HTAnchor_clearHeader((HTParentAnchor *) src_anchor);
  402. src_req->method = METHOD_GET;
  403. src_req->reload = HT_MEM_REFRESH;
  404. src_req->output_stream = NULL;
  405. src_req->output_format = WWW_SOURCE;  /* We want source (for now) */
  406. /* Set up the main link in the source anchor */
  407. {
  408.     HTLink * main_link = HTAnchor_mainLink((HTAnchor *) src_anchor);
  409.     HTAnchor *main_anchor = HTLink_destination(main_link);
  410.     HTMethod method = HTLink_method(main_link);
  411.     if (!main_link || method==METHOD_INVALID) {
  412. if (WWWTRACE)
  413.     TTYPrint(TDEST, "Copy Anchor. No destination found or unspecified methodn");
  414. HTRequest_delete(src_req);
  415. return NO;
  416.     }
  417.     main_dest->GenMask |= HT_G_DATE;  /* Send date header */
  418.     main_dest->reload = HT_CACHE_REFRESH;
  419.     main_dest->method = method;
  420.     main_dest->input_format = WWW_SOURCE;
  421.     HTRequest_addDestination(src_req, main_dest);
  422.     if (HTLoadAnchor(main_anchor, main_dest) == NO)
  423. return NO;
  424. }
  425. /* For all other links in the source anchor */
  426. if ((cur = HTAnchor_subLinks(src_anchor))) {
  427.     HTLink * pres;
  428.     while ((pres = (HTLink *) HTList_nextObject(cur))) {
  429. HTAnchor *dest = HTLink_destination(pres);
  430. HTMethod method = HTLink_method(pres);
  431. HTRequest *dest_req;
  432. if (!dest || method==METHOD_INVALID) {
  433.     if (WWWTRACE)
  434. TTYPrint(TDEST, "Copy Anchor. Bad anchor setup %pn",
  435. dest);
  436.     return NO;
  437. }
  438. dest_req = HTRequest_dupInternal(main_dest);
  439. dest_req->GenMask |= HT_G_DATE;  /* Send date header */
  440. dest_req->reload = HT_CACHE_REFRESH;
  441. dest_req->method = method;
  442. dest_req->output_stream = NULL;
  443. dest_req->output_format = WWW_SOURCE;
  444. HTRequest_addDestination(src_req, dest_req);
  445. if (HTLoadAnchor(dest, dest_req) == NO)
  446.     return NO;
  447.     }
  448. }
  449.     } else {  /* Use the existing Post Web and restart it */
  450. src_req = main_dest->source;
  451. if (src_req->mainDestination)
  452.     if (HTLoadDocument(main_dest, NO) == NO)
  453. return NO;
  454. if (src_req->destinations) {
  455.     HTRequest * pres;
  456.     cur = HTAnchor_subLinks(src_anchor);
  457.     while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL) {
  458. if (HTLoadDocument(pres, NO) == NO)
  459.     return NO;
  460.     }
  461. }
  462.     }
  463.     /* Now open the source */
  464.     return HTLoadAnchor(src_anchor, src_req);
  465. }
  466. /* Upload an Anchor
  467. ** ----------------
  468. ** This function can be used to send data along with a request to a remote
  469. ** server. It can for example be used to POST form data to a remote HTTP
  470. ** server - or it can be used to post a newsletter to a NNTP server. In
  471. ** either case, you pass a callback function which the request calls when
  472. ** the remote destination is ready to accept data. In this callback
  473. ** you get the current request object and a stream into where you can 
  474. ** write data. It is very important that you return the value returned
  475. ** by this stream to the Library so that it knows what to do next. The
  476. ** reason is that the outgoing stream might block or an error may
  477. ** occur and in that case the Library must know about it. The source
  478. ** anchor represents the data object in memory and it points to 
  479. ** the destination anchor by using the POSTWeb method. The source anchor
  480. ** contains metainformation about the data object in memory and the 
  481. ** destination anchor represents the reponse from the remote server.
  482. ** Returns YES if request accepted, else NO
  483. */
  484. PUBLIC BOOL HTUploadAnchor (HTAnchor * source_anchor,
  485.     HTRequest *  request,
  486.     HTPostCallback * callback)
  487. {
  488.     HTLink * link = HTAnchor_mainLink((HTAnchor *) source_anchor);
  489.     HTAnchor * dest_anchor = HTLink_destination(link);
  490.     HTMethod method = HTLink_method(link);
  491.     if (!link || method==METHOD_INVALID || !callback) {
  492. if (WWWTRACE)
  493.     TTYPrint(TDEST, "Upload...... No destination found or unspecified methodn");
  494. return NO;
  495.     }
  496.     request->GenMask |= HT_G_DATE;  /* Send date header */
  497.     request->reload = HT_CACHE_REFRESH;
  498.     request->method = method;
  499.     request->source_anchor = HTAnchor_parent(source_anchor);
  500.     request->PostCallback = callback;
  501.     return HTLoadAnchor(dest_anchor, request);
  502. }
  503. /* POST Callback Handler
  504. ** ---------------------
  505. ** If you do not want to handle the stream interface on your own, you
  506. ** can use this function which writes the source anchor hyperdoc to the
  507. ** target stream for the anchor upload and also handles the return value
  508. ** from the stream. If you don't want to write the source anchor hyperdoc
  509. ** then you can register your own callback function that can get the data
  510. ** you want.
  511. */
  512. PUBLIC int HTUpload_callback (HTRequest * request, HTStream * target)
  513. {
  514.     if (WWWTRACE) TTYPrint(TDEST, "Uploading... from callback functionn");
  515.     if (!request || !request->source_anchor || !target) return HT_ERROR;
  516.     {
  517. int status;
  518. HTParentAnchor * source = request->source_anchor;
  519. char * document = (char *) HTAnchor_document(request->source_anchor);
  520. int len = HTAnchor_length(source);
  521. if (len < 0) {
  522.     len = strlen(document);
  523.     HTAnchor_setLength(source, len);
  524. }
  525. status = (*target->isa->put_block)(target, document, len);
  526. if (status == HT_OK)
  527.     return (*target->isa->flush)(target);
  528. if (status == HT_WOULD_BLOCK) {
  529.     if (PROT_TRACE)TTYPrint(TDEST,"POST Anchor. Target WOULD BLOCKn");
  530.     return HT_WOULD_BLOCK;
  531. } else if (status == HT_PAUSE) {
  532.     if (PROT_TRACE) TTYPrint(TDEST,"POST Anchor. Target PAUSEDn");
  533.     return HT_PAUSE;
  534. } else if (status > 0) {       /* Stream specific return code */
  535.     if (PROT_TRACE)
  536. TTYPrint(TDEST, "POST Anchor. Target returns %dn", status);
  537.     return status;
  538. } else {      /* We have a real error */
  539.     if (PROT_TRACE) TTYPrint(TDEST, "POST Anchor. Target ERRORn");
  540.     return status;
  541. }
  542.     }
  543. }