Annotation of Amaya/amaya/query.c, revision 1.99
1.14 cvs 1: /*
2: *
3: * (c) COPYRIGHT MIT and INRIA, 1996.
4: * Please first read the full copyright statement in file COPYRIGHT.
5: *
6: */
1.4 cvs 7:
1.19 cvs 8: /*
1.83 cvs 9: * query.c : contains all the functions for requesting and publishing
1.19 cvs 10: * URLs via libwww. It handles any eventual HTTP error code
11: * (redirection, authentication needed, not found, etc.)
12: *
1.69 cvs 13: * Author: J. Kahan
1.92 cvs 14: * J. Kahan/R. Guetari Windows 95/NT routines
1.19 cvs 15: */
1.17 cvs 16:
1.44 cvs 17: #ifndef AMAYA_JAVA
18:
1.12 cvs 19: /* Amaya includes */
1.25 cvs 20: #define THOT_EXPORT extern
1.4 cvs 21: #include "amaya.h"
1.70 cvs 22: #ifdef _WINDOWS
23: #include <fcntl.h>
24: #endif /* _WINDOWS */
1.7 cvs 25:
1.4 cvs 26: #if defined(__svr4__)
27: #define CATCH_SIG
28: #endif
29:
30: /* local structures coming from libwww and which are
1.17 cvs 31: not found in any .h file
1.7 cvs 32: */
1.68 cvs 33:
1.7 cvs 34: struct _HTStream
35: {
1.15 cvs 36: const HTStreamClass *isa;
37: FILE *fp;
1.45 cvs 38: BOOL leave_open; /* Close file when TtaFreeMemory? */
1.15 cvs 39: char *end_command; /* Command to execute */
40: BOOL remove_on_close; /* Remove file? */
41: char *filename; /* Name of file */
42: HTRequest *request; /* saved for callback */
43: HTRequestCallback *callback;
1.7 cvs 44: };
45:
1.15 cvs 46:
1.7 cvs 47: struct _HTError
48: {
49: HTErrorElement element; /* Index number into HTError */
50: HTSeverity severity; /* A la VMS */
51: BOOL ignore; /* YES if msg should not go to user */
52: void *par; /* Explanation, e.g. filename */
53: int length; /* For copying by generic routine */
54: char *where; /* Which function */
55: };
56:
57:
58: struct _HTHost
59: {
60: char *hostname; /* name of host + optional port */
61: time_t ntime; /* Creation time */
62: char *type; /* Peer type */
63: int version; /* Peer version */
64: HTMethod methods; /* Public methods (bit-flag) */
65: char *server; /* Server name */
66: char *user_agent; /* User Agent */
67: char *range_units; /* Acceptable range units */
68: HTTransportMode mode; /* Supported mode */
69: HTChannel *channel; /* Persistent channel */
70: HTList *pipeline; /* Pipe line of net objects */
71: HTList *pending; /* List of pending Net objects */
72: time_t expires; /* Persistent channel expires time */
73: };
1.4 cvs 74:
75: /* Type definitions and global variables etc. local to this module */
76:
1.17 cvs 77: /*----------------------------------------------------------------------*/
78:
1.4 cvs 79: /*** private variables ***/
1.17 cvs 80:
1.4 cvs 81: static HTList *converters = NULL; /* List of global converters */
1.27 cvs 82: static HTList *acceptTypes = NULL; /* List of types for the Accept header */
1.4 cvs 83: static HTList *encodings = NULL;
1.16 cvs 84: static int object_counter = 0; /* loaded objects counter */
1.24 cvs 85: static boolean AmayaIsAlive;
1.4 cvs 86:
1.15 cvs 87: #include "answer_f.h"
88: #include "query_f.h"
89: #include "AHTURLTools_f.h"
90: #include "AHTBridge_f.h"
91: #include "AHTMemConv_f.h"
92: #include "AHTFWrite_f.h"
1.4 cvs 93:
1.70 cvs 94: #ifdef _WINDOWS
95: #ifdef __STDC__
96: int WIN_Activate_Request (HTRequest* , HTAlertOpcode, int, const char*, void*, HTAlertPar*);
97: #else
98: int WIN_Activate_Request ();
99: #endif /* __STDC__ */
100: #endif /* _WINDOWS */
1.15 cvs 101:
102: /*----------------------------------------------------------------------
1.17 cvs 103: GetDocIdStatus
104: gets the status associated to a docid
1.15 cvs 105: ----------------------------------------------------------------------*/
106: #ifdef __STDC__
107: AHTDocId_Status *GetDocIdStatus (int docid, HTList * documents)
108: #else
109: AHTDocID_Status *GetDocIdStatus (docid, documents)
110: int docid;
111: HTList *documents;
112:
113: #endif
114: {
115: AHTDocId_Status *me;
116: HTList *cur;
117:
118: if (documents)
119: {
120: cur = documents;
121:
122: while ((me = (AHTDocId_Status *) HTList_nextObject (cur)))
123: {
124: if (me->docid == docid)
125: return (me);
1.18 cvs 126: }
127: }
1.15 cvs 128: return (AHTDocId_Status *) NULL;
129:
130: }
131:
1.5 cvs 132: /*----------------------------------------------------------------------
1.27 cvs 133: AHTGuessAtom_for
134: Converts an Amaya type descriptor into the equivalent MIME type.
135: ----------------------------------------------------------------------*/
136: #ifdef __STDC__
137: static HTAtom *AHTGuessAtom_for (char *urlName, PicType contentType)
138: #else
139: static HTAtom *AHTGuessAtom_for (urlName, contentType)
140: char *urlName;
141: PicType contentType;
142: #endif
143: {
144: HTAtom *atom;
145: char *filename;
146: HTEncoding enc;
147: HTEncoding cte;
148: HTLanguage lang;
1.50 cvs 149: double quality = 1.0;
1.27 cvs 150:
151: switch (contentType)
152: {
153: case xbm_type:
154: atom = HTAtom_for("image/xbm");
155: break;
156: case eps_type:
1.35 cvs 157: atom = HTAtom_for("application/postscript");
1.27 cvs 158: break;
159: case xpm_type:
160: atom = HTAtom_for("image/xpm");
161: break;
162: case gif_type:
163: atom = HTAtom_for("image/gif");
164: break;
165: case jpeg_type:
166: atom = HTAtom_for("image/jpeg");
167: break;
168: case png_type:
169: atom = HTAtom_for("image/png");
170: break;
171: case unknown_type:
172: default:
173: /*
174: ** Amaya could not detect the type, so
175: ** we try to use the filename's suffix to do so.
176: */
1.45 cvs 177: filename = AmayaParseUrl (urlName, "", AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION);
1.27 cvs 178: HTBind_getFormat (filename, &atom, &enc, &cte, &lang, &quality);
1.45 cvs 179: TtaFreeMemory (filename);
1.27 cvs 180: if (atom == WWW_UNKNOWN)
181: /*
182: ** we could not identify the suffix, so we assign it
183: ** a default type
184: */
185: atom = HTAtom_for ("text/html");
186: break;
187: }
188:
189: return atom;
190: }
191:
192: /*----------------------------------------------------------------------
1.17 cvs 193: AHTReqContext_new
194: create a new Amaya Context Object and update the global Amaya
195: request status.
1.5 cvs 196: ----------------------------------------------------------------------*/
1.4 cvs 197: #ifdef __STDC__
198: static AHTReqContext *AHTReqContext_new (int docid)
199: #else
200: static AHTReqContext *AHTReqContext_new (docid)
201: int docid;
202:
203: #endif
204: {
205: AHTReqContext *me;
206: AHTDocId_Status *docid_status;
207:
208: if ((me = (AHTReqContext *) TtaGetMemory (sizeof (AHTReqContext))) == NULL)
209: outofmem (__FILE__, "Context_new");
210:
1.81 cvs 211: /* Bind the Context object together with the Request Object */
212: me->request = HTRequest_new ();
213:
1.80 cvs 214: /* clean the associated file structure) */
1.79 cvs 215: HTRequest_setOutputStream (me->request, NULL);
1.81 cvs 216:
1.4 cvs 217: /* Initialize the other members of the structure */
1.17 cvs 218: me->reqStatus = HT_NEW; /* initial status of a request */
1.4 cvs 219: me->output = NULL;
1.89 cvs 220: me->content_type = NULL;
1.51 cvs 221: # ifndef _WINDOWS
1.4 cvs 222: me->read_xtinput_id = (XtInputId) NULL;
223: me->write_xtinput_id = (XtInputId) NULL;
224: me->except_xtinput_id = (XtInputId) NULL;
1.51 cvs 225: # endif
1.4 cvs 226: me->docid = docid;
227: HTRequest_setMethod (me->request, METHOD_GET);
228: HTRequest_setOutputFormat (me->request, WWW_SOURCE);
229: HTRequest_setContext (me->request, me);
230: me->read_ops = 0;
231: me->write_ops = 0;
232: me->except_ops = 0;
1.36 cvs 233: /* experimental */
234: me->read_sock = INVSOC;
235: me->write_sock = INVSOC;
236: me->except_sock = INVSOC;
1.4 cvs 237:
238: /* Update the global context */
239: HTList_appendObject (Amaya->reqlist, (void *) me);
240:
241: docid_status = GetDocIdStatus (docid, Amaya->docid_status);
242:
1.7 cvs 243: if (docid_status == NULL)
244: {
245: docid_status = (AHTDocId_Status *) TtaGetMemory (sizeof (AHTDocId_Status));
246: docid_status->docid = docid;
247: docid_status->counter = 1;
248: HTList_addObject (Amaya->docid_status, (void *) docid_status);
249: }
250: else
1.4 cvs 251: docid_status->counter++;
252:
253:
254: Amaya->open_requests++;
255:
256: /* error stream handling */
257: me->error_stream = (char *) NULL;
258: me->error_stream_size = 0;
1.74 cvs 259:
260: #ifdef DEBUG_LIBWWW
261: fprintf (stderr, "AHTReqContext_new: Created object %p\n", me);
262: #endif
1.4 cvs 263: return me;
1.74 cvs 264:
1.4 cvs 265: }
266:
1.5 cvs 267: /*----------------------------------------------------------------------
1.17 cvs 268: AHTReqContext_delete
269: Delete an Amaya Context Object and update the global Amaya request
270: status.
1.5 cvs 271: ----------------------------------------------------------------------*/
1.4 cvs 272:
273: #ifdef __STDC__
1.15 cvs 274: boolean AHTReqContext_delete (AHTReqContext * me)
1.4 cvs 275: #else
1.15 cvs 276: boolean AHTReqContext_delete (me)
1.4 cvs 277: AHTReqContext *me;
278:
279: #endif
280: {
281: AHTDocId_Status *docid_status;
282:
1.7 cvs 283: if (me)
284: {
1.4 cvs 285:
1.74 cvs 286: #ifdef DEBUG_LIBWWW
287: fprintf (stderr, "AHTReqContext_delete: Deleting object %p\n", me);
288: #endif
289:
1.7 cvs 290: if (Amaya->reqlist)
291: HTList_removeObject (Amaya->reqlist, (void *) me);
1.4 cvs 292:
1.7 cvs 293: docid_status = GetDocIdStatus (me->docid, Amaya->docid_status);
1.4 cvs 294:
1.7 cvs 295: if (docid_status)
296: {
297: docid_status->counter--;
298:
299: if (docid_status->counter == 0)
300: {
301: HTList_removeObject (Amaya->docid_status, (void *) docid_status);
302: TtaFreeMemory ((void *) docid_status);
303: }
304: }
1.99 ! cvs 305: /* is this necessary??? */
1.79 cvs 306: if (HTRequest_outputStream (me->request))
307: AHTFWriter_FREE (me->request->output_stream);
1.7 cvs 308: HTRequest_delete (me->request);
1.85 cvs 309:
1.89 cvs 310: if (me->output && me->output != stdout)
1.85 cvs 311: {
312: #ifdef DEBUG_LIBWWW
313: fprintf (stderr, "AHTReqContext_delete: URL is %s, closing "
314: "FILE %p\n", me->urlName, me->output);
315: #endif
316: fclose (me->output);
317: me->output = NULL;
318: }
1.79 cvs 319:
1.7 cvs 320: if (me->error_stream != (char *) NULL)
1.70 cvs 321: HT_FREE (me->error_stream);
322: # ifndef _WINDOWS
323: # ifdef WWW_XWINDOWS
1.21 cvs 324: if (me->read_xtinput_id || me->write_xtinput_id ||
325: me->except_xtinput_id)
326: RequestKillAllXtevents(me);
1.70 cvs 327: # endif /* WWW_XWINDOWS */
328: # endif /* !_WINDOWS */
1.74 cvs 329:
1.99 ! cvs 330: if (me->reqStatus == HT_ABORT)
! 331: {
! 332: if (me->outputfile && me->outputfile[0] != EOS)
! 333: {
! 334: TtaFileUnlink (me->outputfile);
! 335: me->outputfile[0] = EOS;
! 336: }
! 337: }
! 338:
1.74 cvs 339: if ((me->mode & AMAYA_ASYNC) || (me->mode & AMAYA_IASYNC))
340: /* for the ASYNC mode, free the memory we allocated in GetObjectWWW
341: or in PutObjectWWW */
342: {
1.79 cvs 343: if (me->urlName)
344: TtaFreeMemory (me->urlName);
345: if (me->outputfile)
346: TtaFreeMemory (me->outputfile);
1.99 ! cvs 347: if (me->content_type)
! 348: TtaFreeMemory (me->content_type);
1.74 cvs 349: }
350:
1.99 ! cvs 351: if (me->mode & AMAYA_FORM_POST)
! 352: TtaFreeMemory (me->mem_ptr);
! 353:
1.7 cvs 354: TtaFreeMemory ((void *) me);
1.4 cvs 355:
1.7 cvs 356: Amaya->open_requests--;
1.4 cvs 357:
1.15 cvs 358: return TRUE;
1.4 cvs 359:
1.7 cvs 360: }
1.15 cvs 361: return FALSE;
1.4 cvs 362: }
363:
364:
1.15 cvs 365: /*----------------------------------------------------------------------
366: AHTUpload_callback
1.17 cvs 367: callback handler for executing the PUT command
1.15 cvs 368: ----------------------------------------------------------------------*/
1.4 cvs 369: #ifdef __STDC__
370: static int AHTUpload_callback (HTRequest * request, HTStream * target)
371: #else
372: static int AHTUpload_callback (request, target)
373: HTRequest *request;
374: HTStream *target;
375:
376: #endif
377: {
378: AHTReqContext *me = HTRequest_context (request);
1.7 cvs 379: HTParentAnchor *entity = HTRequest_entityAnchor (request);
380: int len = HTAnchor_length (entity);
1.4 cvs 381: int status;
382:
383: /* Send the data down the pipe */
1.7 cvs 384:
1.4 cvs 385: status = (*target->isa->put_block) (target, me->mem_ptr, len);
386:
1.7 cvs 387: if (status == HT_LOADED || status == HT_OK)
388: {
1.13 cvs 389: if (PROT_TRACE)
390: HTTrace ("Posting Data Target is SAVED\n");
391: (*target->isa->flush) (target);
392: return (HT_LOADED);
1.7 cvs 393: }
394: if (status == HT_WOULD_BLOCK)
395: {
396: if (PROT_TRACE)
397: HTTrace ("Posting Data Target WOULD BLOCK\n");
1.74 cvs 398: #ifdef _WINDOWS
399: return HT_CONTINUE;
400: #else
401: return HT_WOULD_BLOCK;
402: #endif /* _WINDOWS */
403:
1.7 cvs 404: return HT_WOULD_BLOCK;
405: }
406: else if (status == HT_PAUSE)
407: {
408: if (PROT_TRACE)
409: HTTrace ("Posting Data Target PAUSED\n");
410: return HT_PAUSE;
411: }
412: else if (status > 0)
413: { /* Stream specific return code */
414: if (PROT_TRACE)
415: HTTrace ("Posting Data. Target returns %d\n", status);
416: return status;
417: }
418: else
419: { /* we have a real error */
420: if (PROT_TRACE)
421: HTTrace ("Posting Data Target ERROR %d\n", status);
422: return status;
423: }
1.4 cvs 424: }
425:
1.5 cvs 426: /*----------------------------------------------------------------------
1.17 cvs 427: Thread_deleteAll
428: this function deletes the whole list of active threads.
1.5 cvs 429: ----------------------------------------------------------------------*/
1.4 cvs 430: #ifdef __STDC__
431: static void Thread_deleteAll (void)
432: #else
433: static void Thread_deleteAll ()
434: #endif
435: {
1.21 cvs 436: HTList *cur;
437: AHTReqContext *me;
438: AHTDocId_Status *docid_status;
439:
1.74 cvs 440: if (Amaya && Amaya->reqlist)
441: {
442: if (Amaya->open_requests > 0)
443: #ifdef DEBUG_LIBWWW
444: fprintf (stderr, "Thread_deleteAll: Killing %d outstanding "
445: "requests\n", Amaya->open_requests);
446: #endif
447: {
448: cur = Amaya->reqlist;
449:
450: /* erase the requests */
451: while ((me = (AHTReqContext *) HTList_removeLastObject (cur)))
452: {
453: if (me->request)
454: {
1.70 cvs 455: # ifndef _WINDOWS
1.74 cvs 456: RequestKillAllXtevents (me);
1.70 cvs 457: # endif /* !_WINDOWS */
1.92 cvs 458:
459: if (me->request->net)
460: HTRequest_kill (me->request);
1.96 cvs 461: #ifndef _WINDOWS
462: AHTReqContext_delete (me);
463: #endif /* _WINDOWS */
1.74 cvs 464: }
465: } /* while */
466:
467: /* erase the docid_status entities */
468: while ((docid_status = (AHTDocId_Status *) HTList_removeLastObject ((void *) Amaya->docid_status)))
469: TtaFreeMemory ((void *) docid_status);
470:
471: } /* if */
1.84 cvs 472:
1.74 cvs 473: }
1.4 cvs 474: }
475:
1.5 cvs 476: /*----------------------------------------------------------------------
1.83 cvs 477: AHTOpen_file
478: ----------------------------------------------------------------------*/
479: #ifdef __STDC__
1.85 cvs 480: int AHTOpen_file (HTRequest * request)
1.83 cvs 481: #else
1.85 cvs 482: int AHTOpen_file (request)
1.83 cvs 483: HTRequest *request;
484:
485: #endif /* __STDC__ */
486: {
487: AHTReqContext *me; /* current request */
488:
489: me = HTRequest_context (request);
490:
1.93 cvs 491:
492: if (!me)
493: return HT_ERROR;
494:
1.83 cvs 495: #ifdef DEBUG_LIBWWW
1.85 cvs 496: fprintf(stderr, "AHTOpen_file: start\n");
497: #endif /* DEBUG_LIBWWW */
498:
499: if (me->reqStatus == HT_ABORT)
500: {
501: #ifdef DEBUG_LIBWWW
502: fprintf(stderr, "AHTOpen_file: caught an abort request, skipping it\n");
1.83 cvs 503: #endif /* DEBUG_LIBWWW */
504:
1.85 cvs 505: return HT_OK;
506: }
507:
508: if (HTRequest_outputStream (me->request))
509: {
510:
511: #ifdef DEBUG_LIBWWW
512: fprintf(stderr, "AHTOpen_file: output stream already existed for url %s\n", me->urlName);
513: #endif /* DEBUG_LIBWWW */
514: return HT_OK;
515: }
516:
517: #ifdef DEBUG_LIBWWW
518: fprintf(stderr, "AHTOpen_file: opening output stream for url %s\n", me->urlName);
519: #endif /* DEBUG_LIBWWW */
520:
1.83 cvs 521: if (!(me->output) &&
522: (me->output != stdout) &&
523: #ifndef _WINDOWS
524: (me->output = fopen (me->outputfile, "w")) == NULL)
525: {
526: #else
527: (me->output = fopen (me->outputfile, "wb")) == NULL)
528: {
529: #endif /* !_WINDOWS */
530:
531: me->outputfile[0] = '\0'; /* file could not be opened */
1.85 cvs 532: #ifdef DEBUG_LIBWWW
533: fprintf(stderr, "AHTOpen_file: couldn't open output stream for url %s\n", me->urlName);
534: #endif
1.83 cvs 535: TtaSetStatus (me->docid, 1,
536: TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE),
537: me->outputfile);
538: me->reqStatus = HT_ERR;
539: return (HT_ERROR);
540: }
541:
542: HTRequest_setOutputStream (me->request,
543: AHTFWriter_new (me->request,
544: me->output, YES));
545: me->reqStatus = HT_WAITING;
546:
547: return HT_OK;
548: }
549:
550: /*----------------------------------------------------------------------
1.17 cvs 551: redirection_handler
552: this function is registered to handle permanent and temporary
553: redirections.
554: ----------------------------------------------------------------------*/
1.4 cvs 555: #ifdef __STDC__
1.7 cvs 556: static int redirection_handler (HTRequest * request, HTResponse * response, void *param, int status)
1.4 cvs 557: #else
558: static int redirection_handler (request, context, status)
559: HTRequest *request;
560: HTResponse *response;
561: void *param;
562: int status;
563:
564: #endif
565: {
566:
567: HTAnchor *new_anchor = HTResponse_redirection (response);
1.7 cvs 568: AHTReqContext *me = HTRequest_context (request);
1.4 cvs 569: HTMethod method = HTRequest_method (request);
1.98 cvs 570: char *ref;
571: char *tmp;
1.4 cvs 572:
1.7 cvs 573: if (!new_anchor)
574: {
575: if (PROT_TRACE)
576: HTTrace ("Redirection. No destination\n");
577: return HT_OK;
578: }
1.4 cvs 579:
580: /*
581: ** Only do redirect on GET and HEAD
582: */
1.7 cvs 583: if (!HTMethod_isSafe (method))
584: {
585: HTAlertCallback *prompt = HTAlert_find (HT_A_CONFIRM);
586: if (prompt)
587: {
588: if ((*prompt) (request, HT_A_CONFIRM, HT_MSG_REDIRECTION,
589: NULL, NULL, NULL) != YES)
590: return HT_ERROR;
591: }
592: }
1.4 cvs 593:
594: /*
595: ** Start new request with the redirect anchor found in the headers.
596: ** Note that we reuse the same request object which means that we must
597: ** keep this around until the redirected request has terminated. It also
598: ** allows us in an easy way to keep track of the number of redirections
599: ** so that we can detect endless loops.
600: */
1.17 cvs 601:
1.7 cvs 602: if (HTRequest_doRetry (request))
603: {
604: /* do we need to normalize the URL? */
605: if (strncmp (new_anchor->parent->address, "http:", 5))
606: {
607: /* Yes, so we use the pre-redirection anchor as a base name */
1.74 cvs 608: ref = AmayaParseUrl (new_anchor->parent->address,
609: me->urlName, AMAYA_PARSE_ALL);
1.7 cvs 610: if (ref)
611: {
1.98 cvs 612: HT_FREE (new_anchor->parent->address);
613: tmp = NULL;
614: HTSACopy (&tmp, ref);
615: new_anchor->parent->address = tmp;
616: TtaFreeMemory (ref);
1.7 cvs 617: }
1.98 cvs 618: else
619: return HT_ERROR; /* We can't redirect anymore */
1.7 cvs 620: }
621:
622: /* update the current file name */
1.21 cvs 623: if (strlen (new_anchor->parent->address) > (MAX_LENGTH - 2))
1.7 cvs 624: {
1.74 cvs 625: strncpy (me->urlName, new_anchor->parent->address,
626: MAX_LENGTH - 1);
1.21 cvs 627: me->urlName[MAX_LENGTH - 1] = EOS;
1.7 cvs 628: }
629: else
1.74 cvs 630: strcpy (me->urlName, new_anchor->parent->address);
1.7 cvs 631:
1.38 cvs 632: ChopURL (me->status_urlName, me->urlName);
633:
1.7 cvs 634: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_RED_FETCHING),
1.38 cvs 635: me->status_urlName);
1.7 cvs 636:
637: /* Start request with new credentials */
1.64 cvs 638:
1.79 cvs 639: if (HTRequest_outputStream (me->request) != NULL) {
1.85 cvs 640: AHTFWriter_FREE (request->output_stream);
641: if (me->output != stdout) { /* Are we writing to a file? */
1.74 cvs 642: #ifdef DEBUG_LIBWWW
1.79 cvs 643: fprintf (stderr, "redirection_handler: New URL is %s, closing "
1.74 cvs 644: "FILE %p\n", me->urlName, me->output);
645: #endif
1.79 cvs 646: fclose (me->output);
647: me->output = NULL;
648: }
1.64 cvs 649: }
1.68 cvs 650:
1.69 cvs 651: me->reqStatus = HT_NEW; /* reset the status */
1.7 cvs 652: if (me->method == METHOD_PUT || me->method == METHOD_POST) /* PUT, POST etc. */
1.74 cvs 653: status = HTLoadAbsolute (me->urlName, request);
1.7 cvs 654: else
1.74 cvs 655: HTLoadAnchor (new_anchor, request);
1.7 cvs 656: }
657: else
1.68 cvs 658: {
1.74 cvs 659: HTRequest_addError (request, ERR_FATAL, NO, HTERR_MAX_REDIRECT,
660: NULL, 0, "HTRedirectFilter");
661: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_REDIRECTIONS_LIMIT),
662: NULL);
663: if (me->error_html)
664: DocNetworkStatus[me->docid] |= AMAYA_NET_ERROR;
665: /* so that we can show the error message */
1.68 cvs 666: }
667:
1.4 cvs 668: /*
1.74 cvs 669: ** By returning HT_ERROR we make sure that this is the last handler to be
670: ** called. We do this as we don't want any other filter to delete the
671: ** request object now when we have just started a new one ourselves
672: */
1.4 cvs 673: return HT_ERROR;
674: }
675:
1.5 cvs 676: /*----------------------------------------------------------------------
1.17 cvs 677: terminate_handler
678: this function is registered to handle the result of the request
1.5 cvs 679: ----------------------------------------------------------------------*/
1.4 cvs 680: #if __STDC__
1.7 cvs 681: static int terminate_handler (HTRequest * request, HTResponse * response, void *context, int status)
1.4 cvs 682: #else
683: static int terminate_handler (request, response, context, status)
684: HTRequest *request;
685: HTResponse *response;
686: void *context;
687: int status;
688: #endif
689: {
690: AHTReqContext *me = (AHTReqContext *) HTRequest_context (request);
1.13 cvs 691: boolean error_flag;
1.4 cvs 692:
693: if (!me)
1.74 cvs 694: return HT_OK; /* not an Amaya request */
695:
1.80 cvs 696: /* if Amaya was killed, treat with this request as if it were
697: issued by a Stop button event */
698: if (!AmayaIsAlive)
699: me->reqStatus = HT_ABORT;
1.74 cvs 700:
1.77 cvs 701: if (status == HT_LOADED ||
702: status == HT_CREATED ||
1.79 cvs 703: status == HT_NO_DATA ||
704: me->reqStatus == HT_ABORT)
1.74 cvs 705: error_flag = FALSE;
1.13 cvs 706: else
1.74 cvs 707: error_flag = TRUE;
708:
1.4 cvs 709: /* output any errors from the server */
1.74 cvs 710:
1.77 cvs 711: /*
1.74 cvs 712: ** me->output = output file which will receive an html file
713: ** me->error_html = yes, output HTML errors in the screen
714: ** request->error_stack == if there are any errors, they will be here
715: ** me->error_stream_size If it's != 0 means an error message has already
716: ** been written to the stack
717: */
718:
1.4 cvs 719: /* First, we verify if there are any errors and if they are not
1.17 cvs 720: ** yet written to the error stack. If no, then let's try to write them
721: ** ourselves
722: */
1.74 cvs 723:
724: #ifdef DEBUG_LIBWWW
725: fprintf (stderr, "terminate_handler: URL is "
726: "%s, closing FILE %p status is %d\n", me->urlName, me->output,
727: status);
1.69 cvs 728: #endif
1.74 cvs 729:
1.69 cvs 730: if (me->output && me->output != stdout)
731: {
1.74 cvs 732: /* we are writing to a file */
733: if (me->reqStatus != HT_ABORT)
734: { /* if the request was not aborted and */
1.80 cvs 735: if (error_flag &&
736: me->error_html == TRUE)
737: /* there were some errors and we want to print them */
738: {
739: if (me->error_stream_size == 0)/* and the stream is empty */
740: AHTError_MemPrint (request); /* copy errors from
1.74 cvs 741: **the error stack
1.77 cvs 742: ** into the error stream */
1.80 cvs 743: if (me->error_stream)
744: { /* if the stream is non-empty */
745: fprintf (me->output, me->error_stream);/* output the errors */
1.85 cvs 746: /* Clear the error context, so that we can deal with
747: this answer as if it were a normal reply */
748: HTError_deleteAll( HTRequest_error (request));
749: HTRequest_setError (request, NULL);
750: error_flag = 0;
1.74 cvs 751: }
752: } /* if error_stack */
1.85 cvs 753: }
754:
755: /* if != HT_ABORT */
756:
757: #ifdef DEBUG_LIBWWW
758: fprintf (stderr, "terminate_handler: URL is %s, closing "
759: "FILE %p\n", me->urlName, me->output);
760: #endif
1.74 cvs 761: fclose (me->output);
762: me->output = NULL;
1.69 cvs 763: }
1.80 cvs 764:
1.74 cvs 765:
1.80 cvs 766: if (error_flag)
767: me->reqStatus = HT_ERR;
768: else if (me->reqStatus != HT_ABORT)
769: me->reqStatus = HT_END;
770:
1.88 cvs 771: /* copy the content_type */
772:
773: {
774: char *content_type = request->anchor->content_type->name;
775:
776: if (content_type && content_type [0] && me->content_type)
777: {
778: /* libwww gives www/unknown when it gets an error. As this is
779: an HTML test, we force the type to text/html */
780: if (!strcmp (content_type, "www/unknown"))
781: {
782: strcpy (me->content_type, "text/html");
783: }
784: else
785: {
786: strncpy (me->content_type, content_type,
787: NAME_LENGTH -1);
788: me->content_type [NAME_LENGTH-1] = '\0';
789:
790: /* Content-Type can be specified by a server's admin. To be on
791: the safe side, we normalize its case */
792: ConvertToLowerCase (me->content_type);
793: }
794: #ifdef DEBUG_LIBWWW
795: fprintf (stderr, "content type is: %s\n", me->content_type);
796: #endif /* DEBUG_LIBWWW */
797: }
798: }
799:
1.80 cvs 800: /* don't remove or Xt will hang up during the PUT */
1.28 cvs 801: if (AmayaIsAlive && ((me->method == METHOD_POST) ||
802: (me->method == METHOD_PUT)))
1.7 cvs 803: {
1.80 cvs 804: PrintTerminateStatus (me, status);
805:
806: }
807:
1.91 cvs 808: ProcessTerminateRequest (me);
1.71 cvs 809:
810: return HT_OK;
1.4 cvs 811: }
812:
1.5 cvs 813: /*----------------------------------------------------------------------
1.17 cvs 814: AHTLoadTerminate_handler
1.74 cvs 815: this is an application "AFTER" Callback. It's called by the library
816: when a request has ended, so that we can setup the correct status.
1.5 cvs 817: ----------------------------------------------------------------------*/
1.4 cvs 818:
819: #ifdef __STDC__
1.7 cvs 820: static int AHTLoadTerminate_handler (HTRequest * request, HTResponse * response, void *param, int status)
1.4 cvs 821: #else
822: static int AHTLoadTerminate_handler (request, response, param, status)
823: HTRequest *request;
824: HTResponse *response;
825: void *param;
826: int status;
1.69 cvs 827:
1.4 cvs 828: #endif
829: {
830: AHTReqContext *me = HTRequest_context (request);
831: HTAlertCallback *cbf;
832: AHTDocId_Status *docid_status;
833:
1.7 cvs 834: switch (status)
835: {
836: case HT_LOADED:
837: if (PROT_TRACE)
838: HTTrace ("Load End.... OK: `%s\' has been accessed\n",
1.38 cvs 839: me->status_urlName);
1.4 cvs 840:
1.7 cvs 841: docid_status = GetDocIdStatus (me->docid,
842: Amaya->docid_status);
843:
844: if (docid_status != NULL && docid_status->counter > 1)
1.74 cvs 845: TtaSetStatus (me->docid, 1,
846: TtaGetMessage (AMAYA, AM_ELEMENT_LOADED),
847: me->status_urlName);
1.7 cvs 848: break;
849:
850: case HT_NO_DATA:
851: if (PROT_TRACE)
1.74 cvs 852: HTTrace ("Load End.... OK BUT NO DATA: `%s\'\n",
853: me->status_urlName);
854: TtaSetStatus (me->docid, 1,
855: TtaGetMessage (AMAYA, AM_LOADED_NO_DATA),
1.38 cvs 856: me->status_urlName);
1.7 cvs 857: break;
858:
859: case HT_INTERRUPTED:
860: if (PROT_TRACE)
1.74 cvs 861: HTTrace ("Load End.... INTERRUPTED: `%s\'\n",
862: me->status_urlName);
863: TtaSetStatus (me->docid, 1,
864: TtaGetMessage (AMAYA, AM_LOAD_ABORT),
865: NULL);
1.7 cvs 866: break;
867:
868: case HT_RETRY:
869: if (PROT_TRACE)
870: HTTrace ("Load End.... NOT AVAILABLE, RETRY AT %ld\n",
871: HTResponse_retryTime (response));
1.74 cvs 872: TtaSetStatus (me->docid, 1,
873: TtaGetMessage (AMAYA, AM_NOT_AVAILABLE_RETRY),
1.38 cvs 874: me->status_urlName);
1.7 cvs 875: break;
876:
877: case HT_ERROR:
878:
879: cbf = HTAlert_find (HT_A_MESSAGE);
880: if (cbf)
881: (*cbf) (request, HT_A_MESSAGE, HT_MSG_NULL, NULL,
882: HTRequest_error (request), NULL);
883: break;
884:
885: if (PROT_TRACE)
886: HTTrace ("Load End.... ERROR: Can't access `%s\'\n",
1.74 cvs 887: me->status_urlName ? me->status_urlName :"<UNKNOWN>");
888: TtaSetStatus (me->docid, 1,
889: TtaGetMessage (AMAYA, AM_CANNOT_LOAD),
1.38 cvs 890: me->status_urlName ? me->status_urlName : "<UNKNOWN>");
1.7 cvs 891: break;
892: default:
893: if (PROT_TRACE)
894: HTTrace ("Load End.... UNKNOWN RETURN CODE %d\n", status);
895: break;
896: }
897:
1.4 cvs 898: return HT_OK;
899: }
900:
1.27 cvs 901: /*----------------------------------------------------------------------
902: AHTAcceptTypesInit
1.74 cvs 903: This function prepares the Accept header used by Amaya during
904: the HTTP content negotiation phase
1.27 cvs 905: ----------------------------------------------------------------------*/
906: #ifdef __STDC__
907: static void AHTAcceptTypesInit (HTList *c)
908: #else /* __STDC__ */
909: static void AHTAcceptTypesInit (c)
910: HTList *c;
911: #endif /* __STDC__ */
912: {
913: if (c == (HTList *) NULL)
914: return;
915:
916: /* define here all the mime types that Amaya can accept */
917:
1.74 cvs 918: HTConversion_add (c, "image/png", "www/present",
919: HTThroughLine, 1.0, 0.0, 0.0);
920: HTConversion_add (c, "image/jpeg", "www/present",
921: HTThroughLine, 1.0, 0.0, 0.0);
922: HTConversion_add (c, "image/gif", "www/present",
923: HTThroughLine, 1.0, 0.0, 0.0);
924: HTConversion_add (c, "image/xbm", "www/present",
925: HTThroughLine, 1.0, 0.0, 0.0);
926: HTConversion_add (c, "image/xpm", "www/present",
927: HTThroughLine, 1.0, 0.0, 0.0);
928: HTConversion_add (c, "application/postscript",
929: "www/present", HTThroughLine, 1.0, 0.0, 0.0);
1.4 cvs 930:
1.27 cvs 931: /* Define here the equivalences between MIME types and file extensions for
932: the types that Amaya can display */
933:
934: /* Register the default set of file suffix bindings */
935: HTFileInit ();
936:
937: /* Don't do any case distinction */
938: HTBind_caseSensitive (FALSE);
939: }
1.4 cvs 940:
1.5 cvs 941: /*----------------------------------------------------------------------
1.17 cvs 942: AHTConverterInit
943: Bindings between a source media type and a destination media type
944: (conversion).
1.5 cvs 945: ----------------------------------------------------------------------*/
1.15 cvs 946: #ifdef __STDC__
947: static void AHTConverterInit (HTList *c)
948: #else /* __STDC__ */
949: static void AHTConverterInit (c)
950: HTList *c;
951: #endif /* __STDC__ */
1.4 cvs 952: {
953:
954: /* Handler for custom http error messages */
1.7 cvs 955: HTConversion_add (c, "*/*", "www/debug", AHTMemConverter, 1.0, 0.0, 0.0);
1.4 cvs 956:
957: /*
958: ** These are converters that converts to something other than www/present,
959: ** that is not directly outputting someting to the user on the screen
960: */
961:
962: HTConversion_add (c, "message/rfc822", "*/*", HTMIMEConvert, 1.0, 0.0, 0.0);
963: HTConversion_add (c, "message/x-rfc822-foot", "*/*", HTMIMEFooter,
964: 1.0, 0.0, 0.0);
965: HTConversion_add (c, "message/x-rfc822-head", "*/*", HTMIMEHeader,
966: 1.0, 0.0, 0.0);
967: HTConversion_add (c, "multipart/*", "*/*", HTBoundary,
968: 1.0, 0.0, 0.0);
969: HTConversion_add (c, "text/plain", "text/html", HTPlainToHTML,
970: 1.0, 0.0, 0.0);
971:
972:
973: /*
974: ** The following conversions are converting ASCII output from various
975: ** protocols to HTML objects.
976: */
977: HTConversion_add (c, "text/x-http", "*/*", HTTPStatus_new,
978: 1.0, 0.0, 0.0);
979: HTConversion_add (c, "text/x-nntp-list", "*/*", HTNewsList,
980: 1.0, 0.0, 0.0);
981: HTConversion_add (c, "text/x-nntp-over", "*/*", HTNewsGroup,
982: 1.0, 0.0, 0.0);
983:
984:
985: /*
986: ** We also register a special content type guess stream that can figure out
987: ** the content type by reading the first bytes of the stream
988: */
989: HTConversion_add (c, "www/unknown", "*/*", HTGuess_new,
990: 1.0, 0.0, 0.0);
991:
992: /*
993: ** Register a persistent cache stream which can save an object to local
994: ** file
995: */
996: HTConversion_add (c, "www/cache", "*/*", HTCacheWriter,
997: 1.0, 0.0, 0.0);
998:
999: /*
1000: ** This dumps all other formats to local disk without any further
1001: ** action taken
1002: */
1003: HTConversion_add (c, "*/*", "www/present", HTSaveLocally,
1004: 0.3, 0.0, 0.0);
1005:
1006: }
1007:
1.27 cvs 1008:
1.15 cvs 1009: /*----------------------------------------------------------------------
1.17 cvs 1010: AHTProtocolInit
1011: Registers all amaya supported protocols.
1.15 cvs 1012: ----------------------------------------------------------------------*/
1.4 cvs 1013: static void AHTProtocolInit (void)
1014: {
1015:
1.17 cvs 1016: /*
1.74 cvs 1017: NB. Preemptive == YES means Blocking requests
1018: Non-preemptive == NO means Non-blocking requests
1.17 cvs 1019: */
1.4 cvs 1020:
1.63 cvs 1021: HTProtocol_add ("http", "buffered_tcp", NO, HTLoadHTTP, NULL);
1.4 cvs 1022: /* HTProtocol_add ("http", "tcp", NO, HTLoadHTTP, NULL); */
1023: HTProtocol_add ("file", "local", NO, HTLoadFile, NULL);
1024: HTProtocol_add ("cache", "local", NO, HTLoadCache, NULL);
1.36 cvs 1025: HTProtocol_add ("ftp", "tcp", NO, HTLoadFTP, NULL);
1.17 cvs 1026: #if 0 /* experimental code */
1.4 cvs 1027: HTProtocol_add ("telnet", "", YES, HTLoadTelnet, NULL);
1028: HTProtocol_add ("tn3270", "", YES, HTLoadTelnet, NULL);
1029: HTProtocol_add ("rlogin", "", YES, HTLoadTelnet, NULL);
1030: HTProtocol_add ("nntp", "tcp", NO, HTLoadNews, NULL);
1031: HTProtocol_add ("news", "tcp", NO, HTLoadNews, NULL);
1.17 cvs 1032: #endif
1.4 cvs 1033: }
1034:
1.15 cvs 1035: /*----------------------------------------------------------------------
1.17 cvs 1036: AHTNetInit
1037: Reegisters "before" and "after" request filters.
1.15 cvs 1038: ----------------------------------------------------------------------*/
1.4 cvs 1039: static void AHTNetInit (void)
1040: {
1041:
1042: /* Register BEFORE filters
1.74 cvs 1043: ** The BEFORE filters handle proxies, caches, rule files etc.
1044: ** The filters are called in the order by which the are registered
1045: ** Not done automaticly - may be done by application!
1046: */
1047:
1.4 cvs 1048:
1.74 cvs 1049: HTNet_addBefore (HTCredentialsFilter, "http://*", NULL, 6);
1050: HTNet_addBefore (HTProxyFilter, NULL, NULL, 10);
1.85 cvs 1051: /* HTNet_addBefore (AHTOpen_file, NULL, NULL, 11); */
1052: HTHost_setActivateRequestCallback (AHTOpen_file);
1.4 cvs 1053:
1054: /* register AFTER filters
1.74 cvs 1055: ** The AFTER filters handle error messages, logging, redirection,
1056: ** authentication etc.
1057: ** The filters are called in the order by which the are registered
1058: ** Not done automaticly - may be done by application!
1059: */
1.4 cvs 1060:
1.82 cvs 1061: HTNet_addAfter (HTAuthFilter, "http://*", NULL, HT_NO_ACCESS, HT_FILTER_MIDDLE);
1062: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_TEMP_REDIRECT, HT_FILTER_MIDDLE);
1063: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_PERM_REDIRECT, HT_FILTER_MIDDLE);
1064: HTNet_addAfter (HTUseProxyFilter, "http://*", NULL, HT_USE_PROXY, HT_FILTER_MIDDLE);
1.51 cvs 1065: HTNet_addAfter (AHTLoadTerminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
1066: /* handles all errors */
1.7 cvs 1067: HTNet_addAfter (terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
1.4 cvs 1068: }
1069:
1.15 cvs 1070: /*----------------------------------------------------------------------
1.17 cvs 1071: AHTAlertInit
1072: Register alert messages and their callbacks.
1.15 cvs 1073: ----------------------------------------------------------------------*/
1074: #ifdef __STDC__
1075: static void AHTAlertInit (void)
1076: #else
1077: static void AHTAlertInit ()
1078: #endif
1079: {
1080: HTAlert_add (AHTProgress, HT_A_PROGRESS);
1.70 cvs 1081: # ifndef _WINDOWS
1.83 cvs 1082: /* HTAlert_add ((HTAlertCallback *) Add_NewSocket_to_Loop, HT_PROG_CONNECT); */
1.70 cvs 1083: # else /* _WINDOWS */
1084: HTAlert_add ((HTAlertCallback *) WIN_Activate_Request, HT_PROG_CONNECT);
1085: # endif /* _WINDOWS */
1.15 cvs 1086: HTAlert_add (AHTError_print, HT_A_MESSAGE);
1.48 cvs 1087: HTError_setShow (~((unsigned int) 0 ) & ~((unsigned int) HT_ERR_SHOW_DEBUG)); /* process all messages except debug ones*/
1.15 cvs 1088: HTAlert_add (AHTConfirm, HT_A_CONFIRM);
1089: HTAlert_add (AHTPrompt, HT_A_PROMPT);
1090: HTAlert_add (AHTPromptPassword, HT_A_SECRET);
1091: HTAlert_add (AHTPromptUsernameAndPassword, HT_A_USER_PW);
1092: }
1093:
1094: /*----------------------------------------------------------------------
1.97 cvs 1095: ProxyInit
1096: Reads any proxies settings which may be declared as environmental
1097: variables or in the thot.ini file. The former overrides the latter.
1098: ----------------------------------------------------------------------*/
1099: static void ProxyInit (void)
1100: {
1101: char *strptr;
1102: char *str = NULL;
1103: char *name;
1104:
1105: /* get the proxy settings from the thot.ini file */
1106: strptr = (char *) TtaGetEnvString ("HTTP_PROXY");
1107: if (strptr && *strptr)
1108: HTProxy_add ("http", strptr);
1109: /* get the no_proxy settings from the thot.ini file */
1110: strptr = (char *) TtaGetEnvString ("NO_PROXY");
1111: if (strptr && *strptr)
1112: {
1113: str = TtaStrdup (strptr); /* Get copy we can mutilate */
1114: strptr = str;
1115: while ((name = HTNextField (&strptr)) != NULL) {
1116: char *portstr = strchr (name, ':');
1117: unsigned port=0;
1118: if (portstr) {
1119: *portstr++ = '\0';
1120: if (*portstr) port = (unsigned) atoi(portstr);
1121: }
1122: /* Register it for all access methods */
1123: HTNoProxy_add (name, NULL, port);
1124: }
1125: TtaFreeMemory (str);
1126: }
1127:
1128: /* use libw3's routine to get all proxy settings from the environment */
1129: HTProxy_getEnvVar ();
1130:
1131: }
1132:
1133:
1134: /*----------------------------------------------------------------------
1.17 cvs 1135: AHTProfile_newAmaya
1136: creates the Amaya client profile for libwww.
1.15 cvs 1137: ----------------------------------------------------------------------*/
1138: #ifdef __STDC__
1139: static void AHTProfile_newAmaya (char *AppName, char *AppVersion)
1140: #else /* __STDC__ */
1141: static void AHTProfile_newAmaya (AppName, AppVersion)
1142: char *AppName;
1143: char *AppVersion;
1144: #endif /* __STDC__ */
1.4 cvs 1145: {
1146: /* If the Library is not already initialized then do it */
1147: if (!HTLib_isInitialized ())
1148: HTLibInit (AppName, AppVersion);
1149:
1150: if (!converters)
1151: converters = HTList_new ();
1.27 cvs 1152: if (!acceptTypes)
1153: acceptTypes = HTList_new ();
1.4 cvs 1154: if (!encodings)
1155: encodings = HTList_new ();
1156:
1157: /* Register the default set of transport protocols */
1158: HTTransportInit ();
1159:
1160: /* Register the default set of application protocol modules */
1161: AHTProtocolInit ();
1162:
1163: /* Enable the persistent cache */
1164: /* HTCacheInit (NULL, 20); */
1165:
1166: /* Register the default set of BEFORE and AFTER filters */
1167: AHTNetInit ();
1168:
1169: /* Set up the default set of Authentication schemes */
1170: HTAAInit ();
1171:
1.97 cvs 1172: /* Get any proxy settings */
1173: ProxyInit ();
1.4 cvs 1174:
1175: /* Register the default set of converters */
1176: AHTConverterInit (converters);
1.27 cvs 1177: AHTAcceptTypesInit (acceptTypes);
1.4 cvs 1178: HTFormat_setConversion (converters);
1179:
1180: /* Register the default set of transfer encoders and decoders */
1181: HTEncoderInit (encodings); /* chunks ??? */
1182: HTFormat_setTransferCoding (encodings);
1183:
1184: /* Register the default set of MIME header parsers */
1.74 cvs 1185: HTMIMEInit (); /* must be called again for language selector */
1.4 cvs 1186:
1187: /* Register the default set of Icons for directory listings */
1.27 cvs 1188: /*HTIconInit(NULL); *//* experimental */
1.4 cvs 1189:
1190: /* Register the default set of messages and dialog functions */
1191: AHTAlertInit ();
1192: HTAlert_setInteractive (YES);
1193: }
1194:
1.5 cvs 1195: /*----------------------------------------------------------------------
1.17 cvs 1196: AHTProfile_delete
1197: deletes the Amaya client profile.
1.5 cvs 1198: ----------------------------------------------------------------------*/
1.4 cvs 1199: #ifdef __STDC__
1200: static void AHTProfile_delete (void)
1201: #else
1202: static void AHTProfile_delete ()
1.7 cvs 1203: #endif /* __STDC__ */
1.4 cvs 1204: {
1.22 cvs 1205:
1206: /* free the Amaya global context */
1.74 cvs 1207: if (!converters)
1208: HTConversion_deleteAll (converters);
1209: if (!acceptTypes)
1210: HTConversion_deleteAll (acceptTypes);
1211: if (!encodings)
1212: HTCoding_deleteAll (encodings);
1213:
1214: HTList_delete (Amaya->docid_status);
1215: HTList_delete (Amaya->reqlist);
1216: TtaFreeMemory (Amaya);
1217: {
1.61 cvs 1218:
1.74 cvs 1219: if (HTLib_isInitialized ())
1220:
1.61 cvs 1221: # ifdef _WINDOWS
1222: HTEventTerminate ();
1223: # endif _WINDOWS;
1.74 cvs 1224:
1225: /* Clean up the persistent cache (if any) */
1226: HTCacheTerminate ();
1227:
1228: /* Clean up all the global preferences */
1229: HTFormat_deleteAll ();
1230:
1231: /* Terminate libwww */
1232: HTLibTerminate ();
1233: }
1.4 cvs 1234: }
1235:
1.5 cvs 1236: /*----------------------------------------------------------------------
1.17 cvs 1237: QueryInit
1238: initializes the libwww interface
1.5 cvs 1239: ----------------------------------------------------------------------*/
1.4 cvs 1240: #ifdef __STDC__
1241: void QueryInit ()
1242: #else
1243: void QueryInit ()
1244: #endif
1245: {
1246:
1.24 cvs 1247: AmayaIsAlive = TRUE;
1.4 cvs 1248: AHTProfile_newAmaya (HTAppName, HTAppVersion);
1249:
1.69 cvs 1250: /* New AHTBridge stuff */
1.4 cvs 1251:
1.54 cvs 1252: # ifdef _WINDOWS
1.75 cvs 1253: AHTEventInit ();
1.54 cvs 1254: # endif _WINDOWS;
1.72 cvs 1255:
1.70 cvs 1256: HTEvent_setRegisterCallback (AHTEvent_register);
1.78 cvs 1257: /*** a effacer ***/
1258: HTEvent_setUnregisterCallback (AHTEvent_unregister);
1259: /*** ***/
1.4 cvs 1260:
1.72 cvs 1261: # ifndef _WINDOWS
1262: HTEvent_setUnregisterCallback (AHTEvent_unregister);
1263: # endif /* _WINDOWS */
1264:
1.74 cvs 1265: #ifdef DEBUG_LIBWWW
1266: WWW_TraceFlag = SHOW_CORE_TRACE | SHOW_THREAD_TRACE | PROT_TRACE;
1267: #endif
1.4 cvs 1268:
1269: /* Trace activation (for debugging) */
1.7 cvs 1270: /*
1.4 cvs 1271: WWW_TraceFlag = SHOW_APP_TRACE | SHOW_UTIL_TRACE |
1272: SHOW_BIND_TRACE | SHOW_THREAD_TRACE |
1273: SHOW_STREAM_TRACE | SHOW_PROTOCOL_TRACE |
1274: SHOW_URI_TRACE | SHOW_AUTH_TRACE | SHOW_ANCHOR_TRACE |
1275: SHOW_CORE_TRACE;
1276:
1.7 cvs 1277: */
1.4 cvs 1278:
1279: /***
1280: WWW_TraceFlag = SHOW_CORE_TRACE | SHOW_AUTH_TRACE | SHOW_ANCHOR_TRACE |
1281: SHOW_PROTOCOL_TRACE| SHOW_APP_TRACE | SHOW_UTIL_TRACE;
1282: ***/
1283:
1284: /* Setting up other user interfaces */
1285:
1286: /* Setting up different network parameters */
1.17 cvs 1287: /* Maximum number of simultaneous open sockets */
1.4 cvs 1288: HTNet_setMaxSocket (8);
1.75 cvs 1289: /* different network services timeouts */
1.4 cvs 1290: HTDNS_setTimeout (3600);
1.75 cvs 1291: #ifdef _WINDOWS
1292: /* under windows, the libwww persistent socket handling has
1293: ** some bugs. The following line inhibits idle socket reusal.
1294: ** this is a bit slower, but avoids crashes and gives us time
1295: ** to distribute Amaya before having to patch up libwww.
1296: */
1.76 cvs 1297: HTHost_setPersistTimeout (-1L);
1.75 cvs 1298: #else
1.76 cvs 1299: HTHost_setPersistTimeout (60L);
1.75 cvs 1300: #endif /* _WINDOWS */
1301:
1.17 cvs 1302: /* Cache is disabled in this version */
1.4 cvs 1303: HTCacheMode_setEnabled (0);
1304:
1305: /* Initialization of the global context */
1306: Amaya = (AmayaContext *) TtaGetMemory (sizeof (AmayaContext));
1307: Amaya->reqlist = HTList_new ();
1308: Amaya->docid_status = HTList_new ();
1309: Amaya->open_requests = 0;
1.74 cvs 1310:
1.4 cvs 1311: #ifdef CATCH_SIG
1.18 cvs 1312: signal (SIGPIPE, SIG_IGN);
1.4 cvs 1313: #endif
1.94 cvs 1314:
1315: #if !defined(AMAYA_JAVA) && !defined(AMAYA_ILU) && defined (_WINDOWS)
1316: /* forces libwww to do sync request if true and if in MakeBook mode */
1317: WinMakeBookFlag = FALSE;
1318: #endif /* _WINDOWS */
1.15 cvs 1319: }
1320:
1.69 cvs 1321: #ifndef _WINDOWS
1.15 cvs 1322: /*----------------------------------------------------------------------
1.17 cvs 1323: LoopForStop
1324: a copy of the Thop event loop so we can handle the stop button.
1.69 cvs 1325: Not useful for windows code (Ramzi).
1.15 cvs 1326: ----------------------------------------------------------------------*/
1327: #ifdef __STDC__
1328: static int LoopForStop (AHTReqContext * me)
1329: #else
1330: static int LoopForStop (AHTReqContext * me)
1331: #endif
1332: {
1333:
1.25 cvs 1334: extern ThotAppContext app_cont;
1.51 cvs 1335: XEvent ev;
1336: XtInputMask status;
1.17 cvs 1337: int status_req = HT_OK;
1.15 cvs 1338:
1339: /* to test the async calls */
1.17 cvs 1340: /* Loop while waiting for new events, exists when the request is over */
1.15 cvs 1341: while (me->reqStatus != HT_ABORT &&
1342: me->reqStatus != HT_END &&
1.69 cvs 1343: me->reqStatus != HT_ERR) {
1344: if (!AmayaIsAlive)
1345: /* Amaya was killed by one of the callback handlers */
1346: exit (0);
1347:
1348: status = XtAppPending (app_cont);
1349: if (status & XtIMXEvent) {
1350: XtAppNextEvent (app_cont, &ev);
1351: TtaHandleOneEvent (&ev);
1352: } else if (status & (XtIMAll & (~XtIMXEvent))) {
1353: XtAppProcessEvent (app_cont, (XtIMAll & (~XtIMXEvent)));
1354: } else {
1355: XtAppNextEvent (app_cont, &ev);
1356: TtaHandleOneEvent (&ev);
1357: }
1358: }
1.4 cvs 1359:
1.69 cvs 1360: switch (me->reqStatus) {
1361: case HT_ERR:
1362: case HT_ABORT:
1.15 cvs 1363: status_req = HT_ERROR;
1364: break;
1365:
1.69 cvs 1366: case HT_END:
1.15 cvs 1367: status_req = HT_OK;
1368: break;
1369:
1.69 cvs 1370: default:
1.15 cvs 1371: break;
1.69 cvs 1372: }
1.15 cvs 1373: return (status_req);
1.4 cvs 1374: }
1.69 cvs 1375: #endif /* _WINDOWS */
1.4 cvs 1376:
1.5 cvs 1377: /*----------------------------------------------------------------------
1.15 cvs 1378: QueryClose
1.21 cvs 1379: closes all existing threads, frees all non-automatically deallocated
1380: memory and then ends libwww.
1.5 cvs 1381: ----------------------------------------------------------------------*/
1.4 cvs 1382: void QueryClose ()
1383: {
1.24 cvs 1384:
1385: AmayaIsAlive = FALSE;
1386:
1.21 cvs 1387: /* remove all the handlers and callbacks that may output a message to
1388: a non-existent Amaya window */
1389:
1390: HTNet_deleteAfter (AHTLoadTerminate_handler);
1391: HTNet_deleteAfter (redirection_handler);
1392: HTAlertCall_deleteAll (HTAlert_global () );
1.23 cvs 1393: HTAlert_setGlobal ((HTList *) NULL);
1.24 cvs 1394: HTEvent_setRegisterCallback ((HTEvent_registerCallback *) NULL);
1.27 cvs 1395: HTEvent_setUnregisterCallback ((HTEvent_unregisterCallback *) NULL);
1.87 cvs 1396: HTHost_setActivateRequestCallback (NULL);
1.4 cvs 1397: Thread_deleteAll ();
1.21 cvs 1398:
1.4 cvs 1399: HTProxy_deleteAll ();
1400: HTNoProxy_deleteAll ();
1401: HTGateway_deleteAll ();
1402: AHTProfile_delete ();
1403: }
1404:
1.99 ! cvs 1405:
! 1406: /*----------------------------------------------------------------------
! 1407: InvokeGetObjectWWW_callback
! 1408: A simple function to invoke a callback function whenever there's an error
! 1409: in GetObjectWWW
! 1410: ---------------------------------------------------------------------*/
! 1411:
! 1412: #ifdef _STDC
! 1413: void InvokeGetObjectWWW_callback (int docid, char *urlName, char *outputfile, TTcbf *terminate_cbf, void *context_cbf)
! 1414: #else
! 1415: void InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf, context_tcbf)
! 1416: int docid;
! 1417: char *urlName;
! 1418: char *outputfile;
! 1419: TTcbf *terminate_cbf;
! 1420: void *context_tcbf;
! 1421: #endif /* _STDC */
! 1422: {
! 1423: if (!terminate_cbf)
! 1424: return;
! 1425:
! 1426: (*terminate_cbf) (docid, -1, urlName, outputfile,
! 1427: NULL, context_tcbf);
! 1428: }
! 1429:
! 1430:
! 1431:
1.5 cvs 1432: /*----------------------------------------------------------------------
1.15 cvs 1433: GetObjectWWW
1.17 cvs 1434: this function requests a resource designated by a URLname into a
1435: temporary filename. The download can come from a simple GET operation,
1436: or can come from POSTING/GETTING a form. In the latter
1437: case, the function receives a query string to send to the server.
1438:
1.5 cvs 1439: 4 file retrieval modes are proposed:
1440: AMAYA_SYNC : blocking mode
1441: AMAYA_ISYNC : incremental, blocking mode
1442: AMAYA_ASYNC : non-blocking mode
1443: AMAYA_IASYNC : incremental, non-blocking mode
1444:
1445: In the incremental mode, each time a package arrives, it will be
1446: stored in the temporary file. In addition, if an
1447: incremental_callback function is defined, this function will be
1448: called and handled a copy of the newly received data package.
1449: Finally, if a terminate_callback function is defined, it will be
1450: invoked when the request terminates. The caller of this function
1.4 cvs 1451: can define two different contexts to be passed to the callback
1452: functions.
1453:
1454: When the function is called with the SYNC mode, the function will
1455: return only when the requested file has been loaded.
1456: The ASYNC mode will immediately return after setting up the
1457: call.
1458:
1459: Notes:
1460: At the end of a succesful request, the urlName string contains the
1461: name of the actually retrieved URL. As a URL can change over the time,
1462: (e.g., be redirected elsewhere), it is advised that the function
1.17 cvs 1463: caller verify the value of the urlName variable at the end of
1.4 cvs 1464: a request.
1465:
1466: Inputs:
1467: - docid Document identifier for the set of objects being
1468: retrieved.
1469: - urlName The URL to be retrieved (MAX_URL_LENGTH chars length)
1470: - outputfile A pointer to an empty string of MAX_URL_LENGTH.
1471: - mode The retrieval mode.
1472: - incremental_cbf
1473: - context_icbf
1474: Callback and context for the incremental modes
1475: - terminate_cbf
1476: - context_icbf
1477: Callback and context for a terminate handler
1.17 cvs 1478: -error_html if TRUE, then display any server error message as an
1479: HTML document.
1.88 cvs 1480: - content_type a string
1481:
1.4 cvs 1482: Outputs:
1483: - urlName The URL that was retrieved
1484: - outputfile The name of the temporary file which holds the
1485: retrieved data. (Only in case of success)
1.88 cvs 1486: - if content_type wasn't NULL, it will contain a copy of the parameter
1487: sent in the HTTP answer
1.4 cvs 1488: Returns:
1489: HT_ERROR
1490: HT_OK
1.5 cvs 1491:
1492: ----------------------------------------------------------------------*/
1.4 cvs 1493: #ifdef __STDC__
1.52 cvs 1494: int GetObjectWWW (int docid, char* urlName, char* postString, char* outputfile, int mode,
1495: TIcbf* incremental_cbf, void* context_icbf, TTcbf* terminate_cbf,
1.88 cvs 1496: void* context_tcbf, boolean error_html, char *content_type)
1.4 cvs 1497: #else
1.52 cvs 1498: int GetObjectWWW (docid, urlName, postString, outputfile, mode, incremental_cbf, context_icbf,
1.88 cvs 1499: terminate_cbf, context_tcbf, error_html, content_type)
1.73 cvs 1500: int docid;
1501: char *urlName;
1502: char *postString;
1503: char *outputfile;
1504: int mode;
1505: TIcbf *incremental_cbf;
1506: void *context_icbf;
1507: TTcbf *terminate_cbf;
1508: void *context_tcbf;
1509: boolean error_html;
1.88 cvs 1510: char *content_type;
1.4 cvs 1511: #endif
1512: {
1513: AHTReqContext *me;
1514: char *ref;
1515: int status;
1.7 cvs 1516:
1.69 cvs 1517: if (urlName == NULL || docid == 0 || outputfile == NULL) {
1518: /* no file to be loaded */
1519: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_BAD_URL), urlName);
1520:
1521: if (error_html)
1522: /* so we can show the error message */
1523: DocNetworkStatus[docid] |= AMAYA_NET_ERROR;
1.99 ! cvs 1524: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
! 1525: context_tcbf);
1.69 cvs 1526: return HT_ERROR;
1527: }
1.7 cvs 1528:
1.4 cvs 1529: /* do we support this protocol? */
1.69 cvs 1530: if (IsValidProtocol (urlName) == NO) {
1531: /* return error */
1532: outputfile[0] = EOS; /* file could not be opened */
1533: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_GET_UNSUPPORTED_PROTOCOL), urlName);
1534:
1535: if (error_html)
1536: /* so we can show the error message */
1537: DocNetworkStatus[docid] |= AMAYA_NET_ERROR;
1.99 ! cvs 1538: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
! 1539: context_tcbf);
1.69 cvs 1540: return HT_ERROR;
1541: }
1.4 cvs 1542:
1.58 cvs 1543: /*create a tempfilename */
1.59 cvs 1544: sprintf (outputfile, "%s%c%d%c%04dAM", TempFileDirectory, DIR_SEP, docid, DIR_SEP, object_counter);
1.4 cvs 1545:
1546: /* update the object_counter */
1547: object_counter++;
1548: /* normalize the URL */
1.45 cvs 1549: ref = AmayaParseUrl (urlName, "", AMAYA_PARSE_ALL);
1.4 cvs 1550: /* should we abort the request if we could not normalize the url? */
1.69 cvs 1551: if (ref == (char*) NULL || ref[0] == EOS) {
1552: /*error */
1553: outputfile[0] = EOS;
1554: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_BAD_URL), urlName);
1555:
1556: if (error_html)
1557: /* so we can show the error message */
1558: DocNetworkStatus[docid] |= AMAYA_NET_ERROR;
1.99 ! cvs 1559: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
! 1560: context_tcbf);
1.69 cvs 1561: return HT_ERROR;
1562: }
1.4 cvs 1563: /* verify if that file name existed */
1.9 cvs 1564: if (TtaFileExist (outputfile))
1.77 cvs 1565: TtaFileUnlink (outputfile);
1.4 cvs 1566:
1567: /* Initialize the request structure */
1568: me = AHTReqContext_new (docid);
1.69 cvs 1569: if (me == NULL) {
1.77 cvs 1570: outputfile[0] = EOS;
1571: /* need an error message here */
1572: TtaFreeMemory (ref);
1.99 ! cvs 1573: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
! 1574: context_tcbf);
! 1575: return HT_ERROR;
1.69 cvs 1576: }
1.77 cvs 1577:
1.4 cvs 1578: /* Specific initializations for POST and GET */
1.69 cvs 1579: if (mode & AMAYA_FORM_POST) {
1.77 cvs 1580: me->method = METHOD_POST;
1581: if (postString) {
1582: me->block_size = strlen (postString);
1.99 ! cvs 1583: me->mem_ptr = TtaStrdup (postString);
1.77 cvs 1584: } else {
1585: me->mem_ptr = "";
1586: me->block_size = 0;
1587: }
1588: HTRequest_setMethod (me->request, METHOD_POST);
1.69 cvs 1589: HTRequest_setPostCallback (me->request, AHTUpload_callback);
1590: } else {
1.77 cvs 1591: me->method = METHOD_GET;
1592: me->dest = (HTParentAnchor *) NULL; /*useful only for PUT and POST methods */
1593: if (!HasKnownFileSuffix (ref))
1594: HTRequest_setConversion(me->request, acceptTypes, TRUE);
1.69 cvs 1595: }
1.93 cvs 1596:
1597: #if !defined(AMAYA_JAVA) && !defined(AMAYA_ILU) && defined (_WINDOWS)
1598: /* forces libwww to do sync request if in MakeBook mode */
1599: if (WinMakeBookFlag)
1600: mode = AMAYA_SYNC;
1601: #endif /* _WINDOWS */
1602:
1.4 cvs 1603: /* Common initialization */
1604: me->mode = mode;
1605: me->error_html = error_html;
1606: me->incremental_cbf = incremental_cbf;
1607: me->context_icbf = context_icbf;
1608: me->terminate_cbf = terminate_cbf;
1609: me->context_tcbf = context_tcbf;
1.64 cvs 1610:
1.69 cvs 1611: /* for the async. request modes, we need to have our
1.4 cvs 1612: own copy of outputfile and urlname
1613: */
1614:
1.69 cvs 1615: if ((mode & AMAYA_ASYNC) || (mode & AMAYA_IASYNC)) {
1.77 cvs 1616: char* tmp;
1617:
1.69 cvs 1618: tmp = TtaGetMemory (strlen (outputfile) + 1);
1619: strcpy (tmp, outputfile);
1620: me->outputfile = tmp;
1621:
1622: tmp = TtaGetMemory (MAX_LENGTH + 1);
1623: strncpy (tmp, urlName, MAX_LENGTH);
1624: tmp[MAX_LENGTH] = EOS;
1625: me->urlName = tmp;
1.99 ! cvs 1626: me->content_type = TtaGetMemory (MAX_LENGTH + 1);
! 1627: me->content_type[MAX_LENGTH] = EOS;
1.69 cvs 1628: # ifdef _WINDOWS
1629: HTRequest_setPreemptive (me->request, NO);
1630: } else {
1.77 cvs 1631: me->outputfile = outputfile;
1632: me->urlName = urlName;
1633: HTRequest_setPreemptive (me->request, YES);
1.61 cvs 1634: }
1.99 ! cvs 1635: # else /* !_WINDOWS */
1.69 cvs 1636: } else {
1.77 cvs 1637: me->outputfile = outputfile;
1638: me->urlName = urlName;
1.99 ! cvs 1639: me->content_type = content_type;
1.61 cvs 1640: }
1.77 cvs 1641: /***
1.57 cvs 1642: Change for taking into account the stop button:
1643: The requests will be always asynchronous, however, if mode=AMAYA_SYNC,
1644: we will loop until the document has been received or a stop signal
1645: generated
1.77 cvs 1646: ****/
1647: HTRequest_setPreemptive (me->request, NO);
1.69 cvs 1648: # endif /* _WINDOWS */
1.61 cvs 1649:
1650: /* prepare the URLname that will be displayed in teh status bar */
1651: ChopURL (me->status_urlName, me->urlName);
1652:
1.77 cvs 1653: TtaSetStatus (me->docid, 1,
1654: TtaGetMessage (AMAYA, AM_FETCHING),
1655: me->status_urlName);
1.4 cvs 1656:
1657: me->anchor = (HTParentAnchor *) HTAnchor_findAddress (ref);
1.45 cvs 1658: TtaFreeMemory (ref);
1.4 cvs 1659:
1.69 cvs 1660: if (mode & AMAYA_FORM_POST) {
1661: HTAnchor_setFormat ((HTParentAnchor *) me->anchor, HTAtom_for ("application/x-www-form-urlencoded"));
1662: HTAnchor_setLength ((HTParentAnchor *) me->anchor, me->block_size);
1663: HTRequest_setEntityAnchor (me->request, me->anchor);
1664:
1665: status = HTLoadAbsolute (urlName, me->request);
1666: } else
1.77 cvs 1667: status = HTLoadAnchor ((HTAnchor *) me->anchor, me->request);
1.99 ! cvs 1668:
! 1669: if (status == HT_ERROR && me->reqStatus == HT_NEW)
! 1670: {
! 1671: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
! 1672: context_tcbf);
! 1673: }
1.69 cvs 1674:
1.72 cvs 1675: #ifndef _WINDOWS
1.77 cvs 1676: if (status == HT_ERROR ||
1677: me->reqStatus == HT_END ||
1678: me->reqStatus == HT_ERR)
1679: {
1680: /* in case of error, free all allocated memory and exit */
1.96 cvs 1681: if (me->output && me->output != stdout) {
1.85 cvs 1682: #ifdef DEBUG_LIBWWW
1.96 cvs 1683: fprintf (stderr, "GetObjectWWW:: URL is %s, closing "
1.85 cvs 1684: "FILE %p\n", me->urlName, me->output);
1685: #endif
1.77 cvs 1686: fclose (me->output);
1.82 cvs 1687: me->output = NULL;
1688: }
1689:
1.99 ! cvs 1690: if (me->reqStatus == HT_ERR) {
1.77 cvs 1691: status = HT_ERROR;
1692: /* show an error message on the status bar */
1693: DocNetworkStatus[me->docid] |= AMAYA_NET_ERROR;
1694: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_LOAD), me->
1695: status_urlName);
1.72 cvs 1696: } else
1.77 cvs 1697: status = HT_OK;
1.72 cvs 1698:
1699: AHTReqContext_delete (me);
1.77 cvs 1700: } else {
1.72 cvs 1701: /* part of the stop button handler */
1702: if ((mode & AMAYA_SYNC) || (mode & AMAYA_ISYNC)) {
1703: status = LoopForStop (me);
1704: AHTReqContext_delete (me);
1705: }
1706: }
1707: #else /* !_WINDOWS */
1708:
1.90 cvs 1709: if (status == HT_ERROR ||
1710: me->reqStatus == HT_ERROR)
1711: {
1712: status = HT_ERROR;
1.71 cvs 1713:
1.90 cvs 1714: /* in case of error, close any open files, free all allocated
1715: memory and exit */
1716: if (me->output && me->output != stdout)
1717: {
1.85 cvs 1718: #ifdef DEBUG_LIBWWW
1.90 cvs 1719: fprintf (stderr, "GetObjectWWW: URL is %s, closing "
1720: "FILE %p\n", me->urlName, me->output);
1.85 cvs 1721: #endif
1.90 cvs 1722: fclose (me->output);
1723: me->output = NULL;
1724: }
1.85 cvs 1725:
1.90 cvs 1726: if (me->reqStatus == HT_ERR)
1727: {
1728: /* show an error message on the status bar */
1729: DocNetworkStatus[me->docid] |= AMAYA_NET_ERROR;
1730: TtaSetStatus (me->docid, 1,
1731: TtaGetMessage (AMAYA, AM_CANNOT_LOAD),
1732: me->status_urlName);
1733: }
1734: }
1735: else
1736: {
1737: status = HT_OK;
1738: }
1739:
1.93 cvs 1740: /* part of the stop button handler */
1741: if ((mode & AMAYA_SYNC) || (mode & AMAYA_ISYNC))
1742: {
1743: if (HTRequest_net (me->request))
1744: HTRequest_kill (me->request);
1745: else
1746: AHTReqContext_delete (me);
1747: }
1.4 cvs 1748:
1.72 cvs 1749: #endif /* !_WINDOWS */
1750:
1.4 cvs 1751: return (status);
1752: }
1753:
1.5 cvs 1754: /*----------------------------------------------------------------------
1.17 cvs 1755: PutObjectWWW
1756: frontend for uploading a resource to a URL. This function downloads
1757: a file to be uploaded into memory, it then calls UploadMemWWW to
1758: finish the job.
1759:
1.5 cvs 1760: 2 upload modes are proposed:
1761: AMAYA_SYNC : blocking mode
1762: AMAYA_ASYNC : non-blocking mode
1763:
1.4 cvs 1764: When the function is called with the SYNC mode, the function will
1765: return only when the file has been uploaded.
1766: The ASYNC mode will immediately return after setting up the
1767: call. Furthermore, at the end of an upload, the ASYNC mode will
1768: call back terminate_cbf, handling it the context defined in
1769: context_tcbf.
1770:
1771: Notes:
1772: At the end of a succesful request, the urlName string contains the
1773: name of the actually uploaded URL. As a URL can change over the time,
1774: (e.g., be redirected elsewhere), it is advised that the function
1775: caller verifies the value of the urlName variable at the end of
1776: a request.
1777:
1778: Inputs:
1779: - docid Document identifier for the set of objects being
1780: retrieved.
1781: - fileName A pointer to the local file to upload
1782: - urlName The URL to be uploaded (MAX_URL_LENGTH chars length)
1783: - mode The retrieval mode.
1784: - terminate_cbf
1785: - context_icbf
1786: Callback and context for a terminate handler
1787:
1788: Outputs:
1789: - urlName The URL that was uploaded
1790:
1791: Returns:
1792: HT_ERROR
1793: HT_OK
1.5 cvs 1794: ----------------------------------------------------------------------*/
1.4 cvs 1795: #ifdef __STDC__
1.27 cvs 1796: int PutObjectWWW (int docid, char *fileName, char *urlName, int mode, PicType contentType,
1.4 cvs 1797: TTcbf * terminate_cbf, void *context_tcbf)
1798: #else
1.26 cvs 1799: int PutObjectWWW (docid, urlName, fileName, mode, contentType,
1.4 cvs 1800: ,terminate_cbf, context_tcbf)
1801: int docid;
1802: char *urlName;
1803: char *fileName;
1804: int mode;
1.27 cvs 1805: PicType contentType;
1.4 cvs 1806: TTcbf *terminate_cbf;
1807: void *context_tcbf;
1808:
1809: #endif
1810: {
1.7 cvs 1811: /*AHTReqContext *me; */
1.4 cvs 1812: int status;
1813:
1814: int fd;
1815: struct stat file_stat;
1816: char *mem_ptr;
1817: unsigned long block_size;
1818:
1.33 cvs 1819: AmayaLastHTTPErrorMsg [0] = EOS;
1820:
1.4 cvs 1821: if (urlName == NULL || docid == 0 || fileName == NULL ||
1.9 cvs 1822: !TtaFileExist (fileName))
1.4 cvs 1823: /* no file to be uploaded */
1824: return HT_ERROR;
1825:
1826: /* do we support this protocol? */
1.7 cvs 1827: if (IsValidProtocol (urlName) == NO)
1828: {
1829: /* return error */
1.77 cvs 1830: TtaSetStatus (docid, 1,
1831: TtaGetMessage (AMAYA, AM_PUT_UNSUPPORTED_PROTOCOL),
1.7 cvs 1832: urlName);
1833: return HT_ERROR;
1834: }
1.4 cvs 1835: /* read the file into memory */
1.70 cvs 1836: # ifndef _WINDOWS
1.7 cvs 1837: if ((fd = open (fileName, O_RDONLY)) == -1)
1.70 cvs 1838: # else /* _WINDOWS */
1.74 cvs 1839: if ((fd = open (fileName, _O_RDONLY | _O_BINARY)) == -1)
1.70 cvs 1840: # endif /* _WINDOWS */
1.7 cvs 1841: {
1842: /* if we could not open the file, exit */
1843: /*error msg here */
1844: return (HT_ERROR);
1845: }
1.4 cvs 1846:
1847: fstat (fd, &file_stat);
1848:
1.7 cvs 1849: if (file_stat.st_size == 0)
1850: {
1851: /* file was empty */
1852: /*errmsg here */
1853: close (fd);
1854: return (HT_ERROR);
1855: }
1.4 cvs 1856: block_size = file_stat.st_size;
1857:
1858: if (THD_TRACE)
1859: fprintf (stderr, "file size == %u\n", (unsigned) block_size);
1860:
1861: mem_ptr = (char *) TtaGetMemory (block_size);
1862:
1.7 cvs 1863: if (mem_ptr == (char *) NULL)
1864: {
1865: /* could not allocate enough memory */
1866: /*errmsg here */
1867: close (fd);
1868: return (HT_ERROR);
1869: }
1.4 cvs 1870: read (fd, mem_ptr, block_size);
1871:
1872: close (fd);
1873:
1.27 cvs 1874: status = UploadMemWWW (docid, METHOD_PUT, urlName, contentType, mem_ptr,
1.4 cvs 1875: block_size, mode, terminate_cbf,
1876: context_tcbf, (char *) NULL);
1877:
1878: TtaFreeMemory (mem_ptr);
1.28 cvs 1879: TtaHandlePendingEvents ();
1.4 cvs 1880: return (status);
1881: }
1882:
1.5 cvs 1883: /*----------------------------------------------------------------------
1.17 cvs 1884: UploadMemWWW
1885: low level interface function to libwww for uploading a block of
1886: memory to a URL.
1.5 cvs 1887: ----------------------------------------------------------------------*/
1.4 cvs 1888: #ifdef __STDC__
1889: int UploadMemWWW (int docid, HTMethod method,
1.27 cvs 1890: char *urlName, PicType contentType, char *mem_ptr, unsigned long block_size,
1.4 cvs 1891: int mode, TTcbf * terminate_cbf, void *context_tcbf,
1892: char *outputfile)
1893: #else
1.27 cvs 1894: int UploadMemWWW (docid, method, urlName, contentType, mem_ptr, block_size, mode,
1.4 cvs 1895: terminate_cbf, context_tcbf, outputfile)
1896: int docid;
1897: HTMethod method;
1898: char *urlName;
1.27 cvs 1899: PicType contentType;
1.4 cvs 1900: char *mem_ptr;
1901: usigned long block_size;
1902: int mode;
1903: TTcbf *terminate_cbf;
1904: void *context_tcbf;
1905: char *outputfile;
1.7 cvs 1906:
1.4 cvs 1907: #endif
1908: {
1909: AHTReqContext *me;
1910: int status;
1911:
1912: if (mem_ptr == (char *) NULL ||
1913: block_size == 0 ||
1914: docid == 0 ||
1.7 cvs 1915: urlName == (char *) NULL)
1916: {
1917: /* nothing to be uploaded */
1918: return HT_ERROR;
1919: }
1.4 cvs 1920:
1921: /* Initialize the request structure */
1922: me = AHTReqContext_new (docid);
1923:
1.7 cvs 1924: if (me == NULL)
1925: {
1926: /* need an error message here */
1927: TtaHandlePendingEvents ();
1928: return (HT_ERROR);
1929: }
1.4 cvs 1930: me->mode = mode;
1931:
1932: me->incremental_cbf = (TIcbf *) NULL;
1933: me->context_icbf = (void *) NULL;
1934: me->terminate_cbf = terminate_cbf;
1935: me->context_tcbf = context_tcbf;
1936:
1937: me->output = stdout;
1938: me->outputfile = (char *) NULL;
1939: me->urlName = urlName;
1940:
1.70 cvs 1941: #ifdef _WINDOWS
1942: HTRequest_setPreemptive (me->request, YES);
1943: #else
1.4 cvs 1944: HTRequest_setPreemptive (me->request, NO);
1.70 cvs 1945: #endif /* _WINDOWS */
1.74 cvs 1946:
1.17 cvs 1947: /* select the parameters that distinguish a PUT from a GET/POST */
1.4 cvs 1948: me->method = METHOD_PUT;
1949: HTRequest_setMethod (me->request, METHOD_PUT);
1950: me->output = stdout;
1.17 cvs 1951: /* we are not expecting to receive any input from the server */
1952: me->outputfile = (char *) NULL;
1.4 cvs 1953:
1954: me->mem_ptr = mem_ptr;
1955: me->block_size = block_size;
1.17 cvs 1956:
1957: /* set the callback which will actually copy data into the
1958: output stream */
1959:
1.4 cvs 1960: HTRequest_setPostCallback (me->request, AHTUpload_callback);
1.72 cvs 1961:
1.4 cvs 1962: me->anchor = (HTParentAnchor *) HTAnchor_findAddress (urlName);
1.7 cvs 1963:
1.28 cvs 1964: /* Set the Content-Type of the file we are uploading */
1.77 cvs 1965: HTAnchor_setFormat ((HTParentAnchor *) me->anchor,
1966: AHTGuessAtom_for (me->urlName, contentType));
1.17 cvs 1967:
1.7 cvs 1968: HTAnchor_setLength ((HTParentAnchor *) me->anchor, me->block_size);
1.4 cvs 1969: HTRequest_setEntityAnchor (me->request, me->anchor);
1.74 cvs 1970: /* prepare the URLname that will be displayed in teh status bar */
1971: ChopURL (me->status_urlName, me->urlName);
1972: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_REMOTE_SAVING),
1973: me->status_urlName);
1.4 cvs 1974: status = HTLoadAbsolute (urlName, me->request);
1975:
1.74 cvs 1976: #ifndef _WINDOWS
1.77 cvs 1977: if (status == HT_ERROR ||
1978: me->reqStatus == HT_END ||
1979: me->reqStatus == HT_ERR ||
1980: HTError_hasSeverity (HTRequest_error (me->request), ERR_INFO))
1.7 cvs 1981: {
1.17 cvs 1982: status = HT_ERROR;
1.28 cvs 1983: }
1.7 cvs 1984: else
1985: {
1986: /* part of the stop button handler */
1.4 cvs 1987:
1.7 cvs 1988: if ((mode & AMAYA_SYNC) || (mode & AMAYA_ISYNC))
1989: {
1990: status = LoopForStop (me);
1991: }
1.15 cvs 1992: }
1.90 cvs 1993: #else /* _WINDOWS */
1994: if (status == HT_ERROR ||
1995: me->reqStatus == HT_ERR) /* || Error_hasSeverity (HTRequest_error (me->request), ERR_INFO)) */
1996: status = HT_ERROR;
1997: else
1998: status = HT_OK;
1999: #endif /* _WINDOWS */
2000:
1.92 cvs 2001: if (HTRequest_net (me->request))
2002: {
2003: HTRequest_kill (me->request);
2004: }
1.93 cvs 2005: else
2006: AHTReqContext_delete (me);
1.4 cvs 2007: return (status);
1.28 cvs 2008: }
1.4 cvs 2009:
2010:
2011:
1.5 cvs 2012: /*----------------------------------------------------------------------
1.17 cvs 2013: Stop Request
2014: stops (kills) all active requests associated with a docid
1.5 cvs 2015: ----------------------------------------------------------------------*/
1.4 cvs 2016: #ifdef __STDC__
2017: void StopRequest (int docid)
2018: #else
2019: void StopRequest (docid)
2020: int docid;
2021: #endif
2022: {
2023: HTList *cur;
2024: AHTDocId_Status *docid_status;
2025: AHTReqContext *me;
2026: int open_requests;
2027:
1.84 cvs 2028: HTNet *reqNet;
2029: HTHost *reqHost;
1.85 cvs 2030: HTChannel *reqChannel;
2031: int reqSock;
2032:
1.7 cvs 2033: if (Amaya)
2034: {
2035: docid_status = (AHTDocId_Status *) GetDocIdStatus (docid,
1.4 cvs 2036: Amaya->docid_status);
1.7 cvs 2037: /* verify if there are any requests at all associated with docid */
1.4 cvs 2038:
1.7 cvs 2039: if (docid_status == (AHTDocId_Status *) NULL)
2040: return;
1.4 cvs 2041:
1.7 cvs 2042: open_requests = docid_status->counter;
1.4 cvs 2043:
1.85 cvs 2044: /* First, kill all pending requests */
2045: /* We first inhibit the activation of pending requests */
2046: HTHost_disable_PendingReqLaunch ();
2047: cur = Amaya->reqlist;
2048: while ((me = (AHTReqContext *) HTList_nextObject (cur)))
2049: {
2050: if (me->docid == docid && me->reqStatus == HT_NEW)
2051: {
2052: reqNet = HTRequest_net (me->request);
2053: reqSock = HTNet_socket (reqNet);
2054: reqChannel = HTChannel_find(reqSock);
2055: reqHost = HTChannel_host (reqChannel);
1.95 cvs 2056:
2057: /* If we have an ASYNC request, we kill it.
2058: ** If it's a SYNC request, we just mark it as aborted
2059: */
2060: me->reqStatus = HT_ABORT;
1.96 cvs 2061: if (HTRequest_net (me->request))
2062: /* delete the libwww request context */
2063: HTRequest_kill (me->request);
2064:
2065: #ifndef _WINDOWS
1.99 ! cvs 2066: if (!(me->mode & AMAYA_ASYNC_SAFE_STOP)
! 2067: && ((me->mode & AMAYA_IASYNC) ||
! 2068: (me->mode & AMAYA_ASYNC)))
1.85 cvs 2069: {
1.96 cvs 2070: /* delete the Amaya request context */
2071: AHTReqContext_delete (me);
2072: cur = Amaya->reqlist;
1.85 cvs 2073: }
1.96 cvs 2074: #else /* _WINDOWS */
2075: cur = Amaya->reqlist;
2076: #endif /* _WINDOWS */
1.95 cvs 2077:
2078: /* update the number of open requests */
2079: open_requests--;
1.85 cvs 2080:
2081: if (HTHost_isIdle (reqHost) ) {
2082: #ifdef DEBUG_LIBWWW
2083: fprintf (stderr, "Host is idle, killing socket %d\n",
1.95 cvs 2084: reqSock);
1.85 cvs 2085: #endif /* DEBUG_LIBWWW */
2086:
2087: HTEvent_unregister (reqSock, FD_ALL);
2088: HTEvent_register(reqSock, NULL, (SockOps) FD_READ,
2089: HTHost_catchClose, HT_PRIORITY_MAX);
2090: close (reqSock);
2091: /*
2092: if (reqChannel && reqHost)
2093: HTHost_clearChannel(reqHost, HT_OK);
2094: HTHost_catchClose (reqSock, NULL, FD_CLOSE);
2095: */
2096: }
2097: }
2098: }
2099: /* enable the activation of pending requests */
2100: HTHost_enable_PendingReqLaunch ();
2101:
2102: cur = Amaya->reqlist;
1.7 cvs 2103: while ((me = (AHTReqContext *) HTList_nextObject (cur)))
2104: {
2105: if (me->docid == docid)
2106: {
1.93 cvs 2107: /* kill this request */
1.85 cvs 2108:
1.93 cvs 2109: switch (me->reqStatus)
2110: {
2111: case HT_ABORT:
2112: break;
2113:
2114: case HT_BUSY:
2115: me->reqStatus = HT_ABORT;
2116: break;
1.96 cvs 2117:
1.93 cvs 2118: case HT_NEW_PENDING:
2119: case HT_WAITING:
2120: default:
2121: me->reqStatus = HT_ABORT;
2122:
1.70 cvs 2123: # ifndef _WINDOWS
1.93 cvs 2124: RequestKillAllXtevents (me);
1.74 cvs 2125: # endif _WINDOWS
1.96 cvs 2126:
1.93 cvs 2127: reqNet = HTRequest_net (me->request);
2128: reqSock = HTNet_socket (reqNet);
2129: reqChannel = HTChannel_find(reqSock);
2130: reqHost = HTChannel_host (reqChannel);
1.96 cvs 2131:
2132: if (HTRequest_net (me->request))
2133: HTRequest_kill (me->request);
2134:
2135: #ifndef _WINDOWS
1.99 ! cvs 2136: if (!(me->mode & AMAYA_ASYNC_SAFE_STOP)
! 2137: && ((me->mode & AMAYA_IASYNC)
! 2138: || (me->mode & AMAYA_ASYNC)))
1.93 cvs 2139: {
1.96 cvs 2140: AHTReqContext_delete (me);
2141: cur = Amaya->reqlist;
1.93 cvs 2142: }
1.96 cvs 2143: #else /* _WINDOWS */
2144: cur = Amaya->reqlist;
2145: #endif /* _WINDOWS */
1.95 cvs 2146:
1.93 cvs 2147: /* if there are no more requests, then close
2148: the connection */
2149:
2150: if (HTHost_isIdle (reqHost) ) {
1.85 cvs 2151: #ifdef DEBUG_LIBWWW
1.93 cvs 2152: fprintf (stderr, "Host is idle, "
2153: "killing socket %d\n",
2154: reqSock);
1.85 cvs 2155: #endif /* DEBUG_LIBWWW */
1.93 cvs 2156: HTEvent_unregister (reqSock, FD_ALL);
2157: HTEvent_register(reqSock,
2158: NULL,
2159: (SockOps) FD_READ,
2160: HTHost_catchClose,
2161: HT_PRIORITY_MAX);
2162: close (reqSock);
2163: HTHost_clearChannel (reqHost, HT_ERROR);
2164: /*
2165: if (reqChannel && reqHost)
2166: HTHost_clearChannel(reqHost, HT_OK);
2167: HTHost_catchClose (reqSock, NULL, FD_CLOSE);
2168: */
1.85 cvs 2169: #ifdef DEBUG_LIBWWW
1.93 cvs 2170: fprintf (stderr, "After killing, "
2171: "HTHost_isIdle gives %d\n",
2172: HTHost_isIdle (reqHost));
1.85 cvs 2173: #endif /* DEBUG_LIBWWW */
1.93 cvs 2174: }
2175:
2176: open_requests--;
2177:
2178: break;
2179:
2180: } /* switch */
1.7 cvs 2181: } /* if me docid */
2182: } /* while */
2183: } /* if amaya open requests */
1.93 cvs 2184:
1.85 cvs 2185: } /* StopRequest */
1.17 cvs 2186:
2187: /*
2188: end of Module query.c
2189: */
2190:
1.69 cvs 2191: #endif /* AMAYA_JAVA */
1.77 cvs 2192:
2193:
1.17 cvs 2194:
2195:
Webmaster