Annotation of libwww/Library/src/HTTChunk.c, revision 2.1
2.1 ! frystyk 1: /*
! 2: ** CHUNKED TRANSFER CODING
! 3: **
! 4: ** (c) COPYRIGHT MIT 1995.
! 5: ** Please first read the full copyright statement in the file COPYRIGH.
! 6: ** @(#) $Id: Date Author State $
! 7: **
! 8: ** This stream parses a chunked transfer encoding using multiple chunks.
! 9: **
! 10: ** Authors
! 11: ** HF Henrik Frystyk <frystyk@w3.org>
! 12: **
! 13: ** History:
! 14: ** Apr 96 Written from scratch
! 15: **
! 16: */
! 17:
! 18: /* Library include files */
! 19: #include "sysdep.h"
! 20: #include "WWWUtil.h"
! 21: #include "WWWCore.h"
! 22: #include "HTTChunk.h" /* Implemented here */
! 23:
! 24: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
! 25: #define PUTDEBUG(b, l) (*me->debug->isa->put_block)(me->debug, b, l)
! 26: #define FREE_TARGET (*me->target->isa->_free)(me->target)
! 27:
! 28: struct _HTStream {
! 29: const HTStreamClass * isa;
! 30: HTEncoding coding;
! 31: HTStream * target;
! 32: HTRequest * request;
! 33: long left; /* Remaining bytes in this chunk */
! 34: long total; /* Full length */
! 35: HTEOLState state;
! 36: HTChunk * buf;
! 37: };
! 38:
! 39: /* ------------------------------------------------------------------------- */
! 40:
! 41: /*
! 42: **
! 43: */
! 44: PRIVATE BOOL HTTChunk_header (HTStream * me)
! 45: {
! 46: me->left = strtol(HTChunk_data(me->buf), (char **) NULL, 16); /* hex! */
! 47: if (STREAM_TRACE) HTTrace("Chunked..... chunk size: %X\n", me->left);
! 48: if (me->left) {
! 49: me->total += me->left;
! 50:
! 51: /* Look for arguments */
! 52:
! 53: HTChunk_clear(me->buf);
! 54: } else { /* Last chunk */
! 55: HTRequest * request = me->request;
! 56: me->target = HTStreamStack(WWW_MIME_FOOT, WWW_SOURCE,
! 57: me->target, request, NO);
! 58: }
! 59: return YES;
! 60: }
! 61:
! 62: PRIVATE int HTTChunk_put_block (HTStream * me, const char * b, int l)
! 63: {
! 64: while (l > 0) {
! 65: if (me->left <= 0) {
! 66: while (l > 0) {
! 67: if (me->state == EOL_FLF) {
! 68: HTTChunk_header(me);
! 69: me->state = EOL_DOT;
! 70: break;
! 71: } else if (*b == CR) {
! 72: me->state = me->state == EOL_DOT ? EOL_SCR : EOL_FCR;
! 73: } else if (*b == LF) {
! 74: me->state = me->state == EOL_SCR ? EOL_BEGIN : EOL_FLF;
! 75: } else
! 76: HTChunk_putc(me->buf, *b);
! 77: b++, l--;
! 78: }
! 79: }
! 80: if (l > 0) {
! 81: int bytes = me->left ? HTMIN(l, me->left) : l;
! 82: int status = (*me->target->isa->put_block)(me->target, b, bytes);
! 83: if (status == HT_OK) {
! 84: me->left -= bytes;
! 85: l -= bytes, b+= bytes;
! 86: } else
! 87: return status;
! 88: }
! 89: }
! 90: return HT_OK;
! 91: }
! 92:
! 93: PRIVATE int HTTChunk_put_string (HTStream * me, const char * s)
! 94: {
! 95: return HTTChunk_put_block(me, s, (int) strlen(s));
! 96: }
! 97:
! 98: PRIVATE int HTTChunk_put_character (HTStream * me, char c)
! 99: {
! 100: return HTTChunk_put_block(me, &c, 1);
! 101: }
! 102:
! 103: PRIVATE int HTTChunk_flush (HTStream * me)
! 104: {
! 105: return (*me->target->isa->flush)(me->target);
! 106: }
! 107:
! 108: PRIVATE int HTTChunk_free (HTStream * me)
! 109: {
! 110: int status = HT_OK;
! 111: HTParentAnchor * anchor = HTRequest_anchor(me->request);
! 112: HTAnchor_setLength(anchor, me->total);
! 113: if (me->target) {
! 114: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
! 115: return HT_WOULD_BLOCK;
! 116: }
! 117: if (PROT_TRACE) HTTrace("Chunked..... FREEING....\n");
! 118: HTChunk_delete(me->buf);
! 119: HT_FREE(me);
! 120: return status;
! 121: }
! 122:
! 123: PRIVATE int HTTChunk_abort (HTStream * me, HTList * e)
! 124: {
! 125: int status = HT_ERROR;
! 126: if (me->target) status = (*me->target->isa->abort)(me->target, e);
! 127: if (PROT_TRACE) HTTrace("Chunked..... ABORTING...\n");
! 128: HT_FREE(me);
! 129: return status;
! 130: }
! 131:
! 132: PRIVATE const HTStreamClass HTChunkedClass =
! 133: {
! 134: "HTChunked",
! 135: HTTChunk_flush,
! 136: HTTChunk_free,
! 137: HTTChunk_abort,
! 138: HTTChunk_put_character,
! 139: HTTChunk_put_string,
! 140: HTTChunk_put_block
! 141: };
! 142:
! 143: PUBLIC HTStream * HTChunkedDecoder (HTRequest * request,
! 144: void * param,
! 145: HTEncoding coding,
! 146: HTStream * target)
! 147: {
! 148: HTStream * me;
! 149: HTParentAnchor * anchor = HTRequest_anchor(request);
! 150: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
! 151: HT_OUTOFMEM("HTTChunk");
! 152: me->isa = &HTChunkedClass;
! 153: me->coding = coding;
! 154: me->target = target;
! 155: me->request = request;
! 156: me->state = EOL_BEGIN;
! 157: me->buf = HTChunk_new(64);
! 158:
! 159: /* Adjust information in anchor */
! 160: HTAnchor_setTransfer(anchor, NULL);
! 161:
! 162: if (STREAM_TRACE) HTTrace("Chunked..... Decoder stream created\n");
! 163: return me;
! 164: }
Webmaster