diff --git a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp index db949c17472..ab401be4309 100644 --- a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp +++ b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp @@ -616,7 +616,7 @@ nsXMLHttpRequest::DetectCharset(nsAWritableString& aCharset) rv = httpChannel->GetResponseHeader("content-type", getter_Copies(contenttypeheader)); if (NS_SUCCEEDED(rv)) { nsAutoString contentType; - contentType.AssignWithConversion( NS_STATIC_CAST(const char*, contenttypeheader) ); + contentType.AssignWithConversion( contenttypeheader.get() ); PRInt32 start = contentType.RFind("charset=", PR_TRUE ) ; if(start<0) { start += 8; // 8 = "charset=".length @@ -652,7 +652,7 @@ nsXMLHttpRequest::ConvertBodyToText(PRUnichar **aOutBuffer) { *aOutBuffer = nsnull; - PRInt32 dataLen = mResponseBody.GetBufferLength(); + PRInt32 dataLen = mResponseBody.Length(); if (!dataLen) return NS_OK; @@ -673,7 +673,7 @@ nsXMLHttpRequest::ConvertBodyToText(PRUnichar **aOutBuffer) if (dataCharset.Equals(NS_LITERAL_STRING("ASCII"))) { // XXX There is no ASCII->Unicode decoder? // XXX How to do this without double allocation/copy? - *aOutBuffer = NS_ConvertASCIItoUCS2(mResponseBody.GetBuffer(),dataLen).ToNewUnicode(); + *aOutBuffer = NS_ConvertASCIItoUCS2(mResponseBody.get(),dataLen).ToNewUnicode(); if (!*aOutBuffer) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; @@ -691,7 +691,7 @@ nsXMLHttpRequest::ConvertBodyToText(PRUnichar **aOutBuffer) // This loop here is basically a copy of a similar thing in nsScanner. // It will exit on first iteration in normal cases, but if we get illegal // characters in the input we replace them and then continue. - const char * inBuffer = mResponseBody.GetBuffer(); + const char * inBuffer = mResponseBody.get(); PRUnichar * outBuffer = nsnull; PRInt32 outBufferIndex = 0, inBufferLength = dataLen; PRInt32 outLen; @@ -739,7 +739,9 @@ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(PRUnichar **aResponseText) NS_ENSURE_ARG_POINTER(aResponseText); *aResponseText = nsnull; if ((XML_HTTP_REQUEST_COMPLETED == mStatus)) { - if (!mResponseBody.CanBeString()) + // First check if we can represent the data as a string - if it contains + // nulls we won't try. + if (mResponseBody.FindChar('\0') >= 0) return NS_ERROR_FAILURE; nsresult rv = ConvertBodyToText(aResponseText); if (NS_FAILED(rv)) @@ -835,22 +837,15 @@ nsXMLHttpRequest::OpenRequest(const char *method, nsresult rv; nsCOMPtr uri; - nsCOMPtr loadGroup; PRBool authp = PR_FALSE; - // Return error if we're alreday processing a request + // Return error if we're already processing a request if (XML_HTTP_REQUEST_SENT == mStatus) { return NS_ERROR_FAILURE; } mAsync = async; - // If we have a base document, use it for the base URL and loadgroup - if (mBaseDocument) { - rv = mBaseDocument->GetDocumentLoadGroup(getter_AddRefs(loadGroup)); - if (NS_FAILED(rv)) return rv; - } - rv = NS_NewURI(getter_AddRefs(uri), url, mBaseURI); if (NS_FAILED(rv)) return rv; @@ -874,7 +869,7 @@ nsXMLHttpRequest::OpenRequest(const char *method, } nsCOMPtr channel; - rv = NS_OpenURI(getter_AddRefs(channel), uri, nsnull, loadGroup); + rv = NS_OpenURI(getter_AddRefs(channel), uri, nsnull, nsnull); if (NS_FAILED(rv)) return rv; mChannel = do_QueryInterface(channel); @@ -923,8 +918,17 @@ nsXMLHttpRequest::Open(const char *method, const char *url) NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + nsCOMPtr principal; + rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr codebase = do_QueryInterface(principal); + if (codebase) { + codebase->GetURI(getter_AddRefs(mBaseURI)); + } + } + nsCOMPtr targetURI; - rv = NS_NewURI(getter_AddRefs(targetURI), url, nsnull); + rv = NS_NewURI(getter_AddRefs(targetURI), url, mBaseURI); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; rv = secMan->CheckConnect(cx, targetURI, "XMLHttpRequest","open"); @@ -942,15 +946,6 @@ nsXMLHttpRequest::Open(const char *method, const char *url) return NS_OK; } - nsCOMPtr principal; - rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal)); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr codebase = do_QueryInterface(principal); - if (codebase) { - codebase->GetURI(getter_AddRefs(mBaseURI)); - } - } - if (argc > 2) { JSBool asyncBool; JS_ValueToBoolean(cx, argv[2], &asyncBool); @@ -1033,7 +1028,7 @@ nsXMLHttpRequest::GetStreamForWString(const PRUnichar* aStr, // Copy the post data to immediately follow the header nsCRT::memcpy(postData+headerSize, postData+MAX_HEADER_SIZE, charLength); - // Shove in the traling CRLF + // Shove in the trailing CRLF postData[headerSize+charLength] = nsCRT::CR; postData[headerSize+charLength+1] = nsCRT::LF; postData[headerSize+charLength+2] = '\0'; @@ -1051,10 +1046,7 @@ nsXMLHttpRequest::GetStreamForWString(const PRUnichar* aStr, /* - * Principle stolen from nsParser.cpp - * - * This stuff allows us to read the stream without wiping it out - * so that the XML Parser can see the data as well. + * "Copy" from a stream. */ NS_METHOD nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in, @@ -1065,20 +1057,39 @@ nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in, PRUint32 *writeCount) { nsXMLHttpRequest* xmlHttpRequest = NS_STATIC_CAST(nsXMLHttpRequest*, closure); - if (!xmlHttpRequest) { + if (!xmlHttpRequest || !writeCount) { + NS_WARNING("XMLHttpRequest cannot read from stream: no closure or writeCount"); return NS_ERROR_FAILURE; } // Copy for our own use - nsresult rv = xmlHttpRequest->mResponseBody.Append(fromRawSegment,count); - if (NS_FAILED(rv)) { - xmlHttpRequest->mResponseBody.Truncate(); - return rv; + xmlHttpRequest->mResponseBody.Append(fromRawSegment,count); + + nsresult rv; + + // Give the same data to the parser. + + // We need to wrap the data in a new lightweight stream and pass that + // to the parser, because calling ReadSegments() recursively on the same + // stream is not supported. + nsCOMPtr supportsStream; + rv = NS_NewByteInputStream(getter_AddRefs(supportsStream),fromRawSegment,count); + + if (NS_SUCCEEDED(rv)) { + nsCOMPtr copyStream(do_QueryInterface(supportsStream)); + if (copyStream) { + rv = xmlHttpRequest->mXMLParserStreamListener->OnDataAvailable(xmlHttpRequest->mReadRequest,xmlHttpRequest->mContext,copyStream,toOffset,count); + } else { + NS_ERROR("NS_NewByteInputStream did not give out nsIInputStream!"); + rv = NS_ERROR_UNEXPECTED; + } } - rv = xmlHttpRequest->mXMLParserStreamListener->OnDataAvailable(xmlHttpRequest->mReadRequest,xmlHttpRequest->mContext,in,toOffset,count); - - *writeCount = count; // The parser always copies the whole buffer it gets in OnDataAvailable() + if (NS_SUCCEEDED(rv)) { + *writeCount = count; + } else { + *writeCount = 0; + } return rv; } @@ -1087,12 +1098,12 @@ nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in, NS_IMETHODIMP nsXMLHttpRequest::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) { - nsresult result=NS_OK; + NS_ENSURE_ARG_POINTER(inStr); NS_ABORT_IF_FALSE(mContext.get() == ctxt,"start context different from OnDataAvailable context"); PRUint32 totalRead; - result = inStr->ReadSegments(nsXMLHttpRequest::StreamReaderFunc, (void*)this, count, &totalRead); + nsresult result = inStr->ReadSegments(nsXMLHttpRequest::StreamReaderFunc, (void*)this, count, &totalRead); if (NS_FAILED(result)) { mResponseBody.Truncate(); } @@ -1125,7 +1136,6 @@ NS_IMETHODIMP nsXMLHttpRequest::Send(nsISupports *body) { nsresult rv; - nsCOMPtr postDataStream; // Return error if we're already processing a request if (XML_HTTP_REQUEST_SENT == mStatus) { @@ -1137,7 +1147,13 @@ nsXMLHttpRequest::Send(nsISupports *body) return NS_ERROR_NOT_INITIALIZED; } - if (body) { + // Ignore argument if method is GET, there is no point in trying to upload anything + nsXPIDLCString method; + mChannel->GetRequestMethod(getter_Copies(method)); // If GET, method name will be uppercase + + if (body && nsCRT::strcmp("GET",method.get()) != 0) { + nsCOMPtr postDataStream; + nsCOMPtr doc(do_QueryInterface(body)); if (doc) { // Get an XML serializer @@ -1150,8 +1166,8 @@ nsXMLHttpRequest::Send(nsISupports *body) if (NS_FAILED(rv)) return NS_ERROR_FAILURE; // Convert to a byte stream - rv = GetStreamForWString((const PRUnichar*)serial, - nsCRT::strlen((const PRUnichar*)serial), + rv = GetStreamForWString(serial.get(), + nsCRT::strlen(serial.get()), getter_AddRefs(postDataStream)); if (NS_FAILED(rv)) return rv; } @@ -1165,8 +1181,8 @@ nsXMLHttpRequest::Send(nsISupports *body) if (wstr) { nsXPIDLString holder; wstr->GetData(getter_Copies(holder)); - rv = GetStreamForWString((const PRUnichar*)holder, - nsCRT::strlen((const PRUnichar*)holder), + rv = GetStreamForWString(holder.get(), + nsCRT::strlen(holder.get()), getter_AddRefs(postDataStream)); if (NS_FAILED(rv)) return rv; } diff --git a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h index 321fd0da487..adce912337a 100644 --- a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h +++ b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h @@ -106,7 +106,6 @@ protected: nsCOMPtr mReadRequest; nsCOMPtr mDocument; nsCOMPtr mBaseURI; - nsCOMPtr mBaseDocument; #ifdef IMPLEMENT_SYNC_LOAD nsCOMPtr mChromeWindow; #endif @@ -134,74 +133,7 @@ protected: nsCString mHeaders; }; -#if 1 // When nsCString::Append()/Length() works for strings that contain nulls, remove this buffer impl - class ResponseBodyBuffer { - public: - ResponseBodyBuffer() - : mBuffer(0), - mBufferSize(0), - mBufferFreeIndex(0), - mCanBeString(PR_FALSE), - mBufferChecked(PR_FALSE) {} - ~ResponseBodyBuffer() { nsMemory::Free(mBuffer); } - void Truncate(void) { - nsMemory::Free(mBuffer); - mBuffer=nsnull; - mBufferSize=mBufferFreeIndex=0; - mCanBeString = PR_FALSE; - mBufferChecked = PR_FALSE; - } - nsresult Append(const char* aBuffer, PRUint32 aBufferLen) { - if (aBufferLen > (mBufferSize-mBufferFreeIndex)) { - PRUint32 newBufferSize = (mBufferSize > aBufferLen ? mBufferSize : aBufferLen)<<1; - char * newBuffer = NS_STATIC_CAST(char*,nsMemory::Realloc(mBuffer,newBufferSize)); - if (!newBuffer) { - nsMemory::Free(mBuffer); - mBuffer = nsnull; - mBufferChecked = PR_FALSE; - mCanBeString = PR_FALSE; - return NS_ERROR_OUT_OF_MEMORY; - } - mBuffer = newBuffer; - mBufferSize = newBufferSize; - } - memcpy(&mBuffer[mBufferFreeIndex],aBuffer,aBufferLen); - mBufferFreeIndex += aBufferLen; - mBufferChecked = PR_FALSE; - mCanBeString = PR_FALSE; - return NS_OK; - } - const char * GetBuffer(void) { return mBuffer; } - PRUint32 GetBufferLength(void) { return mBufferFreeIndex; } - PRBool CanBeString(void) { - if (!mBufferFreeIndex) - return PR_TRUE; // Perhaps this is a bit questionable... - if (!mBufferChecked) { - mBufferChecked = PR_TRUE; - - mCanBeString = PR_TRUE; - - PRUint32 i; - for (i = 0; i < mBufferFreeIndex; i++) { - if (!mBuffer[i]) { - mCanBeString = PR_FALSE; - break; - } - } - } - return mCanBeString; - } - private: - char *mBuffer; - PRUint32 mBufferSize; - PRUint32 mBufferFreeIndex; - PRPackedBool mCanBeString; - PRPackedBool mBufferChecked; - }; - ResponseBodyBuffer mResponseBody; -#else nsCString mResponseBody; -#endif nsCOMPtr mXMLParserStreamListener; diff --git a/mozilla/extensions/xmlextras/tests/TestXMLExtras.cpp b/mozilla/extensions/xmlextras/tests/TestXMLExtras.cpp index 0bdebf9b80a..3453520ae94 100644 --- a/mozilla/extensions/xmlextras/tests/TestXMLExtras.cpp +++ b/mozilla/extensions/xmlextras/tests/TestXMLExtras.cpp @@ -33,6 +33,68 @@ #include #include #include "nsIDocument.h" +#include "nsIServiceManager.h" +#include +#include +#include +#include +#include "nsContentCID.h" +static NS_DEFINE_CID( kXMLDocumentCID, NS_XMLDOCUMENT_CID ); + +#if 0 +class nsMyListener : public nsIDOMLoadListener +{ +public: + nsMyListener() {NS_INIT_ISUPPORTS();} + ~nsMyListener() {} + + void Start(const char *a); + + NS_DECL_ISUPPORTS + + // nsIDOMEventListener + virtual nsresult HandleEvent(nsIDOMEvent* aEvent) { return NS_OK;} + + // nsIDOMLoadListener + virtual nsresult Load(nsIDOMEvent* aEvent) {printf("Load\n"); return NS_OK;} + virtual nsresult Unload(nsIDOMEvent* aEvent) {printf("Unload\n"); return NS_OK;} + virtual nsresult Abort(nsIDOMEvent* aEvent) {printf("Abort\n"); return NS_OK;} + virtual nsresult Error(nsIDOMEvent* aEvent) {printf("Error\n"); return NS_OK;} +}; + +NS_IMPL_ADDREF(nsMyListener) +NS_IMPL_RELEASE(nsMyListener) + +NS_INTERFACE_MAP_BEGIN(nsMyListener) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLoadListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) +NS_INTERFACE_MAP_END + +void nsMyListener::Start(const char *arg2) +{ + nsresult rv; + nsCOMPtr doc(do_CreateInstance( kXMLDocumentCID, &rv )); + if (NS_SUCCEEDED( rv )) { + nsCOMPtr pDOMEventTarget = do_QueryInterface( doc, &rv ); + if (NS_SUCCEEDED( rv )) { + nsCOMPtr pDOMEventListener = do_QueryInterface( this, &rv ); + if (NS_SUCCEEDED( rv )) { + nsAutoString sLoadCommand; + sLoadCommand.Assign( NS_LITERAL_STRING("load") ); + rv = pDOMEventTarget->AddEventListener( sLoadCommand, pDOMEventListener, PR_FALSE ); + if (NS_SUCCEEDED( rv )) { + nsCOMPtr pDOMNSDocument = do_QueryInterface( doc, &rv ); + if (NS_SUCCEEDED( rv )) { + rv = pDOMNSDocument->Load( NS_ConvertASCIItoUCS2(arg2) ); + } + } + } + } + } + +} +#endif void usage( ) { printf( "\n" ); @@ -43,6 +105,8 @@ void usage( ) { printf( " xmlfile = A local XML URI (ie. file:///d:/file.xml)\n\n" ); printf( " syncread = Invokes XMLHttpRequest for a synchronous read\n" ); printf( " xmlfile = An XML URI (ie. http://www.w3.org/TR/P3P/base\n\n" ); + printf( " load = Invokes document.load for asynchronous read\n" ); + printf( " xmlfile = An XML URI (ie. http://www.w3.org/TR/P3P/base\n\n" ); return; } @@ -59,6 +123,11 @@ int main (int argc, char* argv[]) nsCOMPtr pDOMDocument; nsCOMPtr pXMLHttpRequest; + nsIServiceManager *servMgr; + + rv = NS_InitXPCOM(&servMgr, nsnull); + if (NS_FAILED(rv)) return rv; + if (argc > 2) { if (nsCRT::strcasecmp( argv[1], "parsestr" ) == 0) { pDOMParser = do_CreateInstance( NS_DOMPARSER_CONTRACTID, @@ -177,6 +246,12 @@ int main (int argc, char* argv[]) printf( "do_CreateInstance of XMLHttpRequest failed for %s - %08X\n", argv[2], rv ); } } +#if 0 + else if (nsCRT::strcasecmp( argv[1], "load" ) == 0) { + nsMyListener * listener = new nsMyListener(); + listener->Start(argv[2]); + } +#endif else { usage( ); } @@ -202,5 +277,8 @@ int main (int argc, char* argv[]) } } - return 0; + if (servMgr) + rv = NS_ShutdownXPCOM(servMgr); + + return rv; } diff --git a/mozilla/extensions/xmlextras/tests/post.html b/mozilla/extensions/xmlextras/tests/post.html index 26bccd3f2c9..3d2184e2ff1 100644 --- a/mozilla/extensions/xmlextras/tests/post.html +++ b/mozilla/extensions/xmlextras/tests/post.html @@ -30,7 +30,7 @@ function myfunc() p.onload = myfunc; netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); -p.open("POST", "http://blueviper/cgi-bin/echo_xml.cgi"); +p.open("POST", "http://green/cgi-bin/echo_xml.cgi"); if (!sendPlainTextData) { p.send(x); diff --git a/mozilla/extensions/xmlextras/tests/syncpost.html b/mozilla/extensions/xmlextras/tests/syncpost.html index ba1439b44c1..fbf0ae45e0f 100644 --- a/mozilla/extensions/xmlextras/tests/syncpost.html +++ b/mozilla/extensions/xmlextras/tests/syncpost.html @@ -10,7 +10,7 @@ x.documentElement.lastChild.setAttributeNS("http://www.w3.org/1999/xhtml","id"," var p = new XMLHttpRequest(); netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); -p.open("POST", "http://blueviper/cgi-bin/echo_xml.cgi", false); +p.open("POST", "http://green/cgi-bin/echo_xml.cgi", false); p.send(x); var d = p.responseXML; var s = new XMLSerializer()