home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
- /* Please leave outside of ifdef for windows precompiled headers */
- #include "mkutils.h"
-
- #ifdef MOZILLA_CLIENT
-
- #include "cvchunk.h" /* prototype */
- #include "mkstream.h"
- #include "mkgeturl.h"
- #include "xp.h"
-
- extern int MK_OUT_OF_MEMORY;
-
- typedef enum {
- FIND_CHUNK_SIZE,
- READ_CHUNK,
- STRIP_CRLF,
- PARSE_FOOTER
- } States;
-
- typedef struct _DataObject {
- NET_StreamClass *next_stream;
- char *in_buf;
- uint32 in_buf_size;
- uint32 chunk_size;
- uint32 amount_of_chunk_parsed;
- States cur_state;
- FO_Present_Types format_out;
- MWContext *context;
- URL_Struct *URL_s;
- } DataObject;
-
-
- /* unchunk the message and return MK_MULTIPART_MESSAGE_COMPLETED
- * when end detected
- */
- PRIVATE int net_ChunkedWrite (NET_StreamClass *stream, char* s, int32 l)
- {
- DataObject *obj=stream->data_object;
- BlockAllocCat(obj->in_buf, obj->in_buf_size, s, l);
- if(!obj->in_buf)
- return MK_OUT_OF_MEMORY;
- obj->in_buf_size += l;
-
- while(obj->in_buf_size > 0)
- {
- if(obj->cur_state == FIND_CHUNK_SIZE)
- {
- char *line_feed;
- char *semicolon;
- char *end;
-
- /* we don't have a current chunk size
- * look for a new chunk size
- *
- * make sure the line has a CRLF
- */
- if((line_feed = XP_STRNCHR(obj->in_buf, LF, obj->in_buf_size)) == NULL)
- {
- return 1; /* need more data */
- }
-
- *line_feed = '\0';
-
- semicolon = XP_STRNCHR(obj->in_buf, ';', line_feed-obj->in_buf);
-
- if(semicolon)
- *semicolon = '\0';
-
- end = semicolon ? semicolon : line_feed;
-
- /* read the first integer and ignore any thing
- * else on the line. Extensions are allowed
- */
- obj->chunk_size = strtol(obj->in_buf, &end, 16);
-
- /* strip everything up to the line feed */
- obj->in_buf_size -= (line_feed+1) - obj->in_buf;
- if(obj->in_buf_size)
- XP_MEMMOVE(obj->in_buf,
- line_feed+1,
- obj->in_buf_size);
-
- if(obj->chunk_size == 0)
- {
- /* the stream should be done now */
- obj->cur_state = PARSE_FOOTER;
- }
- else
- {
- obj->cur_state = READ_CHUNK;
- }
-
- }
- else if(obj->cur_state == READ_CHUNK)
- {
- uint32 data_size;
- int32 status;
-
- /* take as much data as we have and push it up the stream
- */
-
- data_size = MIN(obj->in_buf_size, obj->chunk_size-obj->amount_of_chunk_parsed);
-
- status = (obj->next_stream->put_block)(obj->next_stream,
- obj->in_buf,
- data_size);
- if(status < 0)
- return status;
-
- /* remove the part that has been pushed */
- obj->in_buf_size -= data_size;
- if(obj->in_buf_size)
- XP_MEMMOVE(obj->in_buf,
- obj->in_buf+data_size,
- obj->in_buf_size);
-
- obj->amount_of_chunk_parsed += data_size;
-
- if(obj->amount_of_chunk_parsed >= obj->chunk_size)
- {
- XP_ASSERT(obj->amount_of_chunk_parsed == obj->chunk_size);
- /* reinit */
- obj->amount_of_chunk_parsed = 0;
- obj->cur_state = STRIP_CRLF;
- }
- }
- else if(obj->cur_state == STRIP_CRLF)
- {
- if(obj->in_buf_size > 1 && obj->in_buf[0] == CR && obj->in_buf[1] == LF)
- {
- /* strip two bytes */
- obj->in_buf_size -= 2;
- if(obj->in_buf_size)
- XP_MEMMOVE(obj->in_buf,
- obj->in_buf+2,
- obj->in_buf_size);
- obj->cur_state = FIND_CHUNK_SIZE;
- }
- else if(obj->in_buf[0] == LF)
- {
- /* strip one bytes */
- obj->in_buf_size -= 1;
- if(obj->in_buf_size)
- XP_MEMMOVE(obj->in_buf,
- obj->in_buf+1,
- obj->in_buf_size);
- obj->cur_state = FIND_CHUNK_SIZE;
- }
- else
- {
- if(obj->in_buf_size >= 2)
- {
- int status;
-
- /* a fatal parse error */
- XP_ASSERT(0);
-
- /* just spew the buf to the screen */
- status = (obj->next_stream->put_block)(obj->next_stream,
- obj->in_buf,
- obj->in_buf_size);
- if(status < 0)
- return status;
-
- /* remove the part that has been pushed */
- obj->in_buf_size = 0;
- }
- }
- }
- else if(obj->cur_state == PARSE_FOOTER)
- {
- char *line_feed;
- char *value;
-
- /* parse until we see two CRLF's in a row */
- if((line_feed = XP_STRNCHR(obj->in_buf, LF, obj->in_buf_size)) == NULL)
- {
- return 1; /* need more data */
- }
-
- *line_feed = '\0';
-
- /* strip the CR */
- if(line_feed != obj->in_buf && *(line_feed-1) == CR)
- *(line_feed-1) = '\0';
-
- if(*obj->in_buf == '\0')
- {
- /* end of parse stream */
- return MK_MULTIPART_MESSAGE_COMPLETED;
- }
-
- /* names are separated from values with a colon
- */
- value = XP_STRCHR(obj->in_buf, ':');
- if(value)
- value++;
-
- /* otherwise parse the line as a mime header */
- NET_ParseMimeHeader(obj->format_out,
- obj->context,
- obj->URL_s,
- obj->in_buf,
- value,
- FALSE);
-
- /* strip the line from the buffer */
- obj->in_buf_size -= (line_feed+1) - obj->in_buf;
- if(obj->in_buf_size)
- XP_MEMMOVE(obj->in_buf,
- line_feed+1,
- obj->in_buf_size);
- }
- }
-
- XP_ASSERT(obj->in_buf_size == 0);
-
- return(1);
- }
-
- /* is the stream ready for writeing?
- */
- PRIVATE unsigned int net_ChunkedWriteReady (NET_StreamClass * stream)
- {
- DataObject *obj=stream->data_object;
- return (*obj->next_stream->is_write_ready)(obj->next_stream);
- }
-
-
- PRIVATE void net_ChunkedComplete (NET_StreamClass *stream)
- {
- DataObject *obj=stream->data_object;
- (*obj->next_stream->complete)(obj->next_stream);
-
- FREE(obj);
- return;
- }
-
- PRIVATE void net_ChunkedAbort (NET_StreamClass *stream, int status)
- {
- DataObject *obj=stream->data_object;
- (*obj->next_stream->abort)(obj->next_stream, status);
-
- return;
- }
-
-
- MODULE_PRIVATE NET_StreamClass *
- NET_ChunkedDecoderStream (int format_out,
- void *data_obj,
- URL_Struct *URL_s,
- MWContext *window_id)
- {
- DataObject* obj;
- NET_StreamClass* stream;
-
- TRACEMSG(("Setting up display stream. Have URL: %s\n", URL_s->address));
-
- stream = XP_NEW(NET_StreamClass);
- if(stream == NULL)
- return(NULL);
-
- obj = XP_NEW_ZAP(DataObject);
- if (obj == NULL)
- return(NULL);
-
- stream->name = "Chunked decoder";
- stream->complete = (MKStreamCompleteFunc) net_ChunkedComplete;
- stream->abort = (MKStreamAbortFunc) net_ChunkedAbort;
- stream->put_block = (MKStreamWriteFunc) net_ChunkedWrite;
- stream->is_write_ready = (MKStreamWriteReadyFunc) net_ChunkedWriteReady;
- stream->data_object = obj; /* document info object */
- stream->window_id = window_id;
-
- /* clear the "chunked" encoding */
- if(URL_s->transfer_encoding)
- FREE_AND_CLEAR(URL_s->transfer_encoding);
- else
- FREE_AND_CLEAR(URL_s->content_encoding);
- obj->next_stream = NET_StreamBuilder(format_out, URL_s, window_id);
-
- if(!obj->next_stream)
- {
- XP_FREE(obj);
- XP_FREE(stream);
- return NULL;
- }
-
- obj->context = window_id;
- obj->format_out = format_out;
- obj->URL_s = URL_s;
-
- TRACEMSG(("Returning stream from NET_ChunkedConverter\n"));
-
- return stream;
- }
-
- #endif /* MOZILLA_CLIENT */
-