Ejemplo n.º 1
0
PUBLIC int HTMIME_connection (HTRequest * request, HTResponse * response,
			      char * token, char * value)
{
    /*
    **  Walk through the set of connection directives and add them to the
    **  response association list for connection directives
    */
    char * name_val;
    while ((name_val = HTNextPair(&value)) != NULL) {
	char * name = HTNextField(&name_val);
	char * val = HTNextField(&name_val);

	/*
	**  If we have a name then look if it is concerning persistent
	**  connections. If so, then we handle it here, otherwise we leave it
	**  to somebody else by simply adding it to the list of connection
	**  tokens.
	*/
	if (name) {
	    HTNet * net = HTRequest_net(request);
	    HTHost * host = HTNet_host(net);
	    if (!strcasecomp(name, "close")) {			 /* HTTP/1.1 */
		HTTRACE(STREAM_TRACE, "MIMEParser.. Close received...\n");
		HTHost_setCloseNotification(host, YES);
	    } else if (!strcasecomp(name, "keep-alive")) {       /* HTTP/1.0 */

		/*
		**  In case this is an HTTP/1.1 server sending keep-alive then
		**  ignore it.
		*/
		if (HTHost_version(host) < HTTP_11) {
		    HTNet_setPersistent(net, YES, HT_TP_SINGLE);
		    HTTRACE(STREAM_TRACE, "MIMEParser.. HTTP/1.0 Keep Alive\n");
		} else 
		    HTTRACE(STREAM_TRACE, "MIMEParser.. HTTP/1.0 Keep Alive ignored\n");
	    } else
		HTResponse_addConnection(response, name, val ? val : "");
	}
    }
    return HT_OK;
}
Ejemplo n.º 2
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;
}