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