Example #1
0
/*	Converter from \n to CRLF
**	-------------------------
**	The input is assumed to be in local representation with lines
**	delimited by \n. The \n when found is changed to a CRLF sequence,
**	the network representation of a new line.
**	Conversion: '\r' is stripped and \n => CRLF
*/
PRIVATE int TextToNet_put_block (HTStream * me, const char* b, int len)
{
    int status;
#if 0
    const char *limit = b+len;
#endif    
    if (!me->start)
	me->start = b;
    else {
	len -= (me->start - b);
	b = me->start;
    }
    while (len-- > 0) {
	if (me->had_cr && *b == LF) {
	    if (b > me->start+1) {
		if ((status = PUTBLOCK(me->start, b - me->start-1)) != HT_OK)
		    return status;
	    }
	    me->start = b+1;
	    if ((status = PUTC('\n')) != HT_OK)
		return status;
	}
	me->had_cr = (*b++ == CR);
    }
    if (me->start < b && (status = PUTBLOCK(me->start, b-me->start)) != HT_OK)
	return status;
    me->start = NULL;			      /* Whole buffer is written :-) */
    return HT_OK;
}
Example #2
0
/*	Converter from CRLF to \n
**	-------------------------
**	The input is assumed to be in local representation with lines
**	delimited by (CR,LF) pairs in the local representation.
**	The conversion to local representation is always done in HTSocket.c
**	The (CR,LF) sequence when found is changed to a '\n' character,
**	the internal C representation of a new line.
*/
PRIVATE int NetToText_put_block (HTStream * me, const char * s, int l)
{
    int status;
    if (!me->start)
	me->start = s;
    else {
	l -= (me->start - s);
	s = me->start;
    }
    while (l-- > 0) {
	if (me->had_cr && *s == LF) {
	    if (s > me->start+1) {
		if ((status = PUTBLOCK(me->start, s - me->start-1)) != HT_OK)
		    return status;
	    }
	    me->start = s+1;
	    if ((status = PUTC('\n')) != HT_OK)
		return status;
	}
	me->had_cr = (*s++ == CR);
    }
    if (me->start < s && (status = PUTBLOCK(me->start, s-me->start)) != HT_OK)
	return status;
    me->start = NULL;			      /* Whole buffer is written :-) */
    return HT_OK;
}
Example #3
0
/*
**	Searches for NNTP header line until buffer fills up or a CRLF or LF
**	is found
*/
PRIVATE int HTNewsStatus_put_block (HTStream * me, const char * b, int l)
{
    int status;
    HTHost_setConsumed(me->host, l);
    while (!me->semi_trans && l-- > 0) {
	if (me->EOLstate == EOL_FCR) {
	    if (*b == LF) {
		if (me->junk) me->junk = NO;
		me->EOLstate = EOL_BEGIN;
		if ((status = ScanResponse(me)) != HT_LOADED) return status;
	    }
	} else if (*b == CR) {
	    me->EOLstate = EOL_FCR;
	} else if (*b == LF) {
	    if (me->junk) me->junk = NO;
	    me->EOLstate = EOL_BEGIN;
	    if ((status = ScanResponse(me)) != HT_LOADED) return status;
	} else {
	    *(me->buffer+me->buflen++) = *b;
	    if (me->buflen >= MAX_NEWS_LINE) {
		HTTRACE(PROT_TRACE, "News Status. Line too long - chopped\n");
		me->junk = YES;
		if ((status = ScanResponse(me)) != HT_LOADED) return status;
	    }
	}
	b++;
    }	

    /*
    ** Now see if we have parts of the body to put down the stream pipe.
    ** At this point we are looking for CRLF.CRLF. We are guaranteed a stream
    */
    if (l > 0) {
	int rest = l;
	const char *ptr = b;
	while (rest-- > 0) {
	    if (*ptr == CR) {
		me->EOLstate = me->EOLstate==EOL_DOT ? EOL_SCR : EOL_FCR;
	    } else if (*ptr == '.') {
		me->EOLstate = me->EOLstate==EOL_FLF ? EOL_DOT : EOL_BEGIN;
	    } else if (*ptr == LF) {
		me->EOLstate = me->EOLstate>EOL_DOT ? EOL_SLF : EOL_FLF;
	    } else
		me->EOLstate = EOL_BEGIN;
	    ptr++;
	}
	if (me->EOLstate == EOL_SLF) {
	    int status = PUTBLOCK(b, l-5);
	    return status != HT_OK ? status : HT_LOADED;
	} else {
	    int status = PUTBLOCK(b, l);
	    return status;
	}
    }
    return HT_LOADED;
}
Example #4
0
PRIVATE int HTTPReply_put_block (HTStream * me, const char * b, int l)
{
    if (me->transparent)
        return b ? PUTBLOCK(b, l) : HT_OK;
    else {
        MakeReplyPipe(me, me->request);
        me->transparent = YES;
        return b ? PUTBLOCK(b, l) : HT_OK;
    }
}
Example #5
0
PRIVATE int HTTPResponse_put_block (HTStream * me, const char * b, int l)
{
    if (me->target) {
	if (me->transparent)
	    return PUTBLOCK(b, l);
	else {
	    HTTPMakeResponse(me, me->request);		  /* Generate header */
	    me->transparent = YES;
	    return b ? PUTBLOCK(b, l) : HT_OK;
	}
    }
    return HT_WOULD_BLOCK;
}
Example #6
0
NAMESPACE_END

