Exemplo n.º 1
0
BinURLInputStream::BinURLInputStream(const XMLURL& urlSource)
      : fBuffer(0)
      , fBufferSize(0)
      , fBufferIndex(0)
      , fRemoteFileSize(0)
      , fAnchor(0)
      , fBytesProcessed(0)
      , fMemoryManager(urlSource.getMemoryManager())
{
    fBuffer = (XMLByte*) fMemoryManager->allocate
    (
        URLISBUFMAXSIZE * sizeof(XMLByte)
    );//new XMLByte[URLISBUFMAXSIZE];
    const XMLCh*  uri = urlSource.getURLText();
    char*   uriAsCharStar = localTranscode(uri, fMemoryManager);

    //
    // First find the size of the remote resource being asked for.
    // We use the ContentCounter stream provided by libWWW.
    //

    fAnchor = HTAnchor_findAddress(uriAsCharStar);
    HTRequest*   request = HTRequest_new();
    HTRequest_setOutputFormat(request, WWW_SOURCE);
    HTStream*    counterStrm = HTContentCounter(HTBlackHole(), request, 0xFFFF);
    BOOL  status = HTLoadToStream(uriAsCharStar, counterStrm, request);
    if (status == YES)
    {
        HTParentAnchor * anchor = HTRequest_anchor(request);
        fRemoteFileSize=HTAnchor_length(anchor);
        if(fRemoteFileSize < 0)
        {
            // Patch by Artur Klauser
            // When a redirection is processed in libWWW, it seems that
            // HTAnchor_length(anchor) == -1 on the original anchor, whereas
            // HTResponse_length(response) gives the correct content length of
            // the redirection target. This has confused fRemoteFileSize and it was
            // not checked for a -1 response at all.
            HTResponse * response = HTRequest_response (request);
            fRemoteFileSize = HTResponse_length(response);
            if (fRemoteFileSize < 0) {
                ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_LengthError, fMemoryManager);
            }
        }
    }

    // Cleanup, before you throw any errors.
    fMemoryManager->deallocate(uriAsCharStar);
    HTRequest_delete(request);
    // Don't know whether I am supposed to delete counterStrm.

    if (status == NO)
    {
        ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_LengthError, fMemoryManager);
    }
}
Exemplo n.º 2
0
/*	Create a new coder and insert it into stream chain
**	--------------------------------------------------
**	Creating the content decoding stack is not based on quality factors as
**	we don't have the freedom as with content types. Specify whether you
**	you want encoding or decoding using the BOOL "encode" flag.
*/
PUBLIC HTStream * HTContentCodingStack (HTEncoding	encoding,
					HTStream *	target,
					HTRequest *	request,
					void *		param,
					BOOL		encode)
{
    HTList * coders[2];
    HTStream * top = target;
    HTCoding * pres = NULL;
    HTCoding * best_match = NULL;
    double best_quality = -1e30;		/* Pretty bad! */
    int cnt;
    if (!encoding || !request) {
	HTTRACE(CORE_TRACE, "Codings... Nothing applied...\n");
	return target ? target : HTErrorStream();
    }
    coders[0] = HTRequest_encoding(request);
    coders[1] = HTContentCoders;
    HTTRACE(CORE_TRACE, "C-E......... Looking for `%s\'\n" _ HTAtom_name(encoding));
    for (cnt=0; cnt < 2; cnt++) {
	HTList * cur = coders[cnt];
	while ((pres = (HTCoding *) HTList_nextObject(cur))) {
	    if ((pres->encoding == encoding || HTMIMEMatch(pres->encoding, encoding)) &&
		pres->quality > best_quality) {
		best_match = pres;
		best_quality = pres->quality;
	    }
	}
    }

    if (best_match) {
	HTTRACE(CORE_TRACE, "C-E......... Found `%s\'\n" _ HTAtom_name(best_match->encoding));
	if (encode) {
	    if (best_match->encoder)
		top = (*best_match->encoder)(request, param, encoding, top);
	} else {
	    if (best_match->decoder)
		top = (*best_match->decoder)(request, param, encoding, top);
	}
    } else if (!HTFormat_isUnityContent(encoding)) {

	/*
	**  If this is not a unity coding and we didn't find any coders
	**  that could handle it then put in a local file save stream
	**  instead of the stream that we got.
	*/
	if (encode) {
	    HTTRACE(CORE_TRACE, "C-E......... NOT FOUND - can't encode stream!\n");
	} else {
	    HTTRACE(CORE_TRACE, "C-E......... NOT FOUND - error!\n");
	    top = HTBlackHole();
	}
    }
    return top;
}
Exemplo n.º 3
0
/*	Create a new transfer coder and insert it into stream chain
**	-----------------------------------------------------------
**	Creating the content decoding stack is not based on quality factors as
**	we don't have the freedom as with content types. Specify whether you
**	you want encoding or decoding using the BOOL "encode" flag.
*/
PUBLIC HTStream * HTContentTransferCodingStack (HTEncoding	encoding,
						HTStream *	target,
						HTRequest *	request,
						void *		param,
						BOOL		encode)
{
    HTList * coders[2];
    HTStream * top = target;
    HTCoding * pres = NULL;
    int cnt;
    if (!encoding || !request) {
	HTTRACE(CORE_TRACE, "C-T-E..... Nothing applied...\n");
	return target ? target : HTErrorStream();
    }

    /*
    **  We use the same encoders/decoders as for Transfer-Encodings
    */
    coders[0] = HTRequest_transfer(request);
    coders[1] = HTTransferCoders;
    HTTRACE(CORE_TRACE, "C-T-E....... Looking for %s\n" _ HTAtom_name(encoding));
    for (cnt=0; cnt < 2; cnt++) {
	HTList * cur = coders[cnt];
	while ((pres = (HTCoding *) HTList_nextObject(cur))) {
	    if (pres->encoding == encoding) {
		HTTRACE(CORE_TRACE, "C-T-E....... Found...\n");
		if (encode) {
		    if (pres->encoder)
			top = (*pres->encoder)(request, param, encoding, top);
		    break;
		} else if (pres->decoder) {
		    top = (*pres->decoder)(request, param, encoding, top);
		    break;
		}
	    }
	}
    }

    /*
    **  If this is not a unity coding and we didn't find any coders
    **  that could handle it then put in a local file save stream
    **  instead of the stream that we got.
    */
    if (!HTFormat_isUnityTransfer(encoding) && target==top) {
	if (encode) {	    
	    HTTRACE(CORE_TRACE, "C-T-E....... NOT FOUND - removing encoding!\n");
	    HTAnchor_setContentTransferEncoding(HTRequest_anchor(request), NULL);
	} else {
	    HTTRACE(CORE_TRACE, "C-T-E....... NOT FOUND - error!\n");
	    top = HTBlackHole();
	}
    }
    return top;
}
Exemplo n.º 4
0
/*
**  Here you can provide a complete list instead of a single token.
**  The list has to filled up in the order the _encodings_ are to be applied
*/
PUBLIC HTStream * HTTransferEncodingStack (HTList *	encodings,
					   HTStream *	target,
					   HTRequest *	request,
					   void *	param)
{
    if (encodings) {
	HTList * cur = encodings;
	HTEncoding pres;
	HTStream * top = target;
	while ((pres = (HTEncoding) HTList_nextObject(cur))) {
	    top = HTTransferCodingStack(pres, top, request, param, YES);
	    if (top == HTBlackHole()) break;
	}
	return top;
    }
    return HTErrorStream();
}
Exemplo n.º 5
0
/*
**  Here you can provide a complete list instead of a single token.
**  The list has to be in the order the _encodings_ were applied - that
**  is, the same way that _encodings_ are to be applied. This is all consistent
**  with the order of the Content-Encoding header.
*/
PUBLIC HTStream * HTTransferDecodingStack (HTList *	encodings,
					   HTStream *	target,
					   HTRequest *	request,
					   void *	param)
{
    if (encodings) {
	HTEncoding pres;
	int cnt = HTList_count(encodings);
	HTStream * top = target;
	while (cnt > 0) {
	    pres = (HTEncoding) HTList_objectAt(encodings, --cnt);
	    top = HTTransferCodingStack(pres, top, request, param, NO);
	    if (top == HTBlackHole()) break;
	}
	return top;
    }
    return HTErrorStream();
}
Exemplo n.º 6
0
/*	Take action using a system command
**	----------------------------------
**
**	Creates temporary file, writes to it, executes system command
**	on end-document.  The suffix of the temp file can be given
**	in case the application is fussy, or so that a generic opener can
**	be used.
*/
PUBLIC HTStream* HTSaveAndExecute ARGS5(
	HTRequest *,		request,
	void *,			param,
	HTFormat,		input_format,
	HTFormat,		output_format,
	HTStream *,		output_stream)

