Fixing 36641
git-svn-id: svn://10.0.0.236/trunk@68472 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -49,6 +49,8 @@ CPPSRCS = \
|
||||
nsHTTPSHandler.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES=-I../../../streamconv/converters
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user