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