#ifdef unix
#define REMOVE_FILE unlink
#endif
#ifdef VMS
#define REMOVE_FILE unlink		/* ok? */
#endif

#ifdef REMOVE_FILE
{
    char *fnam, *physical;

    HTStream* me;

    if (HTSecure) {
	HTAlert("Can't save data to file -- please run WWW locally");
	return HTBlackHole();
    }

    if (!HTSaveLocallyDir) {
	if (TRACE) fprintf(stderr, "Save and execute turned off");
	return HTBlackHole();
    }

    me = (HTStream*)calloc(sizeof(*me),1);
    me = (HTStream*)calloc(sizeof(*me), 1);
    if (me == NULL) outofmem(__FILE__, "Save and execute");
    me->isa = &HTFWriter;

    /* Let's find a hash name for this file */
    physical = HTAnchor_physical(request->anchor);
    if ( !physical )
       physical = request->anchor->address;
    if ((fnam = HTFWriter_filename(HTSaveLocallyDir,
				   physical,
				   HTFileSuffix(input_format),
				   1000)) == NULL) {
	HTAlert("Can't find a suitable file name");
	return NULL;
    }

    me->request = request;	/* won't be freed */
    me->fp = fopen (fnam, "w");
    if (!me->fp) {
	HTAlert("Can't open temporary file!");
	free(fnam);
	free(me);
	return NULL;
    }
    StrAllocCopy(me->filename, fnam);

/*	Make command to process file
*/
    me->end_command = (char *)malloc (
			(strlen (param) + 10+ 3*strlen(fnam))
			 * sizeof (char));
    if (me == NULL) outofmem(__FILE__, "SaveAndExecute");

    sprintf (me->end_command, param, fnam, fnam, fnam);

    me->remove_on_close = NO;

    me->announce = NO;
    free (fnam);
    return me;
}
Exemplo n.º 7
0
PRIVATE int pumpData (HTStream * me)
{
    HTRequest * request = me->request;
    HTResponse * response = me->response;
    HTFormat format = HTResponse_format(response);
    HTList * te = HTResponse_transfer(response);
    HTList * ce = HTResponse_encoding(response);
    long length = HTResponse_length(response);
    HTStream * BlackHole = HTBlackHole();
    BOOL savestream = NO;
    me->transparent = YES;		  /* Pump rest of data right through */

    /*
    **  Cache the metainformation in the anchor object by copying
    **  it from the response object. This we do regardless if
    **  we have a persistent cache or not as the memory cache will
    **  use it as well. If we are updating a cache entry using
    **  byte ranges then we already have the metainformation and
    **  hence we can ignore the new one as it'd better be the same.
    */
    if (!(me->mode & HT_MIME_PARTIAL) &&
	HTResponse_isCachable(me->response) != HT_NO_CACHE)
	HTAnchor_update(HTRequest_anchor(request), me->response);

    /*
    **  If we asked only to read the header or footer or we used a HEAD
    **  method then we stop here as we don't expect any body part.
    */
    if (me->mode & (HT_MIME_HEADER | HT_MIME_FOOTER) ||
	HTRequest_method(request) == METHOD_HEAD) {
        HTAlertCallback * cbf = HTAlert_find(HT_PROG_DONE);
        if (cbf) (*cbf)(request, HT_PROG_DONE, HT_MSG_NULL, NULL, NULL, NULL);
        return HT_LOADED;
    }

    /*
    **  If we are paring a 1xx response then return HT_CONTINUE
    */
    if (me->mode & HT_MIME_CONT)
	return HT_CONTINUE;

    /*
    **  If we get a 101 Protocol Switch then we are done here
    **  but not done with the response (which we don't know
    **  how to go about parsing
    */
    if (me->mode & HT_MIME_UPGRADE) {
	me->hasBody = YES;
	return HT_OK;
    }

    /*
    **  If there is no content-length, no transfer encoding and no
    **  content type then we assume that there is no body part in
    **  the message and we can return HT_LOADED
    */
    {
	HTHost * host = HTNet_host(me->net);
	if (length<0 && te==NULL &&
	    HTHost_isPersistent(host) && !HTHost_closeNotification(host)) {
	    if (format != WWW_UNKNOWN) {
		HTTRACE(STREAM_TRACE, "MIME Parser. BAD - there seems to be a body but no length. This must be an HTTP/1.0 server pretending that it is HTTP/1.1\n");
		HTHost_setCloseNotification(host, YES);
	    } else {
                HTAlertCallback * cbf = HTAlert_find(HT_PROG_DONE);
                if (cbf) (*cbf)(request, HT_PROG_DONE, HT_MSG_NULL, NULL, NULL, NULL);
		HTTRACE(STREAM_TRACE, "MIME Parser. No body in this message\n");
		return HT_LOADED;
	    }
	}
    }

    /*
    **  Deal with the body
    */
    me->hasBody = YES;

    /*
    **  Handle any Content Type
    */
    if (!(me->mode & HT_MIME_PARTIAL) &&
	(format != WWW_UNKNOWN || length > 0 || te)) {
	HTStream * target;
	HTTRACE(STREAM_TRACE, "Building.... C-T stack from %s to %s\n" _ 
				  HTAtom_name(format) _ 
				  HTAtom_name(me->target_format));
	if ((target = HTStreamStack(format, me->target_format,
				    me->target, request, YES))==BlackHole) {
	    if (!savestream) {
                if (me->target) (*me->target->isa->abort)(me->target, NULL);
                me->target = me->save_stream(request, NULL,
					     format, me->target_format, me->target);
		savestream = YES;
	    }
	} else
	    me->target = target;
    }

    /*
    **  Handle any Content Encodings
    */
    HTTRACE(STREAM_TRACE, "Building.... Content-Decoding stack\n");
    if (ce) {
	HTStream * target = HTContentDecodingStack(ce, me->target, request, NULL);
	if (target == BlackHole) {
	    if (!savestream) {
		if (me->target) (*me->target->isa->abort)(me->target, NULL);
                me->target = me->save_stream(request, NULL,
					     format, me->target_format, me->target);
		savestream = YES;
	    }
	} else
	    me->target = target;
    }

    /*
    **  Can we cache the data object? If so then create a T stream and hook it 
    **  into the stream pipe. We do it before the transfer decoding so that we
    **  don't have to deal with that when we retrieve the object from cache.
    **  If we are appending to a cache entry then use a different stream than
    **  if creating a new entry.
    */
#ifndef NO_CACHE
    if (HTCacheMode_enabled()) {
	if (me->mode & HT_MIME_PARTIAL) {
	    HTStream * append = HTStreamStack(WWW_CACHE_APPEND,
					      me->target_format,
					      me->target, request, NO);
	    if (append) me->target = HTTee(me->target, append, NULL);
#if 0
	    /* @@ JK: change */
	    if (append) me->target = append;
#endif
	} else if (HTResponse_isCachable(me->response) == HT_CACHE_ALL) {
	    HTStream * cache = HTStreamStack(WWW_CACHE, me->target_format,
					     me->target, request, NO);
	    if (cache) me->target = HTTee(me->target, cache, NULL);
	}
    }
#endif
    
    /*
    **  Handle any Transfer Encodings
    */
    HTTRACE(STREAM_TRACE, "Building.... Transfer-Decoding stack\n");
    if (te) {
	HTStream * target = HTTransferDecodingStack(te, me->target, request, NULL);
	if (target == BlackHole) {
	    if (!savestream) {
		if (me->target) (*me->target->isa->abort)(me->target, NULL);
                me->target = me->save_stream(request, NULL,
					     format, me->target_format, me->target);
		savestream = YES;
	    }
	} else
	    me->target = target;
    }


    /*
    ** If we for some reason couldn't find a target stream
    */
    if (!me->target) me->target = HTBlackHole();
    return HT_OK;
}
Exemplo n.º 8
0
/*	Take action using a system command
**	----------------------------------
**
**	originally from Ghostview handling by Marc Andreseen.
**	Creates temporary file, writes to it, executes system command
**	on end-document.  The suffix of the temp file can be given
**	in case the application is fussy, or so that a generic opener can
**	be used.
*/
PUBLIC HTStream* HTSaveAndExecute ARGS3(
	HTPresentation *,	pres,
	HTParentAnchor *,	anchor,	/* Not used */
	HTStream *,		sink)	/* Not used */

