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