Annotation of Amaya/amaya/query.c, revision 1.301
1.14 cvs 1: /*
2: *
1.265 cvs 3: * (c) COPYRIGHT MIT and INRIA, 1996-2001.
1.14 cvs 4: * Please first read the full copyright statement in file COPYRIGHT.
1.156 cvs 5: *
1.14 cvs 6: */
1.243 cvs 7:
1.19 cvs 8: /*
1.83 cvs 9: * query.c : contains all the functions for requesting and publishing
1.19 cvs 10: * URLs via libwww. It handles any eventual HTTP error code
11: * (redirection, authentication needed, not found, etc.)
12: *
1.69 cvs 13: * Author: J. Kahan
1.92 cvs 14: * J. Kahan/R. Guetari Windows 95/NT routines
1.19 cvs 15: */
1.17 cvs 16:
1.116 cvs 17: /* defines to include elsewhere
18: *********************************/
19:
1.185 cvs 20: #ifdef _WINDOWS
21: #include <string.h>
1.130 cvs 22: #endif /* !_WINDOWS */
1.116 cvs 23: #define AMAYA_WWW_CACHE
1.168 cvs 24: #define AMAYA_LOST_UPDATE
1.116 cvs 25:
1.12 cvs 26: /* Amaya includes */
1.25 cvs 27: #define THOT_EXPORT extern
1.4 cvs 28: #include "amaya.h"
1.214 cvs 29: #include "init_f.h"
1.130 cvs 30: #include <sys/types.h>
1.70 cvs 31: #include <fcntl.h>
1.140 cvs 32: #include "HTEvtLst.h"
1.157 cvs 33: #include "HTAABrow.h"
1.272 cvs 34: #include "string.h"
1.279 cvs 35: #include "interface.h"
1.7 cvs 36:
1.141 cvs 37: #if defined(__svr4__) || defined (_AIX)
1.4 cvs 38: #define CATCH_SIG
39: #endif
40:
41: /* local structures coming from libwww and which are
1.17 cvs 42: not found in any .h file
1.7 cvs 43: */
1.68 cvs 44:
1.7 cvs 45: struct _HTStream
46: {
1.15 cvs 47: const HTStreamClass *isa;
48: FILE *fp;
1.45 cvs 49: BOOL leave_open; /* Close file when TtaFreeMemory? */
1.15 cvs 50: char *end_command; /* Command to execute */
51: BOOL remove_on_close; /* Remove file? */
52: char *filename; /* Name of file */
53: HTRequest *request; /* saved for callback */
54: HTRequestCallback *callback;
1.7 cvs 55: };
56:
1.15 cvs 57:
1.7 cvs 58: struct _HTError
59: {
60: HTErrorElement element; /* Index number into HTError */
61: HTSeverity severity; /* A la VMS */
62: BOOL ignore; /* YES if msg should not go to user */
63: void *par; /* Explanation, e.g. filename */
64: int length; /* For copying by generic routine */
65: char *where; /* Which function */
66: };
67:
1.4 cvs 68: /* Type definitions and global variables etc. local to this module */
69:
1.17 cvs 70: /*----------------------------------------------------------------------*/
1.293 kahan 71:
72: /* libwww default parameters */
73: #ifdef _WINDOWS
74: #define CACHE_DIR_NAME "\\libwww-cache\\"
75: #else
76: #define CACHE_DIR_NAME "/libwww-cache/"
77: #endif
78:
79: #define DEFAULT_CACHE_SIZE 10
80: #define DEFAULT_MAX_CACHE_ENTRY_SIZE 3
81: #define DEFAULT_MAX_SOCKET 32
82: #define DEFAULT_DNS_TIMEOUT 1800L
83: #define DEFAULT_PERSIST_TIMEOUT 60L
84: #define DEFAULT_NET_EVENT_TIMEOUT 60000
1.294 kahan 85: /* defines the priority for general content negotiation */
86: #define GENERAL_ACCEPT_NEGOTIATION "*/*;q=0.1,"AM_SVG_MIME_TYPE","AM_MATHML_MIME_TYPE","AM_XHTML_MIME_TYPE
1.293 kahan 87: /* defines the priority for image content negotiation */
88: #define IMAGE_ACCEPT_NEGOTIATION "*/*;q=0.1,image/*,image/gif,image/jpeg,image/png,image/svg+xml,"AM_SVG_MIME_TYPE
89:
1.4 cvs 90: /*** private variables ***/
1.17 cvs 91:
1.4 cvs 92: static HTList *converters = NULL; /* List of global converters */
1.27 cvs 93: static HTList *acceptTypes = NULL; /* List of types for the Accept header */
1.193 cvs 94: static HTList *acceptLanguages = NULL; /* List of language priorities for the Accept header */
1.151 cvs 95: static HTList *transfer_encodings = NULL;
96: static HTList *content_encodings = NULL;
1.207 cvs 97: /* List of domains where we can do a safe PUT redirect */
98: static HTList *safeput_list = NULL;
99:
1.16 cvs 100: static int object_counter = 0; /* loaded objects counter */
1.191 cvs 101: static ThotBool AmayaAlive_flag; /* set to 1 if the application is active;
1.140 cvs 102: 0 if we have killed */
1.191 cvs 103: static ThotBool CanDoStop_flag; /* set to 1 if we can do a stop, 0
1.140 cvs 104: if we're inside a critical section */
1.214 cvs 105: static ThotBool UserAborted_flag; /* set to 1 if we're processing a user
106: induced stop request operation */
1.128 cvs 107: #ifdef AMAYA_WWW_CACHE
1.130 cvs 108: static int fd_cachelock; /* open handle to the .lock cache file */
109: #endif /* AMAYA_WWW_CACHE */
1.4 cvs 110:
1.246 kahan 111: static ThotBool FTPURL_flag; /* if set to true, we can browse FTP URLs */
112:
1.248 kahan 113: static FILE *trace_fp = NULL; /* file pointer to the trace logs */
114:
1.15 cvs 115: #include "answer_f.h"
116: #include "query_f.h"
117: #include "AHTURLTools_f.h"
118: #include "AHTBridge_f.h"
119: #include "AHTMemConv_f.h"
120: #include "AHTFWrite_f.h"
1.4 cvs 121:
1.298 cvs 122: #ifdef DAV
123: #include "davlib.h"
124: #include "davlib_f.h"
125: #include "davlibCommon_f.h"
126: #endif
127:
1.116 cvs 128: /* prototypes */
129:
1.123 cvs 130: #ifdef _WINDOWS
1.70 cvs 131: int WIN_Activate_Request (HTRequest* , HTAlertOpcode, int, const char*, void*, HTAlertPar*);
1.116 cvs 132: #endif /* _WINDOWS */
1.297 kirschpi 133:
1.130 cvs 134: #ifdef AMAYA_WWW_CACHE
135: /***************************************************************
136: lock functions, used to avoid concurrent use of the cache
137: Mostly based on W. Richard Stevens' APUE book.
138: ***************************************************************/
139: /*----------------------------------------------------------------------
140: set_cachelock
141: sets a write lock on filename.
142: Returns -1 in case of failure, otherwise, it'll open a handle on
143: filename and fd_cachelock will take its value.
144: ----------------------------------------------------------------------*/
1.265 cvs 145: static int set_cachelock (char *filename)
1.130 cvs 146: {
1.188 cvs 147: int status;
1.130 cvs 148: #ifdef _WINDOWS
1.188 cvs 149:
150: status = TtaFileExist (filename);
151: return ((status) ? 0 : -1);
1.130 cvs 152: #else
153: struct flock lock;
154:
155: lock.l_type = F_WRLCK;
156: lock.l_start = 0;
157: lock.l_whence = SEEK_SET;
158: lock.l_len = 0;
159:
160: fd_cachelock = open (filename, O_WRONLY);
161:
162: if (fd_cachelock == -1)
163: status = -1;
164: else
165: status = fcntl(fd_cachelock, F_SETLK, &lock);
166:
167: if (status == -1)
1.190 cvs 168: {
1.179 cvs 169: if (fd_cachelock > 0)
1.190 cvs 170: close (fd_cachelock);
1.179 cvs 171: fd_cachelock = 0;
1.178 cvs 172: }
1.130 cvs 173: return (status);
174: #endif /* _WINDOWS */
175: }
176:
177: /*----------------------------------------------------------------------
178: clear_cachelock
179: remove the write lock set on a filename.
180: It'll close the fd handle on filename and reset *fd to 0.
181: ----------------------------------------------------------------------*/
182: static int clear_cachelock (void)
183: {
184: #ifdef _WINDOWS
185: return 0;
186: #else
187: int status;
188:
1.178 cvs 189: if (!fd_cachelock)
1.130 cvs 190: return (-1);
191:
1.178 cvs 192: status = close (fd_cachelock);
1.130 cvs 193: fd_cachelock = 0;
194:
195: return (status);
196: #endif /* _WINDOWS */
197: }
198:
199: /*----------------------------------------------------------------------
200: test_cachelock
201: returns 0 if a fd is not locked by other process, otherwise
202: returns the pid of the process who has the lock
203: ----------------------------------------------------------------------*/
1.265 cvs 204: static int test_cachelock (char *filename)
1.130 cvs 205: {
206: #ifdef _WINDOWS
1.185 cvs 207: /* if the lock is set, we can't unlink the file under Windows */
1.188 cvs 208: if (!TtaFileUnlink (filename))
209: return 0;
210: else
1.185 cvs 211: return -1;
1.130 cvs 212: #else
213: struct flock lock;
214: int fd, status;
215:
216: lock.l_type = F_WRLCK;
217: lock.l_start = 0;
218: lock.l_whence = SEEK_SET;
219: lock.l_len = 0;
220:
221: fd = open (filename, O_WRONLY);
222:
223: if (fd < 0)
224: return (-1);
225: /* is this file locked ? */
226: status = fcntl (fd, F_GETLK, &lock);
227: close (fd);
228:
229: if (status < 0)
230: return (-1);
231:
232: if (lock.l_type == F_UNLCK)
233: return (0); /* false, region is not locked by another proc */
234: return (lock.l_pid); /* true, return pid of lock owner */
235: #endif /* _WINDOWS */
236: }
237:
238: #endif /* AMAYA_WWW_CACHE */
239:
1.15 cvs 240: /*----------------------------------------------------------------------
1.17 cvs 241: GetDocIdStatus
242: gets the status associated to a docid
1.15 cvs 243: ----------------------------------------------------------------------*/
244: AHTDocId_Status *GetDocIdStatus (int docid, HTList * documents)
245: {
246: AHTDocId_Status *me;
247: HTList *cur;
248:
249: if (documents)
250: {
251: cur = documents;
252:
253: while ((me = (AHTDocId_Status *) HTList_nextObject (cur)))
254: {
255: if (me->docid == docid)
256: return (me);
1.18 cvs 257: }
258: }
1.15 cvs 259: return (AHTDocId_Status *) NULL;
260:
261: }
262:
1.5 cvs 263: /*----------------------------------------------------------------------
1.27 cvs 264: AHTGuessAtom_for
265: Converts an Amaya type descriptor into the equivalent MIME type.
266: ----------------------------------------------------------------------*/
1.276 kahan 267: static HTAtom *AHTGuessAtom_for (char *urlName, char *contentType)
1.27 cvs 268: {
269: HTAtom *atom;
1.265 cvs 270: char * filename;
1.160 cvs 271: HTEncoding enc = NULL;
272: HTEncoding cte = NULL;
273: HTLanguage lang = NULL;
1.50 cvs 274: double quality = 1.0;
1.27 cvs 275:
1.276 kahan 276: /* we already have a MIME type, we jsut return the atom */
277: if (contentType && *contentType)
278: atom = HTAtom_for (contentType);
279: else
1.27 cvs 280: {
1.276 kahan 281: /* we don't have the MIME type, so
282: we try to use the filename's suffix to infer it */
1.265 cvs 283: filename = AmayaParseUrl (urlName, "",
284: AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION);
285: HTBind_getFormat (filename, &atom, &enc, &cte, &lang, &quality);
1.45 cvs 286: TtaFreeMemory (filename);
1.27 cvs 287: if (atom == WWW_UNKNOWN)
1.276 kahan 288: {
1.27 cvs 289: /*
1.276 kahan 290: ** we could not identify the suffix, so we give it a default type.
291: ** (we should ask the user, but we're not ready for that yet).
1.27 cvs 292: */
293: atom = HTAtom_for ("text/html");
1.276 kahan 294: }
1.27 cvs 295: }
296: return atom;
297: }
298:
299: /*----------------------------------------------------------------------
1.238 cvs 300: HTTP_Headers_set
301: Copies the headers in which the application is interested, doing
302: any in-between conversions as needed.
303: ----------------------------------------------------------------------*/
304: void HTTP_headers_set (HTRequest * request, HTResponse * response, void *context, int status)
305: {
1.267 kahan 306: AHTReqContext *me;
1.283 cvs 307: HTAtom *tmp_atom = NULL;
1.267 kahan 308: char *tmp_char;
1.285 kahan 309: char *tmp_char2;
1.284 kahan 310: char tmp_string[20];
1.267 kahan 311: HTParentAnchor *anchor;
1.287 kahan 312: ThotBool use_anchor;
1.267 kahan 313:
314: me = (AHTReqContext *) HTRequest_context (request);
1.282 kahan 315:
1.267 kahan 316: anchor = HTRequest_anchor (request);
1.238 cvs 317:
1.287 kahan 318: /* if we get a cached answer, we should get all the header information
319: from the anchor, instead of from the response object */
320: tmp_char = HTAnchor_physical (anchor);
321: if (tmp_char && !strncmp (tmp_char, "cache:", sizeof ("cache:") - 1))
322: use_anchor = TRUE;
323: else
324: use_anchor = FALSE;
325:
1.263 kahan 326: /* @@@ JK: we need a function here to specify which headers we
1.238 cvs 327: want to copy */
328:
1.267 kahan 329: /* copy the content_type if we didn't force it before */
330: if (me->http_headers.content_type == NULL)
1.260 kahan 331: {
1.267 kahan 332: /* trying to use the info in the anchor, rather than in the response.
333: Seems it's more recent */
1.282 kahan 334:
335: /* @@ JK: trying to use the content type stored in the response object */
1.287 kahan 336: if (!use_anchor && response)
1.282 kahan 337: tmp_atom = HTResponse_format (response);
338: if (!tmp_atom)
339: tmp_atom = HTAnchor_format (anchor);
1.260 kahan 340:
1.267 kahan 341: if (tmp_atom)
342: tmp_char = HTAtom_name (tmp_atom);
343: else
344: tmp_char = "www/unknown";
345:
346: if (tmp_char && tmp_char[0] != EOS)
1.238 cvs 347: {
1.267 kahan 348: /* libwww gives www/unknown when it gets an error. As this is
349: an HTML test, we force the type to text/html */
350: if (!strcmp (tmp_char, "www/unknown"))
351: {
352: /* if it's not a file downloaded from FTP, initialize the
353: content type to text/html by default */
354: me->http_headers.content_type = NULL;
355: }
356: else
1.284 kahan 357: me->http_headers.content_type = TtaStrdup (tmp_char);
1.267 kahan 358:
1.238 cvs 359: #ifdef DEBUG_LIBWWW
1.267 kahan 360: fprintf (stderr, "Set content type to: %s\n",
361: me->http_headers.content_type);
1.238 cvs 362: #endif /* DEBUG_LIBWWW */
1.267 kahan 363: }
1.238 cvs 364: }
1.267 kahan 365:
1.238 cvs 366: /* copy the charset */
1.267 kahan 367:
368: /* @@ JK I think there was a problem when using info directly from
369: the anchor... but what it was? The response object doesn't have
370: it anyway */
371: tmp_atom = HTAnchor_charset (anchor);
372: #if 0
1.260 kahan 373: if (use_anchor)
374: tmp_atom = HTAnchor_charset (anchor);
375: else
376: tmp_atom = HTResponse_charset (response);
1.267 kahan 377: #endif
378:
1.238 cvs 379: if (tmp_atom)
380: {
1.284 kahan 381: tmp_char = HTAtom_name (tmp_atom);
382: if (tmp_char)
383: me->http_headers.charset = TtaStrdup (tmp_char);
1.238 cvs 384: }
1.256 kahan 385:
1.268 kahan 386: /* copy the content length */
1.284 kahan 387: snprintf (tmp_string, sizeof (tmp_string), "%ld", HTAnchor_length (anchor));
388: me->http_headers.content_length = TtaStrdup (tmp_string);
1.268 kahan 389:
1.256 kahan 390: /* copy the reason */
391: tmp_char = HTResponse_reason (response);
392: if (tmp_char)
1.284 kahan 393: me->http_headers.reason = TtaStrdup (tmp_char);
394:
395: /* copy the content-location */
396: tmp_char = HTAnchor_location (anchor);
1.285 kahan 397: if (tmp_char && *tmp_char)
398: {
399: /* only include the filename. We suppose we have either a
400: relative or an absolute URL and that everything after the last
401: slash is the */
402: if (HTURL_isAbsolute (tmp_char))
403: {
404: tmp_char2 = tmp_char + strlen (tmp_char) -1;
405: while (*tmp_char2 != URL_SEP && tmp_char2 != tmp_char)
406: tmp_char2--;
407: if (tmp_char2 != tmp_char && *(tmp_char2 + 1))
408: tmp_char = tmp_char2 + 1;
409: }
410: me->http_headers.content_location = TtaStrdup (tmp_char);
411: }
1.238 cvs 412: }
413:
414: /*----------------------------------------------------------------------
415: HTTP_headers_delete
416: Deletes all the paramaters that were assigned to the response type
417: ----------------------------------------------------------------------*/
418: static void HTTP_headers_delete (AHTHeaders me)
419: {
420: if (me.content_type)
421: TtaFreeMemory (me.content_type);
422:
423: if (me.charset)
424: TtaFreeMemory (me.charset);
1.268 kahan 425:
426: if (me.content_length)
427: TtaFreeMemory (me.content_length);
1.256 kahan 428:
429: if (me.reason)
430: TtaFreeMemory (me.reason);
1.284 kahan 431:
432: if (me.content_location)
433: TtaFreeMemory (me.content_location);
1.238 cvs 434: }
435:
436: /*----------------------------------------------------------------------
437: HTTP_headers
438: Returns the value of a parameter in the HTTP response structure.
439: Returns null if this structure is empty.
440: ----------------------------------------------------------------------*/
1.265 cvs 441: char *HTTP_headers (AHTHeaders *me, AHTHeaderName param)
1.238 cvs 442: {
1.265 cvs 443: char *result;
1.238 cvs 444:
445: if (!me)
446: return NULL;
447:
448: switch (param)
449: {
450: case AM_HTTP_CONTENT_TYPE:
451: result = me->content_type;
452: break;
453: case AM_HTTP_CHARSET:
454: result = me->charset;
1.268 kahan 455: break;
456: case AM_HTTP_CONTENT_LENGTH:
457: result = me->content_length;
1.238 cvs 458: break;
1.256 kahan 459: case AM_HTTP_REASON:
460: result = me->reason;
1.284 kahan 461: break;
462: case AM_HTTP_CONTENT_LOCATION:
463: result = me->content_location;
1.256 kahan 464: break;
1.238 cvs 465: default:
466: result = NULL;
467: }
468:
469: return result;
470: }
471:
472: /*----------------------------------------------------------------------
1.17 cvs 473: AHTReqContext_new
474: create a new Amaya Context Object and update the global Amaya
475: request status.
1.297 kirschpi 476:
477: ----------------------------------------------------------------------
478: MKP: this function is now used in davlib.c file for the WebDAV requests
1.299 kirschpi 479:
1.297 kirschpi 480: ---------------------------------------------------------------------- */
481: AHTReqContext *AHTReqContext_new (int docid)
1.4 cvs 482: {
483: AHTReqContext *me;
484: AHTDocId_Status *docid_status;
485:
486: if ((me = (AHTReqContext *) TtaGetMemory (sizeof (AHTReqContext))) == NULL)
1.116 cvs 487: outofmem (__FILE__, "AHTReqContext_new");
488:
489: /* clear the structure */
490: memset ((void *) me, 0, sizeof (AHTReqContext));
1.4 cvs 491:
1.81 cvs 492: /* Bind the Context object together with the Request Object */
493: me->request = HTRequest_new ();
494:
1.80 cvs 495: /* clean the associated file structure) */
1.79 cvs 496: HTRequest_setOutputStream (me->request, NULL);
1.81 cvs 497:
1.4 cvs 498: /* Initialize the other members of the structure */
1.17 cvs 499: me->reqStatus = HT_NEW; /* initial status of a request */
1.4 cvs 500: me->docid = docid;
501: HTRequest_setMethod (me->request, METHOD_GET);
502: HTRequest_setOutputFormat (me->request, WWW_SOURCE);
503: HTRequest_setContext (me->request, me);
1.116 cvs 504:
1.36 cvs 505: /* experimental */
506: me->read_sock = INVSOC;
507: me->write_sock = INVSOC;
508: me->except_sock = INVSOC;
1.4 cvs 509:
510: /* Update the global context */
511: HTList_appendObject (Amaya->reqlist, (void *) me);
512:
513: docid_status = GetDocIdStatus (docid, Amaya->docid_status);
514:
1.7 cvs 515: if (docid_status == NULL)
516: {
1.116 cvs 517: docid_status = (AHTDocId_Status *)
518: TtaGetMemory (sizeof (AHTDocId_Status));
1.7 cvs 519: docid_status->docid = docid;
520: docid_status->counter = 1;
521: HTList_addObject (Amaya->docid_status, (void *) docid_status);
522: }
523: else
1.4 cvs 524: docid_status->counter++;
525:
1.297 kirschpi 526: #ifdef DAV /* clean the DAV request context */
527: me->dav_context = NULL; /* it should be create only when doing a DAV request */
528: #endif
529:
1.4 cvs 530: Amaya->open_requests++;
531:
1.74 cvs 532: #ifdef DEBUG_LIBWWW
533: fprintf (stderr, "AHTReqContext_new: Created object %p\n", me);
534: #endif
1.116 cvs 535:
1.4 cvs 536: return me;
537: }
538:
1.5 cvs 539: /*----------------------------------------------------------------------
1.17 cvs 540: AHTReqContext_delete
541: Delete an Amaya Context Object and update the global Amaya request
542: status.
1.5 cvs 543: ----------------------------------------------------------------------*/
1.191 cvs 544: ThotBool AHTReqContext_delete (AHTReqContext * me)
1.4 cvs 545: {
546: AHTDocId_Status *docid_status;
547:
1.7 cvs 548: if (me)
549: {
1.74 cvs 550: #ifdef DEBUG_LIBWWW
1.138 cvs 551: fprintf (stderr, "AHTReqContext_delete: Deleting object %p\n", me);
1.74 cvs 552: #endif
1.297 kirschpi 553:
554: #ifdef DAV /* if there is a DAV context object, delete it */
555: if (me->dav_context) AHTDAVContext_delete(me->dav_context);
556: #endif /* DAV */
557:
1.138 cvs 558: if (Amaya->reqlist)
559: HTList_removeObject (Amaya->reqlist, (void *) me);
560:
561: docid_status = GetDocIdStatus (me->docid, Amaya->docid_status);
562: if (docid_status)
563: {
564: docid_status->counter--;
565:
566: if (docid_status->counter == 0)
567: {
568: HTList_removeObject (Amaya->docid_status, (void *) docid_status);
569: TtaFreeMemory ((void *) docid_status);
570: }
571: }
1.215 cvs 572:
573: HTNoFreeStream_delete (HTRequest_outputStream (me->request));
574: HTRequest_setOutputStream (me->request, NULL);
1.190 cvs 575: /* JK: no longer needed in libwww 5.2.3
576: if (me->method != METHOD_PUT && HTRequest_outputStream (me->request))
577: AHTFWriter_FREE (HTRequest_outputStream (me->request));
578: */
1.138 cvs 579: HTRequest_delete (me->request);
580:
581: if (me->output && me->output != stdout)
582: {
1.85 cvs 583: #ifdef DEBUG_LIBWWW
1.138 cvs 584: fprintf (stderr, "AHTReqContext_delete: URL is %s, closing "
585: "FILE %p\n", me->urlName, me->output);
1.85 cvs 586: #endif
1.138 cvs 587: fclose (me->output);
588: me->output = NULL;
589: }
1.79 cvs 590:
1.138 cvs 591: if (me->error_stream != (char *) NULL)
592: HT_FREE (me->error_stream);
593: #ifndef _WINDOWS
594: #ifdef WWW_XWINDOWS
595: if (me->read_xtinput_id || me->write_xtinput_id ||
596: me->except_xtinput_id)
597: RequestKillAllXtevents(me);
598: #endif /* WWW_XWINDOWS */
599: #endif /* !_WINDOWS */
600:
601: if (me->reqStatus == HT_ABORT)
602: {
603: if (me->outputfile && me->outputfile[0] != EOS)
604: {
1.233 cvs 605: TtaFileUnlink (me->outputfile);
1.138 cvs 606: me->outputfile[0] = EOS;
607: }
608: }
609:
610: if ((me->mode & AMAYA_ASYNC) || (me->mode & AMAYA_IASYNC))
611: /* for the ASYNC mode, free the memory we allocated in GetObjectWWW
612: or in PutObjectWWW */
613: {
614: if (me->urlName)
615: TtaFreeMemory (me->urlName);
616: if (me->outputfile)
617: TtaFreeMemory (me->outputfile);
618: }
1.206 cvs 619:
1.208 cvs 620: /* the real name to which we are publishing */
621: if (me->default_put_name)
622: TtaFreeMemory (me->default_put_name);
623:
1.206 cvs 624: /* @@ temp change for the %esc conversion */
625: if (me->method == METHOD_PUT && me->urlName)
626: TtaFreeMemory (me->urlName);
627:
1.138 cvs 628: if (me->formdata)
629: HTAssocList_delete (me->formdata);
1.238 cvs 630:
631: /* erase the response headers */
632: HTTP_headers_delete (me->http_headers);
1.138 cvs 633:
1.228 cvs 634: #ifdef ANNOTATIONS
635: if (me->document)
636: TtaFreeMemory (me->document);
637: #endif /* ANNOTATIONS */
638:
1.138 cvs 639: /* to trace bugs */
640: memset ((void *) me, 0, sizeof (AHTReqContext));
641:
642: TtaFreeMemory ((void *) me);
643:
644: Amaya->open_requests--;
645:
646: return TRUE;
1.7 cvs 647: }
1.15 cvs 648: return FALSE;
1.4 cvs 649: }
650:
651:
1.15 cvs 652: /*----------------------------------------------------------------------
1.17 cvs 653: Thread_deleteAll
654: this function deletes the whole list of active threads.
1.5 cvs 655: ----------------------------------------------------------------------*/
1.4 cvs 656: static void Thread_deleteAll (void)
657: {
1.21 cvs 658: HTList *cur;
659: AHTReqContext *me;
660: AHTDocId_Status *docid_status;
661:
1.74 cvs 662: if (Amaya && Amaya->reqlist)
663: {
664: if (Amaya->open_requests > 0)
665: #ifdef DEBUG_LIBWWW
666: fprintf (stderr, "Thread_deleteAll: Killing %d outstanding "
667: "requests\n", Amaya->open_requests);
668: #endif
669: {
670: cur = Amaya->reqlist;
671:
672: /* erase the requests */
673: while ((me = (AHTReqContext *) HTList_removeLastObject (cur)))
674: {
675: if (me->request)
676: {
1.142 cvs 677: #ifndef _WINDOWS
678: #ifdef WWW_XWINDOWS
1.74 cvs 679: RequestKillAllXtevents (me);
1.142 cvs 680: #endif /* WWW_XWINDOWS */
1.138 cvs 681: #endif /* !_WINDOWS */
1.140 cvs 682: if (!HTRequest_kill (me->request))
683: AHTReqContext_delete (me);
1.74 cvs 684: }
685: } /* while */
686:
687: /* erase the docid_status entities */
688: while ((docid_status = (AHTDocId_Status *) HTList_removeLastObject ((void *) Amaya->docid_status)))
689: TtaFreeMemory ((void *) docid_status);
690:
691: } /* if */
1.84 cvs 692:
1.74 cvs 693: }
1.4 cvs 694: }
1.198 cvs 695:
1.5 cvs 696: /*----------------------------------------------------------------------
1.83 cvs 697: AHTOpen_file
698: ----------------------------------------------------------------------*/
1.85 cvs 699: int AHTOpen_file (HTRequest * request)
1.83 cvs 700: {
701: AHTReqContext *me; /* current request */
702:
703: me = HTRequest_context (request);
1.93 cvs 704: if (!me)
705: return HT_ERROR;
1.83 cvs 706: #ifdef DEBUG_LIBWWW
1.116 cvs 707: fprintf(stderr, "AHTOpen_file: start for object : %p\n", me);
1.85 cvs 708: #endif /* DEBUG_LIBWWW */
709: if (me->reqStatus == HT_ABORT)
710: {
711: #ifdef DEBUG_LIBWWW
712: fprintf(stderr, "AHTOpen_file: caught an abort request, skipping it\n");
1.83 cvs 713: #endif /* DEBUG_LIBWWW */
1.85 cvs 714: return HT_OK;
715: }
716:
1.136 cvs 717: if (me->method == METHOD_PUT)
718: {
719: me->reqStatus = HT_WAITING;
720: return HT_OK;
721: }
722:
1.85 cvs 723: if (HTRequest_outputStream (me->request))
724: {
725: #ifdef DEBUG_LIBWWW
726: fprintf(stderr, "AHTOpen_file: output stream already existed for url %s\n", me->urlName);
727: #endif /* DEBUG_LIBWWW */
728: return HT_OK;
729: }
730:
731: #ifdef DEBUG_LIBWWW
1.265 cvs 732: fprintf(stderr, "AHTOpen_file: opening output stream for url %s\n", me->urlName);
1.85 cvs 733: #endif /* DEBUG_LIBWWW */
734:
1.83 cvs 735: if (!(me->output) &&
736: (me->output != stdout) &&
737: #ifndef _WINDOWS
1.265 cvs 738: (me->output = fopen (me->outputfile, "w")) == NULL)
1.116 cvs 739: #else /* !_WINDOWS */
1.265 cvs 740: (me->output = fopen (me->outputfile, "wb")) == NULL)
741: #endif /* !_WINDOWS */
1.83 cvs 742: {
1.131 cvs 743: me->outputfile[0] = EOS; /* file could not be opened */
1.85 cvs 744: #ifdef DEBUG_LIBWWW
745: fprintf(stderr, "AHTOpen_file: couldn't open output stream for url %s\n", me->urlName);
746: #endif
1.265 cvs 747: TtaSetStatus (me->docid, 1,
748: TtaGetMessage (AMAYA, AM_CANNOT_CREATE_FILE),
749: me->outputfile);
1.83 cvs 750: me->reqStatus = HT_ERR;
751: return (HT_ERROR);
752: }
753:
754: HTRequest_setOutputStream (me->request,
1.265 cvs 755: AHTFWriter_new (me->request, me->output, YES));
1.83 cvs 756: me->reqStatus = HT_WAITING;
757: return HT_OK;
758: }
759:
760: /*----------------------------------------------------------------------
1.265 cvs 761: SafePut_init
762: Sets up the domains which are authorized to make a redirect on
763: a PUT.
764: ----------------------------------------------------------------------*/
765: static void SafePut_init (void)
766: {
767: char *strptr;
1.266 cvs 768: char *ptr, *ptr2;
769: char *domain;
1.265 cvs 770:
771: /* get the proxy settings from the thot.ini file */
772: strptr = TtaGetEnvString ("SAFE_PUT_REDIRECT");
773: if (strptr && *strptr)
774: {
775: /* Get copy we can mutilate */
1.266 cvs 776: ptr2 = TtaStrdup (strptr);
1.265 cvs 777: /* convert to lowercase */
1.266 cvs 778: ptr = ptr2;
1.265 cvs 779: while (*ptr)
780: {
781: *ptr = tolower (*ptr);
782: ptr++;
783: }
784:
785: /* create the list container */
1.266 cvs 786: safeput_list = HTList_new ();
787:
1.265 cvs 788: /* store the domain list */
1.266 cvs 789: ptr = ptr2;
790: while ((domain = HTNextField (&ptr)) != NULL)
1.265 cvs 791: HTList_addObject (safeput_list, TtaStrdup (domain));
792:
793: TtaFreeMemory (ptr2);
794: }
795: }
796:
797: /*----------------------------------------------------------------------
798: SafePut_delete
799: Deletes the safeput_list variable
800: ----------------------------------------------------------------------*/
801: static void SafePut_delete (void)
802: {
803: HTList *cur = safeput_list;
804: char *domain;
805:
806: if (!safeput_list)
807: return;
808:
809: while ((domain = (char *) HTList_nextObject (cur)))
810: TtaFreeMemory (domain);
811: HTList_delete (safeput_list);
812: safeput_list = NULL;
813: }
814:
815: /*----------------------------------------------------------------------
816: SafePut_query
817: returns true if the domain to which belongs the URL accepts an automatic
818: PUT redirect.
819: ----------------------------------------------------------------------*/
820: static ThotBool SafePut_query (char *url)
821: {
1.266 cvs 822: HTList *cur;
823: char *me;
824: ThotBool found;
825: char tmp[MAX_LENGTH];
1.265 cvs 826:
827: /* extract the domain path of the url and normalize it */
828: /* domain = url; */
829: cur = safeput_list;
830: found = FALSE;
831:
1.266 cvs 832: while ((me = (char *) HTList_nextObject (cur)))
833: {
1.273 cvs 834: strcpy (tmp, me);
1.266 cvs 835: if (strstr (url, tmp))
836: {
837: found = TRUE;
838: break;
839: }
840: }
1.265 cvs 841:
842: return (found);
843: }
844:
845: /*----------------------------------------------------------------------
1.17 cvs 846: redirection_handler
847: this function is registered to handle permanent and temporary
848: redirections.
849: ----------------------------------------------------------------------*/
1.265 cvs 850: static int redirection_handler (HTRequest *request, HTResponse *response,
851: void *param, int status)
1.4 cvs 852: {
1.265 cvs 853: HTAnchor *new_anchor = HTResponse_redirection (response);
854: AHTReqContext *me = HTRequest_context (request);
855: HTMethod method = HTRequest_method (request);
856: char *ref;
857: char *escape_src, *dst;
858: char urlAdr[MAX_LENGTH];
859:
860: if (!me)
861: /* if the redirect doesn't come from Amaya, we call libwww's standard redirect filter */
862: return (HTRedirectFilter (request, response, param, status));
863:
864: if (!new_anchor)
865: {
866: if (PROT_TRACE)
1.235 cvs 867: HTTrace ("Redirection. No destination\n");
1.265 cvs 868: return HT_OK;
869: }
1.4 cvs 870:
871: /*
1.207 cvs 872: ** Only do redirect on GET, HEAD, and authorized domains for PUT
1.265 cvs 873: */
874: if ((me->method == METHOD_PUT && !SafePut_query (me->urlName)) ||
875: (me->method != METHOD_PUT && !HTMethod_isSafe (method)))
876: {
877: /*
878: ** If we got a 303 See Other then change the method to GET.
879: ** Otherwise ask the user whether we should continue.
880: */
881: if (status == HT_SEE_OTHER)
882: {
1.235 cvs 883: if (PROT_TRACE)
1.265 cvs 884: HTTrace("Redirection. Changing method from %s to GET\n", HTMethod_name(method));
885: HTRequest_setMethod(request, METHOD_GET);
886: }
887: else
888: {
889: HTAlertCallback *prompt = HTAlert_find (HT_A_CONFIRM);
890: if (prompt)
891: {
892: if ((*prompt) (request, HT_A_CONFIRM, HT_MSG_REDIRECTION, NULL, NULL, NULL) != YES)
893: {
894: /* the user didn't agree on the redirection, so
895: we consider it's an abort */
896: me->reqStatus = HT_ABORT;
897: /* and we return HT_OK so that the terminate_handler
898: will be called */
899: return HT_OK;
900: }
901: }
902: }
903: }
904:
1.4 cvs 905: /*
1.265 cvs 906: ** Start new request with the redirect anchor found in the headers.
907: ** Note that we reuse the same request object which means that we must
908: ** keep this around until the redirected request has terminated. It also
909: ** allows us in an easy way to keep track of the number of redirections
910: ** so that we can detect endless loops.
911: */
912: if (HTRequest_doRetry (request))
913: {
914: /*
915: ** Start request with new credentials
916: */
917: /* only do a redirect using a network protocol understood by Amaya */
1.273 cvs 918: strcpy (urlAdr, new_anchor->parent->address);
1.265 cvs 919: if (IsValidProtocol (urlAdr))
920: {
921: /* if it's a valid URL, we try to normalize it */
922: /* We use the pre-redirection anchor as a base name */
923: /* @@ how to obtain this address here? */
924: dst = urlAdr;
925: escape_src = EscapeURL (me->urlName);
926: if (escape_src)
927: {
928: ref = AmayaParseUrl (dst, escape_src, AMAYA_PARSE_ALL);
929: TtaFreeMemory (escape_src);
930: }
931: else
932: ref = NULL;
933:
934: if (ref)
935: {
936: HTAnchor_setPhysical (HTAnchor_parent (new_anchor), ref);
937: TtaFreeMemory (ref);
938: }
939: else
940: return HT_OK; /* We can't redirect anymore */
941: }
942: else
943: return HT_OK; /* We can't redirect anymore */
944:
945: /* update the current file name */
946: if ((me->mode & AMAYA_ASYNC) || (me->mode & AMAYA_IASYNC) ||
947: (me->method == METHOD_PUT))
948: {
949: TtaFreeMemory (me->urlName);
1.272 cvs 950: me->urlName = TtaStrdup (urlAdr);
1.265 cvs 951: }
952: else
953: {
954: /* it's a SYNC mode, so we should keep the urlName */
955: strncpy (me->urlName, urlAdr, MAX_LENGTH - 1);
956: me->urlName[MAX_LENGTH - 1] = EOS;
957: }
958: ChopURL (me->status_urlName, me->urlName);
1.166 cvs 959:
1.265 cvs 960: /* @@ verify if this is important */
961: /* @@@ new libwww doesn't need this free stream while making
962: a PUT. Is it the case everywhere or just for PUT? */
963: if (me->method != METHOD_PUT &&
964: me->request->orig_output_stream != NULL)
965: {
966: AHTFWriter_FREE (me->request->orig_output_stream);
967: me->request->orig_output_stream = NULL;
968: if (me->output != stdout)
969: {
970: /* Are we writing to a file? */
1.257 kahan 971: #ifdef DEBUG_LIBWWW
1.265 cvs 972: fprintf (stderr, "redirection_handler: New URL is %s, closing FILE %p\n", me->urlName, me->output);
1.257 kahan 973: #endif
1.265 cvs 974: fclose (me->output);
975: me->output = NULL;
976: }
977: }
978:
979: /* tell the user what we're doing */
980: TtaSetStatus (me->docid, 1,
981: TtaGetMessage (AMAYA, AM_RED_FETCHING), me->status_urlName);
982: /*
983: ** launch the request
984: */
985: /* add a link relationship? */
986: /* reset the request status */
987: me->reqStatus = HT_NEW;
988: /* clear the errors */
989: HTError_deleteAll (HTRequest_error (request));
990: HTRequest_setError (request, NULL);
991: /* clear the authentication credentials, as they get regenerated */
992: HTRequest_deleteCredentialsAll (request);
1.297 kirschpi 993:
994: #ifdef DAV
1.299 kirschpi 995: /* remove the old header "If" (WebDAV lock information) */
1.297 kirschpi 996: DAVRemoveIfHeader (me);
997:
998: /* search lock information for the new url */
999: if (me->method == METHOD_POST || me->method == METHOD_PUT)
1000: DAVAddIfHeader (me,me->urlName);
1001: #endif
1.265 cvs 1002:
1003: if (me->method == METHOD_POST || me->method == METHOD_PUT)
1.285 kahan 1004: {
1005: /* PUT, POST etc. */
1006: /* for PUT, we memorize there was a redirection, so that we
1007: can clear the original cache entry in the terminate_handler */
1008: if (me->method == METHOD_PUT)
1009: me->put_redirection = TRUE;
1010: status = HTLoadAbsolute (me->urlName, request);
1011: }
1.265 cvs 1012: else
1013: HTLoadAnchor (new_anchor, request);
1014: }
1015: else
1016: {
1017: HTRequest_addError (request, ERR_FATAL, NO, HTERR_MAX_REDIRECT, NULL, 0, "HTRedirectFilter");
1018: /* so that we can show the error message */
1019: if (me->error_html)
1020: DocNetworkStatus[me->docid] |= AMAYA_NET_ERROR;
1021: me->reqStatus = HT_ERR;
1022: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_REDIRECTIONS_LIMIT), NULL);
1023: }
1024:
1.4 cvs 1025: /*
1.74 cvs 1026: ** By returning HT_ERROR we make sure that this is the last handler to be
1027: ** called. We do this as we don't want any other filter to delete the
1028: ** request object now when we have just started a new one ourselves
1029: */
1.4 cvs 1030: return HT_ERROR;
1031: }
1032:
1.151 cvs 1033: #ifdef AMAYA_LOST_UPDATE
1034: /*----------------------------------------------------------------------
1035: precondition_handler
1036: 412 "Precondition failed" handler
1037: ----------------------------------------------------------------------*/
1.265 cvs 1038: static int precondition_handler (HTRequest *request, HTResponse *response,
1039: void *context, int status)
1.151 cvs 1040: {
1.168 cvs 1041: AHTReqContext *me = (AHTReqContext *) HTRequest_context (request);
1042: HTAlertCallback *prompt = HTAlert_find (HT_A_CONFIRM);
1.191 cvs 1043: ThotBool force_put;
1.151 cvs 1044:
1045: if (!me)
1046: return HT_OK; /* not an Amaya request */
1047:
1.168 cvs 1048: if (prompt)
1049: force_put = (*prompt) (request, HT_A_CONFIRM, HT_MSG_RULES,
1050: NULL, NULL, NULL);
1051: else
1052: force_put = NO;
1053:
1054: if (force_put)
1055: {
1.297 kirschpi 1056: #ifdef DAV
1057: BOOL noIf = NO;
1058:
1059: /* MKP: if the old request has preconditions, *
1060: * then, we supose that these preconditions *
1061: * caused the 412 Precondition Failed status *
1062: * code, otherwise we supose that the cause *
1063: * was an eventual If header. */
1064: if (HTRequest_preconditions(me->request)!=HT_NO_MATCH)
1065: noIf = NO;
1066: else
1067: noIf = YES;
1068: #endif /* DAV */
1069:
1070:
1.168 cvs 1071: /* start a new PUT request without preconditions */
1072: /* @@ do we need to kill the request? */
1073: if (me->output && me->output != stdout)
1074: {
1075: fclose (me->output);
1076: me->output = NULL;
1077: }
1078: /*
1079: ** reset the Amaya and libwww request status
1080: */
1.176 cvs 1081:
1082: /* start with a new, clean request structure */
1083: HTRequest_delete (me->request);
1084: me->request = HTRequest_new ();
1085: /* clean the associated file structure) */
1086: HTRequest_setOutputStream (me->request, NULL);
1087: /* Initialize the other members of the structure */
1.171 cvs 1088: HTRequest_setMethod (me->request, METHOD_GET);
1.176 cvs 1089: HTRequest_setOutputFormat (me->request, WWW_SOURCE);
1090: HTRequest_setContext (me->request, me);
1091: HTRequest_setPreemptive (me->request, NO);
1092: /*
1093: ** Make sure that the first request is flushed immediately and not
1094: ** buffered in the output buffer
1095: */
1096: if (me->mode & AMAYA_FLUSH_REQUEST)
1097: HTRequest_setFlush(me->request, YES);
1098:
1.171 cvs 1099: /* turn off preconditions */
1100: HTRequest_setPreconditions(me->request, HT_NO_MATCH);
1101: me->reqStatus = HT_NEW;
1.297 kirschpi 1102:
1103:
1104: #ifdef DAV
1105: /* MKP: add an If header only if there wasn't preconditions */
1106: if (noIf!=YES) DAVAddIfHeader (me,HTAnchor_address(me->dest));
1107: #endif /* DAV */
1108:
1109:
1.171 cvs 1110: /* make the request */
1.176 cvs 1111: status = HTPutDocumentAnchor (HTAnchor_parent (me->source),
1112: me->dest, me->request);
1.168 cvs 1113: /* stop here */
1114: return HT_ERROR;
1115: }
1116: else
1117: {
1118: /* abort the request */
1119: /* @@ should we call StopRequest here? */
1120: me->reqStatus = HT_ABORT;
1121: /* stop here */
1122: return HT_ERROR;
1123: }
1124: }
1.151 cvs 1125:
1.168 cvs 1126: /*----------------------------------------------------------------------
1127: check_handler
1128: Request HEAD checker filter
1129: ----------------------------------------------------------------------*/
1130: static int check_handler (HTRequest * request, HTResponse * response,
1.151 cvs 1131: void * param, int status)
1132: {
1.168 cvs 1133: AHTReqContext *me = (AHTReqContext *) HTRequest_context (request);
1134: HTAlertCallback *prompt = HTAlert_find (HT_A_CONFIRM);
1.191 cvs 1135: ThotBool force_put;
1.168 cvs 1136:
1137: if (!me)
1138: return HT_OK; /* not an Amaya request */
1139:
1140: HTRequest_deleteAfter(me->request, check_handler);
1141: /*
1142: ** If head request showed that the document doesn't exist
1143: ** then just go ahead and PUT it. Otherwise ask for help
1144: */
1145: if (status == HT_ERROR || status == HT_INTERRUPTED || status == HT_TIMEOUT)
1146: {
1147: /* we'd need to call terminate_handler, to free the resources */
1148: /* abort the request */
1149: /* @@ should we call StopRequest here? */
1150: me->reqStatus = HT_ABORT;
1151: /* stop here */
1152: return HT_ERROR;
1153: }
1154: else if (status == HT_NO_ACCESS || status == HT_NO_PROXY_ACCESS)
1155: {
1156: /* we'd need to call terminate_handler, to free the resources */
1157: /* abort the request */
1158: /* @@ should we call StopRequest here? */
1159: me->reqStatus = HT_ABORT;
1160: /* stop here */
1161: return HT_ERROR;
1162: }
1163: else if ( (abs(status)/100) != 2)
1164: {
1.176 cvs 1165: /* start with a new, clean request structure */
1166: HTRequest_delete (me->request);
1167: me->request = HTRequest_new ();
1.208 cvs 1168: /* add the default PUT name */
1169: HTRequest_setDefaultPutName (me->request, me->default_put_name);
1.176 cvs 1170: /* clean the associated file structure) */
1171: HTRequest_setOutputStream (me->request, NULL);
1172: /* Initialize the other members of the structure */
1.171 cvs 1173: HTRequest_setMethod (me->request, METHOD_GET);
1.176 cvs 1174: HTRequest_setOutputFormat (me->request, WWW_SOURCE);
1175: HTRequest_setContext (me->request, me);
1176: HTRequest_setPreemptive (me->request, NO);
1177: /*
1178: ** Make sure that the first request is flushed immediately and not
1179: ** buffered in the output buffer
1180: */
1181: if (me->mode & AMAYA_FLUSH_REQUEST)
1182: HTRequest_setFlush(me->request, YES);
1.297 kirschpi 1183:
1184: #ifdef DAV
1185: /* MKP: try to add an if header */
1186: DAVAddIfHeader (me,me->urlName);
1187: #endif
1188:
1.176 cvs 1189:
1190: /* turn on the special preconditions, to avoid having this
1191: ressource appear before we do the PUT */
1.168 cvs 1192: HTRequest_setPreconditions(me->request, HT_DONT_MATCH_ANY);
1.171 cvs 1193: me->reqStatus = HT_NEW;
1.168 cvs 1194: status = HTPutDocumentAnchor (HTAnchor_parent (me->source), me->dest, me->request);
1195: return HT_ERROR; /* stop here */
1.176 cvs 1196: }
1.168 cvs 1197: else
1198: {
1199: if (prompt)
1200: force_put = (*prompt) (request, HT_A_CONFIRM, HT_MSG_FILE_REPLACE,
1201: NULL, NULL, NULL);
1202: else
1203: force_put = FALSE;
1204:
1205: if (force_put)
1.151 cvs 1206: {
1207: /* Start a new PUT request without preconditions */
1.176 cvs 1208:
1209: /* get a new, clean request structure */
1210: HTRequest_delete (me->request);
1211: me->request = HTRequest_new ();
1.208 cvs 1212: /* add the default PUT name */
1213: HTRequest_setDefaultPutName (me->request, me->default_put_name);
1.176 cvs 1214: /* clean the associated file structure) */
1215: HTRequest_setOutputStream (me->request, NULL);
1216: /* Initialize the other members of the structure */
1.171 cvs 1217: HTRequest_setMethod (me->request, METHOD_GET);
1.176 cvs 1218: HTRequest_setOutputFormat (me->request, WWW_SOURCE);
1219: HTRequest_setContext (me->request, me);
1220: HTRequest_setPreemptive (me->request, NO);
1.297 kirschpi 1221:
1222: #ifdef DAV
1223: /* MKP: try to add an if header */
1224: DAVAddIfHeader (me,HTAnchor_address(me->dest));
1225: #endif
1226:
1.176 cvs 1227: /*
1228: ** Make sure that the first request is flushed immediately and not
1229: ** buffered in the output buffer
1230: */
1231: if (me->mode & AMAYA_FLUSH_REQUEST)
1232: HTRequest_setFlush(me->request, YES);
1233: /* remove the preconditions */
1.168 cvs 1234: HTRequest_setPreconditions(me->request, HT_NO_MATCH);
1.171 cvs 1235: me->reqStatus = HT_NEW;
1.176 cvs 1236: status = HTPutDocumentAnchor (HTAnchor_parent (me->source),
1237: me->dest, me->request);
1.168 cvs 1238: return HT_ERROR; /* stop here */
1.151 cvs 1239: }
1.168 cvs 1240: else
1241: {
1242: /* we'd need to call terminate_handler, to free the resources */
1243: /* abort the request */
1244: /* @@ should we call StopRequest here? */
1245: me->reqStatus = HT_ABORT;
1246: /* stop here */
1247: return HT_ERROR;
1248: }
1249: }
1250: return HT_ERROR;
1.151 cvs 1251: }
1252: #endif /* AMAYA_LOST_UPDATE */
1253:
1.5 cvs 1254: /*----------------------------------------------------------------------
1.17 cvs 1255: terminate_handler
1256: this function is registered to handle the result of the request
1.5 cvs 1257: ----------------------------------------------------------------------*/
1.265 cvs 1258: static int terminate_handler (HTRequest *request, HTResponse *response,
1259: void *context, int status)
1.4 cvs 1260: {
1.116 cvs 1261: AHTReqContext *me = (AHTReqContext *) HTRequest_context (request);
1.191 cvs 1262: ThotBool error_flag;
1.116 cvs 1263:
1264: if (!me)
1.214 cvs 1265: return HT_ERROR; /* not an Amaya request */
1.116 cvs 1266:
1267: if (me->reqStatus == HT_END)
1268: /* we have already processed this request! */
1269: return HT_OK;
1270:
1271: /* if Amaya was killed, treat with this request as if it were
1272: issued by a Stop button event */
1273:
1274: if (!AmayaIsAlive ())
1.80 cvs 1275: me->reqStatus = HT_ABORT;
1.220 cvs 1276:
1277: /* trying to protect against this problem... hard to place
1278: the detection elsewhere :-/ */
1.240 cvs 1279: /* @@ JK: Is this still needed? */
1.220 cvs 1280: if (IsHTTP09Error (request))
1281: status = -1;
1282:
1.238 cvs 1283: if (status == HT_LOADED
1284: || status == HT_CREATED
1285: || status == HT_NO_DATA
1.249 kahan 1286: /* JK: removed it as the kludge doesn't seem useful anymore */
1.160 cvs 1287: /* kludge for work around libwww problem */
1.249 kahan 1288: /* || (status == HT_INTERRUPTED && me->method == METHOD_PUT) */
1.116 cvs 1289: #ifdef AMAYA_WWW_CACHE
1290: /* what status to use to know we're downloading from a cache? */
1.238 cvs 1291: || status == HT_NOT_MODIFIED
1292: || status == HT_PARTIAL_CONTENT
1.116 cvs 1293: #endif /* AMAYA_WWW_CACHE */
1.238 cvs 1294: || me->reqStatus == HT_ABORT)
1.74 cvs 1295: error_flag = FALSE;
1.297 kirschpi 1296: #ifdef DAV
1297: else if (status == HT_LOCKED
1298: || status == HT_FAILED_DEPENDENCY
1299: || status == HT_MULTI_STATUS) {
1300: /* WebDAV return codes - they are handled in
1301: * specific filters. We don't need to deal
1302: * with them anymore
1303: */
1304: error_flag = FALSE;
1305: }
1306: #endif
1.256 kahan 1307: else
1.74 cvs 1308: error_flag = TRUE;
1.130 cvs 1309:
1.285 kahan 1310: /* If we did a PUT that was redirected, clean the original
1311: cache entry */
1312: if (status == 204 && me->method == METHOD_PUT && me->put_redirection)
1313: {
1314: HTCache * cache;
1315: HTParentAnchor * anchor = HTAnchor_parent (me->dest);
1316: cache = HTCache_find (anchor, NULL);
1317: if (cache)
1318: {
1319: /* what a problem... we update the cache with the wrong data
1320: from the response... after the redirection */
1321: HTCache_resetMeta (cache, request, response);
1322: }
1323: else
1324: /* If entry doesn't already exist then create a new entry */
1325: HTCache_touch(request, response, HTAnchor_parent (me->dest));
1326: }
1327:
1.4 cvs 1328: /* output any errors from the server */
1.130 cvs 1329:
1.77 cvs 1330: /*
1.74 cvs 1331: ** me->output = output file which will receive an html file
1332: ** me->error_html = yes, output HTML errors in the screen
1333: ** request->error_stack == if there are any errors, they will be here
1334: ** me->error_stream_size If it's != 0 means an error message has already
1335: ** been written to the stack
1336: */
1337:
1.4 cvs 1338: /* First, we verify if there are any errors and if they are not
1.17 cvs 1339: ** yet written to the error stack. If no, then let's try to write them
1340: ** ourselves
1341: */
1.74 cvs 1342:
1343: #ifdef DEBUG_LIBWWW
1344: fprintf (stderr, "terminate_handler: URL is "
1345: "%s, closing FILE %p status is %d\n", me->urlName, me->output,
1346: status);
1.69 cvs 1347: #endif
1.74 cvs 1348:
1.69 cvs 1349: if (me->output && me->output != stdout)
1350: {
1.214 cvs 1351: /* we are writing to a local file */
1.74 cvs 1352: if (me->reqStatus != HT_ABORT)
1353: { /* if the request was not aborted and */
1.80 cvs 1354: if (error_flag &&
1355: me->error_html == TRUE)
1356: /* there were some errors and we want to print them */
1357: {
1358: if (me->error_stream_size == 0)/* and the stream is empty */
1.210 cvs 1359: {
1360: /* if the transfer was interrupted, the file may not be
1361: empty. So, we erase it */
1362: fflush (me->output);
1363: rewind (me->output);
1364: AHTError_MemPrint (request); /* copy errors from
1365: **the error stack
1366: ** into the error stream */
1367: }
1.80 cvs 1368: if (me->error_stream)
1369: { /* if the stream is non-empty */
1370: fprintf (me->output, me->error_stream);/* output the errors */
1.85 cvs 1371: /* Clear the error context, so that we can deal with
1372: this answer as if it were a normal reply */
1373: HTError_deleteAll( HTRequest_error (request));
1374: HTRequest_setError (request, NULL);
1375: error_flag = 0;
1.74 cvs 1376: }
1377: } /* if error_stack */
1.85 cvs 1378: }
1379:
1380: /* if != HT_ABORT */
1381:
1382: #ifdef DEBUG_LIBWWW
1383: fprintf (stderr, "terminate_handler: URL is %s, closing "
1384: "FILE %p\n", me->urlName, me->output);
1385: #endif
1.74 cvs 1386: fclose (me->output);
1387: me->output = NULL;
1.69 cvs 1388: }
1.80 cvs 1389:
1.214 cvs 1390: /* a very special handling so that we can put a message box
1391: to tell the user WHAT he has just done... */
1392: if (UserAborted_flag && me->method == METHOD_PUT)
1393: {
1394: HTRequest_addError (request, ERR_FATAL, NO, HTERR_INTERRUPTED,
1395: "Operation aborted by user", 0, NULL);
1396: }
1397:
1.80 cvs 1398: if (error_flag)
1399: me->reqStatus = HT_ERR;
1.214 cvs 1400: else
1401: if (me->reqStatus != HT_ABORT)
1402: me->reqStatus = HT_END;
1.154 cvs 1403:
1.238 cvs 1404: /* copy the headers in which the application is interested */
1405: HTTP_headers_set (request, response, context, status);
1.114 cvs 1406:
1.115 cvs 1407: /* to avoid a hangup while downloading css files */
1.140 cvs 1408: if (AmayaAlive_flag && (me->mode & AMAYA_LOAD_CSS))
1.265 cvs 1409: TtaSetStatus (me->docid, 1,
1410: TtaGetMessage (AMAYA, AM_ELEMENT_LOADED),
1411: me->status_urlName);
1.116 cvs 1412:
1413: /* don't remove or Xt will hang up during the PUT */
1414: if (AmayaIsAlive () && ((me->method == METHOD_POST) ||
1415: (me->method == METHOD_PUT)))
1.7 cvs 1416: {
1.80 cvs 1417: PrintTerminateStatus (me, status);
1418: }
1.114 cvs 1419:
1.111 cvs 1420: ProcessTerminateRequest (request, response, context, status);
1.116 cvs 1421:
1.151 cvs 1422: /* stop here */
1.150 cvs 1423: return HT_ERROR;
1.4 cvs 1424: }
1425:
1.5 cvs 1426: /*----------------------------------------------------------------------
1.17 cvs 1427: AHTLoadTerminate_handler
1.74 cvs 1428: this is an application "AFTER" Callback. It's called by the library
1429: when a request has ended, so that we can setup the correct status.
1.5 cvs 1430: ----------------------------------------------------------------------*/
1.265 cvs 1431: int AHTLoadTerminate_handler (HTRequest *request, HTResponse *response,
1432: void *param, int status)
1.4 cvs 1433: {
1.116 cvs 1434: /** @@@@ use this with printstatus ?? */
1.4 cvs 1435: AHTReqContext *me = HTRequest_context (request);
1436: HTAlertCallback *cbf;
1437: AHTDocId_Status *docid_status;
1438:
1.7 cvs 1439: switch (status)
1.116 cvs 1440: {
1441: case HT_LOADED:
1442: if (PROT_TRACE)
1443: HTTrace ("Load End.... OK: `%s\' has been accessed\n",
1444: me->status_urlName);
1.4 cvs 1445:
1.116 cvs 1446: docid_status = GetDocIdStatus (me->docid,
1447: Amaya->docid_status);
1.7 cvs 1448:
1.116 cvs 1449: if (docid_status != NULL && docid_status->counter > 1)
1450: TtaSetStatus (me->docid, 1,
1451: TtaGetMessage (AMAYA, AM_ELEMENT_LOADED),
1.233 cvs 1452: me->status_urlName);
1.7 cvs 1453: break;
1.116 cvs 1454:
1455: case HT_NO_DATA:
1456: if (PROT_TRACE)
1457: HTTrace ("Load End.... OK BUT NO DATA: `%s\'\n",
1458: me->status_urlName);
1.297 kirschpi 1459: #ifdef DAV
1460: if (me->method==METHOD_UNLOCK) {
1461: /* MKP: NEED set a good status message */
1462: TtaSetStatus (me->docid, 1,
1463: TtaGetMessage (AMAYA, AM_UNLOCK_SUCCEED),
1464: NULL);
1465: }
1466: else
1467: #endif
1468: TtaSetStatus (me->docid, 1,
1.116 cvs 1469: TtaGetMessage (AMAYA, AM_LOADED_NO_DATA),
1.233 cvs 1470: me->status_urlName);
1.116 cvs 1471: break;
1472:
1473: case HT_INTERRUPTED:
1474: if (PROT_TRACE)
1475: HTTrace ("Load End.... INTERRUPTED: `%s\'\n",
1476: me->status_urlName);
1477: TtaSetStatus (me->docid, 1,
1478: TtaGetMessage (AMAYA, AM_LOAD_ABORT),
1479: NULL);
1480: break;
1.7 cvs 1481:
1.116 cvs 1482: case HT_RETRY:
1483: if (PROT_TRACE)
1484: HTTrace ("Load End.... NOT AVAILABLE, RETRY AT %ld\n",
1485: HTResponse_retryTime (response));
1486: TtaSetStatus (me->docid, 1,
1487: TtaGetMessage (AMAYA, AM_NOT_AVAILABLE_RETRY),
1.233 cvs 1488: me->status_urlName);
1.116 cvs 1489: break;
1.7 cvs 1490:
1.247 kahan 1491: case HT_NOT_MODIFIED:
1492: if (PROT_TRACE)
1.265 cvs 1493: HTTrace ("Load End.... NOT MODIFIED (%s)",
1494: me->status_urlName ? me->status_urlName :" <UNKNOWN>");
1.247 kahan 1495: break;
1496:
1.116 cvs 1497: case HT_ERROR:
1498: cbf = HTAlert_find (HT_A_MESSAGE);
1499: if (cbf)
1500: (*cbf) (request, HT_A_MESSAGE, HT_MSG_NULL, NULL,
1501: HTRequest_error (request), NULL);
1.247 kahan 1502: if (PROT_TRACE)
1.265 cvs 1503: HTTrace ("Load End.... ERROR: Can't access `%s\'\n",
1504: me->status_urlName ? me->status_urlName :"<UNKNOWN>");
1505: TtaSetStatus (me->docid, 1,
1506: TtaGetMessage (AMAYA, AM_CANNOT_LOAD),
1507: me->status_urlName ? me->status_urlName : "<UNKNOWN>");
1.116 cvs 1508: break;
1.247 kahan 1509:
1510: case HTERR_TIMEOUT:
1511: cbf = HTAlert_find (HT_A_MESSAGE);
1512: if (cbf)
1513: (*cbf) (request, HT_A_MESSAGE, HT_MSG_NULL, NULL,
1514: HTRequest_error (request), NULL);
1.116 cvs 1515: if (PROT_TRACE)
1.265 cvs 1516: HTTrace ("Load End.... REQUEST TIMEOUT: Can't access `%s\'\n",
1517: me->status_urlName ? me->status_urlName :"<UNKNOWN>");
1518: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_CANNOT_LOAD),
1519: me->status_urlName ? me->status_urlName : "<UNKNOWN>");
1.116 cvs 1520: break;
1.247 kahan 1521:
1.116 cvs 1522: default:
1523: if (PROT_TRACE)
1524: HTTrace ("Load End.... UNKNOWN RETURN CODE %d\n", status);
1525: break;
1526: }
1527:
1528: return HT_OK;
1529: }
1.7 cvs 1530:
1.248 kahan 1531: /*----------------------------------------------------------------------
1532: LineTrace
1533: Makes a file copy of libwww's traces
1534: ----------------------------------------------------------------------*/
1.116 cvs 1535: static int LineTrace (const char * fmt, va_list pArgs)
1536: {
1.248 kahan 1537: vfprintf (trace_fp, fmt, pArgs);
1538: return (fflush (trace_fp));
1.4 cvs 1539: }
1540:
1.27 cvs 1541: /*----------------------------------------------------------------------
1542: AHTAcceptTypesInit
1.74 cvs 1543: This function prepares the Accept header used by Amaya during
1544: the HTTP content negotiation phase
1.27 cvs 1545: ----------------------------------------------------------------------*/
1546: static void AHTAcceptTypesInit (HTList *c)
1547: {
1.223 cvs 1548: if (c == (HTList *) NULL)
1.27 cvs 1549: return;
1550:
1.223 cvs 1551: /* define here all the mime types that Amaya can accept */
1.27 cvs 1552:
1.223 cvs 1553: HTConversion_add (c, "image/png", "www/present", HTThroughLine, 1.0, 0.0, 0.0);
1554: HTConversion_add (c, "image/jpeg", "www/present", HTThroughLine, 1.0, 0.0, 0.0);
1555: HTConversion_add (c, "image/gif", "www/present", HTThroughLine, 1.0, 0.0, 0.0);
1556: HTConversion_add (c, "image/xbm", "www/present", HTThroughLine, 1.0, 0.0, 0.0);
1557: HTConversion_add (c, "image/xpm", "www/present", HTThroughLine, 1.0, 0.0, 0.0);
1.183 cvs 1558:
1.27 cvs 1559: /* Define here the equivalences between MIME types and file extensions for
1.223 cvs 1560: the types that Amaya can display */
1.27 cvs 1561:
1.176 cvs 1562: /* Initialize suffix bindings for local files */
1563: HTBind_init();
1564:
1.27 cvs 1565: /* Register the default set of file suffix bindings */
1566: HTFileInit ();
1567:
1.257 kahan 1568: /* Register additional bindings */
1.276 kahan 1569: HTBind_add("htm", "text/html", NULL, "8bit", NULL, 1.0);
1.257 kahan 1570: HTBind_add("tgz", "application/gnutar", NULL, "binary", NULL, 1.0);
1.293 kahan 1571: HTBind_add("mml", AM_MATHML_MIME_TYPE, NULL, "8bit", NULL, 1.0);
1572: HTBind_add("svg", AM_SVG_MIME_TYPE, NULL, "8bit", NULL, 1.0);
1.260 kahan 1573: HTBind_add("xsl", "text/xml", NULL, "8bit", NULL, 1.0);
1.27 cvs 1574: /* Don't do any case distinction */
1575: HTBind_caseSensitive (FALSE);
1576: }
1.4 cvs 1577:
1.5 cvs 1578: /*----------------------------------------------------------------------
1.193 cvs 1579: AHTAcceptLanguagesInit
1580: This function prepares the Accept header used by Amaya during
1581: the HTTP content negotiation phase
1582: ----------------------------------------------------------------------*/
1.196 cvs 1583: static void AHTAcceptLanguagesInit (HTList *c)
1.193 cvs 1584: {
1.265 cvs 1585: char *ptr;
1586: char *lang_list;
1.223 cvs 1587: char s[3];
1.196 cvs 1588: int count, lg;
1589: double quality;
1590: ThotBool still;
1.193 cvs 1591:
1592: if (c == (HTList *) NULL)
1.265 cvs 1593: return;
1.193 cvs 1594:
1.203 cvs 1595: lang_list = TtaGetEnvString ("ACCEPT_LANGUAGES");
1.197 cvs 1596: s[2] = EOS;
1.272 cvs 1597: if (lang_list && *lang_list != EOS)
1.193 cvs 1598: {
1599: /* add the default language first */
1600: HTLanguage_add (c, "*", -1.0);
1601: /* how many languages do we have? */
1.196 cvs 1602: ptr = lang_list;
1603: count = 0;
1.272 cvs 1604: while (*ptr != EOS)
1.265 cvs 1605: {
1.272 cvs 1606: while (*ptr != EOS &&
1.265 cvs 1607: (*ptr < 'A' || (*ptr > 'Z' && *ptr < 'a') || *ptr > 'z'))
1608: /* skip the whole separator */
1609: ptr++;
1610: lg = 0;
1611: while ((*ptr >= 'A' &&
1612: *ptr <= 'Z') || (*ptr >= 'a' && *ptr <= 'z') || *ptr == '-')
1613: {
1614: /* it's a new language */
1615: ptr++;
1616: lg++;
1617: }
1618: if (lg >= 2)
1619: count++;
1.272 cvs 1620: if (*ptr != EOS)
1.265 cvs 1621: ptr++;
1622: }
1.193 cvs 1623:
1.196 cvs 1624: if (count > 0)
1.265 cvs 1625: quality = 1.1 - (double) count/10.0;
1.193 cvs 1626: else
1.265 cvs 1627: quality = 1.0;
1.193 cvs 1628:
1.265 cvs 1629: /* Read the languages from the registry, then inject them one, by one.
1630: The first one is the one with the highest priority.
1631: The libwww ask for the lowest priority first.
1.196 cvs 1632: */
1633: ptr--;
1634: still = TRUE;
1.265 cvs 1635: while (count)
1636: {
1637: while (still && (*ptr < 'A' || (*ptr > 'Z' && *ptr < 'a') || *ptr > 'z'))
1638: /* skip the whole separator */
1639: if (ptr > lang_list)
1640: ptr--;
1641: else
1642: still = FALSE;
1643: lg = 0;
1644: while (still &&
1645: ((*ptr >= 'A' &&
1646: *ptr <= 'Z') || (*ptr >= 'a' && *ptr <= 'z') || *ptr == '-'))
1647: {
1648: /* it's a new language */
1649: if (ptr > lang_list)
1650: ptr--;
1651: else
1652: still = FALSE;
1653: lg++;
1654: }
1655: if (lg >= 2)
1656: {
1657: if (still)
1658: strncpy (s, &ptr[1], 2);
1659: else
1660: strncpy (s, lang_list, 2);
1661: count--;
1662: HTLanguage_add (c, s, quality);
1663: quality += 0.1;
1664: }
1665: ptr--;
1666: }
1667: }
1.193 cvs 1668: }
1669:
1670: /*----------------------------------------------------------------------
1.17 cvs 1671: AHTConverterInit
1672: Bindings between a source media type and a destination media type
1673: (conversion).
1.5 cvs 1674: ----------------------------------------------------------------------*/
1.15 cvs 1675: static void AHTConverterInit (HTList *c)
1.4 cvs 1676: {
1677: /* Handler for custom http error messages */
1.7 cvs 1678: HTConversion_add (c, "*/*", "www/debug", AHTMemConverter, 1.0, 0.0, 0.0);
1.4 cvs 1679:
1680: /*
1681: ** These are converters that converts to something other than www/present,
1682: ** that is not directly outputting someting to the user on the screen
1683: */
1684:
1.223 cvs 1685: HTConversion_add (c, "message/rfc822", "*/*", HTMIMEConvert, 1.0, 0.0, 0.0);
1686: HTConversion_add (c, "message/x-rfc822-foot", "*/*", HTMIMEFooter, 1.0, 0.0, 0.0);
1687: HTConversion_add (c, "message/x-rfc822-head", "*/*", HTMIMEHeader, 1.0, 0.0, 0.0);
1688: HTConversion_add(c,"message/x-rfc822-cont", "*/*", HTMIMEContinue, 1.0, 0.0, 0.0);
1689: HTConversion_add(c,"message/x-rfc822-partial","*/*", HTMIMEPartial, 1.0, 0.0, 0.0);
1690: HTConversion_add (c, "multipart/*", "*/*", HTBoundary, 1.0, 0.0, 0.0);
1691: HTConversion_add (c, "text/plain", "text/html", HTPlainToHTML, 1.0, 0.0, 0.0);
1.4 cvs 1692:
1693: /*
1.116 cvs 1694: ** The following conversions are converting ASCII output from various
1695: ** protocols to HTML objects.
1696: */
1.223 cvs 1697: HTConversion_add (c, "text/x-http", "*/*", HTTPStatus_new, 1.0, 0.0, 0.0);
1.4 cvs 1698:
1699: /*
1.116 cvs 1700: ** We also register a special content type guess stream that can figure out
1701: ** the content type by reading the first bytes of the stream
1702: */
1.223 cvs 1703: HTConversion_add (c, "www/unknown", "*/*", HTGuess_new, 1.0, 0.0, 0.0);
1.4 cvs 1704:
1.116 cvs 1705: #ifdef AMAYA_WWW_CACHE
1.4 cvs 1706: /*
1.116 cvs 1707: ** Register a persistent cache stream which can save an object to local
1708: ** file
1709: */
1.223 cvs 1710: HTConversion_add (c, "www/cache", "*/*", HTCacheWriter, 1.0, 0.0, 0.0);
1711: HTConversion_add(c,"www/cache-append", "*/*", HTCacheAppend, 1.0, 0.0, 0.0);
1.116 cvs 1712: #endif AMAYA_WWW_CACHE
1.4 cvs 1713:
1714: /*
1.116 cvs 1715: ** This dumps all other formats to local disk without any further
1716: ** action taken
1717: */
1.223 cvs 1718: HTConversion_add (c, "*/*", "www/present", HTSaveLocally, 0.3, 0.0, 0.0);
1.4 cvs 1719: }
1720:
1.27 cvs 1721:
1.15 cvs 1722: /*----------------------------------------------------------------------
1.17 cvs 1723: AHTProtocolInit
1724: Registers all amaya supported protocols.
1.15 cvs 1725: ----------------------------------------------------------------------*/
1.4 cvs 1726: static void AHTProtocolInit (void)
1727: {
1.265 cvs 1728: char *strptr;
1.4 cvs 1729:
1.116 cvs 1730: /*
1731: NB. Preemptive == YES means Blocking requests
1732: Non-preemptive == NO means Non-blocking requests
1733: */
1734: HTTransport_add("tcp", HT_TP_SINGLE, HTReader_new, HTWriter_new);
1735: HTTransport_add("buffered_tcp", HT_TP_SINGLE, HTReader_new,
1736: HTBufferWriter_new);
1737: HTProtocol_add ("http", "buffered_tcp", HTTP_PORT, NO, HTLoadHTTP, NULL);
1.136 cvs 1738: #ifdef _WINDOWS
1739: HTProtocol_add ("file", "local", 0, YES, HTLoadFile, NULL);
1740: #else
1.116 cvs 1741: HTProtocol_add ("file", "local", 0, NO, HTLoadFile, NULL);
1.198 cvs 1742: #endif /* _WINDOWS */
1.116 cvs 1743: #ifdef AMAYA_WWW_CACHE
1744: HTProtocol_add("cache", "local", 0, YES, HTLoadCache, NULL);
1745: #endif /* AMAYA_WWW_CACHE */
1.103 cvs 1746: #if 0 /* experimental code */
1.245 kahan 1747: #endif
1.116 cvs 1748: HTProtocol_add ("ftp", "tcp", FTP_PORT, NO, HTLoadFTP, NULL);
1.245 kahan 1749:
1.116 cvs 1750:
1751: /* initialize pipelining */
1.223 cvs 1752: strptr = TtaGetEnvString ("ENABLE_PIPELINING");
1.265 cvs 1753: if (strptr && *strptr && strcasecmp (strptr, "yes"))
1.116 cvs 1754: HTTP_setConnectionMode (HTTP_11_NO_PIPELINING);
1.4 cvs 1755: }
1756:
1.15 cvs 1757: /*----------------------------------------------------------------------
1.17 cvs 1758: AHTNetInit
1759: Reegisters "before" and "after" request filters.
1.15 cvs 1760: ----------------------------------------------------------------------*/
1.4 cvs 1761: static void AHTNetInit (void)
1762: {
1763:
1764: /* Register BEFORE filters
1.74 cvs 1765: ** The BEFORE filters handle proxies, caches, rule files etc.
1766: ** The filters are called in the order by which the are registered
1767: ** Not done automaticly - may be done by application!
1768: */
1.4 cvs 1769:
1.116 cvs 1770: HTNet_addBefore (HTCredentialsFilter, "http://*", NULL, HT_FILTER_LATE);
1771: HTNet_addBefore (HTProxyFilter, NULL, NULL, HT_FILTER_LATE);
1.85 cvs 1772: HTHost_setActivateRequestCallback (AHTOpen_file);
1.4 cvs 1773:
1774: /* register AFTER filters
1.74 cvs 1775: ** The AFTER filters handle error messages, logging, redirection,
1776: ** authentication etc.
1777: ** The filters are called in the order by which the are registered
1778: ** Not done automaticly - may be done by application!
1779: */
1.4 cvs 1780:
1.223 cvs 1781: HTNet_addAfter (HTAuthFilter, "http://*", NULL, HT_NO_ACCESS, HT_FILTER_MIDDLE);
1782: HTNet_addAfter (HTAuthFilter, "http://*", NULL, HT_REAUTH, HT_FILTER_MIDDLE);
1783: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_PERM_REDIRECT, HT_FILTER_MIDDLE);
1784: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_FOUND, HT_FILTER_MIDDLE);
1785: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_SEE_OTHER, HT_FILTER_MIDDLE);
1786: HTNet_addAfter (redirection_handler, "http://*", NULL, HT_TEMP_REDIRECT, HT_FILTER_MIDDLE);
1787: HTNet_addAfter (HTAuthInfoFilter, "http://*", NULL, HT_ALL, HT_FILTER_MIDDLE);
1788: HTNet_addAfter (HTUseProxyFilter, "http://*", NULL, HT_USE_PROXY, HT_FILTER_MIDDLE);
1.151 cvs 1789: #ifdef AMAYA_LOST_UPDATE
1.223 cvs 1790: HTNet_addAfter (precondition_handler, NULL, NULL, HT_PRECONDITION_FAILED, HT_FILTER_MIDDLE);
1.151 cvs 1791: #endif /* AMAYA_LOST_UPDATE */
1.111 cvs 1792: #ifndef _WINDOWS
1.223 cvs 1793: HTNet_addAfter (AHTLoadTerminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
1.111 cvs 1794: #endif /* !_WINDOWS */
1.116 cvs 1795: /**** for later ?? ****/
1796: /* HTNet_addAfter(HTInfoFilter, NULL, NULL, HT_ALL, HT_FILTER_LATE); */
1.245 kahan 1797: /* @@ JK: Filters for doing ftp authentication */
1798: HTNet_addAfter (HTAuthFilter, "ftp://*", NULL, HT_NO_ACCESS, HT_FILTER_MIDDLE);
1799: HTNet_addAfter (HTAuthFilter, "ftp://*", NULL, HT_REAUTH, HT_FILTER_MIDDLE);
1.51 cvs 1800: /* handles all errors */
1.116 cvs 1801: HTNet_addAfter (terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
1.4 cvs 1802: }
1803:
1.15 cvs 1804: /*----------------------------------------------------------------------
1.17 cvs 1805: AHTAlertInit
1806: Register alert messages and their callbacks.
1.15 cvs 1807: ----------------------------------------------------------------------*/
1808: static void AHTAlertInit (void)
1809: {
1810: HTAlert_add (AHTProgress, HT_A_PROGRESS);
1.120 cvs 1811: #ifdef __WINDOWS
1.70 cvs 1812: HTAlert_add ((HTAlertCallback *) WIN_Activate_Request, HT_PROG_CONNECT);
1.116 cvs 1813: #endif /* _WINDOWS */
1.15 cvs 1814: HTAlert_add (AHTError_print, HT_A_MESSAGE);
1.48 cvs 1815: HTError_setShow (~((unsigned int) 0 ) & ~((unsigned int) HT_ERR_SHOW_DEBUG)); /* process all messages except debug ones*/
1.15 cvs 1816: HTAlert_add (AHTConfirm, HT_A_CONFIRM);
1817: HTAlert_add (AHTPrompt, HT_A_PROMPT);
1818: HTAlert_add (AHTPromptUsernameAndPassword, HT_A_USER_PW);
1.116 cvs 1819: }
1820:
1.118 cvs 1821: #ifdef AMAYA_WWW_CACHE
1822: /*----------------------------------------------------------------------
1.128 cvs 1823: RecCleanCache
1.118 cvs 1824: Clears an existing cache directory
1825: ----------------------------------------------------------------------*/
1.265 cvs 1826: static void RecCleanCache (char *dirname)
1827: {
1.128 cvs 1828: #ifdef _WINDOWS
1.223 cvs 1829: HANDLE hFindFile;
1830: ThotBool status;
1.128 cvs 1831: WIN32_FIND_DATA ffd;
1.290 vatton 1832: char t_dir [MAX_LENGTH];
1833: char *ptr;
1.128 cvs 1834:
1.130 cvs 1835: /* create a t_dir name to start searching for files */
1.265 cvs 1836: if ((strlen (dirname) + 10) > MAX_LENGTH)
1.128 cvs 1837: /* ERROR: directory name is too big */
1838: return;
1839:
1.265 cvs 1840: strcpy (t_dir, dirname);
1.130 cvs 1841: /* save the end of the dirname. We'll use it to make
1842: a complete pathname when erasing files */
1.265 cvs 1843: ptr = &t_dir[strlen (t_dir)];
1844: strcat (t_dir, "*");
1.128 cvs 1845:
1.130 cvs 1846: hFindFile = FindFirstFile (t_dir, &ffd);
1.128 cvs 1847:
1848: if (hFindFile == INVALID_HANDLE_VALUE)
1849: /* nothing to erase? */
1850: return;
1851:
1852: status = TRUE;
1.130 cvs 1853: while (status)
1854: {
1855: if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1.133 cvs 1856: {
1857: /* it's a directory, erase it recursively */
1.265 cvs 1858: if (strcmp (ffd.cFileName, "..") && strcmp (ffd.cFileName, "."))
1.133 cvs 1859: {
1.265 cvs 1860: strcpy (ptr, ffd.cFileName);
1.272 cvs 1861: strcat (ptr, DIR_STR);
1.133 cvs 1862: RecCleanCache (t_dir);
1.274 cvs 1863: rmdir (t_dir);
1.133 cvs 1864: }
1865: }
1866: else
1.130 cvs 1867: {
1.133 cvs 1868: /* it's a file, erase it */
1.265 cvs 1869: strcpy (ptr, ffd.cFileName);
1.133 cvs 1870: TtaFileUnlink (t_dir);
1.130 cvs 1871: }
1872: status = FindNextFile (hFindFile, &ffd);
1873: }
1.128 cvs 1874: FindClose (hFindFile);
1875:
1876: #else /* _WINDOWS */
1.118 cvs 1877: DIR *dp;
1878: struct stat st;
1879: #ifdef HAVE_DIRENT_H
1880: struct dirent *d;
1881: #else
1882: struct direct *d;
1883: #endif /* HAVE_DIRENT_H */
1.128 cvs 1884: char filename[BUFSIZ+1];
1.118 cvs 1885:
1886: if ((dp = opendir (dirname)) == NULL)
1887: {
1888: /* @@@ we couldn't open the directory ... we need some msg */
1889: perror (dirname);
1.176 cvs 1890: return;
1.118 cvs 1891: }
1892:
1893: while ((d = readdir (dp)) != NULL)
1894: {
1895: /* skip the UNIX . and .. links */
1896: if (!strcmp (d->d_name, "..")
1897: || !strcmp (d->d_name, "."))
1898: continue;
1899:
1.188 cvs 1900: sprintf (filename, "%s%c%s", dirname, DIR_SEP, d->d_name);
1.118 cvs 1901: if (lstat (filename, &st) < 0 )
1902: {
1903: /* @@2 need some error message */
1904: perror (filename);
1905: continue;
1906: }
1907:
1908: switch (st.st_mode & S_IFMT)
1909: {
1910: case S_IFDIR:
1911: /* if we find a directory, we erase it, recursively */
1.128 cvs 1912: strcat (filename, DIR_STR);
1913: RecCleanCache (filename);
1914: rmdir (filename);
1.118 cvs 1915: break;
1916: case S_IFLNK:
1917: /* skip any links we find */
1918: continue;
1919: break;
1920: default:
1921: /* erase the filename */
1922: TtaFileUnlink (filename);
1923: break;
1924: }
1925: }
1926: closedir (dp);
1.265 cvs 1927: #endif /* _WINDOWS */
1.118 cvs 1928: }
1929: #endif /* AMAYA_WWW_CACHE */
1930:
1.116 cvs 1931: /*----------------------------------------------------------------------
1.265 cvs 1932: libwww_CleanCache
1933: frontend to the recursive cache cleaning function
1934: ----------------------------------------------------------------------*/
1935: void libwww_CleanCache (void)
1936: {
1937: #ifdef AMAYA_WWW_CACHE
1938: char * real_dir;
1939: char* cache_dir;
1940: char* tmp;
1941: int cache_size;
1942: int cache_expire;
1943: int cache_disconnect;
1944: ThotBool error;
1945: char * ptr;
1946:
1947: if (!HTCacheMode_enabled ())
1948: /* don't do anything if we're not using a cache */
1949: return;
1950: /* temporarily close down the cache, purge it, then restart */
1951: tmp = HTCacheMode_getRoot ();
1952: /* don't do anything if we don't have a valid cache dir */
1953: if (!tmp || *tmp == EOS)
1954: return;
1955: cache_dir = TtaStrdup (tmp);
1956: HT_FREE (tmp);
1957: cache_size = HTCacheMode_maxSize ();
1958: cache_expire = HTCacheMode_expires ();
1959: cache_disconnect = HTCacheMode_disconnected ();
1960:
1961: /* get something we can work on :) */
1962: tmp = HTWWWToLocal (cache_dir, "file:", NULL);
1963: real_dir = TtaGetMemory (strlen (tmp) + 20);
1.273 cvs 1964: strcpy (real_dir, tmp);
1.265 cvs 1965: HT_FREE (tmp);
1966:
1967: /* safeguard... abort the operation if cache_dir doesn't end with
1968: CACHE_DIR_NAME */
1969: error = TRUE;
1970: ptr = strstr (real_dir, CACHE_DIR_NAME);
1971: if (ptr && *ptr && !strcasecmp (ptr, CACHE_DIR_NAME))
1972: error = FALSE;
1973: if (error)
1974: return;
1975:
1976: /* remove the concurrent cache lock */
1977: #ifdef DEBUG_LIBWWW
1978: fprintf (stderr, "Clearing the cache lock\n");
1979: #endif /* DEBUG_LIBWWW */
1980: clear_cachelock ();
1981: HTCacheTerminate ();
1982: HTCacheMode_setEnabled (FALSE);
1983:
1984: RecCleanCache (real_dir);
1985:
1986: HTCacheMode_setExpires (cache_expire);
1987: HTCacheMode_setDisconnected (cache_disconnect);
1988: HTCacheInit (cache_dir, cache_size);
1989: /* set a new concurrent cache lock */
1990: strcat (real_dir, ".lock");
1991: if (set_cachelock (real_dir) == -1)
1992: /* couldn't open the .lock file, so, we close the cache to
1993: be in the safe side */
1994: {
1995: #ifdef DEBUG_LIBWWW
1996: fprintf (stderr, "couldnt set the cache lock\n");
1997: #endif /* DEBUG_LIBWWW */
1998: HTCacheTerminate ();
1999: HTCacheMode_setEnabled (FALSE);
2000: }
2001: #ifdef DEBUG_LIBWWW
2002: fprintf (stderr, "set a cache lock\n");
2003: #endif /* DEBUG_LIBWWW */
2004: TtaFreeMemory (real_dir);
2005: TtaFreeMemory (cache_dir);
2006: #endif /* AMAYA_WWW_CACHE */
2007: }
2008:
2009: /*----------------------------------------------------------------------
1.116 cvs 2010: CacheInit
2011: Reads the cache settings from the thot.ini file.
2012: ----------------------------------------------------------------------*/
2013: static void CacheInit (void)
2014: {
2015: #ifndef AMAYA_WWW_CACHE
2016: HTCacheMode_setEnabled (NO);
2017:
2018: #else /* AMAYA_WWW_CACHE */
1.265 cvs 2019: char *strptr;
2020: char *real_dir = NULL;
2021: char *cache_lockfile;
2022: char *cache_dir = NULL;
1.223 cvs 2023: int cache_size;
2024: int cache_entry_size;
2025: ThotBool cache_enabled;
2026: ThotBool cache_locked;
2027: ThotBool tmp_bool;
1.130 cvs 2028:
1.185 cvs 2029: int i;
2030:
1.116 cvs 2031: /* activate cache? */
1.203 cvs 2032: strptr = TtaGetEnvString ("ENABLE_CACHE");
1.265 cvs 2033: if (strptr && *strptr && strcasecmp (strptr, "yes"))
1.130 cvs 2034: cache_enabled = NO;
1.116 cvs 2035: else
1.130 cvs 2036: cache_enabled = YES;
1.116 cvs 2037:
1.151 cvs 2038: /* cache protected documents? */
1.203 cvs 2039: strptr = TtaGetEnvString ("CACHE_PROTECTED_DOCS");
1.265 cvs 2040: if (strptr && *strptr && !strcasecmp (strptr, "yes"))
1.151 cvs 2041: HTCacheMode_setProtected (YES);
2042: else
2043: HTCacheMode_setProtected (NO);
2044:
1.116 cvs 2045: /* get the cache dir (or use a default one) */
1.203 cvs 2046: strptr = TtaGetEnvString ("CACHE_DIR");
1.116 cvs 2047: if (strptr && *strptr)
2048: {
1.265 cvs 2049: real_dir = TtaGetMemory (strlen (strptr) + strlen (CACHE_DIR_NAME) + 20);
2050: strcpy (real_dir, strptr);
1.272 cvs 2051: if (*(real_dir + strlen (real_dir) - 1) != DIR_SEP)
2052: strcat (real_dir, DIR_STR);
1.116 cvs 2053: }
2054: else
2055: {
1.265 cvs 2056: real_dir = TtaGetMemory (strlen (TempFileDirectory) + strlen (CACHE_DIR_NAME) + 20);
1.272 cvs 2057: sprintf (real_dir, "%s%s", TempFileDirectory, CACHE_DIR_NAME);
1.185 cvs 2058: }
2059:
2060: /* compatiblity with previous versions of Amaya: does real_dir
2061: include CACHE_DIR_NAME? If not, add it */
1.265 cvs 2062: strptr = strstr (real_dir, CACHE_DIR_NAME);
1.185 cvs 2063: if (!strptr)
1.265 cvs 2064: strcat (real_dir, CACHE_DIR_NAME);
1.185 cvs 2065: else
2066: {
1.265 cvs 2067: i = strlen (CACHE_DIR_NAME);
1.272 cvs 2068: if (strptr[i] != EOS)
1.265 cvs 2069: strcat (real_dir, CACHE_DIR_NAME);
1.116 cvs 2070: }
1.185 cvs 2071:
1.211 cvs 2072: /* convert the local cache dir into a file URL, as expected by
2073: libwww */
1.265 cvs 2074: cache_dir = HTLocalToWWW (real_dir, "file:");
1.116 cvs 2075: /* get the cache size (or use a default one) */
1.203 cvs 2076: strptr = TtaGetEnvString ("CACHE_SIZE");
1.116 cvs 2077: if (strptr && *strptr)
1.288 vatton 2078: cache_size = atoi (strptr);
1.116 cvs 2079: else
2080: cache_size = DEFAULT_CACHE_SIZE;
1.176 cvs 2081: /* get the max cached file size (or use a default one) */
1.223 cvs 2082: if (!TtaGetEnvInt ("MAX_CACHE_ENTRY_SIZE", &cache_entry_size))
1.176 cvs 2083: cache_entry_size = DEFAULT_MAX_CACHE_ENTRY_SIZE;
1.130 cvs 2084: if (cache_enabled)
1.116 cvs 2085: {
2086: /* how to remove the lock? force remove it? */
1.265 cvs 2087: cache_lockfile = TtaGetMemory (strlen (real_dir) + 20);
2088: strcpy (cache_lockfile, real_dir);
2089: strcat (cache_lockfile, ".lock");
1.130 cvs 2090: cache_locked = FALSE;
1.223 cvs 2091: if (TtaFileExist (cache_lockfile) && !(cache_locked = test_cachelock (cache_lockfile)))
1.116 cvs 2092: {
1.130 cvs 2093: #ifdef DEBUG_LIBWWW
2094: fprintf (stderr, "found a stale cache, removing it\n");
2095: #endif /* DEBUG_LIBWWW */
2096: /* remove the lock and clean the cache (the clean cache
2097: will remove all, making the following call unnecessary */
2098: /* little trick to win some memory */
1.265 cvs 2099: strptr = strrchr (cache_lockfile, '.');
1.272 cvs 2100: *strptr = EOS;
1.130 cvs 2101: RecCleanCache (cache_lockfile);
1.265 cvs 2102: *strptr = '.';
1.116 cvs 2103: }
2104:
1.130 cvs 2105: if (!cache_locked)
2106: {
2107: /* initialize the cache if there's no other amaya
2108: instance running */
1.177 cvs 2109: HTCacheMode_setMaxCacheEntrySize (cache_entry_size);
1.223 cvs 2110: if (TtaGetEnvBoolean ("CACHE_EXPIRE_IGNORE", &tmp_bool) && tmp_bool)
1.177 cvs 2111: HTCacheMode_setExpires (HT_EXPIRES_IGNORE);
2112: else
2113: HTCacheMode_setExpires (HT_EXPIRES_AUTO);
1.223 cvs 2114: TtaGetEnvBoolean ("CACHE_DISCONNECTED_MODE", &tmp_bool);
1.177 cvs 2115: if (tmp_bool)
2116: HTCacheMode_setDisconnected (HT_DISCONNECT_NORMAL);
2117: else
2118: HTCacheMode_setDisconnected (HT_DISCONNECT_NONE);
1.211 cvs 2119: if (HTCacheInit (cache_dir, cache_size))
1.130 cvs 2120: {
1.188 cvs 2121: if (set_cachelock (cache_lockfile) == -1)
2122: /* couldn't open the .lock file, so, we close the cache to
2123: be in the safe side */
2124: {
2125: HTCacheTerminate ();
2126: HTCacheMode_setEnabled (FALSE);
2127: #ifdef DEBUG_LIBWWW
2128: fprintf (stderr, "couldnt set the cache lock\n");
2129: #endif /* DEBUG_LIBWWW */
2130: }
1.130 cvs 2131: #ifdef DEBUG_LIBWWW
1.188 cvs 2132: else
2133: fprintf (stderr, "created the cache lock\n");
1.130 cvs 2134: #endif /* DEBUG_LIBWWW */
2135: }
1.188 cvs 2136: else
2137: {
1.130 cvs 2138: #ifdef DEBUG_LIBWWW
1.188 cvs 2139: fprintf (stderr, "couldn't create the cache\n");
2140: #endif /* DEBUG_LIBWWW */
2141: HTCacheTerminate ();
2142: }
1.130 cvs 2143: }
2144: else
2145: {
1.185 cvs 2146: HTCacheMode_setEnabled (FALSE);
1.130 cvs 2147: #ifdef DEBUG_LIBWWW
2148: fprintf (stderr, "lock detected, starting libwww without a cache/n");
2149: #endif /* DEBUG_LIBWWW */
2150: }
2151: TtaFreeMemory (cache_lockfile);
1.116 cvs 2152: }
2153: else
1.185 cvs 2154: {
2155: HTCacheMode_setEnabled (FALSE);
2156: }
1.116 cvs 2157: if (cache_dir)
1.211 cvs 2158: HT_FREE (cache_dir);
1.189 cvs 2159: if (real_dir)
2160: TtaFreeMemory (real_dir);
1.185 cvs 2161: /* warn the user if the cache isn't active */
2162: if (cache_enabled && !HTCacheMode_enabled ())
1.291 kahan 2163: {
2164: ThotBool warn_user;
2165:
2166: TtaGetEnvBoolean ("WARN_NO_CACHE", &warn_user);
2167: if (warn_user)
2168: InitInfo ("Cache", TtaGetMessage (AMAYA, AM_CANT_CREATE_CACHE));
2169: }
1.116 cvs 2170: #endif /* AMAYA_WWW_CACHE */
1.15 cvs 2171: }
2172:
2173: /*----------------------------------------------------------------------
1.97 cvs 2174: ProxyInit
2175: Reads any proxies settings which may be declared as environmental
2176: variables or in the thot.ini file. The former overrides the latter.
2177: ----------------------------------------------------------------------*/
2178: static void ProxyInit (void)
2179: {
1.265 cvs 2180: char *strptr;
2181: char *name;
2182: char *tmp = NULL;
2183: char *strptrA;
1.223 cvs 2184: ThotBool proxy_is_onlyproxy;
1.97 cvs 2185:
2186: /* get the proxy settings from the thot.ini file */
1.203 cvs 2187: strptr = TtaGetEnvString ("HTTP_PROXY");
1.228 cvs 2188: if (strptr && *strptr)
2189: {
1.265 cvs 2190: tmp = (char *) TtaGetMemory (strlen (strptr) + 1);
2191: strcpy (tmp, strptr);
1.223 cvs 2192:
1.228 cvs 2193: /* does the proxy env string has an "http://" prefix? */
1.265 cvs 2194: if (!strncasecmp (strptr, "http://", 7))
1.223 cvs 2195: HTProxy_add ("http", tmp);
1.228 cvs 2196: else
2197: {
1.265 cvs 2198: strptrA = (char *) TtaGetMemory (strlen (strptr) + 9);
1.228 cvs 2199: strcpy (strptrA, "http://");
2200: strcat (strptrA, tmp);
2201: HTProxy_add ("http", strptrA);
2202: TtaFreeMemory (strptrA);
2203: }
2204: TtaFreeMemory (tmp);
2205: }
1.216 cvs 2206:
1.97 cvs 2207: /* get the no_proxy settings from the thot.ini file */
1.212 cvs 2208: strptr = TtaGetEnvString ("PROXYDOMAIN");
1.228 cvs 2209: if (strptr && *strptr)
2210: {
1.265 cvs 2211: strptrA = (char *) TtaGetMemory (strlen (strptr) + 1);
2212: tmp = strptrA;
2213: strcpy (tmp, strptr);
1.228 cvs 2214: /* as HTNextField changes the ptr we pass as an argument, we'll
1.265 cvs 2215: work with another variable, so that we can free the tmp
1.228 cvs 2216: block later on */
2217: while ((name = HTNextField (&tmp)) != NULL)
2218: {
2219: char* portstr = strchr (name, ':');
2220: unsigned port=0;
1.265 cvs 2221: if (portstr)
2222: {
2223: *portstr++ = EOS;
2224: if (*portstr)
2225: port = (unsigned) atoi (portstr);
2226: }
1.228 cvs 2227: /* Register it for all access methods */
2228: HTNoProxy_add (name, NULL, port);
2229: }
2230: TtaFreeMemory (strptrA);
2231: }
2232:
1.212 cvs 2233: /* how should we interpret the proxy domain list? */
1.291 kahan 2234:
1.212 cvs 2235: TtaGetEnvBoolean ("PROXYDOMAIN_IS_ONLYPROXY", &proxy_is_onlyproxy);
2236: HTProxy_setNoProxyIsOnlyProxy (proxy_is_onlyproxy);
2237:
2238: /* use libwww's routine to get all proxy settings from the environment */
1.97 cvs 2239: HTProxy_getEnvVar ();
2240: }
2241:
1.207 cvs 2242: /*----------------------------------------------------------------------
1.17 cvs 2243: AHTProfile_newAmaya
2244: creates the Amaya client profile for libwww.
1.15 cvs 2245: ----------------------------------------------------------------------*/
1.265 cvs 2246: static void AHTProfile_newAmaya (char *AppName, char *AppVersion)
1.4 cvs 2247: {
1.265 cvs 2248: char *strptr;
1.158 cvs 2249:
1.4 cvs 2250: /* If the Library is not already initialized then do it */
1.257 kahan 2251: if (!HTLib_isInitialized ())
1.273 cvs 2252: HTLibInit (AppName, AppVersion);
1.4 cvs 2253:
2254: if (!converters)
2255: converters = HTList_new ();
1.27 cvs 2256: if (!acceptTypes)
2257: acceptTypes = HTList_new ();
1.193 cvs 2258: if (!acceptLanguages)
2259: acceptLanguages = HTList_new ();
1.151 cvs 2260: if (!transfer_encodings)
2261: transfer_encodings = HTList_new ();
2262: if (!content_encodings)
2263: content_encodings = HTList_new ();
1.4 cvs 2264:
1.169 cvs 2265: /* inhibits libwww's automatic file_suffix_binding */
2266: HTFile_doFileSuffixBinding (FALSE);
2267:
1.4 cvs 2268: /* Register the default set of transport protocols */
2269: HTTransportInit ();
2270:
2271: /* Register the default set of application protocol modules */
2272: AHTProtocolInit ();
2273:
1.116 cvs 2274: /* Register the default set of messages and dialog functions */
2275: AHTAlertInit ();
2276: HTAlert_setInteractive (YES);
2277:
2278: #ifdef AMAYA_WWW_CACHE
2279: /* Enable the persistent cache */
2280: CacheInit ();
2281: #else
2282: HTCacheMode_setEnabled (NO);
2283: #endif /* AMAYA_WWW_CACHE */
1.4 cvs 2284:
2285: /* Register the default set of BEFORE and AFTER filters */
2286: AHTNetInit ();
2287:
2288: /* Set up the default set of Authentication schemes */
1.223 cvs 2289: HTAA_newModule ("basic", HTBasic_generate, HTBasic_parse, NULL, HTBasic_delete);
1.158 cvs 2290: /* activate MDA by defaul */
1.203 cvs 2291: strptr = TtaGetEnvString ("ENABLE_MDA");
1.265 cvs 2292: if (!strptr || (strptr && *strptr && strcasecmp (strptr, "no")))
1.223 cvs 2293: HTAA_newModule ("digest", HTDigest_generate, HTDigest_parse, HTDigest_updateInfo, HTDigest_delete);
1.257 kahan 2294:
1.97 cvs 2295: /* Get any proxy settings */
2296: ProxyInit ();
1.4 cvs 2297:
1.207 cvs 2298: /* Set up the domains where we accept a redirect on PUT */
2299: SafePut_init ();
2300:
1.4 cvs 2301: /* Register the default set of converters */
2302: AHTConverterInit (converters);
1.151 cvs 2303: HTFormat_setConversion (converters);
1.27 cvs 2304: AHTAcceptTypesInit (acceptTypes);
1.193 cvs 2305: AHTAcceptLanguagesInit (acceptLanguages);
1.4 cvs 2306:
2307: /* Register the default set of transfer encoders and decoders */
1.151 cvs 2308: HTTransferEncoderInit (transfer_encodings);
1.190 cvs 2309: HTFormat_setTransferCoding (transfer_encodings);
2310: /* Register the default set of content encoders and decoders */
1.296 kahan 2311: /* commented because we don't know yet how to handle deflate in the content enconding */
2312: /* HTContentEncoderInit (content_encodings); */
2313: HTCoding_add (content_encodings, "gzip", NULL, HTIdentityCoding, 1.0);
1.190 cvs 2314: /* ignore all other encoding formats (or libwww will send them
1.181 cvs 2315: thru a blackhole otherwise */
2316: HTCoding_add (content_encodings, "*", NULL, HTIdentityCoding, 1.0);
1.151 cvs 2317: if (HTList_count(content_encodings) > 0)
2318: HTFormat_setContentCoding(content_encodings);
2319: else
2320: {
2321: HTList_delete(content_encodings);
2322: content_encodings = NULL;
2323: }
1.4 cvs 2324:
2325: /* Register the default set of MIME header parsers */
1.74 cvs 2326: HTMIMEInit (); /* must be called again for language selector */
1.4 cvs 2327:
2328: /* Register the default set of Icons for directory listings */
1.27 cvs 2329: /*HTIconInit(NULL); *//* experimental */
1.4 cvs 2330: }
2331:
1.5 cvs 2332: /*----------------------------------------------------------------------
1.17 cvs 2333: AHTProfile_delete
2334: deletes the Amaya client profile.
1.5 cvs 2335: ----------------------------------------------------------------------*/
1.4 cvs 2336: static void AHTProfile_delete (void)
2337: {
1.22 cvs 2338: /* free the Amaya global context */
1.151 cvs 2339: /* Clean up all the registred converters */
2340: HTFormat_deleteAll ();
2341: if (acceptTypes)
1.74 cvs 2342: HTConversion_deleteAll (acceptTypes);
1.193 cvs 2343: if (acceptLanguages)
2344: HTLanguage_deleteAll (acceptLanguages);
1.151 cvs 2345:
1.209 cvs 2346: StopAllRequests (1);
1.74 cvs 2347: HTList_delete (Amaya->docid_status);
2348: HTList_delete (Amaya->reqlist);
2349: TtaFreeMemory (Amaya);
1.61 cvs 2350:
1.120 cvs 2351: #ifdef _WINDOWS
1.209 cvs 2352: if (HTLib_isInitialized ())
1.151 cvs 2353: HTEventTerminate ();
1.198 cvs 2354: #endif /* _WINDOWS; */
1.74 cvs 2355:
1.151 cvs 2356: /* Clean up the persistent cache (if any) */
1.116 cvs 2357: #ifdef AMAYA_WWW_CACHE
1.151 cvs 2358: clear_cachelock ();
2359: HTCacheTerminate ();
1.116 cvs 2360: #endif /* AMAYA_WWW_CACHE */
1.217 cvs 2361:
1.218 cvs 2362: /* call remove functions that are not called automatically by libwww */
2363: HTNetCall_deleteBeforeAll (HTNet_before ());
2364: HTNetCall_deleteAfterAll (HTNet_after ());
2365: HTAA_deleteAllModules ();
2366: HTAlertCall_deleteAll (HTAlert_global () );
2367: HTAlert_setGlobal ((HTList *) NULL);
1.259 cvs 2368: HTTimer_deleteAll ();
1.249 kahan 2369: HTEventList_unregisterAll ();
1.218 cvs 2370: /* these two functions are broken, so we can't call them right now
2371: HTHeader_deleteAll ();
2372: HTTimer_deleteAll ();
2373: */
2374: HTTransport_deleteAll ();
1.217 cvs 2375: /* remove bindings between suffixes, media types*/
2376: HTBind_deleteAll ();
1.151 cvs 2377: /* Terminate libwww */
2378: HTLibTerminate ();
1.4 cvs 2379: }
2380:
1.5 cvs 2381: /*----------------------------------------------------------------------
1.116 cvs 2382: AmayacontextInit
2383: initializes an internal Amaya context for our libwww interface
2384: ----------------------------------------------------------------------*/
1.265 cvs 2385: static void AmayaContextInit ()
1.116 cvs 2386: {
1.140 cvs 2387: AmayaAlive_flag = TRUE;
1.116 cvs 2388: /* Initialization of the global context */
2389: Amaya = (AmayaContext *) TtaGetMemory (sizeof (AmayaContext));
2390: Amaya->reqlist = HTList_new ();
2391: Amaya->docid_status = HTList_new ();
2392: Amaya->open_requests = 0;
2393: }
2394:
2395: /*----------------------------------------------------------------------
1.17 cvs 2396: QueryInit
2397: initializes the libwww interface
1.5 cvs 2398: ----------------------------------------------------------------------*/
1.265 cvs 2399: void QueryInit ()
1.4 cvs 2400: {
1.265 cvs 2401: char *strptr;
2402: int tmp_i;
2403: long tmp_l;
1.4 cvs 2404:
1.116 cvs 2405: AmayaContextInit ();
1.4 cvs 2406: AHTProfile_newAmaya (HTAppName, HTAppVersion);
1.140 cvs 2407: CanDoStop_set (TRUE);
1.214 cvs 2408: UserAborted_flag = FALSE;
1.4 cvs 2409:
1.116 cvs 2410: #ifdef _WINDOWS
1.125 cvs 2411: HTEventInit ();
1.116 cvs 2412: #endif /* _WINDOWS */
1.72 cvs 2413:
1.123 cvs 2414: #ifndef _WINDOWS
1.116 cvs 2415: HTEvent_setRegisterCallback ((void *) AHTEvent_register);
2416: HTEvent_setUnregisterCallback ((void *) AHTEvent_unregister);
1.120 cvs 2417: HTTimer_registerSetTimerCallback ((void *) AMAYA_SetTimer);
2418: HTTimer_registerDeleteTimerCallback ((void *) AMAYA_DeleteTimer);
1.116 cvs 2419: #endif /* !_WINDOWS */
1.190 cvs 2420:
1.213 cvs 2421: #ifdef HTDEBUG
1.247 kahan 2422: /* an undocumented option for being able to generate an HTTP protocol
2423: trace. The flag can take values from 1-10, which are interpreted as
2424: different kinds of debug traces. Value 99 means a complete trace.
2425: 0 or other values means No Debug.1 No Debug (default), up to Full debug, respectively. */
1.238 cvs 2426: if (TtaGetEnvInt ("ENABLE_LIBWWW_DEBUG", &tmp_i))
1.247 kahan 2427: {
2428: switch (tmp_i)
2429: {
2430: case 1:
2431: WWW_TraceFlag = SHOW_URI_TRACE;
2432: break;
2433: case 2:
2434: WWW_TraceFlag = SHOW_BIND_TRACE;
2435: break;
2436: case 3:
2437: WWW_TraceFlag = SHOW_THREAD_TRACE;
2438: break;
2439: case 4:
2440: WWW_TraceFlag = SHOW_STREAM_TRACE;
2441: break;
2442: case 5:
2443: WWW_TraceFlag = SHOW_PROTOCOL_TRACE;
2444: break;
2445: case 6:
2446: WWW_TraceFlag = SHOW_MEM_TRACE;
2447: break;
2448: case 7:
2449: WWW_TraceFlag = SHOW_URI_TRACE;
2450: break;
2451: case 8:
2452: WWW_TraceFlag = SHOW_AUTH_TRACE;
2453: break;
2454: case 9:
2455: WWW_TraceFlag = SHOW_ANCHOR_TRACE;
2456: break;
2457: case 10 :
2458: WWW_TraceFlag = SHOW_CORE_TRACE;
2459: break;
1.251 kahan 2460: case 11 :
2461: WWW_TraceFlag = SHOW_CORE_TRACE | SHOW_ANCHOR_TRACE | SHOW_AUTH_TRACE | SHOW_URI_TRACE | SHOW_THREAD_TRACE | SHOW_STREAM_TRACE;
2462: break;
1.247 kahan 2463: case 99 :
2464: WWW_TraceFlag = SHOW_ALL_TRACE;
2465: break;
2466: default:
2467: WWW_TraceFlag = 0;
2468: break;
2469: }
1.248 kahan 2470: if (WWW_TraceFlag)
2471: {
2472: /* Trace activation (for debugging) */
1.265 cvs 2473: char *s, *tmp;
1.248 kahan 2474: s = TtaGetEnvString ("APP_TMPDIR");
1.265 cvs 2475: tmp = TtaGetMemory (strlen (s) + sizeof ("/libwww.log") + 1);
2476: strcpy (tmp, s);
2477: strcat (tmp, "/libwww.log");
2478: trace_fp = fopen (tmp, "ab");
1.248 kahan 2479: TtaFreeMemory (tmp);
2480: if (trace_fp)
2481: HTTrace_setCallback(LineTrace);
2482: }
1.247 kahan 2483: }
1.208 cvs 2484: else
2485: WWW_TraceFlag = 0;
1.213 cvs 2486: #endif /* HTDEBUG */
1.208 cvs 2487:
1.74 cvs 2488: #ifdef DEBUG_LIBWWW
1.116 cvs 2489: /* forwards error messages to our own function */
2490: WWW_TraceFlag = THD_TRACE;
1.138 cvs 2491: HTTrace_setCallback(LineTrace);
1.248 kahan 2492:
1.148 cvs 2493: /***
1.138 cvs 2494: WWW_TraceFlag = SHOW_CORE_TRACE | SHOW_THREAD_TRACE | SHOW_PROTOCOL_TRACE;
2495: ***/
1.152 cvs 2496: #endif
1.247 kahan 2497:
2498: TtaGetEnvBoolean ("ENABLE_FTP", &FTPURL_flag);
1.152 cvs 2499:
1.148 cvs 2500: /* Setting up different network parameters */
1.151 cvs 2501:
1.148 cvs 2502: /* Maximum number of simultaneous open sockets */
1.203 cvs 2503: strptr = TtaGetEnvString ("MAX_SOCKET");
1.151 cvs 2504: if (strptr && *strptr)
1.288 vatton 2505: tmp_i = atoi (strptr);
1.151 cvs 2506: else
2507: tmp_i = DEFAULT_MAX_SOCKET;
2508: HTNet_setMaxSocket (tmp_i);
2509:
1.148 cvs 2510: /* different network services timeouts */
1.151 cvs 2511: /* dns timeout */
1.203 cvs 2512: strptr = TtaGetEnvString ("DNS_TIMEOUT");
1.151 cvs 2513: if (strptr && *strptr)
1.288 vatton 2514: tmp_i = atoi (strptr);
1.151 cvs 2515: else
2516: tmp_i = DEFAULT_DNS_TIMEOUT;
2517: HTDNS_setTimeout (tmp_i);
2518:
2519: /* persistent connections timeout */
1.203 cvs 2520: strptr = TtaGetEnvString ("PERSIST_CX_TIMEOUT");
1.151 cvs 2521: if (strptr && *strptr)
1.288 vatton 2522: tmp_l = atol (strptr);
1.151 cvs 2523: else
2524: tmp_l = DEFAULT_PERSIST_TIMEOUT;
2525: HTHost_setPersistTimeout (tmp_l);
2526:
1.148 cvs 2527: /* default timeout in ms */
1.203 cvs 2528: strptr = TtaGetEnvString ("NET_EVENT_TIMEOUT");
1.151 cvs 2529: if (strptr && *strptr)
1.288 vatton 2530: tmp_i = atoi (strptr);
1.151 cvs 2531: else
2532: tmp_i = DEFAULT_NET_EVENT_TIMEOUT;
2533: HTHost_setEventTimeout (tmp_i);
2534:
1.173 cvs 2535: HTRequest_setMaxRetry (8);
1.4 cvs 2536: #ifdef CATCH_SIG
1.148 cvs 2537: signal (SIGPIPE, SIG_IGN);
1.4 cvs 2538: #endif
1.15 cvs 2539: }
2540:
2541: /*----------------------------------------------------------------------
1.17 cvs 2542: LoopForStop
1.136 cvs 2543: a copy of the Thop event loop so we can handle the stop button in Unix
2544: and preemptive requests under Windows
1.15 cvs 2545: ----------------------------------------------------------------------*/
2546: static int LoopForStop (AHTReqContext * me)
2547: {
1.136 cvs 2548: #ifdef _WINDOWS
2549: MSG msg;
2550: unsigned long libwww_msg;
2551: HWND old_active_window, libwww_window;
2552: int status_req = HT_OK;
2553:
2554: old_active_window = GetActiveWindow ();
2555: libwww_window = HTEventList_getWinHandle (&libwww_msg);
1.137 cvs 2556:
1.149 cvs 2557: while (me->reqStatus != HT_END && me->reqStatus != HT_ERR
1.253 cvs 2558: && me->reqStatus != HT_ABORT && AmayaIsAlive () &&
2559: GetMessage (&msg, NULL, 0, 0))
2560: {
2561: if (msg.message != WM_QUIT)
2562: TtaHandleOneEvent (&msg);
2563: else
2564: break;
2565: }
1.136 cvs 2566: if (!AmayaIsAlive ())
2567: /* Amaya was killed by one of the callback handlers */
2568: exit (0);
2569: #else /* _WINDOWS */
1.277 kahan 2570: ThotEvent ev;
1.17 cvs 2571: int status_req = HT_OK;
1.15 cvs 2572:
2573: /* to test the async calls */
1.17 cvs 2574: /* Loop while waiting for new events, exists when the request is over */
1.15 cvs 2575: while (me->reqStatus != HT_ABORT &&
2576: me->reqStatus != HT_END &&
1.69 cvs 2577: me->reqStatus != HT_ERR) {
1.116 cvs 2578: if (!AmayaIsAlive ())
1.69 cvs 2579: /* Amaya was killed by one of the callback handlers */
2580: exit (0);
1.277 kahan 2581:
2582: if (TtaFetchOneAvailableEvent (&ev))
2583: TtaHandleOneEvent (&ev);
1.69 cvs 2584: }
1.136 cvs 2585: #endif /* _WINDOWS */
1.69 cvs 2586: switch (me->reqStatus) {
2587: case HT_ERR:
2588: case HT_ABORT:
1.130 cvs 2589: status_req = NO;
1.15 cvs 2590: break;
2591:
1.69 cvs 2592: case HT_END:
1.130 cvs 2593: status_req = YES;
1.15 cvs 2594: break;
2595:
1.69 cvs 2596: default:
1.15 cvs 2597: break;
1.69 cvs 2598: }
1.15 cvs 2599: return (status_req);
1.4 cvs 2600: }
2601:
1.5 cvs 2602: /*----------------------------------------------------------------------
1.15 cvs 2603: QueryClose
1.21 cvs 2604: closes all existing threads, frees all non-automatically deallocated
2605: memory and then ends libwww.
1.5 cvs 2606: ----------------------------------------------------------------------*/
1.116 cvs 2607: void QueryClose ()
1.4 cvs 2608: {
1.24 cvs 2609:
1.140 cvs 2610: AmayaAlive_flag = FALSE;
1.24 cvs 2611:
1.116 cvs 2612: /* remove all the handlers and callbacks that may output a message to
2613: a non-existent Amaya window */
2614: HTEvent_setRegisterCallback ((HTEvent_registerCallback *) NULL);
2615: HTEvent_setUnregisterCallback ((HTEvent_unregisterCallback *) NULL);
2616: #ifndef _WINDOWS
2617: /** need to erase all existing timers too **/
2618: HTTimer_registerSetTimerCallback (NULL);
2619: HTTimer_registerDeleteTimerCallback (NULL);
2620: #endif /* !_WINDOWS */
2621: HTHost_setActivateRequestCallback (NULL);
2622: Thread_deleteAll ();
1.21 cvs 2623:
1.116 cvs 2624: HTProxy_deleteAll ();
2625: HTNoProxy_deleteAll ();
1.207 cvs 2626: SafePut_delete ();
1.116 cvs 2627: HTGateway_deleteAll ();
2628: AHTProfile_delete ();
1.248 kahan 2629:
2630: /* close the trace file (if it exists) */
2631: if (trace_fp)
2632: fclose (trace_fp);
2633:
1.116 cvs 2634: }
2635:
2636: /*----------------------------------------------------------------------
2637: NextNameValue
2638: ---------------------------------------------------------------------*/
1.265 cvs 2639: static char * NextNameValue (char **pstr, char **name, char **value)
1.116 cvs 2640: {
2641: char * p = *pstr;
2642: char * start = NULL;
2643: if (!pstr || !*pstr) return NULL;
2644:
2645: if (!*p) {
2646: *pstr = p;
2647: *name = NULL;
2648: *value = NULL;
2649: return NULL; /* No field */
2650: }
2651:
2652: /* Now search for the next '&' and ';' delimitators */
2653: start = p;
2654: while (*p && *p != '&' && *p != ';') p++;
2655: if (*p)
2656: *p++ = '\0';
2657: *pstr = p;
2658:
2659: /* Search for the name and value */
2660: *name = start;
2661: p = start;
2662:
2663: while(*p && *p != '=')
2664: p++;
2665: if (*p)
2666: *p++ = '\0';
2667: *value = p;
2668:
2669: return start;
2670: }
2671:
2672: /*----------------------------------------------------------------------
2673: PrepareFormdata
2674: ---------------------------------------------------------------------*/
1.265 cvs 2675: static HTAssocList * PrepareFormdata (char *string)
1.116 cvs 2676: {
1.266 cvs 2677: char *tmp_string, *tmp_string_ptr;
2678: char *name;
2679: char *value;
2680: HTAssocList *formdata;
1.116 cvs 2681:
2682: if (!string)
2683: return NULL;
2684:
2685: /* store the ptr in another variable, as the original address will
2686: change
2687: */
1.236 cvs 2688:
1.265 cvs 2689: tmp_string_ptr = TtaGetMemory (strlen (string) + 1);
1.236 cvs 2690: tmp_string = tmp_string_ptr;
1.273 cvs 2691: strcpy (tmp_string_ptr, string);
1.116 cvs 2692: formdata = HTAssocList_new();
2693:
2694: while (*tmp_string)
2695: {
2696: NextNameValue (&tmp_string, &name, &value);
2697: HTAssocList_addObject(formdata,
2698: name, value);
2699: }
2700:
2701: TtaFreeMemory (tmp_string_ptr);
2702: return formdata;
1.4 cvs 2703: }
2704:
1.236 cvs 2705: /*----------------------------------------------------------------------
2706: ---------------------------------------------------------------------*/
1.216 cvs 2707: void AHTRequest_setCustomAcceptHeader (HTRequest *request, char *value)
2708: {
2709: HTRqHd rqhd = HTRequest_rqHd (request);
2710: rqhd = rqhd & (~HT_C_ACCEPT_TYPE);
2711: HTRequest_setRqHd (request, rqhd);
1.221 cvs 2712: HTRequest_addExtraHeader (request, "Accept", value);
1.216 cvs 2713: }
2714:
1.228 cvs 2715: /*----------------------------------------------------------------------
1.99 cvs 2716: InvokeGetObjectWWW_callback
2717: A simple function to invoke a callback function whenever there's an error
2718: in GetObjectWWW
2719: ---------------------------------------------------------------------*/
1.265 cvs 2720: void InvokeGetObjectWWW_callback (int docid, char *urlName,
2721: char *outputfile, TTcbf *terminate_cbf,
2722: void *context_tcbf, int status)
1.99 cvs 2723: {
2724: if (!terminate_cbf)
2725: return;
2726:
1.116 cvs 2727: (*terminate_cbf) (docid, status, urlName, outputfile,
1.99 cvs 2728: NULL, context_tcbf);
2729: }
2730:
2731:
2732:
1.5 cvs 2733: /*----------------------------------------------------------------------
1.15 cvs 2734: GetObjectWWW
1.17 cvs 2735: this function requests a resource designated by a URLname into a
2736: temporary filename. The download can come from a simple GET operation,
2737: or can come from POSTING/GETTING a form. In the latter
2738: case, the function receives a query string to send to the server.
2739:
1.5 cvs 2740: 4 file retrieval modes are proposed:
2741: AMAYA_SYNC : blocking mode
2742: AMAYA_ISYNC : incremental, blocking mode
2743: AMAYA_ASYNC : non-blocking mode
2744: AMAYA_IASYNC : incremental, non-blocking mode
2745:
2746: In the incremental mode, each time a package arrives, it will be
2747: stored in the temporary file. In addition, if an
2748: incremental_callback function is defined, this function will be
2749: called and handled a copy of the newly received data package.
2750: Finally, if a terminate_callback function is defined, it will be
2751: invoked when the request terminates. The caller of this function
1.4 cvs 2752: can define two different contexts to be passed to the callback
2753: functions.
2754:
2755: When the function is called with the SYNC mode, the function will
2756: return only when the requested file has been loaded.
2757: The ASYNC mode will immediately return after setting up the
2758: call.
2759:
2760: Notes:
2761: At the end of a succesful request, the urlName string contains the
2762: name of the actually retrieved URL. As a URL can change over the time,
2763: (e.g., be redirected elsewhere), it is advised that the function
1.17 cvs 2764: caller verify the value of the urlName variable at the end of
1.4 cvs 2765: a request.
2766:
2767: Inputs:
2768: - docid Document identifier for the set of objects being
2769: retrieved.
2770: - urlName The URL to be retrieved (MAX_URL_LENGTH chars length)
2771: - outputfile A pointer to an empty string of MAX_URL_LENGTH.
2772: - mode The retrieval mode.
2773: - incremental_cbf
2774: - context_icbf
2775: Callback and context for the incremental modes
2776: - terminate_cbf
2777: - context_icbf
2778: Callback and context for a terminate handler
1.17 cvs 2779: -error_html if TRUE, then display any server error message as an
2780: HTML document.
1.88 cvs 2781: - content_type a string
2782:
1.4 cvs 2783: Outputs:
2784: - urlName The URL that was retrieved
2785: - outputfile The name of the temporary file which holds the
2786: retrieved data. (Only in case of success)
1.88 cvs 2787: - if content_type wasn't NULL, it will contain a copy of the parameter
2788: sent in the HTTP answer
1.4 cvs 2789: Returns:
2790: HT_ERROR
2791: HT_OK
1.5 cvs 2792: ----------------------------------------------------------------------*/
1.265 cvs 2793: int GetObjectWWW (int docid, char *urlName, char *formdata,
2794: char *outputfile, int mode, TIcbf *incremental_cbf,
2795: void *context_icbf, TTcbf *terminate_cbf,
2796: void *context_tcbf, ThotBool error_html, char *content_type)
1.4 cvs 2797: {
2798: AHTReqContext *me;
1.301 ! vatton 2799: char *ref;
! 2800: char *esc_url;
1.107 cvs 2801: int status, l;
1.114 cvs 2802: int tempsubdir;
1.191 cvs 2803: ThotBool bool_tmp;
1.7 cvs 2804:
1.116 cvs 2805: if (urlName == NULL || docid == 0 || outputfile == NULL)
2806: {
2807: /* no file to be loaded */
2808: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_BAD_URL), urlName);
1.69 cvs 2809:
1.116 cvs 2810: if (error_html)
1.69 cvs 2811: /* so we can show the error message */
2812: DocNetworkStatus[docid] |= AMAYA_NET_ERROR;
1.116 cvs 2813: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
2814: context_tcbf, HT_ERROR);
2815: return HT_ERROR;
2816: }
1.7 cvs 2817:
1.159 cvs 2818: /* if it's a 'docImage', we have already downloaded it */
1.265 cvs 2819: if (!strncmp ("internal:", urlName, 9))
1.159 cvs 2820: {
1.265 cvs 2821: strcpy (outputfile, urlName);
1.159 cvs 2822: InvokeGetObjectWWW_callback (docid, urlName, outputfile,
2823: terminate_cbf, context_tcbf, HT_OK);
2824: return HT_OK;
2825: }
2826:
1.4 cvs 2827: /* do we support this protocol? */
1.116 cvs 2828: if (IsValidProtocol (urlName) == NO)
2829: {
2830: /* return error */
2831: outputfile[0] = EOS; /* file could not be opened */
2832: TtaSetStatus (docid, 1,
2833: TtaGetMessage (AMAYA, AM_GET_UNSUPPORTED_PROTOCOL),
2834: urlName);
2835:
2836: if (error_html)
1.69 cvs 2837: /* so we can show the error message */
2838: DocNetworkStatus[docid] |= AMAYA_NET_ERROR;
1.116 cvs 2839: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
2840: context_tcbf, HT_ERROR);
2841: return HT_ERROR;
2842: }
1.4 cvs 2843:
1.114 cvs 2844: /* we store CSS in subdir named 0; all the other files go to a subidr
2845: named after their own docid */
2846: tempsubdir = (mode & AMAYA_LOAD_CSS) ? 0 : docid;
1.116 cvs 2847: /* create a tempfilename */
1.272 cvs 2848: sprintf (outputfile, "%s%c%d%c%04dAM", TempFileDirectory, DIR_SEP, tempsubdir, DIR_SEP, object_counter);
1.116 cvs 2849: /* update the object_counter (used for the tempfilename) */
1.4 cvs 2850: object_counter++;
2851: /* normalize the URL */
1.300 kahan 2852: esc_url = EscapeURL (urlName);
1.206 cvs 2853: if (esc_url)
2854: {
1.265 cvs 2855: ref = AmayaParseUrl (esc_url, "", AMAYA_PARSE_ALL);
1.206 cvs 2856: TtaFreeMemory (esc_url);
2857: }
2858: else
2859: ref = NULL;
2860:
1.4 cvs 2861: /* should we abort the request if we could not normalize the url? */
1.198 cvs 2862: if (ref == NULL || ref[0] == EOS) {
1.69 cvs 2863: /*error */
2864: outputfile[0] = EOS;
2865: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_BAD_URL), urlName);
1.214 cvs 2866: if (ref)
2867: TtaFreeMemory (ref);
1.69 cvs 2868: if (error_html)
1.116 cvs 2869: /* so we can show the error message */
2870: DocNetworkStatus[docid] |= AMAYA_NET_ERROR;
1.99 cvs 2871: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
1.116 cvs 2872: context_tcbf, HT_ERROR);
1.69 cvs 2873: return HT_ERROR;
2874: }
1.116 cvs 2875:
1.4 cvs 2876: /* verify if that file name existed */
1.9 cvs 2877: if (TtaFileExist (outputfile))
1.77 cvs 2878: TtaFileUnlink (outputfile);
1.116 cvs 2879:
1.4 cvs 2880: /* Initialize the request structure */
2881: me = AHTReqContext_new (docid);
1.116 cvs 2882: if (me == NULL)
2883: {
2884: outputfile[0] = EOS;
2885: /* need an error message here */
2886: TtaFreeMemory (ref);
2887: InvokeGetObjectWWW_callback (docid, urlName, outputfile, terminate_cbf,
2888: context_tcbf, HT_ERROR);
2889: return HT_ERROR;
2890: }
2891:
1.4 cvs 2892: /* Specific initializations for POST and GET */
1.222 cvs 2893: if (mode & AMAYA_FORM_POST
1.228 cvs 2894: || mode & AMAYA_FILE_POST)
1.116 cvs 2895: {
2896: me->method = METHOD_POST;
2897: HTRequest_setMethod (me->request, METHOD_POST);
2898: }
2899: else
2900: {
1.254 kahan 2901: #ifdef ANNOTATIONS
2902: /* we support the DELETE method for deleting annotations.
2903: the rest of the request is similar to the GET */
2904: if (mode & AMAYA_DELETE)
2905: {
2906: me->method = METHOD_GET;
2907: HTRequest_setMethod (me->request, METHOD_DELETE);
2908: }
2909: else
2910: #endif /* ANNOTATIONS */
2911: me->method = METHOD_GET;
1.295 kahan 2912: #ifdef ANNOTATIONS
2913: /* use the custom sent content_type */
2914: if (content_type && content_type[0] != EOS)
2915: AHTRequest_setCustomAcceptHeader (me->request, content_type);
2916: else
2917: #endif /* ANNOTATIONS */
2918: if (!HasKnownFileSuffix (ref))
1.216 cvs 2919: {
2920: /* try to adjust the Accept header in an netwise economical way */
2921: if (mode & AMAYA_LOAD_IMAGE)
2922: AHTRequest_setCustomAcceptHeader (me->request, IMAGE_ACCEPT_NEGOTIATION);
2923: else if (mode & AMAYA_LOAD_CSS)
2924: AHTRequest_setCustomAcceptHeader (me->request, "*/*;q=0.1,css/*");
1.294 kahan 2925: else
2926: AHTRequest_setCustomAcceptHeader (me->request, GENERAL_ACCEPT_NEGOTIATION);
1.216 cvs 2927: /*
2928: HTRequest_setConversion(me->request, acceptTypes, TRUE);
2929: */
2930: }
1.295 kahan 2931: else
2932: AHTRequest_setCustomAcceptHeader (me->request, GENERAL_ACCEPT_NEGOTIATION);
2933: /* language negotiation */
2934: HTRequest_setLanguage (me->request, acceptLanguages, TRUE);
1.116 cvs 2935: }
1.93 cvs 2936:
1.116 cvs 2937: /* Common initialization for all HTML methods */
1.4 cvs 2938: me->mode = mode;
2939: me->error_html = error_html;
2940: me->incremental_cbf = incremental_cbf;
2941: me->context_icbf = context_icbf;
2942: me->terminate_cbf = terminate_cbf;
2943: me->context_tcbf = context_tcbf;
1.64 cvs 2944:
1.69 cvs 2945: /* for the async. request modes, we need to have our
1.4 cvs 2946: own copy of outputfile and urlname
1.116 cvs 2947: */
1.4 cvs 2948:
1.116 cvs 2949: if ((mode & AMAYA_ASYNC) || (mode & AMAYA_IASYNC))
2950: {
1.265 cvs 2951: l = strlen (outputfile);
1.116 cvs 2952: if (l > MAX_LENGTH)
1.265 cvs 2953: me->outputfile = TtaGetMemory (l + 2);
1.116 cvs 2954: else
1.265 cvs 2955: me->outputfile = TtaGetMemory (MAX_LENGTH + 2);
2956: strcpy (me->outputfile, outputfile);
2957: l = strlen (urlName);
1.116 cvs 2958: if (l > MAX_LENGTH)
1.265 cvs 2959: me->urlName = TtaGetMemory (l + 2);
1.116 cvs 2960: else
1.265 cvs 2961: me->urlName = TtaGetMemory (MAX_LENGTH + 2);
2962: strcpy (me->urlName, urlName);
1.116 cvs 2963: #ifdef _WINDOWS
2964: /* force windows ASYNC requests to always be non preemptive */
2965: HTRequest_setPreemptive (me->request, NO);
2966: #endif /*_WINDOWS */
2967: } /* AMAYA_ASYNC mode */
2968: else
2969: #ifdef _WINDOWS
2970: {
1.233 cvs 2971: me->outputfile = outputfile;
2972: me->urlName = urlName;
1.116 cvs 2973: /* force windows SYNC requests to always be non preemptive */
2974: HTRequest_setPreemptive (me->request, YES);
2975: }
2976: #else /* !_WINDOWS */
2977: {
2978: me->outputfile = outputfile;
2979: me->urlName = urlName;
2980: }
2981: /***
1.136 cvs 2982: In order to take into account the stop button,
2983: the requests will be always asynchronous, however, if mode=AMAYA_SYNC,
1.57 cvs 2984: we will loop until the document has been received or a stop signal
2985: generated
1.77 cvs 2986: ****/
1.116 cvs 2987: HTRequest_setPreemptive (me->request, NO);
2988: #endif /* _WINDOWS */
1.61 cvs 2989:
1.151 cvs 2990: /*
2991: ** Make sure that the first request is flushed immediately and not
2992: ** buffered in the output buffer
2993: */
2994: if (mode & AMAYA_FLUSH_REQUEST)
2995: HTRequest_setFlush(me->request, YES);
2996: HTRequest_setFlush(me->request, YES);
2997:
1.61 cvs 2998: /* prepare the URLname that will be displayed in teh status bar */
2999: ChopURL (me->status_urlName, me->urlName);
1.77 cvs 3000: TtaSetStatus (me->docid, 1,
3001: TtaGetMessage (AMAYA, AM_FETCHING),
1.233 cvs 3002: me->status_urlName);
1.4 cvs 3003:
1.265 cvs 3004: me->anchor = (HTParentAnchor *) HTAnchor_findAddress (ref);
1.45 cvs 3005: TtaFreeMemory (ref);
1.177 cvs 3006:
1.223 cvs 3007: TtaGetEnvBoolean ("CACHE_DISCONNECTED_MODE", &bool_tmp);
1.177 cvs 3008: if (!bool_tmp && (mode & AMAYA_NOCACHE))
1.116 cvs 3009: HTRequest_setReloadMode (me->request, HT_CACHE_FLUSH);
3010:
3011: /* prepare the query string and format for POST */
3012: if (mode & AMAYA_FORM_POST)
1.114 cvs 3013: {
1.116 cvs 3014: HTAnchor_setFormat ((HTParentAnchor *) me->anchor,
3015: HTAtom_for ("application/x-www-form-urlencoded"));
3016: HTAnchor_setLength ((HTParentAnchor *) me->anchor, me->block_size);
3017: HTRequest_setEntityAnchor (me->request, me->anchor);
3018: }
1.114 cvs 3019:
1.127 cvs 3020: /* create the formdata element for libwww */
1.236 cvs 3021: if (formdata && ! (mode & AMAYA_FILE_POST))
3022: me->formdata = PrepareFormdata (formdata);
1.127 cvs 3023:
1.297 kirschpi 3024:
3025: #ifdef DAV
3026: /* try to add an If header for POST requests and for GET forms */
3027: if (HTRequest_method(me->request) == METHOD_POST ||
3028: (HTRequest_method(me->request) == METHOD_GET && me->formdata))
3029: DAVAddIfHeader (me,HTAnchor_address((HTAnchor*)me->anchor));
3030: #endif
3031:
3032:
1.116 cvs 3033: /* do the request */
3034: if (mode & AMAYA_FORM_POST)
1.119 cvs 3035: {
1.191 cvs 3036: /* this call doesn't give back a ThotBool */
1.119 cvs 3037: HTParentAnchor * posted = NULL;
3038:
3039: posted = HTPostFormAnchor (me->formdata, (HTAnchor *) me->anchor,
3040: me->request);
3041: status = posted ? YES : NO;
3042: }
1.222 cvs 3043: #ifdef ANNOTATIONS
1.251 kahan 3044: else if (mode & AMAYA_FILE_POST)
1.222 cvs 3045: {
1.228 cvs 3046: unsigned long filesize;
3047: char *fileURL;
3048:
3049: /* @@@ a very ugly patch :)))
3050: I'm copying here some of the functionality I use in the PUT
3051: I need to put the common parts in another module */
1.252 kahan 3052: AM_GetFileSize (formdata, &filesize);
1.228 cvs 3053: me->block_size = filesize;
3054:
1.233 cvs 3055: fileURL = HTParse (formdata, "file:/", PARSE_ALL);
1.228 cvs 3056: me->source = HTAnchor_findAddress (fileURL);
3057: HT_FREE (fileURL);
1.222 cvs 3058:
1.228 cvs 3059: /* hardcoded ... */
3060: AHTRequest_setCustomAcceptHeader (me->request, "application/xml");
1.222 cvs 3061: HTAnchor_setFormat (HTAnchor_parent (me->source),
3062: HTAtom_for ("application/xml"));
1.228 cvs 3063: HTAnchor_setFormat (me->anchor,
3064: HTAtom_for ("application/xml"));
3065: HTAnchor_setLength ((HTParentAnchor *) me->source, me->block_size);
3066: /* @@ here I need to actually read the file and put it in document,
3067: then, when I kill the request, I need to kill it */
3068: {
3069: FILE *fp;
3070: int i;
3071: char c;
3072:
1.255 swick 3073: me->document = TtaGetMemory (me->block_size + 1);
1.233 cvs 3074: fp = fopen (formdata, "r");
1.244 kahan 3075: i = 0;
1.228 cvs 3076: c = getc (fp);
3077: while (!feof (fp))
3078: {
3079: me->document[i++] = c;
3080: c = getc (fp);
3081: }
3082: me->document[i] = '\0';
3083: fclose (fp);
3084: }
3085: HTAnchor_setDocument ( (HTParentAnchor *) me->source,
3086: (void * ) me->document);
3087: HTRequest_setEntityAnchor (me->request, HTAnchor_parent (me->source));
3088:
3089: status = HTPostAnchor (HTAnchor_parent (me->source),
1.222 cvs 3090: (HTAnchor *) me->anchor,
3091: me->request);
3092: }
3093: #endif /* ANNOTATIONS */
1.127 cvs 3094: else if (formdata)
3095: status = HTGetFormAnchor(me->formdata, (HTAnchor *) me->anchor,
3096: me->request);
1.116 cvs 3097: else
1.77 cvs 3098: status = HTLoadAnchor ((HTAnchor *) me->anchor, me->request);
1.69 cvs 3099:
1.123 cvs 3100: /* @@@ may need some special windows error msg here */
1.116 cvs 3101: /* control the errors */
1.4 cvs 3102:
1.130 cvs 3103: if (status == NO)
1.116 cvs 3104: /* the request invocation failed */
3105: {
3106: /* show an error message on the status bar */
3107: DocNetworkStatus[docid] |= AMAYA_NET_ERROR;
3108: TtaSetStatus (docid, 1,
3109: TtaGetMessage (AMAYA, AM_CANNOT_LOAD),
3110: urlName);
3111: if (me->reqStatus == HT_NEW)
3112: /* manually invoke the last processing that usually gets done
3113: in a succesful request */
3114: InvokeGetObjectWWW_callback (docid, urlName, outputfile,
3115: terminate_cbf, context_tcbf, HT_ERROR);
3116: /* terminate_handler wasn't called */
1.136 cvs 3117: AHTReqContext_delete (me);
1.116 cvs 3118: }
3119: else
1.136 cvs 3120: /* end treatment for SYNC requests */
1.120 cvs 3121: if ((mode & AMAYA_SYNC) || (mode & AMAYA_ISYNC))
3122: {
1.136 cvs 3123: /* wait here untilt the asynchronous request finishes */
1.130 cvs 3124: status = LoopForStop (me);
1.136 cvs 3125: /* if status returns HT_ERROR, should we invoke the callback? */
1.120 cvs 3126: if (!HTRequest_kill (me->request))
3127: AHTReqContext_delete (me);
3128: }
1.130 cvs 3129:
1.136 cvs 3130: /* an interface problem!!! */
3131: return (status == YES ? 0 : -1);
1.4 cvs 3132: }
3133:
1.5 cvs 3134: /*----------------------------------------------------------------------
1.17 cvs 3135: PutObjectWWW
3136: frontend for uploading a resource to a URL. This function downloads
3137: a file to be uploaded into memory, it then calls UploadMemWWW to
3138: finish the job.
3139:
1.5 cvs 3140: 2 upload modes are proposed:
3141: AMAYA_SYNC : blocking mode
3142: AMAYA_ASYNC : non-blocking mode
3143:
1.4 cvs 3144: When the function is called with the SYNC mode, the function will
3145: return only when the file has been uploaded.
3146: The ASYNC mode will immediately return after setting up the
3147: call. Furthermore, at the end of an upload, the ASYNC mode will
3148: call back terminate_cbf, handling it the context defined in
3149: context_tcbf.
3150:
3151: Notes:
3152: At the end of a succesful request, the urlName string contains the
3153: name of the actually uploaded URL. As a URL can change over the time,
3154: (e.g., be redirected elsewhere), it is advised that the function
3155: caller verifies the value of the urlName variable at the end of
3156: a request.
3157:
3158: Inputs:
3159: - docid Document identifier for the set of objects being
3160: retrieved.
3161: - fileName A pointer to the local file to upload
3162: - urlName The URL to be uploaded (MAX_URL_LENGTH chars length)
3163: - mode The retrieval mode.
3164: - terminate_cbf
3165: - context_icbf
3166: Callback and context for a terminate handler
3167:
3168: Outputs:
3169: - urlName The URL that was uploaded
3170:
3171: Returns:
3172: HT_ERROR
3173: HT_OK
1.5 cvs 3174: ----------------------------------------------------------------------*/
1.276 kahan 3175: int PutObjectWWW (int docid, char *fileName, char *urlName,
3176: char *contentType, int mode,
1.265 cvs 3177: TTcbf *terminate_cbf, void *context_tcbf)
1.4 cvs 3178: {
1.116 cvs 3179: AHTReqContext *me;
1.250 cvs 3180: CHARSET charset;
1.4 cvs 3181: int status;
1.250 cvs 3182: unsigned long file_size;
1.116 cvs 3183: char *fileURL;
1.168 cvs 3184: char *etag = NULL;
1.169 cvs 3185: HTParentAnchor *dest_anc_parent;
1.265 cvs 3186: char *tmp;
3187: char *esc_url;
1.168 cvs 3188: int UsePreconditions;
1.191 cvs 3189: ThotBool lost_update_check = TRUE;
1.235 cvs 3190: char url_name[MAX_LENGTH];
1.285 kahan 3191: char *resource_name;
1.265 cvs 3192: char *tmp2;
1.239 cvs 3193: #ifdef _WINDOWS
3194: char file_name[MAX_LENGTH];
3195: #endif /* _WINDOWS */
1.172 cvs 3196:
3197: /* should we protect the PUT against lost updates? */
1.203 cvs 3198: tmp = TtaGetEnvString ("ENABLE_LOST_UPDATE_CHECK");
1.265 cvs 3199: if (tmp && *tmp && strcasecmp (tmp, "yes"))
1.172 cvs 3200: lost_update_check = FALSE;
1.168 cvs 3201:
3202: UsePreconditions = mode & AMAYA_USE_PRECONDITIONS;
1.4 cvs 3203:
1.33 cvs 3204: AmayaLastHTTPErrorMsg [0] = EOS;
1.256 kahan 3205: AmayaLastHTTPErrorMsgR [0] = EOS;
3206:
1.33 cvs 3207:
1.116 cvs 3208: if (urlName == NULL || docid == 0 || fileName == NULL
3209: || !TtaFileExist (fileName))
1.4 cvs 3210: /* no file to be uploaded */
3211: return HT_ERROR;
3212:
3213: /* do we support this protocol? */
1.7 cvs 3214: if (IsValidProtocol (urlName) == NO)
3215: {
3216: /* return error */
1.198 cvs 3217: TtaSetStatus (docid, 1, TtaGetMessage (AMAYA, AM_PUT_UNSUPPORTED_PROTOCOL), urlName);
1.7 cvs 3218: return HT_ERROR;
3219: }
1.116 cvs 3220:
1.228 cvs 3221: /* get the size of the file */
1.252 kahan 3222: if (!AM_GetFileSize (fileName, &file_size) || file_size == 0L)
1.7 cvs 3223: {
3224: /* file was empty */
3225: /*errmsg here */
3226: return (HT_ERROR);
3227: }
1.116 cvs 3228:
3229: /* prepare the request context */
1.4 cvs 3230: if (THD_TRACE)
1.228 cvs 3231: fprintf (stderr, "file size == %u\n", (unsigned) file_size);
1.4 cvs 3232:
3233: me = AHTReqContext_new (docid);
1.7 cvs 3234: if (me == NULL)
3235: {
1.168 cvs 3236: /* @@ need an error message here */
1.151 cvs 3237: TtaHandlePendingEvents ();
1.7 cvs 3238: return (HT_ERROR);
1.208 cvs 3239: }
3240:
3241: /*
3242: ** Set up the original URL name
3243: */
1.285 kahan 3244:
3245: /* are we using content-location? */
3246: if (DocumentMeta[docid]->content_location)
3247: resource_name = DocumentMeta[docid]->content_location;
3248: else
3249: resource_name = NULL;
3250:
3251: /* prepare the target URL */
3252: if (resource_name)
1.208 cvs 3253: {
1.285 kahan 3254: tmp = strstr (urlName, resource_name);
3255: if (!tmp)
1.208 cvs 3256: {
1.285 kahan 3257: /* urlName does not include the resource name */
3258: me->default_put_name = TtaGetMemory (strlen (urlName)
3259: + strlen (resource_name)
3260: + sizeof (URL_SEP)
3261: + 1);
3262: strcpy (me->default_put_name, urlName);
3263: tmp = strrchr (me->default_put_name, URL_SEP);
3264: if (tmp)
1.208 cvs 3265: {
1.285 kahan 3266: /* it is a URL finishing in /. Only add the resrouce name */
3267: tmp++;
3268: strcpy (tmp, resource_name);
3269: }
3270: else
3271: {
3272: strcat (me->default_put_name, URL_STR);
3273: strcat (me->default_put_name, resource_name);
1.208 cvs 3274: }
3275: }
1.7 cvs 3276: }
1.285 kahan 3277:
3278: if (!me->default_put_name)
1.271 kahan 3279: me->default_put_name = TtaStrdup (urlName);
3280:
1.285 kahan 3281: HTRequest_setDefaultPutName (me->request, me->default_put_name);
1.116 cvs 3282:
1.4 cvs 3283: me->mode = mode;
3284: me->incremental_cbf = (TIcbf *) NULL;
3285: me->context_icbf = (void *) NULL;
3286: me->terminate_cbf = terminate_cbf;
3287: me->context_tcbf = context_tcbf;
1.286 kahan 3288:
3289: /* normalize the URL */
1.300 kahan 3290: esc_url = EscapeURL (urlName);
1.272 cvs 3291: me->urlName = TtaStrdup (esc_url);
1.206 cvs 3292: TtaFreeMemory (esc_url);
1.300 kahan 3293:
1.228 cvs 3294: me->block_size = file_size;
1.17 cvs 3295: /* select the parameters that distinguish a PUT from a GET/POST */
1.4 cvs 3296: me->method = METHOD_PUT;
3297: me->output = stdout;
1.17 cvs 3298: /* we are not expecting to receive any input from the server */
1.265 cvs 3299: me->outputfile = (char *) NULL;
1.4 cvs 3300:
1.134 cvs 3301: #ifdef _WINDOWS
3302: /* libwww's HTParse function doesn't take into account the drive name;
1.168 cvs 3303: so we sidestep it */
1.238 cvs 3304:
1.134 cvs 3305: fileURL = NULL;
3306: StrAllocCopy (fileURL, "file:");
1.273 cvs 3307: strcpy (file_name, fileName);
1.235 cvs 3308: StrAllocCat (fileURL, file_name);
1.134 cvs 3309: #else
1.116 cvs 3310: fileURL = HTParse (fileName, "file:/", PARSE_ALL);
1.134 cvs 3311: #endif /* _WINDOWS */
1.168 cvs 3312: me->source = HTAnchor_findAddress (fileURL);
1.116 cvs 3313: HT_FREE (fileURL);
1.273 cvs 3314: strcpy (url_name, me->urlName);
1.235 cvs 3315: me->dest = HTAnchor_findAddress (url_name);
1.169 cvs 3316: /* we memorize the anchor's parent @ as we use it a number of times
3317: in the following lines */
3318: dest_anc_parent = HTAnchor_parent (me->dest);
1.168 cvs 3319:
1.169 cvs 3320: /*
3321: ** Set the Content-Type of the file we are uploading
3322: */
3323: /* we try to use any content-type previosuly associated
3324: with the parent. If it doesn't exist, we try to guess it
3325: from the URL */
1.276 kahan 3326: /* @@ JK: trying to use the content type we stored */
3327: /*
1.235 cvs 3328: tmp2 = HTAtom_name (HTAnchor_format (dest_anc_parent));
1.276 kahan 3329: */
3330: tmp2 = NULL;
1.235 cvs 3331: if (!tmp2 || !strcmp (tmp2, "www/unknown"))
1.169 cvs 3332: {
1.260 kahan 3333: HTAtom *tmp_atom;
1.276 kahan 3334:
1.260 kahan 3335: tmp_atom = AHTGuessAtom_for (me->urlName, contentType);
1.276 kahan 3336: if (!tmp_atom || !strcmp (HTAtom_name (tmp_atom), "www/unknown"))
3337: {
3338: /* ask the user for a MIME type */
3339: }
1.260 kahan 3340: HTAnchor_setFormat (dest_anc_parent, tmp_atom);
1.235 cvs 3341: tmp2 = HTAtom_name (HTAnchor_format (dest_anc_parent));
1.169 cvs 3342: }
3343: /* .. and we give the same type to the source anchor */
3344: /* we go thru setOutputFormat, rather than change the parent's
3345: anchor, as that's the place that libwww expects it to be */
1.235 cvs 3346: HTAnchor_setFormat (HTAnchor_parent (me->source), HTAtom_for (tmp2));
1.219 cvs 3347:
1.235 cvs 3348: HTRequest_setOutputFormat (me->request, HTAtom_for (tmp2));
1.219 cvs 3349:
3350: /*
3351: ** Set the Charset of the file we are uploading
3352: */
1.240 cvs 3353: /* we set the charset as indicated in the document's metadata
3354: structure (and only if it exists) */
1.250 cvs 3355: charset = TtaGetDocumentCharset (docid);
3356: if (charset != UNDEFINED_CHARSET)
1.240 cvs 3357: {
1.250 cvs 3358: tmp = TtaGetCharsetName (charset);
1.272 cvs 3359: if (tmp && *tmp != EOS)
1.250 cvs 3360: {
1.273 cvs 3361: tmp2 = TtaStrdup (tmp);
1.250 cvs 3362: HTAnchor_setCharset (dest_anc_parent, HTAtom_for (tmp2));
3363: TtaFreeMemory (tmp2);
3364: tmp2 = HTAtom_name (HTAnchor_charset (dest_anc_parent));
3365: /* .. and we give the same charset to the source anchor */
3366: /* we go thru setCharSet, rather than change the parent's
3367: anchor, as that's the place that libwww expects it to be */
3368: HTAnchor_setCharset (HTAnchor_parent (me->source),
3369: HTAtom_for (tmp2));
3370: }
1.219 cvs 3371: }
3372:
3373: /*
3374: ** define other request characteristics
3375: */
1.116 cvs 3376: #ifdef _WINDOWS
1.136 cvs 3377: HTRequest_setPreemptive (me->request, NO);
1.116 cvs 3378: #else
1.134 cvs 3379: HTRequest_setPreemptive (me->request, NO);
1.116 cvs 3380: #endif /* _WINDOWS */
3381:
1.151 cvs 3382: /*
3383: ** Make sure that the first request is flushed immediately and not
3384: ** buffered in the output buffer
3385: */
3386: if (mode & AMAYA_FLUSH_REQUEST)
3387: HTRequest_setFlush(me->request, YES);
1.168 cvs 3388:
3389: /* Should we use preconditions? */
1.172 cvs 3390: if (lost_update_check)
1.168 cvs 3391: {
1.172 cvs 3392: if (UsePreconditions)
3393: etag = HTAnchor_etag (HTAnchor_parent (me->dest));
3394:
3395: if (etag)
3396: {
3397: HTRequest_setPreconditions(me->request, HT_MATCH_THIS);
3398: }
3399: else
3400: {
3401: HTRequest_setPreconditions(me->request, HT_NO_MATCH);
3402: HTRequest_addAfter(me->request, check_handler, NULL, NULL, HT_ALL,
3403: HT_FILTER_MIDDLE, YES);
1.175 cvs 3404: HTRequest_addAfter (me->request, HTAuthFilter, "http://*", NULL,
3405: HT_NO_ACCESS, HT_FILTER_MIDDLE, YES);
3406: HTRequest_addAfter (me->request, HTAuthFilter, "http://*", NULL,
3407: HT_REAUTH, HT_FILTER_MIDDLE, YES);
3408: HTRequest_addAfter (me->request, HTAuthInfoFilter, "http://*", NULL,
3409: HT_ALL, HT_FILTER_MIDDLE, YES);
3410: HTRequest_addAfter (me->request, HTUseProxyFilter, "http://*", NULL,
3411: HT_USE_PROXY, HT_FILTER_MIDDLE, YES);
1.172 cvs 3412: }
1.168 cvs 3413: }
3414: else
3415: {
1.172 cvs 3416: /* don't use preconditions */
1.168 cvs 3417: HTRequest_setPreconditions(me->request, HT_NO_MATCH);
3418: }
1.151 cvs 3419:
1.136 cvs 3420: /* don't use the cache while saving a document */
3421: HTRequest_setReloadMode (me->request, HT_CACHE_FLUSH);
1.116 cvs 3422:
1.164 cvs 3423: /* Throw away any reponse body */
3424: /*
3425: HTRequest_setOutputStream (me->request, HTBlackHole());
3426: */
3427:
1.168 cvs 3428: /* prepare the URLname that will be displayed in the status bar */
1.74 cvs 3429: ChopURL (me->status_urlName, me->urlName);
1.233 cvs 3430: TtaSetStatus (me->docid, 1, TtaGetMessage (AMAYA, AM_REMOTE_SAVING), me->status_urlName);
1.114 cvs 3431:
1.297 kirschpi 3432:
3433: #ifdef DAV
3434: /* MKP: for a PUT request, try to add an if header
3435: * for a HEAD request, leave this for check_handler */
3436: if ( !(lost_update_check && (!UsePreconditions || !etag)) )
3437: DAVAddIfHeader (me,HTAnchor_address(me->dest));
3438: #endif
3439:
3440:
1.164 cvs 3441: /* make the request */
1.172 cvs 3442: if (lost_update_check && (!UsePreconditions || !etag))
1.168 cvs 3443: status = HTHeadAnchor (me->dest, me->request);
3444: else
3445: status = HTPutDocumentAnchor (HTAnchor_parent (me->source), me->dest, me->request);
1.4 cvs 3446:
1.130 cvs 3447: if (status == YES && me->reqStatus != HT_ERR)
1.7 cvs 3448: {
1.168 cvs 3449: /* part of the stop button handler */
3450: if ((mode & AMAYA_SYNC) || (mode & AMAYA_ISYNC))
3451: status = LoopForStop (me);
1.15 cvs 3452: }
1.136 cvs 3453: if (!HTRequest_kill (me->request))
3454: AHTReqContext_delete (me);
1.168 cvs 3455:
1.116 cvs 3456: TtaHandlePendingEvents ();
1.90 cvs 3457:
1.130 cvs 3458: return (status == YES ? 0 : -1);
1.28 cvs 3459: }
1.4 cvs 3460:
1.5 cvs 3461: /*----------------------------------------------------------------------
1.138 cvs 3462: StopRequest
1.17 cvs 3463: stops (kills) all active requests associated with a docid
1.5 cvs 3464: ----------------------------------------------------------------------*/
1.4 cvs 3465: void StopRequest (int docid)
3466: {
1.140 cvs 3467: if (Amaya && CanDoStop ())
1.138 cvs 3468: {
1.139 cvs 3469: #if 0 /* for later */
1.140 cvs 3470: AHTDocId_Status *docid_status;
3471: /* verify if there are any requests at all associated with docid */
1.138 cvs 3472: docid_status = (AHTDocId_Status *) GetDocIdStatus (docid,
3473: Amaya->docid_status);
3474: if (docid_status == (AHTDocId_Status *) NULL)
3475: return;
1.139 cvs 3476: #endif /* 0 */
1.138 cvs 3477: /* temporary call to stop all requests, as libwww changed its API */
3478: StopAllRequests (docid);
3479: }
3480: }
3481:
1.190 cvs 3482: /* @@@ the docid parameter isn't used... clean it up */
1.138 cvs 3483: /*----------------------------------------------------------------------
3484: StopAllRequests
3485: stops (kills) all active requests. We use the docid
3486: ----------------------------------------------------------------------*/
3487: void StopAllRequests (int docid)
3488: {
1.4 cvs 3489: HTList *cur;
3490: AHTReqContext *me;
1.191 cvs 3491: static ThotBool lock_stop = 0;
3492: ThotBool async_flag;
1.232 cvs 3493: AHTReqStatus old_reqStatus;
1.116 cvs 3494:
1.138 cvs 3495: /* only do the stop if we're not being called while processing a
1.146 cvs 3496: request, and if we're not already dealing with a stop */
3497: if (Amaya && CanDoStop () && !lock_stop)
1.7 cvs 3498: {
1.100 cvs 3499: #ifdef DEBUG_LIBWWW
1.138 cvs 3500: fprintf (stderr, "StopRequest: number of Amaya requests "
3501: "before kill: %d\n", Amaya->open_requests);
1.100 cvs 3502: #endif /* DEBUG_LIBWWW */
1.150 cvs 3503: /* enter the critical section */
1.146 cvs 3504: lock_stop = TRUE;
1.214 cvs 3505: /* set a module global variable so that we can do special
3506: processing easier */
3507: UserAborted_flag = TRUE;
1.232 cvs 3508: /* abort all outstanding libwww UI dialogues */
1.265 cvs 3509: CallbackDialogue (BaseDialog + FormAnswer, STRING_DATA, NULL);
3510: CallbackDialogue (BaseDialog + ConfirmForm, INTEGER_DATA, NULL);
1.164 cvs 3511: /* expire all outstanding timers */
3512: HTTimer_expireAll ();
1.160 cvs 3513: /* HTNet_killAll (); */
1.245 kahan 3514: if (Amaya->open_requests)
1.116 cvs 3515: {
1.245 kahan 3516: cur = Amaya->reqlist;
3517: while ((me = (AHTReqContext *) HTList_nextObject (cur)))
1.160 cvs 3518: {
1.245 kahan 3519: if (AmayaIsAlive ())
3520: {
1.161 cvs 3521: #ifdef DEBUG_LIBWWW
1.245 kahan 3522: fprintf (stderr,"StopRequest: killing req %p, url %s, status %d\n", me, me->urlName, me->reqStatus);
1.161 cvs 3523: #endif /* DEBUG_LIBWWW */
1.245 kahan 3524:
3525: if (me->reqStatus != HT_END && me->reqStatus != HT_ABORT)
1.163 cvs 3526: {
1.245 kahan 3527: if ((me->mode & AMAYA_ASYNC)
3528: || (me->mode & AMAYA_IASYNC))
3529: async_flag = TRUE;
3530: else
3531: async_flag = FALSE;
3532:
3533: /* change the status to say that the request aborted */
3534: /* if the request was "busy", we just change a flag to say so and
3535: let the handler finish the processing itself */
3536: old_reqStatus = me->reqStatus;
3537: me->reqStatus = HT_ABORT;
3538: if (old_reqStatus == HT_BUSY)
3539: continue;
3540:
3541: /* kill the request, using the appropriate function */
3542: if (me->request->net)
3543: HTNet_killPipe (me->request->net);
3544: else
3545: {
3546: if (me->terminate_cbf)
3547: (*me->terminate_cbf) (me->docid, -1, me->urlName,
3548: me->outputfile,
3549: NULL,
3550: me->context_tcbf);
3551:
3552: if (async_flag)
3553: /* explicitly free the request context for async
3554: requests. The sync requests context is freed
3555: by LoopForStop */
3556: AHTReqContext_delete (me);
3557: }
3558: cur = Amaya->reqlist;
1.160 cvs 3559: }
1.142 cvs 3560: #ifndef _WINDOWS
3561: #ifdef WWW_XWINDOWS
1.245 kahan 3562: /* to be on the safe side, remove all outstanding
3563: X events */
1.160 cvs 3564: else
3565: RequestKillAllXtevents (me);
1.142 cvs 3566: #endif /* WWW_XWINDOWS */
3567: #endif /* !_WINDOWS */
1.245 kahan 3568: }
1.160 cvs 3569: }
1.245 kahan 3570: /* Delete remaining channels */
3571: HTChannel_safeDeleteAll ();
1.116 cvs 3572: }
1.214 cvs 3573: /* reset the stop status */
3574: UserAborted_flag = FALSE;
1.150 cvs 3575: /* exit the critical section */
1.148 cvs 3576: lock_stop = FALSE;
1.100 cvs 3577: #ifdef DEBUG_LIBWWW
1.138 cvs 3578: fprintf (stderr, "StopRequest: number of Amaya requests "
3579: "after kill: %d\n", Amaya->open_requests);
1.100 cvs 3580: #endif /* DEBUG_LIBWWW */
1.138 cvs 3581: }
3582: } /* StopAllRequests */
1.17 cvs 3583:
3584:
1.105 cvs 3585: /*----------------------------------------------------------------------
3586: AmayaIsAlive
1.140 cvs 3587: returns the value of the AmayaAlive_flag
1.105 cvs 3588: ----------------------------------------------------------------------*/
1.191 cvs 3589: ThotBool AmayaIsAlive (void)
1.105 cvs 3590: {
1.140 cvs 3591: return AmayaAlive_flag;
3592: }
3593:
3594: /*----------------------------------------------------------------------
3595: CanDoStop
3596: returns the value of the CanDoStop flag
3597: ----------------------------------------------------------------------*/
1.191 cvs 3598: ThotBool CanDoStop (void)
1.140 cvs 3599: {
3600: return CanDoStop_flag;
3601: }
3602:
3603: /*----------------------------------------------------------------------
3604: CanDoStop_set
3605: sets the value of the CanDoStop flag
3606: ----------------------------------------------------------------------*/
1.191 cvs 3607: void CanDoStop_set (ThotBool value)
1.140 cvs 3608: {
3609: CanDoStop_flag = value;
1.176 cvs 3610: }
3611:
1.265 cvs 3612: /*----------------------------------------------------------------------
3613: ----------------------------------------------------------------------*/
1.176 cvs 3614: void libwww_updateNetworkConf (int status)
3615: {
3616: /* @@@ the docid parameter isn't used... clean it up */
3617: int docid = 1;
3618:
3619: /* first, stop all current requests, as the network
3620: may make some changes */
3621: StopAllRequests (docid);
1.207 cvs 3622:
3623: if (status & AMAYA_SAFEPUT_RESTART)
3624: {
3625: SafePut_delete ();
3626: SafePut_init ();
3627: }
1.176 cvs 3628:
3629: if (status & AMAYA_PROXY_RESTART)
3630: {
3631: HTProxy_deleteAll ();
3632: ProxyInit ();
3633: }
3634:
3635: if (status & AMAYA_CACHE_RESTART)
3636: {
3637: clear_cachelock ();
3638: HTCacheTerminate ();
3639: HTCacheMode_setEnabled (NO);
3640: CacheInit ();
3641: }
1.193 cvs 3642:
3643: if (status & AMAYA_LANNEG_RESTART)
3644: {
3645: /* clear the current values */
3646: if (acceptLanguages)
3647: HTLanguage_deleteAll (acceptLanguages);
3648: /* read in the new ones */
3649: acceptLanguages = HTList_new ();
3650: AHTAcceptLanguagesInit (acceptLanguages);
3651: }
1.105 cvs 3652: }
1.246 kahan 3653:
3654: /****************************************************************************
3655: ** The following two functions allow to set and read the value of *
3656: ** the FTPURL_flag. If this flag is true, it means we can browse FTP URLs *
3657: ***************************************************************************/
3658:
3659: /*----------------------------------------------------------------------
3660: AHT_FTPURL_flag_set
3661: ----------------------------------------------------------------------*/
3662: void AHTFTPURL_flag_set (ThotBool value)
3663: {
3664: FTPURL_flag = value;
3665: }
3666:
3667: /*----------------------------------------------------------------------
3668: AHT_FTPURL_flag
3669: ----------------------------------------------------------------------*/
3670: ThotBool AHTFTPURL_flag (void)
3671: {
3672: return (FTPURL_flag);
3673: }
3674:
Webmaster