#ifdef UNIX
#define REMOVE_COMMAND "/bin/rm -f %s\n"
#endif
#ifdef VMS
#define REMOVE_COMMAND "delete/noconfirm/nolog %s.."
#endif

#ifdef REMOVE_COMMAND
{
    char *fnam;
    CONST char * suffix;

    HTStream* me;

    if (HTClientHost) {
	HTAlert(CANNOT_SAVE_REMOTE);
	return HTBlackHole();
    }

    me = (HTStream*)malloc(sizeof(*me));
    if (me == NULL) outofmem(__FILE__, "Save and execute");
    me->isa = &HTFWriter;

    /* Save the file under a suitably suffixed name */

    suffix = HTFileSuffix(pres->rep, anchor->content_encoding);

    fnam = (char *)malloc (L_tmpnam + 16 + strlen(suffix));
    if (fnam == NULL)
	outofmem(__FILE__, "HTSaveAndExecute");
    tmpnam (fnam);
    strcat(fnam, suffix);

    me->fp = fopen (fnam, BIN_W);
    if (!me->fp) {
	HTAlert(CANNOT_OPEN_TEMP);
	FREE(fnam);
	FREE(me);
	return NULL;
    }

/*	Make command to process file
*/
    me->end_command = 0;
    HTSprintf0(&(me->end_command), pres->command, fnam, fnam, fnam);

    me->remove_command = NULL;	/* If needed, put into end_command */
#ifdef NOPE
/*	Make command to delete file
*/
    me->remove_command = 0;
    HTSprintf0(&(me->remove_command), REMOVE_COMMAND, fnam);
#endif

    me->announce = NO;
    FREE(fnam);
    return me;
}
Exemplo n.º 9
0
/*	Save Locally
**	------------
**	Saves a file to local disk. This can for example be used to dump
**	data objects of unknown media types to local disk. The stream prompts
**	for a file name for the temporary file.
*/
PUBLIC HTStream* HTSaveLocally (HTRequest *	request,
				void *		param,
				HTFormat	input_format,
				HTFormat	output_format,
				HTStream *	output_stream)
{
    FILE * fp = NULL;
    char * filename = NULL;
    HTUserProfile * up = HTRequest_userProfile(request);
    char * tmproot = HTUserProfile_tmp(up);
    if (HTLib_secure()) {
	HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
			   NULL, 0, "HTSaveLocally");
	return HTErrorStream();
    }
    if (!tmproot) {
	HTTRACE(STREAM_TRACE, "Save File... turned off\n");
	return HTErrorStream();
    }
	
    /* Let's prompt the user for a file name for this file */
    {
	HTAlertCallback *cbf = HTAlert_find(HT_A_PROMPT);
	HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);

	/*
	**  If we found an alert handler for prompting the user then call it.
	**  If not then either we are in non-interactive mode or no handler
	**  has been registered. For now we then return a blackhole which may
	**  not be the best thing to do.
	*/
	if (cbf) {
	    HTAlertPar * reply = HTAlert_newReply();
	    char * suffix = HTBind_getSuffix(anchor);
	    char * deflt = get_filename(tmproot, HTAnchor_physical(anchor), suffix, YES);
	    if ((*cbf)(request, HT_A_PROMPT, HT_MSG_FILENAME,deflt,NULL,reply))
		filename = HTAlert_replyMessage(reply);
	    HTAlert_deleteReply(reply);
	    HT_FREE(suffix);
	    HT_FREE(deflt);
	}
	if (filename) {
	    if ((fp = fopen(filename, "wb")) == NULL) {
		HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
				   filename, strlen(filename),"HTSaveLocally");
		HT_FREE(filename);
		return HTErrorStream();
	    }
	} else if (cbf) {
	    HTTRACE(STREAM_TRACE, "Save File... No file name - error stream\n");
	    return HTErrorStream();
	} else {
	    HTTRACE(STREAM_TRACE, "Save File... No file name - black hole\n");
	    return HTBlackHole();
	}
    }
    
    /* Now we are ready for creating the file writer stream */
    if (fp) {
	HTStream * me = HTFileSave_new(request, fp, NO);
	me->filename = filename;
	return me;
    }
    HT_FREE(filename);
    return HTErrorStream();
}
Exemplo n.º 10
0
int main (int argc, char ** argv)
{
    int		status = 0;	
    int		arg;
    int		tokencount = 0;
    BOOL	formdata = NO;
    HTChunk *	keywords = NULL;			/* From command line */
    HTAssocList*formfields = NULL;
    HTMethod	method = METHOD_GET;			    /* Default value */
    ComLine *	cl = ComLine_new();
    BOOL	cache = NO;			     /* Use persistent cache */
    BOOL	flush = NO;		       /* flush the persistent cache */
    char *	cache_root = NULL;

    /* Starts Mac GUSI socket library */
#ifdef GUSI
    GUSISetup(GUSIwithSIOUXSockets);
    GUSISetup(GUSIwithInternetSockets);
#endif

#ifdef __MWERKS__ /* STR */
    InitGraf((Ptr) &qd.thePort); 
    InitFonts(); 
    InitWindows(); 
    InitMenus(); TEInit(); 
    InitDialogs(nil); 
    InitCursor();
    SIOUXSettings.asktosaveonclose = false;
    argc=ccommand(&argv);
#endif

    /* Initiate W3C Reference Library with a client profile */
    HTProfile_newNoCacheClient(APP_NAME, APP_VERSION);

    /* Need our own trace and print functions */
    HTPrint_setCallback(printer);
    HTTrace_setCallback(tracer);

    /*
    ** Delete the default Username/password handler so that we can handle
    ** parameters handed to us from the command line. The default is set
    ** by the profile.
    */
    HTAlert_deleteOpcode(HT_A_USER_PW);
    HTAlert_add(PromptUsernameAndPassword, HT_A_USER_PW);

    /*
    ** Add default content decoder. We insert a through line as it doesn't
    ** matter that we get an encoding that we don't know.
    */
    HTFormat_addCoding("*", HTIdentityCoding, HTIdentityCoding, 0.3);

    /* Scan command Line for parameters */
    for (arg=1; arg<argc; arg++) {
	if (*argv[arg] == '-') {
	    
	    /* - alone => filter */
	    if (argv[arg][1] == '\0') {
		cl->flags |= CL_FILTER;	   
	    
	    /* -? or -help: show the command line help page */
	    } else if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) {
		cl->anchor = (HTParentAnchor *) HTAnchor_findAddress(W3C_HELP);
		tokencount = 1;

	    /* non-interactive */
	    } else if (!strcmp(argv[arg], "-n")) {
		HTAlert_setInteractive(NO);

	    /* Treat the keywords as form data with a <name> "=" <value> */
	    } else if (!strcmp(argv[arg], "-form")) {
		formdata = YES;

	    /* from -- Initial represntation (only with filter) */
	    } else if (!strcmp(argv[arg], "-from")) {
		cl->format = (arg+1 < argc && *argv[arg+1] != '-') ?
		    HTAtom_for(argv[++arg]) : WWW_HTML;

	    /* to -- Final representation */
	    } else if (!strcmp(argv[arg], "-to")) {
		HTFormat format = (arg+1 < argc && *argv[arg+1] != '-') ?
		    HTAtom_for(argv[++arg]) : DEFAULT_FORMAT;
		HTRequest_setOutputFormat(cl->request, format);

	    /* destination for PUT, POST etc. */
	    } else if (!strcmp(argv[arg], "-dest")) {
		if (arg+1 < argc && *argv[arg+1] != '-') {
		    char * dest = HTParse(argv[++arg], cl->cwd, PARSE_ALL);
		    cl->dest = (HTParentAnchor *) HTAnchor_findAddress(dest);
		    HT_FREE(dest);
		}

	    /* source please */
	    } else if (!strcmp(argv[arg], "-source")) {
		HTRequest_setOutputFormat(cl->request, WWW_RAW);

	    /* log file */
	    } else if (!strcmp(argv[arg], "-l")) {
		cl->logfile = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : DEFAULT_LOG_FILE;

	    /* Max forward hops in case of TRACE request */
	    } else if (!strcmp(argv[arg], "-hops") ||
		       !strcmp(argv[arg], "-maxforwards")) {
		int hops = (arg+1 < argc && *argv[arg+1] != '-') ?
		    atoi(argv[++arg]) : DEFAULT_HOPS;
		if (hops >= 0) HTRequest_setMaxForwards(cl->request, hops);

	    /* automated authentication of format user:password@realm */
	    } else if (!strncmp(argv[arg], "-auth", 5)) {
		char * credentials = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : NULL;
		if (credentials) ParseCredentials(cl, credentials);

	    /* rule file */
	    } else if (!strcmp(argv[arg], "-r")) {
		cl->rules = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : DEFAULT_RULE_FILE;

	    /* output filename */
	    } else if (!strcmp(argv[arg], "-o")) { 
		cl->outputfile = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : DEFAULT_OUTPUT_FILE;

	    /* timeout -- Change the default request timeout */
	    } else if (!strcmp(argv[arg], "-timeout")) {
		int timeout = (arg+1 < argc && *argv[arg+1] != '-') ?
		    atoi(argv[++arg]) : DEFAULT_TIMEOUT;
		if (timeout >= 1) cl->timer = timeout*MILLIES;

	    /* preemptive or non-preemptive access */
	    } else if (!strcmp(argv[arg], "-single")) {
		HTRequest_setPreemptive(cl->request, YES);

	    /* content Length Counter */
	    } else if (!strcmp(argv[arg], "-cl")) { 
		cl->flags |= CL_COUNT;

	    /* print version and exit */
	    } else if (!strcmp(argv[arg], "-version")) { 
		VersionInfo(argv[0]);
		Cleanup(cl, 0);

	    /* run in quiet mode */
	    } else if (!strcmp(argv[arg], "-q")) { 
		cl->flags |= CL_QUIET;

	    /* Start the persistent cache */
	    } else if (!strcmp(argv[arg], "-cache")) {
		cache = YES;

	    /* Determine the cache root */
	    } else if (!strcmp(argv[arg], "-cacheroot")) { 
		cache_root = (arg+1 < argc && *argv[arg+1] != '-') ?
		    argv[++arg] : NULL;

	    /* Persistent cache flush */
	    } else if (!strcmp(argv[arg], "-flush")) {
		flush = YES;

	    /* Do a cache validation */
	    } else if (!strcmp(argv[arg], "-validate")) {
		cl->flags |= CL_VALIDATE;

	    /* Do an end-to-end cache-validation */
	    } else if (!strcmp(argv[arg], "-endvalidate")) {
		cl->flags |= CL_END_VALIDATE;

	    /* Force complete reload */
	    } else if (!strcmp(argv[arg], "-nocache")) {
		cl->flags |= CL_CACHE_FLUSH;

#ifdef WWWTRACE
	    /* trace flags */
	    } else if (!strncmp(argv[arg], "-v", 2)) {
		HTSetTraceMessageMask(argv[arg]+2);
#endif

	    /* GET method */
	    } else if (!strcasecomp(argv[arg], "-get")) {
		method = METHOD_GET;

	    /* HEAD method */
	    } else if (!strcasecomp(argv[arg], "-head")) {
		method = METHOD_HEAD;

	    /* DELETE method */
	    } else if (!strcasecomp(argv[arg], "-delete")) {
		method = METHOD_DELETE;

	    /* POST Method */
	    } else if (!strcasecomp(argv[arg], "-post")) {
		method = METHOD_POST;

	    /* PUT Method */
	    } else if (!strcasecomp(argv[arg], "-put")) {
		method = METHOD_PUT;

	    /* OPTIONS Method */
	    } else if (!strcasecomp(argv[arg], "-options")) {
		method = METHOD_OPTIONS;

	    /* TRACE Method */
	    } else if (!strcasecomp(argv[arg], "-trace")) {
		method = METHOD_TRACE;

	    } else {
		if (SHOW_MSG) HTPrint("Bad Argument (%s)\n", argv[arg]);
	    }
	} else {	 /* If no leading `-' then check for URL or keywords */
    	    if (!tokencount) {
		char * ref = HTParse(argv[arg], cl->cwd, PARSE_ALL);
		cl->anchor = (HTParentAnchor *) HTAnchor_findAddress(ref);
		tokencount = 1;
		HT_FREE(ref);
	    } else if (formdata) {		   /* Keywords are form data */
		char * string = argv[arg];
		if (tokencount++ <= 1) formfields = HTAssocList_new();
		HTParseFormInput(formfields, string);
	    } else {		   	       /* keywords are search tokens */
		char * escaped = HTEscape(argv[arg], URL_XALPHAS);
		if (tokencount++ <= 1)
		    keywords = HTChunk_new(128);
		else
		    HTChunk_putc(keywords, ' ');
		HTChunk_puts(keywords, HTStrip(escaped));
		HT_FREE(escaped);
	    }
	}
    }

    if (!tokencount && !cl->flags & CL_FILTER) {
	VersionInfo(argv[0]);
	Cleanup(cl, 0);
    }

    /* Should we use persistent cache? */
    if (cache) {
	HTCacheInit(cache_root, 20);

	/* Should we start by flushing? */
	if (flush) HTCache_flushAll();
    }

    /*
    ** Check whether we should do some kind of cache validation on
    ** the load
    */
    if (cl->flags & CL_VALIDATE)
	HTRequest_setReloadMode(cl->request, HT_CACHE_VALIDATE);
    else if (cl->flags & CL_END_VALIDATE)
	HTRequest_setReloadMode(cl->request, HT_CACHE_END_VALIDATE);
    else if (cl->flags & CL_CACHE_FLUSH)
	HTRequest_setReloadMode(cl->request, HT_CACHE_FLUSH);

    /* Add progress notification */
    if (cl->flags & CL_QUIET) HTAlert_deleteOpcode(HT_A_PROGRESS);

    /* Output file specified? */
    if (cl->outputfile) {
	if ((cl->output = fopen(cl->outputfile, "wb")) == NULL) {
	    if (SHOW_MSG) HTPrint("Can't open `%s'\\n",cl->outputfile);
	    cl->output = OUTPUT;
	}
    }

    /*
    ** Set up the output. Even though we don't use this explicit, it is
    ** required in order to show the stream stack that we know that we are
    ** getting raw data output on the output stream of the request object.
    */
    HTRequest_setOutputStream(cl->request,
			      HTFWriter_new(cl->request, cl->output, YES));

    /* Setting event timeout */
    HTHost_setEventTimeout(cl->timer);

    /*
    ** Make sure that the first request is flushed immediately and not
    ** buffered in the output buffer
    */
    HTRequest_setFlush(cl->request, YES);

    /* Log file specifed? */
    if (cl->logfile) {
	cl->log = HTLog_open(cl->logfile, YES, YES);
        if (cl->log) HTNet_addAfter(HTLogFilter, NULL, cl->log, HT_ALL, HT_FILTER_LATE);
    }

    /* Just convert formats */
    if (cl->flags & CL_FILTER) {
#ifdef STDIN_FILENO
	HTRequest_setAnchor(cl->request, (HTAnchor *) cl->anchor);
	HTRequest_setPreemptive(cl->request, YES);
	HTLoadSocket(STDIN_FILENO, cl->request);
#endif
	Cleanup(cl, 0);
    }
    
    /* Content Length Counter */
    if (cl->flags & CL_COUNT) {
	HTRequest_setOutputStream(cl->request,
				  HTContentCounter(HTBlackHole(),
						   cl->request, 0x2000));
    }

    /* Rule file specified? */
    if (cl->rules) {
	char * rules = HTParse(cl->rules, cl->cwd, PARSE_ALL);
	if (!HTLoadRulesAutomatically(rules))
	    if (SHOW_MSG) HTPrint("Can't access rules\n");
	HT_FREE(rules);
    }

    /* Add our own filter to update the history list */
    HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);

    /* Start the request */
    switch (method) {
    case METHOD_GET:

	if (formdata)
	    status = HTGetFormAnchor(formfields, (HTAnchor *) cl->anchor,
				     cl->request);
	else if (keywords)
	    status = HTSearchAnchor(keywords, (HTAnchor *) cl->anchor,
				    cl->request);
	else
	    status = HTLoadAnchor((HTAnchor *) cl->anchor, cl->request);
	break;

    case METHOD_HEAD:
	if (formdata) {
	    HTRequest_setMethod(cl->request, METHOD_HEAD);
	    status = HTGetFormAnchor(formfields, (HTAnchor *) cl->anchor,
				     cl->request);
	} else if (keywords) {
	    HTRequest_setMethod(cl->request, METHOD_HEAD);
	    status = HTSearchAnchor(keywords, (HTAnchor *) cl->anchor,
				    cl->request);
	} else
	    status = HTHeadAnchor((HTAnchor *) cl->anchor, cl->request);
	break;

    case METHOD_DELETE:
	status = HTDeleteAnchor((HTAnchor *) cl->anchor, cl->request);
	break;

    case METHOD_POST:
	if (formdata) {
	    HTParentAnchor * posted = NULL;
#if 1
	    posted = HTPostFormAnchor(formfields, (HTAnchor *) cl->anchor,
				      cl->request);
	    status = posted ? YES : NO;
#else
	    /* If we want output to a chunk instead */
	    post_result = HTPostFormAnchorToChunk(formfields, (HTAnchor *) cl->anchor,
						  cl->request);
	    status = post_result ? YES : NO;
#endif
	} else {
	    if (SHOW_MSG) HTPrint("Nothing to post to this address\n");
	    status = NO;	    
	}
	break;

    case METHOD_PUT:
	status = HTPutDocumentAnchor(cl->anchor, (HTAnchor *) cl->dest,
				     cl->request);
	break;

    case METHOD_OPTIONS:
	status = HTOptionsAnchor((HTAnchor *) cl->anchor, cl->request);
	break;	

    case METHOD_TRACE:
	status = HTTraceAnchor((HTAnchor *) cl->anchor, cl->request);
	break;	

    default:
	if (SHOW_MSG) HTPrint("Don't know this method\n");
	break;
    }

    if (keywords) HTChunk_delete(keywords);
    if (formfields) HTAssocList_delete(formfields);
    if (status != YES) {
	if (SHOW_MSG) HTPrint("Sorry, can't access resource\n");
	Cleanup(cl, -1);
    }

    /* Go into the event loop... */
    HTEventList_loop(cl->request);

    /* Only gets here if event loop fails */
    Cleanup(cl, 0);
    return 0;
}
Exemplo n.º 11
0
/*	Create a Content Type filter stack
**	----------------------------------
**	If a wildcard match is made, a temporary HTPresentation
**	structure is made to hold the destination format while the
**	new stack is generated. This is just to pass the out format to
**	MIME so far.  Storing the format of a stream in the stream might
**	be a lot neater.
**
**	The star/star format is special, in that if you can take
**	that you can take anything.
*/
PUBLIC HTStream * HTStreamStack (HTFormat	rep_in,
				 HTFormat	rep_out,
				 HTStream *	output_stream,
				 HTRequest *	request,
				 BOOL		guess)
{
    HTList * conversion[2];
    int which_list;
    double best_quality = -1e30;		/* Pretty bad! */
    HTPresentation *pres, *best_match=NULL;
    if (rep_out == WWW_RAW) {
	HTTRACE(CORE_TRACE, "StreamStack. Raw output...\n");
	return output_stream ? output_stream : HTErrorStream();
    }

    if (rep_out == rep_in) {
	HTTRACE(CORE_TRACE, "StreamStack. Identical input/output format (%s)\n" _ 
		     HTAtom_name(rep_out));
	return output_stream ? output_stream : HTErrorStream();
    }

#ifdef HTDEBUG
    if (CORE_TRACE) {
	const char *p = HTAtom_name(rep_in);
	const char *q = HTAtom_name(rep_out); 
	HTTRACE(CORE_TRACE, "StreamStack. Constructing stream stack for %s to %s\n" _
		p ? p : "<NULL>" _ q ? q : "<NULL>");
    }
#endif /* HTDEBUG */

    conversion[0] = HTRequest_conversion(request);
    conversion[1] = HTConversions;

    for(which_list = 0; which_list<2; which_list++) {
	HTList * cur = conversion[which_list];
	while ((pres = (HTPresentation*)HTList_nextObject(cur))) {
	    if ((pres->rep==rep_in || HTMIMEMatch(pres->rep, rep_in)) &&
		(pres->rep_out==rep_out || HTMIMEMatch(pres->rep_out,rep_out))){
		if (!best_match || better_match(pres->rep, best_match->rep) ||
		    (!better_match(best_match->rep, pres->rep) &&
		     pres->quality > best_quality)) {
#ifdef HAVE_SYSTEM
		    int result=0;
		    if (pres->test_command) {
			result = system(pres->test_command);
			HTTRACE(CORE_TRACE, "StreamStack. system(%s) returns %d\n" _ pres->test_command _ result);
		    }
		    if (!result) {
			best_match = pres;
			best_quality = pres->quality;
		    }
#else
		    best_match = pres;
		    best_quality = pres->quality;
#endif /* HAVE_SYSTEM */
		}
	    }
	}
    }

    if (best_match) {
 	if (rep_out == WWW_SOURCE && best_match->rep_out != WWW_SOURCE) {
	    HTTRACE(CORE_TRACE, "StreamStack. Source output\n");
	    return output_stream ? output_stream : HTErrorStream();
	}
	return (*best_match->converter)(request, best_match->command,
					rep_in, rep_out, output_stream);
    }
    if (rep_out == WWW_SOURCE) {
	HTTRACE(CORE_TRACE, "StreamStack. Source output\n");
	return output_stream ? output_stream : HTErrorStream();
    }

    HTTRACE(CORE_TRACE, "StreamStack. NOT FOUND - error!\n");
    return HTBlackHole();
}