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