void RC6Encryption::ProcessBlock(const byte *in, byte *out) const
{
	const RC6_WORD *sptr = sTable;
	RC6_WORD a, b, c, d, t, u;

	GETBLOCK(in, a, b, c, d);
	b += sptr[0];
	d += sptr[1];
	sptr += 2;

	for(unsigned i=0; i<r; i++)
	{
		t = ROTL(b*(2*b+1), 5);
		u = ROTL(d*(2*d+1), 5);
		a = ROTL(a^t,u) + sptr[0];
		c = ROTL(c^u,t) + sptr[1];
		t = a; a = b; b = c; c = d; d = t;
		sptr += 2;
	}

	a += sptr[0];
	c += sptr[1];

	PUTBLOCK(out, a, b, c, d);
}
Example #7
0
void RC6Decryption::ProcessBlock(const byte *in, byte *out) const
{
	const RC6_WORD *sptr = sTable+sTable.size;
	RC6_WORD a, b, c, d, t, u;

	GETBLOCK(in, a, b, c, d);

	sptr -= 2;
	c -= sptr[1];
	a -= sptr[0];

	for (unsigned i=0; i < r; i++)
	{
		sptr -= 2;
		t = a; a = d; d = c; c = b; b = t;
		u = ROTL(d*(2*d+1), 5);
		t = ROTL(b*(2*b+1), 5);
		c = ROTR(c-sptr[1], t) ^ u;
		a = ROTR(a-sptr[0], u) ^ t;
	}

	sptr -= 2;
	d -= sTable[1];
	b -= sTable[0];

	PUTBLOCK(out, a, b, c, d);
}
Example #8
0
/*	HTTPMakeResponse
**	----------------
**	Makes a HTTP/1.0-1.1 response header.
*/
PRIVATE int HTTPMakeResponse (HTStream * me, HTRequest * request)
{
    char crlf[3];
    HTRsHd response_mask = HTRequest_rsHd(request);
    *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0';

    if (response_mask & HT_S_LOCATION) {		/* @@@ */

    }
    if (response_mask & HT_S_PROXY_AUTH) {		/* @@@ */

    }
    if (response_mask & HT_S_PUBLIC) {			/* @@@ */

    }
    if (response_mask & HT_S_RETRY_AFTER) {		/* @@@ */

    }
    if (response_mask & HT_S_SERVER) {
	PUTS("Server: ");
	PUTS(HTLib_appName());
	PUTC('/');
	PUTS(HTLib_appVersion());
	PUTC(' ');
	PUTS(HTLib_name());
	PUTC('/');
	PUTS(HTLib_version());
	PUTBLOCK(crlf, 2);
    }
    if (response_mask & HT_S_WWW_AUTH) {		/* @@@ */

    }
    HTTRACE(PROT_TRACE, "HTTP........ Generating Response Headers\n");
    return HT_OK;
}
Example #9
0
PRIVATE int NewsPost_put_block (HTStream * me, const char* b, int l)
{
    if (!me->target) {
	return HT_WOULD_BLOCK;
    } else if (me->transparent)
	return b ? PUTBLOCK(b, l) : HT_OK;
    else {
	int status;
	NewsPost_start(me, me->request);
	if ((status = PUTBLOCK(HTChunk_data(me->buffer),
			       HTChunk_size(me->buffer))) == HT_OK) {
	    me->transparent = YES;
	    return b ? PUTBLOCK(b, l) : HT_OK;
	}
	return status;
    }
}
Example #10
0
PRIVATE int HTBufferWriter_write (HTOutputStream * me, const char * buf, int len)
{
    int status;
    while (1) {
	int available = me->data + me->allocated - me->read;

	/* If we have enough buffer space */
	if (len <= available) {
	    int size = 0;
	    memcpy(me->read, buf, len);
	    me->read += len;
        
	    /* If we have accumulated enough data then flush */
	    if ((size = me->read - me->data) > me->growby) {
		me->lastFlushTime = HTGetTimeInMillis();
		status = PUTBLOCK(me->data, size);
		if (status == HT_OK) {
		    me->read = me->data;
		} else {
		    return (status == HT_WOULD_BLOCK) ? HT_OK : HT_ERROR;
		}
	    }
	    return HT_OK;
	} else {

	    /* Fill the existing buffer (if not already) and flush */
	    if (available) {
		memcpy(me->read, buf, available);
		buf += available;
		len -= available;
		me->read += available;
	    }
	    me->lastFlushTime = HTGetTimeInMillis();
	    status = PUTBLOCK(me->data, me->allocated);
	    if (status == HT_OK) {
		me->read = me->data;
	    } else if (status == HT_WOULD_BLOCK) {
		HTBufferWriter_addBuffer(me, len);
		memcpy(me->read, buf, len);
		me->read += len;
		return HT_OK;
	    }
	}
    }
}
Example #11
0
/*	NewsPost_end
**	------------
**	End the posting by CRLF.CRLF
**	returns whatever PUT_BLOCK returns
*/
PRIVATE int NewsPost_end (HTStream * me)
{
    char buf[6];
    *buf = CR;
    *(buf+1) = LF;
    *(buf+2) = '.';
    *(buf+3) = CR;
    *(buf+4) = LF;
    *(buf+5) = '\0';
    return PUTBLOCK(buf, 5);
}
Example #12
0
PRIVATE int HTTPRequest_put_block (HTStream * me, const char * b, int l)
{
    if (!me->target) {
	return HT_WOULD_BLOCK;
    } else if (me->transparent)
	return b ? PUTBLOCK(b, l) : HT_OK;
    else {
	int status = HT_OK;
	if (me->version == HTTP_09) {
	    status = HTTP09Request(me, me->request);
	    if (status != HT_OK) return status;
	} else {
	    status = HTTPMakeRequest(me, me->request);
	    if (status != HT_OK) return status;
	    me->transparent = YES;
	    return b ? PUTBLOCK(b, l) : HT_OK;
	}
	return status;
    }
}
Example #13
0
/*
**  This function is only called from either FlushEvent or HTBufferWriter_lazyFlush
**  which means that only the host object or timeout can cause a flush
*/
PRIVATE int HTBufferWriter_flush (HTOutputStream * me)
{
    int status = HT_OK;
    if (me && me->read > me->data) {
	me->lastFlushTime = HTGetTimeInMillis();
        if ((status = PUTBLOCK(me->data, me->read - me->data))==HT_WOULD_BLOCK)
	    return HT_WOULD_BLOCK;
	me->read = me->data;
    }
    return status;
}
Example #14
0
/*
**	After flushing the buffer we go into transparent mode so that we still
**	can handle incoming data. If we already are in transparent mode then
**	don't do anything.
*/
PRIVATE int buf_flush (HTStream * me)
{
    if (me->state != HT_BS_TRANSPARENT) {
	HTBufItem * cur;
	if (me->tmp_buf) append_buf(me);
	while ((cur = me->head)) {
	    int status;
	    if ((status = PUTBLOCK(cur->buf, cur->len)) != HT_OK) {
		return status;
	    }
	    me->head = cur->next;
	    free_buf(cur);
	}

	/* If we are not a pipe then do no more buffering */
	if ((me->mode & HT_BM_PIPE)) me->state = HT_BS_TRANSPARENT;
    }
    return (*me->target->isa->flush)(me->target);
}
Example #15
0
/*
**	Searches for HTTP Request Line before going into transparent mode
*/
PRIVATE int HTTPReceive_put_block (HTStream * me, const char * b, int l)
{
    if (!me->transparent) {
        const char *p=b;
        while (l>0 && *p!=CR && *p!=LF) l--, p++;
        HTChunk_putb(me->buffer, b, p-b);
        if (*p==CR || *p==LF) {
            int status = ParseRequest(me);
            HTChunk_clear(me->buffer);
            if (status != HT_OK) return status;
            me->transparent = YES;
            b=p;
        }
    }
    if (l > 0) {
        int status = PUTBLOCK(b, l);
        if (status == HT_LOADED) me->transparent = NO;
        return status;
    }
    return HT_OK;
}
Example #16
0
PUBLIC int HTMuxChannel_sendControl (HTMuxChannel * muxch, HTMuxSessionId sid,
				     HTMuxHeader opcode, int value,
				     const void * param, int param_size)
{
    if (muxch && muxch->host) {
	HTOutputStream * me = HTChannel_output(HTHost_channel(muxch->host));
	HTMuxHeader header[2];
	switch (opcode) {
	case MUX_STRING:
	    if (param && param_size) {
		header[0] = HT_WORDSWAP(MUX_CONTROL | MUX_LONG_LENGTH | MUX_SET_LEN(value));
		header[1] = HT_WORDSWAP(param_size);
		PUTBLOCK((const char *) header, 8);
		PUTBLOCK((const char *) param, MUX_LONG_ALIGN(param_size));
	    }
	    break;
	case MUX_STACK:
	    if (param && param_size) {
		header[0] = HT_WORDSWAP(MUX_CONTROL | MUX_LONG_LENGTH | MUX_SET_LEN(value));
		header[1] = HT_WORDSWAP(param_size);
		PUTBLOCK((const char *) header, 8);
		PUTBLOCK((const char *) param, MUX_LONG_ALIGN(param_size));
	    }
	    break;
	case MUX_FRAGMENT:
	    header[0] = HT_WORDSWAP(MUX_CONTROL | MUX_SET_SID(sid) | MUX_SET_LEN(value));
	    PUTBLOCK((const char *) header, 4);
	    break;
	case MUX_CREDIT:
	    header[0] = HT_WORDSWAP(MUX_CONTROL | MUX_LONG_LENGTH | MUX_SET_SID(sid));
	    header[1] = HT_WORDSWAP(value);
	    PUTBLOCK((const char *) header, 8);
	    break;
	default:
	    HTTRACE(MUX_TRACE, "Mux Channel. UNKNOWN OPCODE %d\n" _ opcode);
	    return HT_ERROR;
	}

	/* Flush for now */
#if 1
	return (*me->isa->flush)(me);
#else
	return HT_OK;
#endif
    }
    return HT_ERROR;
}
Example #17
0
/*	HTTPMakeRequest
**	---------------
**	Makes a HTTP/1.0-1.1 request header.
*/
PRIVATE int HTTPMakeRequest (HTStream * me, HTRequest * request)
{
    HTMethod method = HTRequest_method(request);
    HTRqHd request_mask = HTRequest_rqHd(request);
    HTParentAnchor * anchor = HTRequest_anchor(request);
    char * etag = HTAnchor_etag(anchor);
    char crlf[3];
    char qstr[10];
    *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0';

    /* Generate the HTTP/1.x RequestLine */
    if (me->state == 0) {
	if (method != METHOD_INVALID) {
	    PUTS(HTMethod_name(method));
	    PUTC(' ');
	} else
	    PUTS("GET ");
	me->state++;
    }

    /*
    **  Generate the Request URI. If we are using full request URI then it's
    **  easy. Otherwise we must filter out the path part of the URI.
    **  In case it's a OPTIONS request then if there is no pathinfo then use
    **  a * instead. If we use a method different from GET or HEAD then use
    **  the content-location if available.
    */
    if (me->state == 1) {
	char * abs_location = NULL;
	char * addr = HTAnchor_physical(anchor);
	char * location;

        /* JK: If the application specified a content-location (which is
           stored in the request in default put-name!), we use it instead
           of the URL that's being saved to. This is like having a user
           defined Content-Location */
        location = HTRequest_defaultPutName (request);
        if (location)
	  {
	    if (HTURL_isAbsolute (location))
	      {
		char * relative;
		relative = HTRelative (location, location);
		abs_location = HTParse (relative + 2, addr, PARSE_ALL);
		HT_FREE (relative);
	      }
	    else
	      abs_location = HTParse (location, addr, PARSE_ALL);
	    addr = abs_location;
	  }

#if 0
	/*
	**  We don't use the content-location any more as it is superseeded
	**  by etags and the combination of the two might do more harm than
	**  good (The etag is not guaranteed to be unique over multiple URIs)
	*/

	/*
	**  If we are using a method different from HEAD and GET then use
	**  the Content-Location if available, else the Request-URI.
	*/
	if (!HTMethod_isSafe(method)) {
	    char * location = HTAnchor_location(anchor);
	    if (location) {
		if (HTURL_isAbsolute(location))
		    addr = location;
		else {
		    /*
		    **  We have a content-location but it is relative and
		    **  must expand it either to the content-base or to
		    **  the Request-URI itself.
		    */
		    char * base = HTAnchor_base(anchor);
		    abs_location = HTParse(location, base, PARSE_ALL);
		    addr = abs_location;
		}
	    }
	}
#endif

	/*
	**  If we are using a proxy or newer versions of HTTP then we can
	**  send the full URL. Otherwise we only send the path.
	*/
	if (HTRequest_fullURI(request))
	    StrAllocCopy(me->url, addr);
	else {
	    me->url = HTParse(addr, "", PARSE_PATH | PARSE_PUNCTUATION);
	    if (method == METHOD_OPTIONS) {
		/*
		** We don't preserve the final slash or lack of same through
		** out the code. This is mainly for optimization reasons
		** but it gives a problem OPTIONS. We can either send a "*"
		** or a "/" but not both. For now we send a "*".
		*/
		if (!strcmp(me->url, "/")) *me->url = '*';
	    }
	}
	HT_FREE(abs_location);
	me->state++;
    }

    /*
    **  Now send the URL that we have put together
    */
    if (me->state == 2) {
	int status = HT_OK;
	if ((status = PUTS(me->url)) != HT_OK) return status;
	me->state++;

#if 0
	fprintf(stderr, "Requesting '%s'\n", me->url);
#endif

    }
    PUTC(' ');

    /*
    **  Send out the version number. If we know it is a HTTP/1.0 server we
    **  are talking to then use HTTP/1.0, else use HTTP/1.1 as default version
    **  number
    */
    if (me->version == HTTP_10)
	PUTS(HTTP_VERSION_10);
    else
	PUTS(HTTP_VERSION);
    PUTBLOCK(crlf, 2);

    /* Request Headers */
    if (request_mask & HT_C_ACCEPT_TYPE) {
	HTFormat format = HTRequest_outputFormat(request);
	
	/*
	** If caller has specified a specific output format then use this.
	** Otherwise use all the registered converters to generate the 
	** accept header
	*/
	if (format == WWW_PRESENT) {
	    int list;
	    HTList *cur;
	    BOOL first=YES;
	    for (list=0; list<2; list++) {
		if ((!list && ((cur = HTFormat_conversion()) != NULL)) ||
		    (list && ((cur = HTRequest_conversion(request))!=NULL))) {
		    HTPresentation * pres;
		    while ((pres=(HTPresentation *) HTList_nextObject(cur))) {
			if (pres->rep_out==WWW_PRESENT && pres->quality<=1.0) {
			    if (first) {
				PUTS("Accept: ");
				first=NO;
			    } else
				PUTC(',');
			    PUTS(HTAtom_name(pres->rep));
			    if (pres->quality < 1.0 && pres->quality >= 0.0) {
				sprintf(qstr, ";q=%1.1f", pres->quality);
				PUTS(qstr);
			    }
			}
		    }
		}
	    }
	    if (!first) PUTBLOCK(crlf, 2);
	} else {

	    /*
	    **  If we have an explicit output format then only send
	    **  this one if not this is an internal libwww format
	    **	of type www/<star>
	    */
	    if (!HTMIMEMatch(WWW_INTERNAL, format)) {
		PUTS("Accept: ");
		PUTS(HTAtom_name(format));
		PUTBLOCK(crlf, 2);
	    }
	}	
    }
    if (request_mask & HT_C_ACCEPT_CHAR) {
	int list;
	HTList *cur;
	BOOL first=YES;
	for (list=0; list<2; list++) {
	    if ((!list && ((cur = HTFormat_charset()) != NULL)) ||
		(list && ((cur = HTRequest_charset(request)) != NULL))) {
		HTAcceptNode *pres;
		while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
		    if (first) {
			PUTS("Accept-Charset: ");
			first=NO;
		    } else
			PUTC(',');
		    PUTS(HTAtom_name(pres->atom));
		    if (pres->quality < 1.0 && pres->quality >= 0.0) {
			sprintf(qstr, ";q=%1.1f", pres->quality);
			PUTS(qstr);
		    }
		}
	    }
	}
	if (!first) PUTBLOCK(crlf, 2);
    }
    if (request_mask & HT_C_ACCEPT_ENC) {
	int list;
	HTList *cur;
	BOOL first=YES;
	for (list=0; list<2; list++) {
	    if ((!list && ((cur = HTFormat_contentCoding()) != NULL)) ||
		(list && ((cur = HTRequest_encoding(request)) != NULL))) {
		HTCoding * pres;
		while ((pres = (HTCoding *) HTList_nextObject(cur))) {
		    double quality = HTCoding_quality(pres);
		    if (first) {
			PUTS("Accept-Encoding: ");
			first = NO;
		    } else
			PUTC(',');
		    PUTS(HTCoding_name(pres));
		    if (quality < 1.0 && quality >= 0.0) {
			sprintf(qstr, ";q=%1.1f", quality);
			PUTS(qstr);
		    }
		}
	    }
	}
	if (!first) PUTBLOCK(crlf, 2);
    }
    if (request_mask & HT_C_ACCEPT_TE) {
	int list;
	HTList *cur;
	BOOL first=YES;
	for (list=0; list<2; list++) {
	    if ((!list && ((cur = HTFormat_transferCoding()) != NULL)) ||
		(list && ((cur = HTRequest_transfer(request)) != NULL))) {
		HTCoding * pres;
		while ((pres = (HTCoding *) HTList_nextObject(cur))) {
		    double quality = HTCoding_quality(pres);
		    const char * coding = HTCoding_name(pres);
		    if (first) {
			PUTS("TE: ");
			first = NO;
		    } else
			PUTC(',');

		    /* Special check for "chunked" which is translated to "trailers" */
		    if (!strcasecomp(coding, "chunked"))
			PUTS("trailers");
		    else
			PUTS(coding);
		    if (quality < 1.0 && quality >= 0.0) {
			sprintf(qstr, ";q=%1.1f", quality);
			PUTS(qstr);
		    }
		}
	    }
	}
	if (!first) PUTBLOCK(crlf, 2);
    }
    if (request_mask & HT_C_ACCEPT_LAN) {
	int list;
	HTList *cur;
	BOOL first=YES;
	for (list=0; list<2; list++) {
	    if ((!list && ((cur = HTFormat_language()) != NULL)) ||
		(list && ((cur = HTRequest_language(request)) != NULL))) {
		HTAcceptNode *pres;
		while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
		    if (first) {
			PUTS("Accept-Language: ");
			first=NO;
		    } else
			PUTC(',');
		    PUTS(HTAtom_name(pres->atom));
		    if (pres->quality < 1.0 && pres->quality >= 0.0) {
			sprintf(qstr, ";q=%1.1f", pres->quality);
			PUTS(qstr);
		    }
		}
	    }
	}
	if (!first) PUTBLOCK(crlf, 2);
    }
    if (request_mask & HT_C_AUTH) {
	HTAssocList * cur = HTRequest_credentials(request);
	if (cur) {				    /* Access authentication */
	    HTAssoc * pres;
	    while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
		PUTS(HTAssoc_name(pres));
		PUTS(": ");
		PUTS(HTAssoc_value(pres));
		PUTBLOCK(crlf, 2);
	    }
	}
    }
    if (request_mask & HT_C_EXPECT) {
	HTAssocList * cur = HTRequest_expect(request);
	if (cur) {
	    BOOL first=YES;
	    HTAssoc * pres;
	    while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
		char * value = HTAssoc_value(pres);
		if (first) {
		    PUTS("Expect: ");
		    first = NO;
		} else
		    PUTC(',');

		/* Output the name */
		PUTS(HTAssoc_name(pres));

		/* Only output the value if not empty string */
		if (*value) {
		    PUTS("=");
		    PUTS(value);
		}
	    }
	    PUTBLOCK(crlf, 2);
	}
    }
    if (request_mask & HT_C_FROM) {
	HTUserProfile * up = HTRequest_userProfile(request);
	const char * mailaddress = HTUserProfile_email(up);
	if (mailaddress) {
	    PUTS("From: ");
	    PUTS(mailaddress);
	    PUTBLOCK(crlf, 2);
	}
    }
    if (request_mask & HT_C_HOST) {
	char *orig = HTAnchor_address((HTAnchor *) anchor);
	char *host = HTParse(orig, "", PARSE_HOST);
	char hostace[256];
#if 0
	/* Keep the port number for HTTP/1.1 compliance */
	char *ptr = strchr(host, ':');		     /* Chop off port number */
	if (ptr) *ptr = '\0';
#endif
        PUTS("Host: ");
    /****** still have to check UTF8toACE with port number */
    if (!HTACEfromUTF8 (host, hostace, 255)) {
	    PUTS(hostace);
	}
	else {
	    PUTS(host); /* this may be dangerous, but helps server side debugging */
        HTTRACE(PROT_TRACE, "HTTP........ Error: Cannot convert to ACE: `%s\'\n" _ host);
	}
	PUTBLOCK(crlf, 2);
	HT_FREE(orig);
	HT_FREE(host);
    }

    /*
    **  In the "If-*" series of headers, the ones related to etags have higher
    **  priority than the date relates ones. That is, if we have a etag then
    **  use that, otherwise use the date. First we check for range, match, and
    **  unmodified-since.
    */
    if (request_mask & HT_C_IF_RANGE && etag) {
	PUTS("If-Range: \"");
	PUTS(etag);
	PUTC('"');
	PUTBLOCK(crlf, 2);
	HTTRACE(PROT_TRACE, "HTTP........ If-Range using etag `%s\'\n" _ etag);
    } else if (request_mask & HT_C_IF_MATCH_ANY) {
	PUTS("If-Match: *");
	PUTBLOCK(crlf, 2);
	HTTRACE(PROT_TRACE, "HTTP........ If-Match using `*\'\n");
    } else if (request_mask & HT_C_IF_MATCH && etag) {
	PUTS("If-Match: \"");
	PUTS(etag);
	PUTC('"');
	PUTBLOCK(crlf, 2);
	HTTRACE(PROT_TRACE, "HTTP........ If-Match using etag `%s\'\n" _ etag);
    } else if (request_mask & HT_C_IF_UNMOD_SINCE) {
	time_t lm = HTAnchor_lastModified(anchor);
	if (lm > 0) {
	    PUTS("If-Unmodified-Since: ");
	    PUTS(HTDateTimeStr(&lm, NO));
	    PUTBLOCK(crlf, 2);
	    HTTRACE(PROT_TRACE, "HTTP........ If-Unmodified-Since `%s\'\n" _ HTDateTimeStr(&lm, NO));
	}
    }

    /*
    **  If-None-Match and If-Modified-Since are equivalent except that the
    **  first uses etags and the second uses dates. Etags have precedence over
    **  dates.
    */
    if (request_mask & HT_C_IF_NONE_MATCH_ANY) {
	PUTS("If-None-Match: *");
	PUTBLOCK(crlf, 2);
	HTTRACE(PROT_TRACE, "HTTP........ If-None-Match using `*\'\n");
    } else if (request_mask & HT_C_IF_NONE_MATCH && etag) {
	PUTS("If-None-Match: \"");
	PUTS(etag);
	PUTC('"');
	PUTBLOCK(crlf, 2);
	HTTRACE(PROT_TRACE, "HTTP........ If-None-Match `%s\'\n" _ etag);
    }
    if (request_mask & HT_C_IMS) {
	time_t lm = HTAnchor_lastModified(anchor);
	if (lm > 0) {
	    PUTS("If-Modified-Since: ");
	    PUTS(HTDateTimeStr(&lm, NO));
	    PUTBLOCK(crlf, 2);
	    HTTRACE(PROT_TRACE, "HTTP........ If-Modified-Since `%s\'\n" _ HTDateTimeStr(&lm, NO));
	}
    }

    /*
    **  Max forwards is mainly for TRACE where we want to be able to stop the
    **  TRACE at a specific location un the message path.
    */
    if (request_mask & HT_C_MAX_FORWARDS) {
	int hops = HTRequest_maxForwards(request);
	if (hops >= 0) {
	    sprintf(qstr, "%d", hops);
	    PUTS("Max-Forwards: ");
	    PUTS(qstr);
	    PUTBLOCK(crlf, 2);
	}
    }

    /*
    **  Range requests. For now, we only take the first entry registered for
    **  this request. This means that you can only send a single "unit" and
    **  then a set of range within this unit. This is in accordance with 
    **  HTTP/1.1. Multiple units will go on multiple lines.
    */
    if (request_mask & HT_C_RANGE) {
	HTAssocList * cur = HTRequest_range(request);
	if (cur) {				    	   /* Range requests */
	    HTAssoc * pres;
	    while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
		PUTS("Range: ");
		PUTS(HTAssoc_name(pres));			     /* Unit */
		PUTS("=");
		PUTS(HTAssoc_value(pres));	  /* Ranges within this unit */
		PUTBLOCK(crlf, 2);
	    }
	}
    }
    if (request_mask & HT_C_REFERER) {
	HTParentAnchor * parent_anchor = HTRequest_parent(request);
	if (parent_anchor) {
	    char * act = HTAnchor_address((HTAnchor *) anchor);
	    char * parent = HTAnchor_address((HTAnchor *) parent_anchor);
#if 1
	    char * relative = HTRelative(parent, act);
#else
	    char * relative = HTParse(parent, act,
				      PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
#endif
	    if (relative && *relative) {
		PUTS("Referer: ");
		PUTS(relative);
		PUTBLOCK(crlf, 2);
	    }
	    HT_FREE(act);
	    HT_FREE(parent);
	    HT_FREE(relative);
	}
    }
    if (request_mask & HT_C_USER_AGENT) {
	PUTS("User-Agent: ");
	PUTS(HTLib_appName());
	PUTC('/');
	PUTS(HTLib_appVersion());
	PUTC(' ');
	PUTS(HTLib_name());
	PUTC('/');
	PUTS(HTLib_version());
	PUTBLOCK(crlf, 2);
    }
    HTTRACE(PROT_TRACE, "HTTP........ Generating HTTP/1.x Request Headers\n");
    return HT_OK;
}
Example #18
0
PRIVATE int HTBoundary_put_block (HTStream * me, const char * b, int l)
{
    const char *start = b;
    const char *end = b;
    while (l-- > 0) {
	if (me->state == EOL_FCR) {
	    me->state = (*b == LF) ? EOL_FLF : EOL_BEGIN;
	} else if (me->state == EOL_FLF) {
	    if (me->dash == 2) {
		while (l>0 && *me->bpos && *me->bpos==*b) l--, me->bpos++, b++;
		if (!*me->bpos) {
		    HTTRACE(STREAM_TRACE, "Boundary.... `%s\' found\n" _ me->boundary);
		    me->bpos = me->boundary;
		    me->body = YES;
		    me->state = EOL_DOT;
		} else if (l>0) {
		    me->dash = 0;
		    me->bpos = me->boundary;
		    me->state = EOL_BEGIN;
		}
	    }
	    if (*b == '-') {
		me->dash++;
	    } else if (*b != CR && *b != LF) {
		me->dash = 0;
		me->state = EOL_BEGIN;
	    }
	} else if (me->state == EOL_SLF) {	    /* Look for closing '--' */
	    if (me->dash == 4) {
		if (end > start) {
		    int status = PUTBLOCK(start, end-start);
		    if (status != HT_OK) return status;
		}
		HTTRACE(STREAM_TRACE, "Boundary.... Ending\n");
		start = b;
		me->dash = 0;
		me->state = EOL_BEGIN;
	    }
	    if (*b == '-') {
		me->dash++;
	    } else if (*b != CR && *b != LF) {
		me->dash = 0;
		me->state = EOL_BEGIN;
	    }
	    me->body = NO;
	} else if (me->state == EOL_DOT) {
	    int status;
	    if (me->body) {
		if (me->target) FREE_TARGET;
		me->target = HTStreamStack(WWW_MIME,me->format,
					   HTMerge(me->orig_target, 2),
					   me->request, YES);
		if (end > start) {
		    if ((status = PUTBLOCK(start, end-start)) != HT_OK)
			return status;
		}
	    } else {
		if (me->debug)
		    if ((status = PUTDEBUG(start, end-start)) != HT_OK)
			return status;
	    }
	    start = b;
	    if (*b == '-') me->dash++;
	    me->state = EOL_SLF;
	} else if (*b == CR) {
	    me->state = EOL_FCR;
	    end = b;
	} else if (*b == LF) {
	    if (me->state != EOL_FCR) end = b;
	    me->state = EOL_FLF;
	}
	b++;
    }
    return (start<b && me->body) ? PUTBLOCK(start, b-start) : HT_OK;
}
Example #19
0
PRIVATE int buf_put_block (HTStream * me, const char * b, int l)
{
    /*
    **  If we are in pause mode then don't write anything but return PAUSE.
    **  The upper stream should then respect it and don't write any more data.
    */
    if (me->state == HT_BS_PAUSE) return HT_PAUSE;

    /*
    **  Start handling the incoming data. If we are still buffering then add
    **  it to the buffer. Otherwise just pump it through. Note that we still
    **  count the length - even if we have given up buffering!
    */
    me->conlen += l;
    if (me->state != HT_BS_TRANSPARENT) {

	/*
	**  If there is still room in the existing chunk then fill it up.
	**  Otherwise create a new chunk and add it to the linked list of
	**  chunks. If the buffer fills up then either return HT_PAUSE or
	**  flush it and go transparent.
	*/
	if (me->tmp_buf && me->tmp_max-me->tmp_ind >= l) {     /* Still room */
	    memcpy(me->tmp_buf + me->tmp_ind, b, l);
	    me->tmp_ind += l;
	    return HT_OK;
	} else {

	    /*
	    **  Add the temporary buffer (if any) to the list of chunks
	    */
	    if (me->tmp_buf) append_buf(me);

	    /*
	    **  Find the right size of the next chunk. We increase the size
	    **  exponentially until we reach HT_MAX_BLOCK in order to minimize
	    **  the number of mallocs.
	    */
	    if (me->cur_size < HT_MAX_BLOCK) {
		int newsize = me->cur_size ? me->cur_size : HT_MIN_BLOCK;
		while (l > newsize && newsize < HT_MAX_BLOCK) newsize *= 2;
		me->cur_size = newsize;
	    }

	    if (alloc_new(me, me->cur_size)) {
		/* Buffer could accept the new data */
		memcpy(me->tmp_buf, b, l);
		me->tmp_ind = l;
	    } else if (me->mode & HT_BM_DELAY) {
		/* Buffer ran full and we pause */
		me->state = HT_BS_PAUSE;
		HTTRACE(STREAM_TRACE, "Buffer....... Paused\n");
		return HT_PAUSE;
	    } else {
		/* Buffer ran full and we flush and go transparent */
		int status = buf_flush(me);
		if (status != HT_OK) return status;
	    }
	}
    }

    /*
    **  If we couldn't buffer the data then check whether we should give up
    **  or pause the stream. If we are in transparent mode then put the rest
    **  of the data down the pipe.
    */
    if (me->state == HT_BS_TRANSPARENT) return PUTBLOCK(b, l);
    return HT_OK;
}