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