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