Annotation of libwww/Library/src/HTAccess.c, revision 1.118
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.114 frystyk 21: ** 8 Jul 94 Insulate HT_FREE();
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.117 frystyk 34: #ifndef W3C_VERSION
35: #define W3C_VERSION "unknown"
1.99 frystyk 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";
1.117 frystyk 42: PRIVATE char * HTLibVersion = W3C_VERSION;
1.99 frystyk 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: */
1.117 frystyk 59: PUBLIC const char * HTLib_appName (void)
1.93 frystyk 60: {
1.99 frystyk 61: return HTAppName ? HTAppName : "UNKNOWN";
62: }
63:
1.117 frystyk 64: PUBLIC const char * HTLib_appVersion (void)
1.99 frystyk 65: {
66: return HTAppVersion ? HTAppVersion : "0.0";
1.93 frystyk 67: }
68:
1.99 frystyk 69: /* Information about libwww
70: ** ------------------------
71: */
1.117 frystyk 72: PUBLIC const char * HTLib_name (void)
1.99 frystyk 73: {
74: return HTLibName ? HTLibName : "UNKNOWN";
75: }
76:
1.117 frystyk 77: PUBLIC const char * HTLib_version (void)
1.99 frystyk 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.117 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;
1.113 frystyk 112: OSVERSIONINFO osInfo;
1.105 frystyk 113:
114: wc.style=0;
115: wc.lpfnWndProc=(WNDPROC)AsyncWindowProc;
116: wc.cbClsExtra=0;
117: wc.cbWndExtra=0;
118: wc.hIcon=0;
119: wc.hCursor=0;
120: wc.hbrBackground=0;
121: wc.lpszMenuName=(LPSTR)0;
122: wc.lpszClassName=className;
1.113 frystyk 123:
124: osInfo.dwOSVersionInfoSize = sizeof(osInfo);
125: GetVersionEx(&osInfo);
126: if (osInfo.dwPlatformId == VER_PLATFORM_WIN32s || osInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
127: wc.hInstance=GetModuleHandle(NULL); /* 95 and non threaded platforms */
128: else
129: wc.hInstance=GetCurrentProcess(); /* NT and hopefully everything following */
1.105 frystyk 130: #endif /* WWW_WIN_ASYNC */
131:
1.91 frystyk 132: if (WWWTRACE)
1.115 eric 133: HTTrace("WWWLibInit.. INITIALIZING LIBRARY OF COMMON CODE\n");
1.63 frystyk 134:
1.93 frystyk 135: /* Set the application name and version */
136: if (AppName) {
137: char *ptr;
138: StrAllocCopy(HTAppName, AppName);
139: ptr = HTAppName;
140: while (*ptr) {
141: if (WHITE(*ptr)) *ptr = '_';
142: ptr++;
143: }
144: }
145: if (AppVersion) {
146: char *ptr;
147: StrAllocCopy(HTAppVersion, AppVersion);
148: ptr = HTAppVersion;
149: while (*ptr) {
150: if (WHITE(*ptr)) *ptr = '_';
151: ptr++;
152: }
153: }
154:
155: HTBind_init(); /* Initialize bindings */
1.61 frystyk 156:
1.62 frystyk 157: #ifdef WWWLIB_SIG
1.61 frystyk 158: /* On Solaris (and others?) we get a BROKEN PIPE signal when connecting
1.67 frystyk 159: ** to a port where we should get `connection refused'. We ignore this
1.61 frystyk 160: ** using the following function call
161: */
162: HTSetSignal(); /* Set signals in library */
1.1 timbl 163: #endif
164:
1.105 frystyk 165: #ifdef WWW_WIN_ASYNC
166: if (!RegisterClass(&wc)) {
1.115 eric 167: HTTrace("HTEvent_Loop.. Can't RegisterClass \"%s\"\n", className);
1.105 frystyk 168: return NO;
169: }
1.113 frystyk 170: if (!(htSocketWin = CreateWindow(className, "WWW_WIN_ASYNC", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
171: CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, wc.hInstance,0))) {
172: char space[50];
1.115 eric 173: HTTrace("HTEvent_Loop.. Can't CreateWindow \"WWW_WIN_ASYNC\" - error:");
1.113 frystyk 174: sprintf(space, "%ld\n", GetLastError());
1.115 eric 175: HTTrace(space);
1.105 frystyk 176: return NO;
177: }
178: HTEvent_setWinHandle (htSocketWin, WM_USER); /* use first available message since app uses none */
179: #endif /* WWW_WIN_ASYNC */
180:
1.108 frystyk 181: #ifdef _WINSOCKAPI_
1.67 frystyk 182: /*
183: ** Initialise WinSock DLL. This must also be shut down! PMH
184: */
185: {
186: WSADATA wsadata;
187: if (WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata)) {
1.91 frystyk 188: if (WWWTRACE)
1.115 eric 189: HTTrace("WWWLibInit.. Can't initialize WinSoc\n");
1.67 frystyk 190: WSACleanup();
191: return NO;
192: }
193: if (wsadata.wVersion < MINIMUM_WINSOCK_VERSION) {
1.91 frystyk 194: if (WWWTRACE)
1.115 eric 195: HTTrace("WWWLibInit.. Bad version of WinSoc\n");
1.67 frystyk 196: WSACleanup();
197: return NO;
198: }
199: }
1.108 frystyk 200: #endif /* _WINSOCKAPI_ */
1.67 frystyk 201:
1.71 frystyk 202: HTGetTimeZoneOffset(); /* Find offset from GMT if using mktime() */
1.70 frystyk 203: HTTmp_setRoot(NULL); /* Set up default tmp directory */
1.61 frystyk 204: return YES;
205: }
206:
207:
1.90 frystyk 208: /* HTLibTerminate
209: ** --------------
1.117 frystyk 210: ** This function HT_FREEs memory kept by the Library and should be called
1.63 frystyk 211: ** before exit of an application (if you are on a PC platform)
1.61 frystyk 212: */
1.101 frystyk 213: PUBLIC BOOL HTLibTerminate (void)
1.61 frystyk 214: {
1.116 frystyk 215: if (WWWTRACE) HTTrace("WWWLibTerm.. Cleaning up LIBRARY OF COMMON CODE\n");
216:
217: HT_FREE(HTAppName); /* Freed thanks to Wade Ogden <wade@ebt.com> */
218: HT_FREE(HTAppVersion);
219:
1.101 frystyk 220: HTAtom_deleteAll(); /* Remove the atoms */
221: HTDNS_deleteAll(); /* Remove the DNS host cache */
222: HTAnchor_deleteAll(NULL); /* Delete anchors and drop hyperdocs */
1.73 frystyk 223:
1.81 frystyk 224: HTProtocol_deleteAll(); /* Remove bindings between access and protocols */
1.73 frystyk 225: HTBind_deleteAll(); /* Remove bindings between suffixes, media types */
226:
1.77 frystyk 227: HTFreeHostName(); /* Free up some internal strings */
1.63 frystyk 228: HTFreeMailAddress();
1.118 ! eric 229: HTTmp_freeRoot();
1.67 frystyk 230:
1.108 frystyk 231: #ifdef _WINSOCKAPI_
1.67 frystyk 232: WSACleanup();
1.105 frystyk 233: #endif
234:
235: #ifdef WWW_WIN_ASYNC
236: DestroyWindow(HTEvent_getWinHandle(0));
1.67 frystyk 237: #endif
238:
1.61 frystyk 239: return YES;
240: }
241:
1.59 frystyk 242: /* --------------------------------------------------------------------------*/
1.104 frystyk 243: /* Load Access functions */
1.59 frystyk 244: /* --------------------------------------------------------------------------*/
1.33 luotonen 245:
1.90 frystyk 246: /* Request a document
247: ** -----------------
248: ** Private version that requests a document from the request manager
249: ** Returns YES if request accepted, else NO
1.88 frystyk 250: */
1.101 frystyk 251: PRIVATE BOOL HTLoadDocument (HTRequest * request, BOOL recursive)
1.88 frystyk 252: {
253: if (PROT_TRACE) {
1.90 frystyk 254: HTParentAnchor *anchor = HTRequest_anchor(request);
255: char * full_address = HTAnchor_address((HTAnchor *) anchor);
1.115 eric 256: HTTrace("HTAccess.... Accessing document %s\n", full_address);
1.114 frystyk 257: HT_FREE(full_address);
1.88 frystyk 258: }
1.96 frystyk 259: return HTLoad(request, recursive);
1.58 frystyk 260: }
1.1 timbl 261:
262:
1.90 frystyk 263: /* Request a document from absolute name
264: ** -------------------------------------
265: ** Request a document referencd by an absolute URL.
266: ** Returns YES if request accepted, else NO
267: */
1.117 frystyk 268: PUBLIC BOOL HTLoadAbsolute (const char * url, HTRequest* request)
1.90 frystyk 269: {
270: if (url && request) {
271: HTAnchor * anchor = HTAnchor_findAddress(url);
272: HTRequest_setAnchor(request, anchor);
273: return HTLoadDocument(request, NO);
274: }
275: return NO;
276: }
277:
278:
279: /* Request a document from absolute name to stream
280: ** -----------------------------------------------
281: ** Request a document referencd by an absolute URL and sending the data
282: ** down a stream. This is _excactly_ the same as HTLoadAbsolute as
283: ** the ourputstream is specified using the function
284: ** HTRequest_setOutputStream(). 'filter' is ignored!
285: ** Returns YES if request accepted, else NO
286: */
1.117 frystyk 287: PUBLIC BOOL HTLoadToStream (const char * url, BOOL filter, HTRequest *request)
1.90 frystyk 288: {
289: return HTLoadAbsolute(url, request);
290: }
291:
292:
293: /* Request a document from relative name
294: ** -------------------------------------
295: ** Request a document referenced by a relative URL. The relative URL is
296: ** made absolute by resolving it relative to the address of the 'base'
297: ** anchor.
298: ** Returns YES if request accepted, else NO
299: */
1.117 frystyk 300: PUBLIC BOOL HTLoadRelative (const char * relative,
1.90 frystyk 301: HTParentAnchor * base,
302: HTRequest * request)
303: {
304: BOOL status = NO;
305: if (relative && base && request) {
306: char * rel = NULL;
307: char * full_url = NULL;
308: char * base_url = HTAnchor_address((HTAnchor *) base);
309: StrAllocCopy(rel, relative);
310: full_url = HTParse(HTStrip(rel), base_url,
311: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
312: status = HTLoadAbsolute(full_url, request);
1.114 frystyk 313: HT_FREE(rel);
314: HT_FREE(full_url);
315: HT_FREE(base_url);
1.90 frystyk 316: }
317: return status;
318: }
319:
320:
321: /* Request an anchor
322: ** -----------------
323: ** Request the document referenced by the anchor
324: ** Returns YES if request accepted, else NO
325: */
326: PUBLIC BOOL HTLoadAnchor (HTAnchor * anchor, HTRequest * request)
327: {
328: if (anchor && request) {
329: HTRequest_setAnchor(request, anchor);
330: return HTLoadDocument(request, NO);
331: }
332: return NO;
333: }
334:
335:
336: /* Request an anchor
337: ** -----------------
338: ** Same as HTLoadAnchor but any information in the Error Stack in the
339: ** request object is kept, so that any error messages in one
1.52 frystyk 340: ** This function is almost identical to HTLoadAnchor, but it doesn't
341: ** clear the error stack so that the information in there is kept.
1.90 frystyk 342: ** Returns YES if request accepted, else NO
343: */
344: PUBLIC BOOL HTLoadAnchorRecursive (HTAnchor * anchor, HTRequest * request)
345: {
346: if (anchor && request) {
347: HTRequest_setAnchor(request, anchor);
348: return HTLoadDocument(request, YES);
349: }
350: return NO;
351: }
352:
353:
354: /* Search an Anchor
355: ** ----------------
356: ** Performs a keyword search on word given by the user. Adds the keyword
357: ** to the end of the current address and attempts to open the new address.
358: ** The list of keywords must be a space-separated list and spaces will
359: ** be converted to '+' before the request is issued.
360: ** Search can also be performed by HTLoadAbsolute() etc.
361: ** Returns YES if request accepted, else NO
362: */
1.117 frystyk 363: PUBLIC BOOL HTSearch (const char * keywords,
1.90 frystyk 364: HTParentAnchor * base,
365: HTRequest * request)
366: {
1.99 frystyk 367: BOOL status = NO;
1.90 frystyk 368: if (keywords && base && request) {
369: char *base_url = HTAnchor_address((HTAnchor *) base);
370: if (*keywords) {
371: char *plus;
372: StrAllocCat(base_url, "?");
373: StrAllocCat(base_url, keywords);
374: plus = strchr(base_url, '?');
375: while (*plus) {
376: if (*plus == ' ') *plus = '+';
377: plus++;
378: }
1.2 timbl 379: }
1.99 frystyk 380: status = HTLoadAbsolute(base_url, request);
1.114 frystyk 381: HT_FREE(base_url);
1.90 frystyk 382: }
1.99 frystyk 383: return status;
1.2 timbl 384: }
385:
386:
1.90 frystyk 387: /* Search a document from absolute name
388: ** ------------------------------------
389: ** Request a document referencd by an absolute URL appended with the
390: ** keywords given. The URL can NOT contain any fragment identifier!
391: ** The list of keywords must be a space-separated list and spaces will
392: ** be converted to '+' before the request is issued.
393: ** Returns YES if request accepted, else NO
394: */
1.117 frystyk 395: PUBLIC BOOL HTSearchAbsolute (const char * keywords,
396: const char * url,
1.90 frystyk 397: HTRequest * request)
398: {
399: if (url && request) {
400: HTAnchor * anchor = HTAnchor_findAddress(url);
401: return HTSearch(keywords, HTAnchor_parent(anchor), request);
402: }
403: return NO;
1.57 howcome 404: }
405:
1.70 frystyk 406: /* --------------------------------------------------------------------------*/
1.104 frystyk 407: /* Post Access Functions */
1.70 frystyk 408: /* --------------------------------------------------------------------------*/
409:
1.90 frystyk 410: /* Copy an anchor
1.70 frystyk 411: ** --------------
1.90 frystyk 412: ** Fetch the URL (possibly local file URL) and send it using either PUT
413: ** or POST to the remote destination using HTTP. The caller can decide the
414: ** exact method used and which HTTP header fields to transmit by setting
415: ** the user fields in the request structure.
1.92 frystyk 416: ** If posting to NNTP then we can't dispatch at this level but must pass
417: ** the source anchor to the news module that then takes all the refs
418: ** to NNTP and puts into the "newsgroups" header
1.90 frystyk 419: ** Returns YES if request accepted, else NO
1.70 frystyk 420: */
1.109 frystyk 421: PUBLIC BOOL HTCopyAnchor (HTAnchor * src_anchor, HTRequest * main_dest)
1.80 frystyk 422: {
1.106 frystyk 423: HTRequest * src_req;
424: HTList * cur;
1.109 frystyk 425: if (!src_anchor || !main_dest) {
1.115 eric 426: if (WWWTRACE) HTTrace("Copy........ BAD ARGUMENT\n");
1.90 frystyk 427: return NO;
1.109 frystyk 428: }
1.70 frystyk 429:
1.112 frystyk 430: /* Set the source anchor */
431: main_dest->source_anchor = HTAnchor_parent(src_anchor);
432:
1.80 frystyk 433: /* Build the POST web if not already there */
1.109 frystyk 434: if (!main_dest->source) {
435: src_req = HTRequest_dupInternal(main_dest); /* Get a duplicate */
1.80 frystyk 436: HTAnchor_clearHeader((HTParentAnchor *) src_anchor);
1.109 frystyk 437: src_req->method = METHOD_GET;
1.85 frystyk 438: src_req->reload = HT_MEM_REFRESH;
1.104 frystyk 439: src_req->output_stream = NULL;
1.80 frystyk 440: src_req->output_format = WWW_SOURCE; /* We want source (for now) */
441:
442: /* Set up the main link in the source anchor */
443: {
1.106 frystyk 444: HTLink * main_link = HTAnchor_mainLink((HTAnchor *) src_anchor);
445: HTAnchor *main_anchor = HTLink_destination(main_link);
446: HTMethod method = HTLink_method(main_link);
1.85 frystyk 447: if (!main_link || method==METHOD_INVALID) {
1.91 frystyk 448: if (WWWTRACE)
1.115 eric 449: HTTrace("Copy Anchor. No destination found or unspecified method\n");
1.80 frystyk 450: HTRequest_delete(src_req);
1.90 frystyk 451: return NO;
1.80 frystyk 452: }
1.109 frystyk 453: main_dest->GenMask |= HT_G_DATE; /* Send date header */
454: main_dest->reload = HT_CACHE_REFRESH;
455: main_dest->method = method;
456: main_dest->input_format = WWW_SOURCE;
457: HTRequest_addDestination(src_req, main_dest);
458: if (HTLoadAnchor(main_anchor, main_dest) == NO)
459: return NO;
1.80 frystyk 460: }
1.78 frystyk 461:
1.80 frystyk 462: /* For all other links in the source anchor */
1.106 frystyk 463: if ((cur = HTAnchor_subLinks(src_anchor))) {
464: HTLink * pres;
1.109 frystyk 465: while ((pres = (HTLink *) HTList_nextObject(cur))) {
1.106 frystyk 466: HTAnchor *dest = HTLink_destination(pres);
467: HTMethod method = HTLink_method(pres);
1.80 frystyk 468: HTRequest *dest_req;
469: if (!dest || method==METHOD_INVALID) {
1.91 frystyk 470: if (WWWTRACE)
1.115 eric 471: HTTrace("Copy Anchor. Bad anchor setup %p\n",
1.80 frystyk 472: dest);
1.90 frystyk 473: return NO;
1.80 frystyk 474: }
1.109 frystyk 475: dest_req = HTRequest_dupInternal(main_dest);
1.107 frystyk 476: dest_req->GenMask |= HT_G_DATE; /* Send date header */
1.85 frystyk 477: dest_req->reload = HT_CACHE_REFRESH;
1.80 frystyk 478: dest_req->method = method;
1.104 frystyk 479: dest_req->output_stream = NULL;
480: dest_req->output_format = WWW_SOURCE;
1.109 frystyk 481: HTRequest_addDestination(src_req, dest_req);
1.104 frystyk 482:
1.90 frystyk 483: if (HTLoadAnchor(dest, dest_req) == NO)
484: return NO;
1.80 frystyk 485: }
486: }
487: } else { /* Use the existing Post Web and restart it */
1.109 frystyk 488: src_req = main_dest->source;
1.80 frystyk 489: if (src_req->mainDestination)
1.109 frystyk 490: if (HTLoadDocument(main_dest, NO) == NO)
1.90 frystyk 491: return NO;
1.80 frystyk 492: if (src_req->destinations) {
1.106 frystyk 493: HTRequest * pres;
494: cur = HTAnchor_subLinks(src_anchor);
1.80 frystyk 495: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL) {
1.90 frystyk 496: if (HTLoadDocument(pres, NO) == NO)
497: return NO;
1.80 frystyk 498: }
499: }
1.78 frystyk 500: }
501:
1.80 frystyk 502: /* Now open the source */
503: return HTLoadAnchor(src_anchor, src_req);
1.70 frystyk 504: }
505:
506:
1.90 frystyk 507: /* Upload an Anchor
1.70 frystyk 508: ** ----------------
1.111 frystyk 509: ** This function can be used to send data along with a request to a remote
510: ** server. It can for example be used to POST form data to a remote HTTP
511: ** server - or it can be used to post a newsletter to a NNTP server. In
512: ** either case, you pass a callback function which the request calls when
513: ** the remote destination is ready to accept data. In this callback
514: ** you get the current request object and a stream into where you can
515: ** write data. It is very important that you return the value returned
516: ** by this stream to the Library so that it knows what to do next. The
517: ** reason is that the outgoing stream might block or an error may
518: ** occur and in that case the Library must know about it. The source
519: ** anchor represents the data object in memory and it points to
520: ** the destination anchor by using the POSTWeb method. The source anchor
521: ** contains metainformation about the data object in memory and the
522: ** destination anchor represents the reponse from the remote server.
1.90 frystyk 523: ** Returns YES if request accepted, else NO
524: */
1.111 frystyk 525: PUBLIC BOOL HTUploadAnchor (HTAnchor * source_anchor,
526: HTRequest * request,
527: HTPostCallback * callback)
528: {
529: HTLink * link = HTAnchor_mainLink((HTAnchor *) source_anchor);
530: HTAnchor * dest_anchor = HTLink_destination(link);
531: HTMethod method = HTLink_method(link);
532: if (!link || method==METHOD_INVALID || !callback) {
533: if (WWWTRACE)
1.115 eric 534: HTTrace("Upload...... No destination found or unspecified method\n");
1.90 frystyk 535: return NO;
1.109 frystyk 536: }
1.111 frystyk 537: request->GenMask |= HT_G_DATE; /* Send date header */
538: request->reload = HT_CACHE_REFRESH;
539: request->method = method;
540: request->source_anchor = HTAnchor_parent(source_anchor);
541: request->PostCallback = callback;
542: return HTLoadAnchor(dest_anchor, request);
543: }
544:
545: /* POST Callback Handler
546: ** ---------------------
547: ** If you do not want to handle the stream interface on your own, you
548: ** can use this function which writes the source anchor hyperdoc to the
549: ** target stream for the anchor upload and also handles the return value
550: ** from the stream. If you don't want to write the source anchor hyperdoc
551: ** then you can register your own callback function that can get the data
552: ** you want.
553: */
554: PUBLIC int HTUpload_callback (HTRequest * request, HTStream * target)
555: {
1.115 eric 556: if (WWWTRACE) HTTrace("Uploading... from callback function\n");
1.111 frystyk 557: if (!request || !request->source_anchor || !target) return HT_ERROR;
558: {
559: int status;
560: HTParentAnchor * source = request->source_anchor;
561: char * document = (char *) HTAnchor_document(request->source_anchor);
562: int len = HTAnchor_length(source);
563: if (len < 0) {
564: len = strlen(document);
565: HTAnchor_setLength(source, len);
566: }
567: status = (*target->isa->put_block)(target, document, len);
568: if (status == HT_OK)
569: return (*target->isa->flush)(target);
570: if (status == HT_WOULD_BLOCK) {
1.115 eric 571: if (PROT_TRACE)HTTrace("POST Anchor. Target WOULD BLOCK\n");
1.111 frystyk 572: return HT_WOULD_BLOCK;
573: } else if (status == HT_PAUSE) {
1.115 eric 574: if (PROT_TRACE) HTTrace("POST Anchor. Target PAUSED\n");
1.111 frystyk 575: return HT_PAUSE;
576: } else if (status > 0) { /* Stream specific return code */
577: if (PROT_TRACE)
1.115 eric 578: HTTrace("POST Anchor. Target returns %d\n", status);
1.111 frystyk 579: return status;
580: } else { /* We have a real error */
1.115 eric 581: if (PROT_TRACE) HTTrace("POST Anchor. Target ERROR\n");
1.111 frystyk 582: return status;
583: }
1.70 frystyk 584: }
1.1 timbl 585: }
Webmaster