Annotation of Amaya/amaya/query.c, revision 1.24
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: /*
9: * query.c : contains all the functions for requesting iand publishing
10: * URLs via libwww. It handles any eventual HTTP error code
11: * (redirection, authentication needed, not found, etc.)
12: *
13: * Author: J. Kahan
14: *
15: */
1.17 cvs 16:
1.12 cvs 17: /* Amaya includes */
1.15 cvs 18: #define EXPORT extern
1.4 cvs 19: #include "amaya.h"
1.7 cvs 20:
1.4 cvs 21: #if defined(__svr4__)
22: #define CATCH_SIG
23: #endif
24:
1.17 cvs 25: /*----------------------------------------------------------------------*/
26:
1.4 cvs 27: /* local structures coming from libwww and which are
1.17 cvs 28: not found in any .h file
1.7 cvs 29: */
1.4 cvs 30:
1.7 cvs 31: struct _HTStream
32: {
1.15 cvs 33: const HTStreamClass *isa;
34: FILE *fp;
35: BOOL leave_open; /* Close file when HT_FREE? */
36: char *end_command; /* Command to execute */
37: BOOL remove_on_close; /* Remove file? */
38: char *filename; /* Name of file */
39: HTRequest *request; /* saved for callback */
40: HTRequestCallback *callback;
1.7 cvs 41: };
42:
1.15 cvs 43:
1.7 cvs 44: struct _HTError
45: {
46: HTErrorElement element; /* Index number into HTError */
47: HTSeverity severity; /* A la VMS */
48: BOOL ignore; /* YES if msg should not go to user */
49: void *par; /* Explanation, e.g. filename */
50: int length; /* For copying by generic routine */
51: char *where; /* Which function */
52: };
53:
54:
55: struct _HTHost
56: {
57: char *hostname; /* name of host + optional port */
58: time_t ntime; /* Creation time */
59: char *type; /* Peer type */
60: int version; /* Peer version */
61: HTMethod methods; /* Public methods (bit-flag) */
62: char *server; /* Server name */
63: char *user_agent; /* User Agent */
64: char *range_units; /* Acceptable range units */
65: HTTransportMode mode; /* Supported mode */
66: HTChannel *channel; /* Persistent channel */
67: HTList *pipeline; /* Pipe line of net objects */
68: HTList *pending; /* List of pending Net objects */
69: time_t expires; /* Persistent channel expires time */
70: };
1.4 cvs 71:
72: /* Type definitions and global variables etc. local to this module */
73:
1.17 cvs 74: /*----------------------------------------------------------------------*/
75:
1.4 cvs 76: /*** private variables ***/
1.17 cvs 77:
1.4 cvs 78: static HTList *converters = NULL; /* List of global converters */
79: static HTList *encodings = NULL;
1.16 cvs 80: static int object_counter = 0; /* loaded objects counter */
1.24 ! cvs 81: static boolean AmayaIsAlive;
1.4 cvs 82:
1.15 cvs 83: #include "answer_f.h"
84: #include "query_f.h"
85: #include "AHTURLTools_f.h"
86: #include "AHTBridge_f.h"
87: #include "AHTMemConv_f.h"
88: #include "AHTFWrite_f.h"
1.4 cvs 89:
1.15 cvs 90:
91: /*----------------------------------------------------------------------
1.17 cvs 92: GetDocIdStatus
93: gets the status associated to a docid
1.15 cvs 94: ----------------------------------------------------------------------*/
95: #ifdef __STDC__
96: AHTDocId_Status *GetDocIdStatus (int docid, HTList * documents)
97: #else
98: AHTDocID_Status *GetDocIdStatus (docid, documents)
99: int docid;
100: HTList *documents;
101:
102: #endif
103: {
104: AHTDocId_Status *me;
105: HTList *cur;
106:
107: if (documents)
108: {
109: cur = documents;
110:
111: while ((me = (AHTDocId_Status *) HTList_nextObject (cur)))
112: {
113: if (me->docid == docid)
114: return (me);
1.18 cvs 115: }
116: }
1.15 cvs 117: return (AHTDocId_Status *) NULL;
118:
119: }
120:
1.5 cvs 121: /*----------------------------------------------------------------------
1.17 cvs 122: AHTReqContext_new
123: create a new Amaya Context Object and update the global Amaya
124: request status.
1.5 cvs 125: ----------------------------------------------------------------------*/
1.4 cvs 126: #ifdef __STDC__
127: static AHTReqContext *AHTReqContext_new (int docid)
128: #else
129: static AHTReqContext *AHTReqContext_new (docid)
130: int docid;
131:
132: #endif
133: {
134: AHTReqContext *me;
135: AHTDocId_Status *docid_status;
136:
137: if ((me = (AHTReqContext *) TtaGetMemory (sizeof (AHTReqContext))) == NULL)
138: outofmem (__FILE__, "Context_new");
139:
140: /* Bind the Context object together with the Request Object */
141:
142: me->request = HTRequest_new ();
1.17 cvs 143:
1.4 cvs 144: /* Initialize the other members of the structure */
1.17 cvs 145: me->reqStatus = HT_NEW; /* initial status of a request */
1.4 cvs 146: me->output = NULL;
147: #ifdef WWW_XWINDOWS
148: me->read_xtinput_id = (XtInputId) NULL;
149: me->write_xtinput_id = (XtInputId) NULL;
150: me->except_xtinput_id = (XtInputId) NULL;
151: #endif
152: me->docid = docid;
153: HTRequest_setConversion (me->request, converters, YES);
154: HTRequest_setMethod (me->request, METHOD_GET);
155: HTRequest_setOutputFormat (me->request, WWW_SOURCE);
156: HTRequest_setContext (me->request, me);
157:
1.17 cvs 158: /* an interface to Eric's new routines */
1.4 cvs 159: me->read_ops = 0;
160: me->write_ops = 0;
161: me->except_ops = 0;
162:
163: /* Update the global context */
164: HTList_appendObject (Amaya->reqlist, (void *) me);
165:
166: docid_status = GetDocIdStatus (docid, Amaya->docid_status);
167:
1.7 cvs 168: if (docid_status == NULL)
169: {
170: docid_status = (AHTDocId_Status *) TtaGetMemory (sizeof (AHTDocId_Status));
171: docid_status->docid = docid;
172: docid_status->counter = 1;
173: HTList_addObject (Amaya->docid_status, (void *) docid_status);
174: }
175: else
1.4 cvs 176: docid_status->counter++;
177:
178:
179: Amaya->open_requests++;
180:
181: /* error stream handling */
182: me->error_stream = (char *) NULL;
183: me->error_stream_size = 0;
1.17 cvs 184:
1.4 cvs 185: return me;
186: }
187:
1.5 cvs 188: /*----------------------------------------------------------------------
1.17 cvs 189: AHTReqContext_delete
190: Delete an Amaya Context Object and update the global Amaya request
191: status.
1.5 cvs 192: ----------------------------------------------------------------------*/
1.4 cvs 193:
194: #ifdef __STDC__
1.15 cvs 195: boolean AHTReqContext_delete (AHTReqContext * me)
1.4 cvs 196: #else
1.15 cvs 197: boolean AHTReqContext_delete (me)
1.4 cvs 198: AHTReqContext *me;
199:
200: #endif
201: {
202: AHTDocId_Status *docid_status;
203:
1.7 cvs 204: if (me)
205: {
1.4 cvs 206:
1.7 cvs 207: if (Amaya->reqlist)
208: HTList_removeObject (Amaya->reqlist, (void *) me);
1.4 cvs 209:
1.7 cvs 210: docid_status = GetDocIdStatus (me->docid, Amaya->docid_status);
1.4 cvs 211:
1.7 cvs 212: if (docid_status)
213: {
214: docid_status->counter--;
215:
216: if (docid_status->counter == 0)
217: {
218: HTList_removeObject (Amaya->docid_status, (void *) docid_status);
219: TtaFreeMemory ((void *) docid_status);
220: }
221: }
222: HTRequest_delete (me->request);
1.4 cvs 223:
1.7 cvs 224: if (me->error_stream != (char *) NULL)
225: HT_FREE (me->error_stream);
1.21 cvs 226:
227: if (me->read_xtinput_id || me->write_xtinput_id ||
228: me->except_xtinput_id)
229: RequestKillAllXtevents(me);
1.4 cvs 230:
1.7 cvs 231: TtaFreeMemory ((void *) me);
1.4 cvs 232:
1.7 cvs 233: Amaya->open_requests--;
1.4 cvs 234:
1.15 cvs 235: return TRUE;
1.4 cvs 236:
1.7 cvs 237: }
1.15 cvs 238: return FALSE;
1.4 cvs 239: }
240:
241:
1.15 cvs 242: /*----------------------------------------------------------------------
243: AHTUpload_callback
1.17 cvs 244: callback handler for executing the PUT command
1.15 cvs 245: ----------------------------------------------------------------------*/
1.4 cvs 246: #ifdef __STDC__
247: static int AHTUpload_callback (HTRequest * request, HTStream * target)
248: #else
249: static int AHTUpload_callback (request, target)
250: HTRequest *request;
251: HTStream *target;
252:
253: #endif
254: {
255: AHTReqContext *me = HTRequest_context (request);
1.7 cvs 256: HTParentAnchor *entity = HTRequest_entityAnchor (request);
257: int len = HTAnchor_length (entity);
1.4 cvs 258: int status;
259:
260: /* Send the data down the pipe */
1.7 cvs 261:
1.4 cvs 262: status = (*target->isa->put_block) (target, me->mem_ptr, len);
263:
1.7 cvs 264: if (status == HT_LOADED || status == HT_OK)
265: {
1.13 cvs 266: if (PROT_TRACE)
267: HTTrace ("Posting Data Target is SAVED\n");
268: (*target->isa->flush) (target);
269: return (HT_LOADED);
1.7 cvs 270: }
271: if (status == HT_WOULD_BLOCK)
272: {
273: if (PROT_TRACE)
274: HTTrace ("Posting Data Target WOULD BLOCK\n");
275: return HT_WOULD_BLOCK;
276: }
277: else if (status == HT_PAUSE)
278: {
279: if (PROT_TRACE)
280: HTTrace ("Posting Data Target PAUSED\n");
281: return HT_PAUSE;
282: }
283: else if (status > 0)
284: { /* Stream specific return code */
285: if (PROT_TRACE)
286: HTTrace ("Posting Data. Target returns %d\n", status);
287: return status;
288: }
289: else
290: { /* we have a real error */
291: if (PROT_TRACE)
292: HTTrace ("Posting Data Target ERROR %d\n", status);
293: return status;
294: }
1.4 cvs 295: }
296:
1.5 cvs 297: /*----------------------------------------------------------------------
1.17 cvs 298: Thread_deleteAll
299: this function deletes the whole list of active threads.
1.5 cvs 300: ----------------------------------------------------------------------*/
1.4 cvs 301: #ifdef __STDC__
302: static void Thread_deleteAll (void)
303: #else
304: static void Thread_deleteAll ()
305: #endif
306: {
1.21 cvs 307: HTList *cur;
308: AHTReqContext *me;
309: AHTDocId_Status *docid_status;
310:
1.7 cvs 311: if (Amaya && Amaya->reqlist)
312: {
313: if (Amaya->open_requests > 0)
314: {
1.21 cvs 315: cur = Amaya->reqlist;
1.7 cvs 316:
317: HTNet_killAll ();
318: /* erase the requests */
319: while ((me = (AHTReqContext *) HTList_nextObject (cur)))
320: {
321: if (me->request)
322: {
1.4 cvs 323: #ifdef WWW_XWINDOWS
1.7 cvs 324: RequestKillAllXtevents (me);
1.4 cvs 325: #endif /* WWW_XWINDOWS */
1.7 cvs 326: AHTReqContext_delete (me);
327: }
328: } /* while */
1.21 cvs 329:
1.7 cvs 330: /* erase the docid_status entities */
331: while ((docid_status = (AHTDocId_Status *) HTList_removeLastObject ((void *) Amaya->docid_status)))
332: TtaFreeMemory ((void *) docid_status);
333:
334: } /* if */
335: }
1.4 cvs 336: }
337:
1.5 cvs 338: /*----------------------------------------------------------------------
1.17 cvs 339: redirection_handler
340: this function is registered to handle permanent and temporary
341: redirections.
342: ----------------------------------------------------------------------*/
1.4 cvs 343: #ifdef __STDC__
1.7 cvs 344: static int redirection_handler (HTRequest * request, HTResponse * response, void *param, int status)
1.4 cvs 345: #else
346: static int redirection_handler (request, context, status)
347: HTRequest *request;
348: HTResponse *response;
349: void *param;
350: int status;
351:
352: #endif
353: {
354:
355: char *ref;
356: HTAnchor *new_anchor = HTResponse_redirection (response);
1.7 cvs 357: AHTReqContext *me = HTRequest_context (request);
1.4 cvs 358: HTMethod method = HTRequest_method (request);
359:
360:
1.7 cvs 361: if (!new_anchor)
362: {
363: if (PROT_TRACE)
364: HTTrace ("Redirection. No destination\n");
365: return HT_OK;
366: }
1.4 cvs 367:
368: /*
369: ** Only do redirect on GET and HEAD
370: */
1.7 cvs 371: if (!HTMethod_isSafe (method))
372: {
373: HTAlertCallback *prompt = HTAlert_find (HT_A_CONFIRM);
374:
375: if (prompt)
376: {
377: if ((*prompt) (request, HT_A_CONFIRM, HT_MSG_REDIRECTION,
378: NULL, NULL, NULL) != YES)
379: return HT_ERROR;
380: }
381: }
1.4 cvs 382:
383: /*
384: ** Start new request with the redirect anchor found in the headers.
385: ** Note that we reuse the same request object which means that we must
386: ** keep this around until the redirected request has terminated. It also
387: ** allows us in an easy way to keep track of the number of redirections
388: ** so that we can detect endless loops.
389: */
1.17 cvs 390:
1.7 cvs 391: if (HTRequest_doRetry (request))
392: {
393:
394: /* Verify if this is not redundant */
395:
396: /* do we need to normalize the URL? */
397: if (strncmp (new_anchor->parent->address, "http:", 5))
398: {
399: /* Yes, so we use the pre-redirection anchor as a base name */
400: ref = HTParse (new_anchor->parent->address, me->urlName, PARSE_ALL);
401: if (ref)
402: {
403: HT_FREE (new_anchor->parent->address);
404: new_anchor->parent->address = ref;
405: }
406: }
407:
408: /* update the current file name */
1.21 cvs 409: if (strlen (new_anchor->parent->address) > (MAX_LENGTH - 2))
1.7 cvs 410: {
411: /*
412: ** copy MAX_LENGTH cars. The error will be detected later on and shown on the
413: ** screen. This code will be fixed up later on
414: */
1.21 cvs 415: strncpy (me->urlName, new_anchor->parent->address, MAX_LENGTH - 1);
416: me->urlName[MAX_LENGTH - 1] = EOS;
1.7 cvs 417: }
418: else
419: strcpy (me->urlName, new_anchor->parent->address);
420:
421: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_RED_FETCHING),
422: me->urlName);
423:
424: /* Start request with new credentials */
1.17 cvs 425: me->reqStatus = HT_NEW; /* reset the status */
1.7 cvs 426: if (me->method == METHOD_PUT || me->method == METHOD_POST) /* PUT, POST etc. */
427: status = HTLoadAbsolute (me->urlName, request);
428: else
429: HTLoadAnchor (new_anchor, request);
430: }
431: else
432: {
433: HTRequest_addError (request, ERR_FATAL, NO, HTERR_MAX_REDIRECT,
434: NULL, 0, "HTRedirectFilter");
435: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_REDIRECTIONS_LIMIT),
436: NULL);
437: if (me->error_html)
438: FilesLoading[me->docid] = 2; /* so we can show the error message */
439: }
1.4 cvs 440:
441: /*
1.7 cvs 442: ** By returning HT_ERROR we make sure that this is the last handler to be
443: ** called. We do this as we don't want any other filter to delete the
444: ** request object now when we have just started a new one ourselves
445: */
1.4 cvs 446: return HT_ERROR;
447: }
448:
1.5 cvs 449: /*----------------------------------------------------------------------
1.17 cvs 450: terminate_handler
451: this function is registered to handle the result of the request
1.5 cvs 452: ----------------------------------------------------------------------*/
1.4 cvs 453: #if __STDC__
1.7 cvs 454: static int terminate_handler (HTRequest * request, HTResponse * response, void *context, int status)
1.4 cvs 455: #else
456: static int terminate_handler (request, response, context, status)
457: HTRequest *request;
458: HTResponse *response;
459: void *context;
460: int status;
461:
462: #endif
463: {
464: AHTReqContext *me = (AHTReqContext *) HTRequest_context (request);
1.13 cvs 465: boolean error_flag;
1.4 cvs 466:
467: if (!me)
468: return HT_OK; /* not an Amaya request */
469:
1.24 ! cvs 470: if (!AmayaIsAlive)
! 471: me->reqStatus = HT_ABORT;
! 472:
1.13 cvs 473: if (status == HT_LOADED || status == HT_CREATED || status == HT_NO_DATA)
474: error_flag = FALSE;
475: else
476: error_flag = TRUE;
477:
1.4 cvs 478: /* output any errors from the server */
479:
1.5 cvs 480: /***
1.4 cvs 481: ** me->output = output file which will receive an html file
482: ** me->error_html = yes, output HTML errors in the screen
483: ** request->error_stack == if there are any errors, they will be here
484: ** me->error_stream_size If it's != 0 means an error message has already
485: ** been written to the stack
486: */
487:
488: /* First, we verify if there are any errors and if they are not
1.17 cvs 489: ** yet written to the error stack. If no, then let's try to write them
490: ** ourselves
491: */
1.4 cvs 492:
1.7 cvs 493: if (me->output && me->output != stdout)
494: {
495: /* we are writing to a file */
496: if (me->reqStatus != HT_ABORT)
497: { /* if the request was not aborted and */
1.13 cvs 498: if (error_flag)
499: { /* there were some errors */
1.15 cvs 500: if (me->error_html == TRUE)
1.13 cvs 501: { /* and we want to print errors */
502: if (me->error_stream_size == 0) /* and the stream is empty */
1.7 cvs 503: AHTError_MemPrint (request); /* copy errors from the error stack
504: ** into a data structure */
505: if (me->error_stream)
506: { /* if the stream is non-empty */
507: fprintf (me->output, me->error_stream); /* output the errors */
1.13 cvs 508: error_flag = FALSE; /* show it in the HTML window */
1.7 cvs 509: }
510: else
511: me->reqStatus = HT_ERR; /* we did not get an error msg,
512: ** so just
513: ** mark error
514: */
515: }
516: else
517: me->reqStatus = HT_ERR; /* we don't want to print the error */
518: } /* if error_stack */
1.13 cvs 519: } /* if != HT_ABORT */
1.7 cvs 520: fclose (me->output);
521: }
522: else
523: {
524: /* We must be doing a PUT. Verify if there was an error */
1.13 cvs 525: if (error_flag)
526: me->reqStatus = HT_ERR;
1.7 cvs 527: } /* if me-output */
528:
1.17 cvs 529: /* Second Step: choose a correct treatment in function of the request's
530: being associated with an error, with an interruption, or with a
531: succesful completion */
1.7 cvs 532:
1.13 cvs 533: if (!error_flag && me->reqStatus != HT_ERR
1.7 cvs 534: && me->reqStatus != HT_ABORT)
535: {
536: me->reqStatus = HT_END; /* no errors */
537: if (me->terminate_cbf)
538: (*me->terminate_cbf) ((AHTReqContext *) me,
539: HT_LOADED);
540: }
541: else if (me->reqStatus == HT_ABORT)
1.21 cvs 542: /* either the application ended or the user pressed the stop
543: button. We erase the incoming file, if it exists */
1.7 cvs 544: {
545: if (me->outputfile && me->outputfile[0] != EOS)
546: {
1.9 cvs 547: TtaFileUnlink (me->outputfile);
1.7 cvs 548: me->outputfile[0] = EOS;
549: }
550: }
551: else if (me->reqStatus == HT_ERR)
552: {
553: /* there was an error */
554: if (me->terminate_cbf)
555: (*me->terminate_cbf) ((AHTReqContext *) me,
556: HT_ERROR);
557:
558: if (me->outputfile && me->outputfile[0] != EOS)
559: {
1.9 cvs 560: TtaFileUnlink (me->outputfile);
1.7 cvs 561: me->outputfile[0] = EOS;
562: }
1.4 cvs 563: }
1.13 cvs 564: else if (error_flag &&
1.7 cvs 565: (me->reqStatus == HT_BUSY || me->reqStatus == HT_WAITING))
566: {
567: /* there was an error */
568: if (me->terminate_cbf)
569: (*me->terminate_cbf) ((AHTReqContext *) me,
570: HT_ERROR);
571:
572: if (me->outputfile && me->outputfile[0] != EOS)
573: {
1.9 cvs 574: TtaFileUnlink (me->outputfile);
1.7 cvs 575: me->outputfile[0] = EOS;
576: me->reqStatus = HT_ERR;
577: }
578: } /* if-else HT_END, HT_ABORT, HT_ERROR */
1.4 cvs 579: if (HTLog_isOpen ())
1.7 cvs 580: HTLog_add (request, status);
1.4 cvs 581:
1.7 cvs 582: if ((me->mode & AMAYA_ASYNC) || (me->mode & AMAYA_IASYNC))
1.17 cvs 583: /* for the ASYNC mode, free the memory we allocated in GetObjectWWW
584: or in PutObjectWWW */
1.7 cvs 585: {
586: TtaFreeMemory (me->urlName);
1.21 cvs 587: me->urlName = NULL;
1.7 cvs 588: TtaFreeMemory (me->outputfile);
1.21 cvs 589: me->outputfile = NULL;
1.7 cvs 590: }
1.17 cvs 591:
1.4 cvs 592: /* don't remove or Xt will hang up during the put */
593:
1.24 ! cvs 594: if (AmayaIsAlive && me->method == METHOD_PUT || me->method == METHOD_POST)
1.7 cvs 595: {
1.21 cvs 596: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_PROG_WRITE),
597: me->urlName);
1.4 cvs 598:
1.7 cvs 599: }
1.4 cvs 600: return HT_OK;
601: }
602:
1.5 cvs 603: /*----------------------------------------------------------------------
1.17 cvs 604: AHTLoadTerminate_handler
605: this is an application "AFTER" Callback. It uses all the functionaly
606: that the app part of the Library gives for handling AFTER a request.
1.5 cvs 607: ----------------------------------------------------------------------*/
1.4 cvs 608:
609: #ifdef __STDC__
1.7 cvs 610: static int AHTLoadTerminate_handler (HTRequest * request, HTResponse * response, void *param, int status)
1.4 cvs 611: #else
612: static int AHTLoadTerminate_handler (request, response, param, status)
613: HTRequest *request;
614: HTResponse *response;
615: void *param;
616: int status;
617:
618: #endif
619: {
620: char *uri = HTAnchor_address ((HTAnchor *) request->anchor);
621: AHTReqContext *me = HTRequest_context (request);
622: HTAlertCallback *cbf;
623: AHTDocId_Status *docid_status;
624:
1.7 cvs 625: switch (status)
626: {
627: case HT_LOADED:
628: if (PROT_TRACE)
629: HTTrace ("Load End.... OK: `%s\' has been accessed\n",
1.4 cvs 630: uri);
631:
1.7 cvs 632: docid_status = GetDocIdStatus (me->docid,
633: Amaya->docid_status);
634:
635: if (docid_status != NULL && docid_status->counter > 1)
636: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA,
637: AM_ELEMENT_LOADED), uri);
638:
639: break;
640:
641: case HT_NO_DATA:
642: if (PROT_TRACE)
643: HTTrace ("Load End.... OK BUT NO DATA: `%s\'\n", uri);
644: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_LOADED_NO_DATA),
645: uri);
646: break;
647:
648: case HT_INTERRUPTED:
649: if (PROT_TRACE)
650: HTTrace ("Load End.... INTERRUPTED: `%s\'\n", uri);
651: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_LOAD_ABORT), NULL);
652:
653: break;
654:
655: case HT_RETRY:
656: if (PROT_TRACE)
657: HTTrace ("Load End.... NOT AVAILABLE, RETRY AT %ld\n",
658: HTResponse_retryTime (response));
659: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_NOT_AVAILABLE_RETRY),
660: uri);
661: break;
662:
663: case HT_ERROR:
664:
665: cbf = HTAlert_find (HT_A_MESSAGE);
666: if (cbf)
667: (*cbf) (request, HT_A_MESSAGE, HT_MSG_NULL, NULL,
668: HTRequest_error (request), NULL);
669: break;
670:
671: if (PROT_TRACE)
672: HTTrace ("Load End.... ERROR: Can't access `%s\'\n",
673: uri ? uri : "<UNKNOWN>");
674: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_LOAD),
675: uri ? uri : "<UNKNOWN>");
676: break;
677: default:
678: if (PROT_TRACE)
679: HTTrace ("Load End.... UNKNOWN RETURN CODE %d\n", status);
680: break;
681: }
682:
1.4 cvs 683: /* Should we do logging? */
684: if (HTLog_isOpen ())
1.7 cvs 685: HTLog_add (request, status);
1.4 cvs 686: HT_FREE (uri);
1.7 cvs 687:
1.4 cvs 688: return HT_OK;
689: }
690:
691:
692:
1.5 cvs 693: /*----------------------------------------------------------------------
1.17 cvs 694: AHTConverterInit
695: Bindings between a source media type and a destination media type
696: (conversion).
1.5 cvs 697: ----------------------------------------------------------------------*/
1.15 cvs 698: #ifdef __STDC__
699: static void AHTConverterInit (HTList *c)
700: #else /* __STDC__ */
701: static void AHTConverterInit (c)
702: HTList *c;
703: #endif /* __STDC__ */
1.4 cvs 704: {
705:
706: /* Handler for custom http error messages */
1.7 cvs 707: HTConversion_add (c, "*/*", "www/debug", AHTMemConverter, 1.0, 0.0, 0.0);
1.4 cvs 708:
709: /*
710: ** These are converters that converts to something other than www/present,
711: ** that is not directly outputting someting to the user on the screen
712: */
713:
714: HTConversion_add (c, "message/rfc822", "*/*", HTMIMEConvert, 1.0, 0.0, 0.0);
715: HTConversion_add (c, "message/x-rfc822-foot", "*/*", HTMIMEFooter,
716: 1.0, 0.0, 0.0);
717: HTConversion_add (c, "message/x-rfc822-head", "*/*", HTMIMEHeader,
718: 1.0, 0.0, 0.0);
719: HTConversion_add (c, "multipart/*", "*/*", HTBoundary,
720: 1.0, 0.0, 0.0);
721: HTConversion_add (c, "text/plain", "text/html", HTPlainToHTML,
722: 1.0, 0.0, 0.0);
723:
724:
725: /*
726: ** The following conversions are converting ASCII output from various
727: ** protocols to HTML objects.
728: */
729: HTConversion_add (c, "text/x-http", "*/*", HTTPStatus_new,
730: 1.0, 0.0, 0.0);
731: HTConversion_add (c, "text/x-nntp-list", "*/*", HTNewsList,
732: 1.0, 0.0, 0.0);
733: HTConversion_add (c, "text/x-nntp-over", "*/*", HTNewsGroup,
734: 1.0, 0.0, 0.0);
735:
736:
737: /*
738: ** We also register a special content type guess stream that can figure out
739: ** the content type by reading the first bytes of the stream
740: */
741: HTConversion_add (c, "www/unknown", "*/*", HTGuess_new,
742: 1.0, 0.0, 0.0);
743:
744: /*
745: ** Register a persistent cache stream which can save an object to local
746: ** file
747: */
748: HTConversion_add (c, "www/cache", "*/*", HTCacheWriter,
749: 1.0, 0.0, 0.0);
750:
751: /*
752: ** This dumps all other formats to local disk without any further
753: ** action taken
754: */
755: HTConversion_add (c, "*/*", "www/present", HTSaveLocally,
756: 0.3, 0.0, 0.0);
757:
758: }
759:
1.15 cvs 760: /*----------------------------------------------------------------------
1.17 cvs 761: AHTProtocolInit
762: Registers all amaya supported protocols.
1.15 cvs 763: ----------------------------------------------------------------------*/
1.4 cvs 764: static void AHTProtocolInit (void)
765: {
766:
1.17 cvs 767: /*
768: NB. Preemptive == YES = Blocking request
769: Non-preemptive == NO = Non-blocking request
770: */
1.4 cvs 771:
772: HTProtocol_add ("http", "buffered_tcp", NO, HTLoadHTTP, NULL);
773: /* HTProtocol_add ("http", "tcp", NO, HTLoadHTTP, NULL); */
774: HTProtocol_add ("file", "local", NO, HTLoadFile, NULL);
775: HTProtocol_add ("cache", "local", NO, HTLoadCache, NULL);
1.17 cvs 776: #if 0 /* experimental code */
1.4 cvs 777: HTProtocol_add ("telnet", "", YES, HTLoadTelnet, NULL);
778: HTProtocol_add ("tn3270", "", YES, HTLoadTelnet, NULL);
779: HTProtocol_add ("rlogin", "", YES, HTLoadTelnet, NULL);
780:
781: HTProtocol_add ("ftp", "tcp", NO, HTLoadFTP, NULL);
782: HTProtocol_add ("nntp", "tcp", NO, HTLoadNews, NULL);
783: HTProtocol_add ("news", "tcp", NO, HTLoadNews, NULL);
1.17 cvs 784: #endif
1.4 cvs 785: }
786:
1.15 cvs 787: /*----------------------------------------------------------------------
1.17 cvs 788: AHTNetInit
789: Reegisters "before" and "after" request filters.
1.15 cvs 790: ----------------------------------------------------------------------*/
1.4 cvs 791: static void AHTNetInit (void)
792: {
793:
794: /* Register BEFORE filters
795: ** The BEFORE filters handle proxies, caches, rule files etc.
796: ** The filters are called in the order by which the are registered
797: ** Not done automaticly - may be done by application!
798: */
799:
800:
1.7 cvs 801: /*#ifndef HACK_WWW */
802: HTNet_addBefore (HTCredentialsFilter, "http://*", NULL, 6);
803: HTNet_addBefore (HTProxyFilter, NULL, NULL, 10);
1.4 cvs 804:
1.7 cvs 805: /*#endif */
1.4 cvs 806:
807: /* register AFTER filters
808: ** The AFTER filters handle error messages, logging, redirection,
809: ** authentication etc.
810: ** The filters are called in the order by which the are registered
811: ** Not done automaticly - may be done by application!
812: */
813:
814: #ifndef HACK_WWW
815:
1.7 cvs 816: HTNet_addAfter (HTAuthFilter, "http://*", NULL, HT_NO_ACCESS,
817: 5);
1.4 cvs 818:
1.7 cvs 819: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_TEMP_REDIRECT,
820: 5);
821: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_PERM_REDIRECT,
822: 5);
823: HTNet_addAfter (HTUseProxyFilter, "http://*", NULL, HT_USE_PROXY,
824: 5);
1.4 cvs 825:
1.7 cvs 826: HTNet_addAfter (AHTLoadTerminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST); /* handles all errors */
827: HTNet_addAfter (terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
1.4 cvs 828: #endif
829: }
830:
1.15 cvs 831: /*----------------------------------------------------------------------
1.17 cvs 832: AHTAlertInit
833: Register alert messages and their callbacks.
1.15 cvs 834: ----------------------------------------------------------------------*/
835: #ifdef __STDC__
836: static void AHTAlertInit (void)
837: #else
838: static void AHTAlertInit ()
839: #endif
840: {
841:
842: HTAlert_add (AHTProgress, HT_A_PROGRESS);
843: HTAlert_add ((HTAlertCallback *) Add_NewSocket_to_Loop, HT_PROG_CONNECT);
844: HTAlert_add (AHTError_print, HT_A_MESSAGE);
845: HTError_setShow (0xFF); /* process all messages */
846: HTAlert_add (AHTConfirm, HT_A_CONFIRM);
847: HTAlert_add (AHTPrompt, HT_A_PROMPT);
848: HTAlert_add (AHTPromptPassword, HT_A_SECRET);
849: HTAlert_add (AHTPromptUsernameAndPassword, HT_A_USER_PW);
850: }
851:
852: /*----------------------------------------------------------------------
1.17 cvs 853: AHTProfile_newAmaya
854: creates the Amaya client profile for libwww.
1.15 cvs 855: ----------------------------------------------------------------------*/
856: #ifdef __STDC__
857: static void AHTProfile_newAmaya (char *AppName, char *AppVersion)
858: #else /* __STDC__ */
859: static void AHTProfile_newAmaya (AppName, AppVersion)
860: char *AppName;
861: char *AppVersion;
862: #endif /* __STDC__ */
1.4 cvs 863: {
864: /* If the Library is not already initialized then do it */
865: if (!HTLib_isInitialized ())
866: HTLibInit (AppName, AppVersion);
867:
868: if (!converters)
869: converters = HTList_new ();
870: if (!encodings)
871: encodings = HTList_new ();
872:
873: /* Register the default set of transport protocols */
874: HTTransportInit ();
875:
876: /* Register the default set of application protocol modules */
877: #ifndef HACK_WWW
878: AHTProtocolInit ();
879: #endif
880:
881: /* Enable the persistent cache */
882: /* HTCacheInit (NULL, 20); */
883:
884: /* Register the default set of BEFORE and AFTER filters */
885: AHTNetInit ();
886:
887: /* Set up the default set of Authentication schemes */
888: HTAAInit ();
889:
890: /* Get any proxy or gateway environment variables */
891: HTProxy_getEnvVar ();
892:
893: /* Register the default set of converters */
894: AHTConverterInit (converters);
895: HTFormat_setConversion (converters);
896:
897: /* Register the default set of transfer encoders and decoders */
898: HTEncoderInit (encodings); /* chunks ??? */
899: HTFormat_setTransferCoding (encodings);
900:
901: /* Register the default set of MIME header parsers */
902: HTMIMEInit (); /* must be called again for language selector */
903:
904: /* Register the default set of file suffix bindings */
905: HTFileInit ();
906:
907: /* Register the default set of Icons for directory listings */
908: /*HTIconInit(NULL); *//*is this useful ? */
909:
910: /* Register the default set of messages and dialog functions */
911: AHTAlertInit ();
912: HTAlert_setInteractive (YES);
913: }
914:
1.5 cvs 915: /*----------------------------------------------------------------------
1.17 cvs 916: AHTProfile_delete
917: deletes the Amaya client profile.
1.5 cvs 918: ----------------------------------------------------------------------*/
1.4 cvs 919: #ifdef __STDC__
920: static void AHTProfile_delete (void)
921: #else
922: static void AHTProfile_delete ()
1.7 cvs 923: #endif /* __STDC__ */
1.4 cvs 924: {
1.22 cvs 925:
926: /* free the Amaya global context */
927: HTList_delete (Amaya->docid_status);
928: HTList_delete (Amaya->reqlist);
929: TtaFreeMemory (Amaya);
930:
931: if (HTLib_isInitialized ())
932: {
933:
934: /* Clean up the persistent cache (if any) */
935: HTCacheTerminate ();
1.4 cvs 936:
1.22 cvs 937: /* Clean up all the global preferences */
938: HTFormat_deleteAll ();
1.4 cvs 939:
1.22 cvs 940: /* Terminate libwww */
941: HTLibTerminate ();
942: }
1.4 cvs 943: }
944:
1.5 cvs 945: /*----------------------------------------------------------------------
1.17 cvs 946: QueryInit
947: initializes the libwww interface
1.5 cvs 948: ----------------------------------------------------------------------*/
1.4 cvs 949: #ifdef __STDC__
950: void QueryInit ()
951: #else
952: void QueryInit ()
953: #endif
954: {
955:
1.24 ! cvs 956: AmayaIsAlive = TRUE;
1.4 cvs 957: AHTProfile_newAmaya (HTAppName, HTAppVersion);
958:
959: /* New AHTBridge stuff */
960:
961: HTEvent_setRegisterCallback (AHTEvent_register);
962: HTEvent_setUnregisterCallback (AHTEvent_unregister);
963:
964: /* Setup authentication manager */
965: /***
966: HTAuthCall_add("basic", HTBasic_parse, HTBasic_generate, HTBasic_delete);
967: ****/
968:
969: /* Trace activation (for debugging) */
1.7 cvs 970: /*
1.4 cvs 971: WWW_TraceFlag = SHOW_APP_TRACE | SHOW_UTIL_TRACE |
972: SHOW_BIND_TRACE | SHOW_THREAD_TRACE |
973: SHOW_STREAM_TRACE | SHOW_PROTOCOL_TRACE |
974: SHOW_URI_TRACE | SHOW_AUTH_TRACE | SHOW_ANCHOR_TRACE |
975: SHOW_CORE_TRACE;
976:
1.7 cvs 977: */
1.4 cvs 978:
979: /***
980: WWW_TraceFlag = SHOW_CORE_TRACE | SHOW_AUTH_TRACE | SHOW_ANCHOR_TRACE |
981: SHOW_PROTOCOL_TRACE| SHOW_APP_TRACE | SHOW_UTIL_TRACE;
982: ***/
983:
984: HTBind_caseSensitive (FALSE);
985: HTBind_addType ("html", "text/html", 0.9);
986: HTBind_addType ("htm", "text/html", 0.9);
987: HTBind_addType ("gif", "image/gif", 0.9);
988: HTBind_addType ("png", "image/png", 0.9);
989: HTBind_addType ("jpg", "image/jpeg", 0.9);
990: HTBind_addType ("txt", "text/plain", 0.9);
991:
992: /* Setting up other user interfaces */
993: /* needs a little bit more work */
994:
995: /* Setting up handlers */
996: #ifndef HACK_WWW
997: /* HTNetCall_addBefore(HTLoadStart, NULL, 0); */
998: #endif
999:
1000: /* Setting up different network parameters */
1.17 cvs 1001: /* Maximum number of simultaneous open sockets */
1.4 cvs 1002: HTNet_setMaxSocket (8);
1003: HTDNS_setTimeout (3600);
1.17 cvs 1004: /* Cache is disabled in this version */
1.4 cvs 1005: HTCacheMode_setEnabled (0);
1006:
1007: /* Initialization of the global context */
1008: Amaya = (AmayaContext *) TtaGetMemory (sizeof (AmayaContext));
1009: Amaya->reqlist = HTList_new ();
1010: Amaya->docid_status = HTList_new ();
1011: Amaya->open_requests = 0;
1012:
1013: #ifdef CATCH_SIG
1.18 cvs 1014: signal (SIGPIPE, SIG_IGN);
1.4 cvs 1015: #endif
1.15 cvs 1016: }
1017:
1018:
1019: /*----------------------------------------------------------------------
1.17 cvs 1020: LoopForStop
1021: a copy of the Thop event loop so we can handle the stop button.
1.15 cvs 1022: ----------------------------------------------------------------------*/
1023: #ifdef __STDC__
1024: static int LoopForStop (AHTReqContext * me)
1025: #else
1026: static int LoopForStop (AHTReqContext * me)
1027: #endif
1028: {
1029:
1030: #ifdef WWW_XWINDOWS
1031: extern XtAppContext app_cont;
1032: XEvent ev;
1033: XtInputMask status;
1034:
1035: #endif /* WWW_XWINDOWS */
1.17 cvs 1036: int status_req = HT_OK;
1.15 cvs 1037:
1038: /* to test the async calls */
1.17 cvs 1039: /* Loop while waiting for new events, exists when the request is over */
1.15 cvs 1040: while (me->reqStatus != HT_ABORT &&
1041: me->reqStatus != HT_END &&
1042: me->reqStatus != HT_ERR)
1043: {
1044:
1045: #ifdef WWW_XWINDOWS
1046: status = XtAppPending (app_cont);
1047: if (status & XtIMXEvent)
1048: {
1049: XtAppNextEvent (app_cont, &ev);
1050: TtaHandleOneEvent (&ev);
1051: }
1052: else if (status & (XtIMAll & (~XtIMXEvent)))
1053: {
1054: XtAppProcessEvent (app_cont,
1055: (XtIMAll & (~XtIMXEvent)));
1056: }
1057: else
1058: {
1059: XtAppNextEvent (app_cont, &ev);
1060: TtaHandleOneEvent (&ev);
1061: }
1062:
1.24 ! cvs 1063: if (!AmayaIsAlive)
! 1064: /* Amaya was killed during one of the callback handlers */
! 1065: exit (0);
! 1066:
1.15 cvs 1067: #endif /* WWW_XWINDOWS */
1068: }
1069:
1070: switch (me->reqStatus)
1071: {
1.4 cvs 1072:
1.15 cvs 1073: case HT_ERR:
1074: case HT_ABORT:
1075: status_req = HT_ERROR;
1076: break;
1077:
1078: case HT_END:
1079: status_req = HT_OK;
1080: break;
1081:
1082: default:
1083: break;
1084: }
1.12 cvs 1085:
1.15 cvs 1086: return (status_req);
1.4 cvs 1087: }
1088:
1089:
1.5 cvs 1090: /*----------------------------------------------------------------------
1.15 cvs 1091: QueryClose
1.21 cvs 1092: closes all existing threads, frees all non-automatically deallocated
1093: memory and then ends libwww.
1.5 cvs 1094: ----------------------------------------------------------------------*/
1.4 cvs 1095: void QueryClose ()
1096: {
1.24 ! cvs 1097:
! 1098: AmayaIsAlive = FALSE;
! 1099:
1.21 cvs 1100: /* remove all the handlers and callbacks that may output a message to
1101: a non-existent Amaya window */
1102:
1103: HTNet_deleteAfter (AHTLoadTerminate_handler);
1104: HTNet_deleteAfter (redirection_handler);
1105: HTAlertCall_deleteAll (HTAlert_global () );
1.23 cvs 1106: HTAlert_setGlobal ((HTList *) NULL);
1.24 ! cvs 1107: HTEvent_setRegisterCallback ((HTEvent_registerCallback *) NULL);
! 1108: HTEvent_setUnregisterCallback ((HTEvent_registerCallback *) NULL);
1.21 cvs 1109:
1.4 cvs 1110: Thread_deleteAll ();
1.21 cvs 1111:
1.4 cvs 1112: #ifndef HACK_WWW
1113: /** HTAuthInfo_deleteAll (); **/
1114: #endif
1115: HTProxy_deleteAll ();
1116: HTNoProxy_deleteAll ();
1117: HTGateway_deleteAll ();
1118: AHTProfile_delete ();
1119: }
1120:
1121:
1.5 cvs 1122: /*----------------------------------------------------------------------
1.15 cvs 1123: GetObjectWWW
1.17 cvs 1124: this function requests a resource designated by a URLname into a
1125: temporary filename. The download can come from a simple GET operation,
1126: or can come from POSTING/GETTING a form. In the latter
1127: case, the function receives a query string to send to the server.
1128:
1.5 cvs 1129: 4 file retrieval modes are proposed:
1130: AMAYA_SYNC : blocking mode
1131: AMAYA_ISYNC : incremental, blocking mode
1132: AMAYA_ASYNC : non-blocking mode
1133: AMAYA_IASYNC : incremental, non-blocking mode
1134:
1135: In the incremental mode, each time a package arrives, it will be
1136: stored in the temporary file. In addition, if an
1137: incremental_callback function is defined, this function will be
1138: called and handled a copy of the newly received data package.
1139: Finally, if a terminate_callback function is defined, it will be
1140: invoked when the request terminates. The caller of this function
1.4 cvs 1141: can define two different contexts to be passed to the callback
1142: functions.
1143:
1144: When the function is called with the SYNC mode, the function will
1145: return only when the requested file has been loaded.
1146: The ASYNC mode will immediately return after setting up the
1147: call.
1148:
1149: Notes:
1150: At the end of a succesful request, the urlName string contains the
1151: name of the actually retrieved URL. As a URL can change over the time,
1152: (e.g., be redirected elsewhere), it is advised that the function
1.17 cvs 1153: caller verify the value of the urlName variable at the end of
1.4 cvs 1154: a request.
1155:
1156: Inputs:
1157: - docid Document identifier for the set of objects being
1158: retrieved.
1159: - urlName The URL to be retrieved (MAX_URL_LENGTH chars length)
1160: - outputfile A pointer to an empty string of MAX_URL_LENGTH.
1161: - mode The retrieval mode.
1162: - incremental_cbf
1163: - context_icbf
1164: Callback and context for the incremental modes
1165: - terminate_cbf
1166: - context_icbf
1167: Callback and context for a terminate handler
1.17 cvs 1168: -error_html if TRUE, then display any server error message as an
1169: HTML document.
1.4 cvs 1170:
1171: Outputs:
1172: - urlName The URL that was retrieved
1173: - outputfile The name of the temporary file which holds the
1174: retrieved data. (Only in case of success)
1175: Returns:
1176: HT_ERROR
1177: HT_OK
1.5 cvs 1178:
1179: ----------------------------------------------------------------------*/
1.4 cvs 1180: #ifdef __STDC__
1181: int GetObjectWWW (int docid, char *urlName, char *postString,
1182: char *outputfile, int mode,
1183: TIcbf * incremental_cbf, void *context_icbf,
1.15 cvs 1184: TTcbf * terminate_cbf, void *context_tcbf, boolean error_html)
1.4 cvs 1185: #else
1186: int GetObjectWWW (docid, urlName, postString, outputfile, mode,
1187: incremental_cbf, context_icbf, terminate_cbf, context_tcbf,
1188: error_html)
1189: int docid;
1190: char *urlName;
1191: char *postString;
1192: char *outputfile;
1193: int mode;
1194: TIcbf *incremental_cbf;
1195: void *context_icbf;
1196: TTcbf *terminate_cbf;
1197: void *context_tcbf;
1.15 cvs 1198: boolean error_html;
1.4 cvs 1199: #endif
1200: {
1201: AHTReqContext *me;
1202:
1203: FILE *tmp_fp;
1204: char *tmp_dir;
1205: char *ref;
1206: int status;
1207: HTList *cur, *pending;
1.7 cvs 1208:
1209: if (urlName == NULL || docid == 0 || outputfile == NULL)
1210: {
1211: /* no file to be loaded */
1212: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_BAD_URL),
1213: urlName);
1214:
1215: if (error_html)
1216: FilesLoading[docid] = 2; /* so we can show the error message */
1217: return HT_ERROR;
1.4 cvs 1218:
1.7 cvs 1219: }
1.4 cvs 1220: /* do we support this protocol? */
1.7 cvs 1221: if (IsValidProtocol (urlName) == NO)
1222: {
1223: /* return error */
1224: outputfile[0] = EOS; /* file could not be opened */
1225: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_GET_UNSUPPORTED_PROTOCOL),
1226: urlName);
1227:
1228: if (error_html)
1229: FilesLoading[docid] = 2; /* so we can show the error message */
1230: return HT_ERROR;
1231: }
1.4 cvs 1232:
1233: /* verify if a docid directory exists */
1234:
1235: tmp_dir = TtaGetMemory (strlen (TempFileDirectory) + 5 + 1);
1236: sprintf (tmp_dir, "%s/%d", TempFileDirectory, docid);
1237:
1238: tmp_fp = fopen (tmp_dir, "r");
1.7 cvs 1239: if (tmp_fp == 0)
1240: {
1241: /*directory did not exist */
1242: if (mkdir (tmp_dir, S_IRWXU) == -1)
1243: {
1244: /*error */
1245: outputfile[0] = EOS;
1246: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_CACHE_ERROR),
1247: urlName);
1248:
1249: if (error_html)
1250: FilesLoading[docid] = 2; /* so we can show the error message */
1251:
1252: return HT_ERROR;
1253: }
1254: }
1255: else
1.4 cvs 1256: fclose (tmp_fp);
1257:
1258: /*create a tempfilename */
1259:
1260: sprintf (outputfile, "%s/%04dAM", tmp_dir, object_counter);
1261:
1262: TtaFreeMemory (tmp_dir);
1263:
1264: /* update the object_counter */
1265: object_counter++;
1266:
1267: /* normalize the URL */
1268: ref = HTParse (urlName, "", PARSE_ALL);
1269:
1270: /* should we abort the request if we could not normalize the url? */
1271:
1.7 cvs 1272: if (ref == (char *) NULL || ref[0] == EOS)
1273: {
1274: /*error */
1275: outputfile[0] = EOS;
1276: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_BAD_URL),
1277: urlName);
1.4 cvs 1278:
1.7 cvs 1279: if (error_html)
1280: FilesLoading[docid] = 2; /* so we can show the error message */
1.4 cvs 1281:
1.7 cvs 1282: return HT_ERROR;
1283: }
1.4 cvs 1284: /* verify if that file name existed */
1.9 cvs 1285: if (TtaFileExist (outputfile))
1.7 cvs 1286: {
1.9 cvs 1287: TtaFileUnlink (outputfile);
1.7 cvs 1288: }
1.4 cvs 1289:
1290: /* try to open the outputfile */
1291:
1.7 cvs 1292: if ((tmp_fp = fopen (outputfile, "w")) == NULL)
1293: {
1294: outputfile[0] = EOS; /* file could not be opened */
1295: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE),
1296: outputfile);
1297: HT_FREE (ref);
1298:
1299: if (error_html)
1300: FilesLoading[docid] = 2; /* so we can show the error message */
1301: return (HT_ERROR);
1302: }
1.4 cvs 1303:
1304: /* the terminate_handler closes the above open fp */
1305: /* Not anymore, we do that in the AHTCallback_bridge, as all
1306: requests are now asynchronous */
1307:
1308: /* Initialize the request structure */
1309:
1310: me = AHTReqContext_new (docid);
1311:
1.7 cvs 1312: if (me == NULL)
1313: {
1314: fclose (tmp_fp);
1315: outputfile[0] = EOS;
1316: /* need an error message here */
1317: HT_FREE (ref);
1318: return (HT_ERROR);
1319: }
1.4 cvs 1320:
1321:
1322: /* Specific initializations for POST and GET */
1.7 cvs 1323: if (mode & AMAYA_FORM_POST)
1324: {
1325: me->method = METHOD_POST;
1.20 cvs 1326: if (postString)
1327: {
1328: me->mem_ptr = postString;
1329: me->block_size = strlen (postString);
1330: }
1331: else
1332: {
1333: me->mem_ptr = "";
1334: me->block_size = 0;
1335: }
1.7 cvs 1336: HTRequest_setMethod (me->request, METHOD_POST);
1337: HTRequest_setPostCallback (me->request, AHTUpload_callback);
1338: }
1339: else
1340: {
1341: me->method = METHOD_GET;
1342: me->dest = (HTParentAnchor *) NULL; /*useful only for PUT and POST methods */
1343: }
1.4 cvs 1344:
1345: /* Common initialization */
1346:
1347: me->mode = mode;
1348: me->error_html = error_html;
1349: me->incremental_cbf = incremental_cbf;
1350: me->context_icbf = context_icbf;
1351: me->terminate_cbf = terminate_cbf;
1352: me->context_tcbf = context_tcbf;
1353: me->output = tmp_fp;
1354:
1355: HTRequest_setOutputStream (me->request,
1356: AHTFWriter_new (me->request, me->output, YES));
1.7 cvs 1357:
1.4 cvs 1358:
1359: /*for the async. request modes, we need to have our
1360: own copy of outputfile and urlname
1361: */
1362:
1.7 cvs 1363: if ((mode & AMAYA_ASYNC) || (mode & AMAYA_IASYNC))
1364: {
1365: char *tmp;
1366:
1367: tmp = TtaGetMemory (strlen (outputfile) + 1);
1368: strcpy (tmp, outputfile);
1369: me->outputfile = tmp;
1370:
1.21 cvs 1371: tmp = TtaGetMemory (MAX_LENGTH + 1);
1372: strncpy (tmp, urlName, MAX_LENGTH);
1373: tmp[MAX_LENGTH] = EOS;
1.7 cvs 1374: me->urlName = tmp;
1375: }
1376: else
1377: {
1378: me->outputfile = outputfile;
1379: me->urlName = urlName;
1380: }
1.4 cvs 1381:
1382: /***
1383: Change for taking into account the stop button:
1384: The requests will be always asynchronous, however, if mode=AMAYA_SYNC,
1385: we will loop until the document has been received or a stop signal
1386: generated
1387: ****/
1388:
1389: HTRequest_setPreemptive (me->request, NO);
1390: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_FETCHING),
1391: me->urlName);
1392:
1393: me->anchor = (HTParentAnchor *) HTAnchor_findAddress (ref);
1394:
1395: HT_FREE (ref);
1396:
1.7 cvs 1397: if (mode & AMAYA_FORM_POST)
1398: {
1399: HTAnchor_setFormat ((HTParentAnchor *) me->anchor, HTAtom_for ("application/x-www-form-urlencoded"));
1400: HTAnchor_setLength ((HTParentAnchor *) me->anchor, me->block_size);
1401: HTRequest_setEntityAnchor (me->request, me->anchor);
1.4 cvs 1402:
1.7 cvs 1403: status = HTLoadAbsolute (urlName, me->request);
1404: }
1405: else
1.4 cvs 1406: status = HTLoadAnchor ((HTAnchor *) me->anchor,
1407: me->request);
1408:
1409: if (status == HT_ERROR || me->reqStatus == HT_END
1.7 cvs 1410: || me->reqStatus == HT_ERR)
1411: {
1.4 cvs 1412:
1.7 cvs 1413: /* in case of error, free all allocated memory and exit */
1414:
1.21 cvs 1415: if (me->output)
1416: fclose (me->output);
1417:
1.7 cvs 1418: if ((mode & AMAYA_ASYNC) || (mode & AMAYA_IASYNC))
1419: {
1.21 cvs 1420: if(me->outputfile)
1421: TtaFreeMemory (me->outputfile);
1422: if(me->urlName)
1423: TtaFreeMemory (me->urlName);
1.7 cvs 1424: }
1425: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_LOAD),
1426: me->urlName);
1.4 cvs 1427:
1.7 cvs 1428: status = (me->reqStatus == HT_END) ? HT_OK : HT_ERROR;
1429:
1430: AHTReqContext_delete (me);
1431:
1432: }
1433: else
1434: {
1435:
1436: /* part of the stop button handler */
1437:
1438: if ((mode & AMAYA_SYNC) || (mode & AMAYA_ISYNC))
1439: {
1440: status = LoopForStop (me);
1441: AHTReqContext_delete (me);
1442: }
1443: else
1444: {
1445:
1446: /* ASYNC MODE */
1447: /* if the request went to the pending events queue, then we close
1448: ** the file. It'll be open by AddEventLoop upon liberation of the
1449: ** queue
1.4 cvs 1450: */
1.7 cvs 1451:
1452: /* verify if this request went to the pending request queue */
1453:
1454: if ((cur = (HTList *) me->request->net->host->pending))
1455: while ((pending = HTList_nextObject (cur)))
1456: {
1457: if (me->request->net == (HTNet *) pending)
1458: {
1459: /* To correct: see if we can fine tune this request */
1460: if (me->reqStatus == HT_WAITING)
1461: break;
1462: me->reqStatus = HT_NEW_PENDING;
1463: /* the request went to the pending queue, so we close the fd to
1464: **avoid having many of them open without being used
1465: */
1466: if (THD_TRACE)
1467: fprintf (stderr, "GetObjectWWW: %s is pending. Closing fd %d\n", me->urlName, (int) me->output);
1.21 cvs 1468: /* free the allocated stream object */
1469: AHTFWriter_FREE (HTRequest_outputStream(me->request));
1470: HTRequest_setOutputStream (me->request, (HTStream *) NULL);
1.7 cvs 1471: fclose (me->output);
1472: me->output = NULL;
1473: break;
1474: }
1475: }
1476:
1.4 cvs 1477: }
1.7 cvs 1478: }
1.4 cvs 1479: TtaHandlePendingEvents ();
1480:
1481: return (status);
1482: }
1483:
1.5 cvs 1484: /*----------------------------------------------------------------------
1.17 cvs 1485: PutObjectWWW
1486: frontend for uploading a resource to a URL. This function downloads
1487: a file to be uploaded into memory, it then calls UploadMemWWW to
1488: finish the job.
1489:
1.5 cvs 1490: 2 upload modes are proposed:
1491: AMAYA_SYNC : blocking mode
1492: AMAYA_ASYNC : non-blocking mode
1493:
1.4 cvs 1494: When the function is called with the SYNC mode, the function will
1495: return only when the file has been uploaded.
1496: The ASYNC mode will immediately return after setting up the
1497: call. Furthermore, at the end of an upload, the ASYNC mode will
1498: call back terminate_cbf, handling it the context defined in
1499: context_tcbf.
1500:
1501: Notes:
1502: At the end of a succesful request, the urlName string contains the
1503: name of the actually uploaded URL. As a URL can change over the time,
1504: (e.g., be redirected elsewhere), it is advised that the function
1505: caller verifies the value of the urlName variable at the end of
1506: a request.
1507:
1508: Inputs:
1509: - docid Document identifier for the set of objects being
1510: retrieved.
1511: - fileName A pointer to the local file to upload
1512: - urlName The URL to be uploaded (MAX_URL_LENGTH chars length)
1513: - mode The retrieval mode.
1514: - terminate_cbf
1515: - context_icbf
1516: Callback and context for a terminate handler
1517:
1518: Outputs:
1519: - urlName The URL that was uploaded
1520:
1521: Returns:
1522: HT_ERROR
1523: HT_OK
1.5 cvs 1524: ----------------------------------------------------------------------*/
1.4 cvs 1525: #ifdef __STDC__
1526: int PutObjectWWW (int docid, char *fileName, char *urlName, int mode,
1527: TTcbf * terminate_cbf, void *context_tcbf)
1528: #else
1529: int PutObjectWWW (docid, urlName, fileName, mode,
1530: ,terminate_cbf, context_tcbf)
1531: int docid;
1532: char *urlName;
1533: char *fileName;
1534: int mode;
1535: TTcbf *terminate_cbf;
1536: void *context_tcbf;
1537:
1538: #endif
1539: {
1.7 cvs 1540: /*AHTReqContext *me; */
1.4 cvs 1541: int status;
1542:
1543: #ifdef WWW_XWINDOWS
1544: int fd;
1545: struct stat file_stat;
1546: char *mem_ptr;
1547: unsigned long block_size;
1548:
1549: if (urlName == NULL || docid == 0 || fileName == NULL ||
1.9 cvs 1550: !TtaFileExist (fileName))
1.4 cvs 1551: /* no file to be uploaded */
1552: return HT_ERROR;
1553:
1554: /* do we support this protocol? */
1.7 cvs 1555: if (IsValidProtocol (urlName) == NO)
1556: {
1557: /* return error */
1558: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_PUT_UNSUPPORTED_PROTOCOL),
1559: urlName);
1560: return HT_ERROR;
1561: }
1.4 cvs 1562: /* read the file into memory */
1563:
1.7 cvs 1564: if ((fd = open (fileName, O_RDONLY)) == -1)
1565: {
1566: /* if we could not open the file, exit */
1567: /*error msg here */
1568: return (HT_ERROR);
1569: }
1.4 cvs 1570:
1571: fstat (fd, &file_stat);
1572:
1.7 cvs 1573: if (file_stat.st_size == 0)
1574: {
1575: /* file was empty */
1576: /*errmsg here */
1577: close (fd);
1578: return (HT_ERROR);
1579: }
1.4 cvs 1580: block_size = file_stat.st_size;
1581:
1582: if (THD_TRACE)
1583: fprintf (stderr, "file size == %u\n", (unsigned) block_size);
1584:
1585: mem_ptr = (char *) TtaGetMemory (block_size);
1586:
1.7 cvs 1587: if (mem_ptr == (char *) NULL)
1588: {
1589: /* could not allocate enough memory */
1590: /*errmsg here */
1.4 cvs 1591:
1.7 cvs 1592: close (fd);
1593: return (HT_ERROR);
1594: }
1.4 cvs 1595: read (fd, mem_ptr, block_size);
1596:
1597: close (fd);
1598:
1599: status = UploadMemWWW (docid, METHOD_PUT, urlName, mem_ptr,
1600: block_size, mode, terminate_cbf,
1601: context_tcbf, (char *) NULL);
1602:
1603: TtaFreeMemory (mem_ptr);
1604:
1605: #endif /*WWW_XWINDOWS */
1606:
1607: return (status);
1608: }
1609:
1610:
1.5 cvs 1611: /*----------------------------------------------------------------------
1.17 cvs 1612: UploadMemWWW
1613: low level interface function to libwww for uploading a block of
1614: memory to a URL.
1.5 cvs 1615: ----------------------------------------------------------------------*/
1.4 cvs 1616: #ifdef __STDC__
1617: int UploadMemWWW (int docid, HTMethod method,
1618: char *urlName, char *mem_ptr, unsigned long block_size,
1619: int mode, TTcbf * terminate_cbf, void *context_tcbf,
1620: char *outputfile)
1621: #else
1622: int UploadMemWWW (docid, method, urlName, mem_ptr, block_size, mode,
1623: terminate_cbf, context_tcbf, outputfile)
1624: int docid;
1625: HTMethod method;
1626: char *urlName;
1627: char *mem_ptr;
1628: usigned long block_size;
1629: int mode;
1630: TTcbf *terminate_cbf;
1631: void *context_tcbf;
1632: char *outputfile;
1.7 cvs 1633:
1.4 cvs 1634: #endif
1635: {
1636: AHTReqContext *me;
1637: int status;
1638:
1639: if (mem_ptr == (char *) NULL ||
1640: block_size == 0 ||
1641: docid == 0 ||
1.7 cvs 1642: urlName == (char *) NULL)
1643: {
1644: /* nothing to be uploaded */
1645: return HT_ERROR;
1646: }
1.4 cvs 1647:
1648: /* Initialize the request structure */
1649: me = AHTReqContext_new (docid);
1650:
1.7 cvs 1651: if (me == NULL)
1652: {
1653: /* need an error message here */
1654: TtaHandlePendingEvents ();
1655: return (HT_ERROR);
1656: }
1.4 cvs 1657: me->mode = mode;
1658:
1659: me->incremental_cbf = (TIcbf *) NULL;
1660: me->context_icbf = (void *) NULL;
1661: me->terminate_cbf = terminate_cbf;
1662: me->context_tcbf = context_tcbf;
1663:
1664: me->output = stdout;
1665: me->outputfile = (char *) NULL;
1666: me->urlName = urlName;
1667:
1668: HTRequest_setPreemptive (me->request, NO);
1669:
1.17 cvs 1670: /* select the parameters that distinguish a PUT from a GET/POST */
1.4 cvs 1671: me->method = METHOD_PUT;
1672: HTRequest_setMethod (me->request, METHOD_PUT);
1673: me->output = stdout;
1.17 cvs 1674: /* we are not expecting to receive any input from the server */
1675: me->outputfile = (char *) NULL;
1.4 cvs 1676:
1677: me->mem_ptr = mem_ptr;
1678: me->block_size = block_size;
1.17 cvs 1679:
1680: /* set the callback which will actually copy data into the
1681: output stream */
1682:
1.4 cvs 1683: HTRequest_setPostCallback (me->request, AHTUpload_callback);
1684:
1685: HTRequest_setOutputStream (me->request,
1686: HTFWriter_new (me->request, me->output, YES));
1687:
1688: me->anchor = (HTParentAnchor *) HTAnchor_findAddress (urlName);
1.7 cvs 1689:
1.17 cvs 1690: /* First steps towards a full content-negotiation */
1691: /*
1692: HTAnchor_setFormat ((HTParentAnchor *) me->anchor, HTAtom_for ("text/html"));
1693: */
1694:
1.7 cvs 1695: HTAnchor_setLength ((HTParentAnchor *) me->anchor, me->block_size);
1.4 cvs 1696: HTRequest_setEntityAnchor (me->request, me->anchor);
1697: status = HTLoadAbsolute (urlName, me->request);
1698:
1699: if (status == HT_ERROR || me->reqStatus == HT_END
1.7 cvs 1700: || me->reqStatus == HT_ERR || HTError_hasSeverity (HTRequest_error (me->request), ERR_NON_FATAL))
1701: {
1.17 cvs 1702: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_SAVE),
1703: me->urlName);
1.4 cvs 1704:
1.17 cvs 1705: status = HT_ERROR;
1706: AHTReqContext_delete (me);
1.7 cvs 1707: }
1708: else
1709: {
1710: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_REMOTE_SAVING),
1711: me->urlName);
1.4 cvs 1712:
1.7 cvs 1713: /* part of the stop button handler */
1.4 cvs 1714:
1.7 cvs 1715: if ((mode & AMAYA_SYNC) || (mode & AMAYA_ISYNC))
1716: {
1717: status = LoopForStop (me);
1718: AHTReqContext_delete (me);
1719: }
1.15 cvs 1720: }
1.4 cvs 1721:
1722: return (status);
1723:
1724: }
1725:
1726:
1.5 cvs 1727: /*----------------------------------------------------------------------
1.17 cvs 1728: Stop Request
1729: stops (kills) all active requests associated with a docid
1.5 cvs 1730: ----------------------------------------------------------------------*/
1.4 cvs 1731: #ifdef __STDC__
1732: void StopRequest (int docid)
1733: #else
1734: void StopRequest (docid)
1735: int docid;
1736: #endif
1737: {
1738: HTList *cur;
1739: AHTDocId_Status *docid_status;
1740: AHTReqContext *me;
1741: int open_requests;
1742:
1.7 cvs 1743: if (Amaya)
1744: {
1.4 cvs 1745:
1.7 cvs 1746: cur = Amaya->reqlist;
1747: docid_status = (AHTDocId_Status *) GetDocIdStatus (docid,
1.4 cvs 1748: Amaya->docid_status);
1749:
1.7 cvs 1750: /* verify if there are any requests at all associated with docid */
1.4 cvs 1751:
1.7 cvs 1752: if (docid_status == (AHTDocId_Status *) NULL)
1753: return;
1.4 cvs 1754:
1.7 cvs 1755: open_requests = docid_status->counter;
1.4 cvs 1756:
1.7 cvs 1757: while ((me = (AHTReqContext *) HTList_nextObject (cur)))
1758: {
1.4 cvs 1759:
1.7 cvs 1760: if (me->docid == docid)
1761: {
1762: /* kill this request */
1.4 cvs 1763:
1.7 cvs 1764: switch (me->reqStatus)
1765: {
1766: case HT_ABORT:
1767: break;
1.4 cvs 1768:
1.7 cvs 1769: case HT_BUSY:
1770: me->reqStatus = HT_ABORT;
1771: break;
1772: case HT_NEW_PENDING:
1773: case HT_WAITING:
1774: default:
1.4 cvs 1775: #ifdef WWW_XWINDOWS
1.7 cvs 1776: RequestKillAllXtevents (me);
1.4 cvs 1777: #endif
1.7 cvs 1778: me->reqStatus = HT_ABORT;
1779: HTRequest_kill (me->request);
1.4 cvs 1780:
1.7 cvs 1781: if (me->mode == AMAYA_ASYNC ||
1782: me->mode == AMAYA_IASYNC)
1783: {
1.4 cvs 1784:
1.7 cvs 1785: AHTReqContext_delete (me);
1786: }
1787: cur = Amaya->reqlist;
1.4 cvs 1788:
1.7 cvs 1789: open_requests--;
1.4 cvs 1790:
1.7 cvs 1791: break;
1.4 cvs 1792:
1.7 cvs 1793: } /* switch */
1794: } /* if me docid */
1795: } /* while */
1796: } /* if amaya open requests */
1.4 cvs 1797: } /* StopRequest */
1.17 cvs 1798:
1799:
1800: /*
1801: end of Module query.c
1802: */
1803:
1804:
1805:
1806:
1807:
1808:
1809:
1810:
1811:
1812:
1813:
1814:
1815:
1816:
1817:
1818:
1819:
1820:
Webmaster