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