Fixing 36641

git-svn-id: svn://10.0.0.236/trunk@68472 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ruslan%netscape.com
2000-05-06 00:06:28 +00:00
parent d24292d0d4
commit 18d95e357f
6 changed files with 227 additions and 18 deletions

View File

@@ -49,6 +49,8 @@ CPPSRCS = \
nsHTTPSHandler.cpp \
$(NULL)
LOCAL_INCLUDES=-I../../../streamconv/converters
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
include $(topsrcdir)/config/rules.mk

View File

@@ -59,7 +59,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsAuthEngine.obj \
$(NULL)
LOCAL_INCLUDES=-I.
LOCAL_INCLUDES=-I. -I../../../streamconv/converters
INCLUDES = $(LOCAL_INCLUDES)
@@ -68,6 +68,7 @@ REQUIRES= necko
INCS = $(INCS) \
-I$(DEPTH)\dist\include \
-I..\public \
-I../../../streamconv/converters \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -32,6 +32,7 @@
#include "nsCRT.h"
#include "nsIStreamConverterService.h"
#include "nsIStreamConverter.h"
#include "nsRepository.h"
#include "nsHTTPAtoms.h"
#include "nsIHttpNotify.h"
@@ -224,6 +225,9 @@ nsresult nsHTTPCacheListener::Abort()
}
static NS_DEFINE_CID(kSupportsVoidCID, NS_SUPPORTS_VOID_CID);
static NS_DEFINE_IID(kSupportsVoidIID, NS_ISUPPORTSVOID_IID);
////////////////////////////////////////////////////////////////////////////////
//
// nsHTTPServerListener Implementation
@@ -247,10 +251,11 @@ nsHTTPServerListener::nsHTTPServerListener(nsHTTPChannel* aChannel, nsHTTPHandle
{
mChannel -> mHTTPServerListener = this;
NS_NewISupportsPRBool (getter_AddRefs (mChunkHeaderEOF));
nsRepository::CreateInstance (kSupportsVoidCID, NULL,
kSupportsVoidIID, getter_AddRefs (mChunkHeaderEOF));
if (mChunkHeaderEOF)
mChunkHeaderEOF -> SetData (PR_FALSE);
mChunkHeaderEOF -> SetData (&mChunkHeaderCtx);
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("Creating nsHTTPServerListener [this=%x].\n", this));
@@ -468,6 +473,9 @@ nsHTTPServerListener::OnDataAvailable(nsIChannel* channel,
nsXPIDLCString chunkHeader;
rv = mResponse -> GetHeader (nsHTTPAtoms::Transfer_Encoding, getter_Copies (chunkHeader));
nsXPIDLCString trailerHeader;
rv = mResponse -> GetHeader (nsHTTPAtoms::Trailer, getter_Copies (trailerHeader));
if (NS_SUCCEEDED (rv) && chunkHeader)
{
NS_WITH_SERVICE (nsIStreamConverterService,
@@ -477,8 +485,31 @@ nsHTTPServerListener::OnDataAvailable(nsIChannel* channel,
nsString fromStr; fromStr.AssignWithConversion ( chunkHeader );
nsString toStr; toStr.AssignWithConversion ( "unchunked" );
if (mChunkHeaderEOF)
mChunkHeaderEOF -> SetData (PR_FALSE);
mChunkHeaderCtx.SetEOF (PR_FALSE);
if (trailerHeader)
{
nsCString ts (trailerHeader);
ts.StripWhitespace ();
char *cp = ts;
while (*cp)
{
char * pp = PL_strchr (cp , ',');
if (pp == NULL)
{
mChunkHeaderCtx.AddTrailerHeader (cp);
break;
}
else
{
*pp = 0;
mChunkHeaderCtx.AddTrailerHeader (cp);
*pp = ',';
cp = pp + 1;
}
}
}
nsCOMPtr<nsIStreamListener> converterListener;
rv = StreamConvService->AsyncConvertData(
@@ -507,13 +538,25 @@ nsHTTPServerListener::OnDataAvailable(nsIChannel* channel,
if (NS_FAILED(rv)) return rv;
}
PRBool eof = PR_FALSE;
if (mChunkHeaderEOF)
mChunkHeaderEOF -> GetData (&eof);
PRBool eof = mChunkHeaderCtx.GetEOF ();
if (mPipelinedRequest
&& (cl != -1 && cl - mBodyBytesReceived == 0 || eof))
{
if (eof && mResponse)
{
nsVoidArray *mh = mChunkHeaderCtx.GetAllHeaders ();
for (int i = mh -> Count () - 1; i >= 0; i--)
{
nsHTTPChunkConvHeaderEntry *he = (nsHTTPChunkConvHeaderEntry *) mh -> ElementAt (i);
if (he)
{
nsCOMPtr<nsIAtom> hAtom = dont_AddRef (NS_NewAtom (he -> mName));
mResponse -> SetHeader (hAtom, he -> mValue);
}
}
}
nsresult rv1 = mPipelinedRequest -> AdvanceToNextRequest ();
if (NS_FAILED (rv1))
@@ -580,8 +623,7 @@ nsHTTPServerListener::OnStartRequest (nsIChannel* channel, nsISupports* i_pConte
mChannel = nsnull;
mResponseDataListener = null_nsCOMPtr ();
if (mChunkHeaderEOF)
mChunkHeaderEOF -> SetData (PR_FALSE);
mChunkHeaderCtx.SetEOF (PR_FALSE);
nsHTTPRequest * req;
mPipelinedRequest -> GetCurrentRequest (&req);

View File

@@ -26,6 +26,7 @@
#include "nsIChannel.h"
#include "nsIStreamListener.h"
#include "nsHTTPChunkConv.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
@@ -124,8 +125,10 @@ protected:
PRBool mCompressHeaderChecked;
PRBool mChunkHeaderChecked;
PRBool mDataReceived;
nsCOMPtr<nsISupportsPRBool> mChunkHeaderEOF;
nsCOMPtr<nsISupportsVoid> mChunkHeaderEOF;
nsHTTPPipelinedRequest* mPipelinedRequest;
nsHTTPChunkConvContext mChunkHeaderCtx;
};

View File

@@ -41,6 +41,12 @@ nsHTTPChunkConv::nsHTTPChunkConv()
mListener = nsnull;
mChunkBuffer = NULL;
mState = CHUNK_STATE_INIT;
mValueBufLen = 0;
mHeaderBufLen= 0;
mHeadersCount= mHeadersExpected = 0;
mChunkContext= NULL;
}
nsHTTPChunkConv::~nsHTTPChunkConv ()
@@ -78,8 +84,14 @@ nsHTTPChunkConv::AsyncConvertData (
mListener = aListener;
NS_ADDREF (mListener);
mAsyncConvContext = (nsISupportsPRBool *) aCtxt;
mAsyncConvContext = (nsISupportsVoid *) aCtxt;
if (mAsyncConvContext)
{
const void *p;
mAsyncConvContext -> GetData (&p);
mChunkContext = (nsHTTPChunkConvContext *)p;
}
return NS_OK;
}
@@ -200,8 +212,8 @@ nsHTTPChunkConv::OnDataAvailable (
}
else
{
if (mAsyncConvContext)
mAsyncConvContext -> SetData (PR_TRUE);
if (mChunkContext)
mChunkContext -> SetEOF (PR_TRUE);
}
mState = CHUNK_STATE_INIT;
@@ -254,7 +266,7 @@ nsHTTPChunkConv::OnDataAvailable (
mState = CHUNK_STATE_CR_FINAL;
}
else
mState = CHUNK_STATE_FINAL;
mState = CHUNK_STATE_TRAILER;
c = 0;
break;
@@ -314,6 +326,58 @@ nsHTTPChunkConv::OnDataAvailable (
streamLen -= rl;
}
break;
case CHUNK_STATE_TRAILER:
if (!mChunkContext || mHeadersCount == mChunkContext -> GetTrailerHeaderCount ())
mState = CHUNK_STATE_FINAL;
else
mState = CHUNK_STATE_TRAILER_HEADER;
break;
case CHUNK_STATE_TRAILER_HEADER:
rv = iStr -> Read (&c, 1, &rl);
if (NS_FAILED (rv))
return rv;
streamLen--;
if (isalnum (c) && mHeaderBufLen < sizeof (mHeaderBuf) - 1)
mHeaderBuf[mHeaderBufLen++] = c;
else
if (c == ':')
{
mHeaderBuf[mHeaderBufLen] = 0;
mState = CHUNK_STATE_TRAILER_VALUE;
}
break;
case CHUNK_STATE_TRAILER_VALUE:
rv = iStr -> Read (&c, 1, &rl);
if (NS_FAILED (rv))
return rv;
streamLen--;
if (isspace (c) && mValueBufLen == 0 || c == '\r')
break;
else
if (c == '\n')
{
mValueBuf[mValueBufLen] = 0;
mHeadersCount++;
mChunkContext -> SetResponseHeader (mHeaderBuf, mValueBuf);
mHeaderBufLen = mValueBufLen = 0;
mState = CHUNK_STATE_TRAILER;
}
else
if (mValueBufLen < sizeof (mValueBuf) - 1)
mValueBuf[mValueBufLen++] = c;
break;
} /* switch */
} /* while */
} /* DO_UNCHUNKING */
@@ -351,3 +415,5 @@ NS_NewHTTPChunkConv (nsHTTPChunkConv ** aHTTPChunkConv)
NS_ADDREF(*aHTTPChunkConv);
return NS_OK;
}

View File

@@ -26,6 +26,9 @@
#include "nsIStreamConverter.h"
#include "nsIFactory.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
#include "nsHashtable.h"
#include "nsString.h"
#include "nsISupportsPrimitives.h"
@@ -54,12 +57,17 @@ typedef enum enum_ChunkState
CHUNK_STATE_DATA,
CHUNK_STATE_CR_FINAL,
CHUNK_STATE_LF_FINAL,
CHUNK_STATE_FINAL
CHUNK_STATE_FINAL,
CHUNK_STATE_TRAILER_HEADER,
CHUNK_STATE_TRAILER_VALUE,
CHUNK_STATE_TRAILER
} ChunkState;
#define HTTP_CHUNK_TYPE "chunked"
#define HTTP_UNCHUNK_TYPE "unchunked"
class nsHTTPChunkConvContext;
class nsHTTPChunkConv : public nsIStreamConverter {
public:
// nsISupports methods
@@ -87,7 +95,94 @@ private:
char mLenBuf[20];
PRUint32 mLenBufCnt;
nsCOMPtr<nsISupportsPRBool> mAsyncConvContext;
nsCOMPtr<nsISupportsVoid> mAsyncConvContext;
char mValueBuf [4096];
PRUint32 mValueBufLen;
char mHeaderBuf [400];
PRUint32 mHeaderBufLen;
PRUint32 mHeadersCount;
PRUint32 mHeadersExpected;
nsHTTPChunkConvContext *mChunkContext;
};
class nsHTTPChunkConvHeaderEntry {
public:
nsHTTPChunkConvHeaderEntry (const char *aName, const char* aValue)
{
mName = aName;
mValue = aValue;
}
nsHTTPChunkConvHeaderEntry::~nsHTTPChunkConvHeaderEntry()
{
}
nsCString mName;
nsCString mValue;
};
class nsHTTPChunkConvContext {
public:
nsHTTPChunkConvContext ()
: mEof (PR_FALSE), mHeadersCount (0)
{
}
~nsHTTPChunkConvContext ()
{
PRInt32 i = mHeaders.Count ();
while (i > 0)
{
nsHTTPChunkConvHeaderEntry *e = (nsHTTPChunkConvHeaderEntry *)mHeaders.RemoveElementAt (i - 1);
delete e;
}
}
void SetEOF (PRBool eof)
{
mEof = eof;
}
PRBool GetEOF () { return mEof; }
nsVoidArray * GetAllHeaders ()
{
return &mHeaders;
}
PRUint32 GetTrailerHeaderCount ()
{
return mHeadersCount;
}
void AddTrailerHeader (const char *header)
{
nsStringKey key (header);
mTrailer.Put (&key, (void *) 1);
mHeadersCount++;
}
void SetResponseHeader (const char *header, const char *value)
{
nsHTTPChunkConvHeaderEntry *e = new nsHTTPChunkConvHeaderEntry (header, value);
mHeaders.AppendElement (e);
}
private:
PRBool mEof;
nsVoidArray mHeaders;
nsHashtable mTrailer;
PRUint32 mHeadersCount;
};