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