version 2.10, 1998/05/04 19:36:19
|
version 2.11, 1998/11/30 03:52:36
|
Line 1
|
Line 1
|
/* HTBound.c |
/* HTBound.c
|
** MIME MULTIPART PARSER STREAM |
** MIME MULTIPART PARSER STREAM
|
** |
**
|
** (c) COPYRIGHT MIT 1995. |
** (c) COPYRIGHT MIT 1995.
|
** Please first read the full copyright statement in the file COPYRIGH. |
** Please first read the full copyright statement in the file COPYRIGH.
|
** @(#) $Id$ |
** @(#) $Id$
|
** |
**
|
** This stream parses a MIME multipart stream and builds a set of new |
** This stream parses a MIME multipart stream and builds a set of new
|
** streams via the stream stack each time we encounter a boundary start. |
** streams via the stream stack each time we encounter a boundary start.
|
** We get the boundary from the normal MIME parser via the Request object |
** We get the boundary from the normal MIME parser via the Request object
|
** |
**
|
** Authors |
** Authors
|
** HF Henrik Frystyk <frystyk@w3.org> |
** HF Henrik Frystyk <frystyk@w3.org>
|
** |
**
|
** History: |
** History:
|
** Nov 95 Written from scratch |
** Nov 95 Written from scratch
|
** |
**
|
*/ |
*/
|
|
|
/* Library include files */ |
/* Library include files */
|
#include "wwwsys.h" |
#include "wwwsys.h"
|
#include "WWWUtil.h" |
#include "WWWUtil.h"
|
#include "WWWCore.h" |
#include "WWWCore.h"
|
#include "HTReqMan.h" |
#include "WWWStream.h"
|
#include "HTBound.h" /* Implemented here */ |
#include "HTReqMan.h"
|
|
#include "HTBound.h" /* Implemented here */
|
#define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l) |
|
#define PUTDEBUG(b, l) (*me->debug->isa->put_block)(me->debug, b, l) |
#define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
|
#define FREE_TARGET (*me->target->isa->_free)(me->target) |
#define PUTDEBUG(b, l) (*me->debug->isa->put_block)(me->debug, b, l)
|
|
#define FREE_TARGET (*me->target->isa->_free)(me->target)
|
struct _HTStream { |
|
const HTStreamClass * isa; |
struct _HTStream {
|
HTStream * target; |
const HTStreamClass * isa;
|
HTStream * orig_target; |
HTStream * target;
|
HTFormat format; |
HTStream * orig_target;
|
HTStream * debug; /* For preamble and epilog */ |
HTFormat format;
|
HTRequest * request; |
HTStream * debug; /* For preamble and epilog */
|
BOOL body; /* Body or preamble|epilog */ |
HTRequest * request;
|
HTEOLState state; |
BOOL body; /* Body or preamble|epilog */
|
int dash; /* Number of dashes */ |
HTEOLState state;
|
char * boundary; |
int dash; /* Number of dashes */
|
char * bpos; |
char * boundary;
|
}; |
char * bpos;
|
|
};
|
/* ------------------------------------------------------------------------- */ |
|
|
/* ------------------------------------------------------------------------- */
|
/* |
|
** Searches for FTP line until buffer fills up or a CRLF or LF is found |
/*
|
*/ |
** Searches for FTP line until buffer fills up or a CRLF or LF is found
|
PRIVATE int HTBoundary_put_block (HTStream * me, const char * b, int l) |
*/
|
{ |
PRIVATE int HTBoundary_put_block (HTStream * me, const char * b, int l)
|
const char *start = b; |
{
|
const char *end = b; |
const char *start = b;
|
while (l-- > 0) { |
const char *end = b;
|
if (me->state == EOL_FCR) { |
while (l-- > 0) {
|
me->state = (*b == LF) ? EOL_FLF : EOL_BEGIN; |
if (me->state == EOL_FCR) {
|
} else if (me->state == EOL_FLF) { |
me->state = (*b == LF) ? EOL_FLF : EOL_BEGIN;
|
if (me->dash == 2) { |
} else if (me->state == EOL_FLF) {
|
while (l>0 && *me->bpos && *me->bpos==*b) l--, me->bpos++, b++; |
if (me->dash == 2) {
|
if (!*me->bpos) { |
while (l>0 && *me->bpos && *me->bpos==*b) l--, me->bpos++, b++;
|
if (STREAM_TRACE && !*me->bpos) |
if (!*me->bpos) {
|
HTTrace("Boundary.... `%s\' found\n", me->boundary); |
if (STREAM_TRACE && !*me->bpos)
|
me->bpos = me->boundary; |
HTTrace("Boundary.... `%s\' found\n", me->boundary);
|
me->body = YES; |
me->bpos = me->boundary;
|
me->state = EOL_DOT; |
me->body = YES;
|
} else if (l>0) { |
me->state = EOL_DOT;
|
me->dash = 0; |
} else if (l>0) {
|
me->bpos = me->boundary; |
me->dash = 0;
|
me->state = EOL_BEGIN; |
me->bpos = me->boundary;
|
} |
me->state = EOL_BEGIN;
|
} |
}
|
if (*b == '-') { |
}
|
me->dash++; |
if (*b == '-') {
|
} else if (*b != LF) { |
me->dash++;
|
me->dash = 0; |
} else if (*b != CR && *b != LF) {
|
me->state = EOL_BEGIN; |
me->dash = 0;
|
} |
me->state = EOL_BEGIN;
|
} else if (me->state == EOL_SLF) { /* Look for closing '--' */ |
}
|
if (me->dash == 4) { |
} else if (me->state == EOL_SLF) { /* Look for closing '--' */
|
if (end > start) { |
if (me->dash == 4) {
|
int status = PUTBLOCK(start, end-start); |
if (end > start) {
|
if (status != HT_OK) return status; |
int status = PUTBLOCK(start, end-start);
|
} |
if (status != HT_OK) return status;
|
if (STREAM_TRACE) HTTrace("Boundary.... Ending\n"); |
}
|
start = b; |
if (STREAM_TRACE) HTTrace("Boundary.... Ending\n");
|
me->dash = 0; |
start = b;
|
me->state = EOL_BEGIN; |
me->dash = 0;
|
} |
me->state = EOL_BEGIN;
|
if (*b == '-') { |
}
|
me->dash++; |
if (*b == '-') {
|
} else if (*b != LF) { |
me->dash++;
|
me->dash = 0; |
} else if (*b != CR && *b != LF) {
|
me->state = EOL_BEGIN; |
me->dash = 0;
|
} |
me->state = EOL_BEGIN;
|
me->body = NO; |
}
|
} else if (me->state == EOL_DOT) { |
me->body = NO;
|
int status; |
} else if (me->state == EOL_DOT) {
|
if (me->body) { |
int status;
|
if (me->target) FREE_TARGET; |
if (me->body) {
|
me->target = HTStreamStack(WWW_MIME,me->format,me->orig_target, |
if (me->target) FREE_TARGET;
|
me->request, YES); |
me->target = HTStreamStack(WWW_MIME,me->format,
|
if (end > start) { |
HTMerge(me->orig_target, 2),
|
if ((status = PUTBLOCK(start, end-start)) != HT_OK) |
me->request, YES);
|
return status; |
if (end > start) {
|
} |
if ((status = PUTBLOCK(start, end-start)) != HT_OK)
|
} else { |
return status;
|
if (me->debug) |
}
|
if ((status = PUTDEBUG(start, end-start)) != HT_OK) |
} else {
|
return status; |
if (me->debug)
|
} |
if ((status = PUTDEBUG(start, end-start)) != HT_OK)
|
start = b; |
return status;
|
if (*b == '-') me->dash++; |
}
|
me->state = EOL_SLF; |
start = b;
|
} else if (*b == CR) { |
if (*b == '-') me->dash++;
|
me->state = EOL_FCR; |
me->state = EOL_SLF;
|
end = b; |
} else if (*b == CR) {
|
} else if (*b == LF) { |
me->state = EOL_FCR;
|
if (me->state != EOL_FCR) end = b; |
end = b;
|
me->state = EOL_FLF; |
} else if (*b == LF) {
|
} |
if (me->state != EOL_FCR) end = b;
|
b++; |
me->state = EOL_FLF;
|
} |
}
|
return (start<b && me->body) ? PUTBLOCK(start, b-start) : HT_OK; |
b++;
|
} |
}
|
|
return (start<b && me->body) ? PUTBLOCK(start, b-start) : HT_OK;
|
PRIVATE int HTBoundary_put_string (HTStream * me, const char * s) |
}
|
{ |
|
return HTBoundary_put_block(me, s, (int) strlen(s)); |
PRIVATE int HTBoundary_put_string (HTStream * me, const char * s)
|
} |
{
|
|
return HTBoundary_put_block(me, s, (int) strlen(s));
|
PRIVATE int HTBoundary_put_character (HTStream * me, char c) |
}
|
{ |
|
return HTBoundary_put_block(me, &c, 1); |
PRIVATE int HTBoundary_put_character (HTStream * me, char c)
|
} |
{
|
|
return HTBoundary_put_block(me, &c, 1);
|
PRIVATE int HTBoundary_flush (HTStream * me) |
}
|
{ |
|
return (*me->target->isa->flush)(me->target); |
PRIVATE int HTBoundary_flush (HTStream * me)
|
} |
{
|
|
return (*me->target->isa->flush)(me->target);
|
PRIVATE int HTBoundary_free (HTStream * me) |
}
|
{ |
|
int status = HT_OK; |
PRIVATE int HTBoundary_free (HTStream * me)
|
if (me->target) { |
{
|
if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK) |
int status = HT_OK;
|
return HT_WOULD_BLOCK; |
if (me->target) {
|
} |
if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
|
if (PROT_TRACE) HTTrace("Boundary.... FREEING....\n"); |
return HT_WOULD_BLOCK;
|
HT_FREE(me->boundary); |
}
|
HT_FREE(me); |
if (PROT_TRACE) HTTrace("Boundary.... FREEING....\n");
|
return status; |
HT_FREE(me->boundary);
|
} |
HT_FREE(me);
|
|
return status;
|
PRIVATE int HTBoundary_abort (HTStream * me, HTList * e) |
}
|
{ |
|
int status = HT_ERROR; |
PRIVATE int HTBoundary_abort (HTStream * me, HTList * e)
|
if (me->target) status = (*me->target->isa->abort)(me->target, e); |
{
|
if (PROT_TRACE) HTTrace("Boundary.... ABORTING...\n"); |
int status = HT_ERROR;
|
HT_FREE(me->boundary); |
if (me->target) status = (*me->target->isa->abort)(me->target, e);
|
HT_FREE(me); |
if (PROT_TRACE) HTTrace("Boundary.... ABORTING...\n");
|
return status; |
HT_FREE(me->boundary);
|
} |
HT_FREE(me);
|
|
return status;
|
PRIVATE const HTStreamClass HTBoundaryClass = |
}
|
{ |
|
"HTBoundary", |
PRIVATE const HTStreamClass HTBoundaryClass =
|
HTBoundary_flush, |
{
|
HTBoundary_free, |
"HTBoundary",
|
HTBoundary_abort, |
HTBoundary_flush,
|
HTBoundary_put_character, |
HTBoundary_free,
|
HTBoundary_put_string, |
HTBoundary_abort,
|
HTBoundary_put_block |
HTBoundary_put_character,
|
}; |
HTBoundary_put_string,
|
|
HTBoundary_put_block
|
PUBLIC HTStream * HTBoundary (HTRequest * request, |
};
|
void * param, |
|
HTFormat input_format, |
PUBLIC HTStream * HTBoundary (HTRequest * request,
|
HTFormat output_format, |
void * param,
|
HTStream * output_stream) |
HTFormat input_format,
|
{ |
HTFormat output_format,
|
HTParentAnchor * anchor = HTRequest_anchor(request); |
HTStream * output_stream)
|
HTAssocList * type_param = HTAnchor_formatParam(anchor); |
{
|
char * boundary = HTAssocList_findObject(type_param, "boundary"); |
HTResponse * response = HTRequest_response(request);
|
if (boundary) { |
HTParentAnchor * anchor = HTRequest_anchor(request);
|
HTStream * me; |
HTAssocList * type_param = response ?
|
if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL) |
HTResponse_formatParam(response) :
|
HT_OUTOFMEM("HTBoundary"); |
HTAnchor_formatParam(anchor);
|
me->isa = &HTBoundaryClass; |
char * boundary = HTAssocList_findObject(type_param, "boundary");
|
me->request = request; |
if (boundary) {
|
me->format = output_format; |
HTStream * me;
|
me->orig_target = output_stream; |
if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
|
me->debug = HTRequest_debugStream(request); |
HT_OUTOFMEM("HTBoundary");
|
me->state = EOL_FLF; |
me->isa = &HTBoundaryClass;
|
StrAllocCopy(me->boundary, boundary); /* Local copy */ |
me->request = request;
|
me->bpos = me->boundary; |
me->format = output_format;
|
if (STREAM_TRACE) |
me->orig_target = output_stream;
|
HTTrace("Boundary.... Stream created with boundary '%s\'\n", me->boundary); |
me->debug = HTRequest_debugStream(request);
|
return me; |
me->state = EOL_FLF;
|
} else { |
StrAllocCopy(me->boundary, boundary); /* Local copy */
|
if (STREAM_TRACE) HTTrace("Boundary.... UNKNOWN boundary!\n"); |
me->bpos = me->boundary;
|
return HTErrorStream(); |
if (STREAM_TRACE)
|
} |
HTTrace("Boundary.... Stream created with boundary '%s\'\n", me->boundary);
|
} |
return me;
|
|
} else {
|
|
if (STREAM_TRACE) HTTrace("Boundary.... UNKNOWN boundary!\n");
|
|
return HTErrorStream();
|
|
}
|
|
}
|