зеркало из https://github.com/mozilla/pjs.git
fix #115308, NPN_PostURL[Notify] does not handle binary data; r=bnesse, sr=darin
This commit is contained in:
Родитель
4956c2f3c0
Коммит
a150c8ccad
|
@ -2261,20 +2261,11 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
|
|||
|
||||
// deal with post data, either in a file or raw data, and any headers
|
||||
if (aPostData) {
|
||||
const char * dataToPost = (const char *)aPostData; // default to raw data
|
||||
nsXPIDLCString filename;
|
||||
|
||||
if (isFile) {
|
||||
// convert file:///c:/ to c: if needed
|
||||
nsCOMPtr<nsILocalFile> aFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
if (NS_SUCCEEDED(NS_InitFileFromURLSpec(aFile,dataToPost)) &&
|
||||
NS_SUCCEEDED(aFile->GetPath(getter_Copies(filename))))
|
||||
dataToPost = filename;
|
||||
}
|
||||
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), dataToPost, aPostDataLen, isFile);
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), (const char *)aPostData, aPostDataLen, isFile);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin post data stream");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aHeadersData) {
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(headersDataStream),
|
||||
|
@ -2284,6 +2275,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
|
|||
PR_TRUE); // last arg says we are headers, no /r/n/r/n fixup!
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin header data stream");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2261,20 +2261,11 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
|
|||
|
||||
// deal with post data, either in a file or raw data, and any headers
|
||||
if (aPostData) {
|
||||
const char * dataToPost = (const char *)aPostData; // default to raw data
|
||||
nsXPIDLCString filename;
|
||||
|
||||
if (isFile) {
|
||||
// convert file:///c:/ to c: if needed
|
||||
nsCOMPtr<nsILocalFile> aFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
if (NS_SUCCEEDED(NS_InitFileFromURLSpec(aFile,dataToPost)) &&
|
||||
NS_SUCCEEDED(aFile->GetPath(getter_Copies(filename))))
|
||||
dataToPost = filename;
|
||||
}
|
||||
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), dataToPost, aPostDataLen, isFile);
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), (const char *)aPostData, aPostDataLen, isFile);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin post data stream");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aHeadersData) {
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(headersDataStream),
|
||||
|
@ -2284,6 +2275,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge
|
|||
PR_TRUE); // last arg says we are headers, no /r/n/r/n fixup!
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin header data stream");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,39 @@ public:
|
|||
*/
|
||||
NS_IMETHOD
|
||||
SetIsScriptableInstance(nsCOMPtr<nsIPluginInstance> aPluginInstance, PRBool aScriptable) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* This method parses post buffer to find out case insensitive "Content-length" string
|
||||
* and CR or LF some where after that, then it assumes there is http headers in
|
||||
* the input buffer and continue to search for end of headers (CRLFCRLF or LFLF).
|
||||
* It will *always malloc()* output buffer (caller is responsible to free it)
|
||||
* if input buffer starts with LF, which comes from 4.x spec
|
||||
* http://developer.netscape.com/docs/manuals/communicator/plugin/pgfn2.htm#1007754
|
||||
* "If no custom headers are required, simply add a blank
|
||||
* line ('\n') to the beginning of the file or buffer.",
|
||||
* it skips that '\n' and considers rest of the input buffer as data.
|
||||
* If "Content-length" string and end of headers is found
|
||||
* it substitutes single LF with CRLF in the headers, so the end of headers
|
||||
* always will be CRLFCRLF (single CR in headers, if any, remain untouched)
|
||||
* else
|
||||
* it puts "Content-length: "+size_of_data+CRLFCRLF at the beginning of the output buffer
|
||||
* and memcpy data to the output buffer
|
||||
*
|
||||
* On failure outPostData and outPostDataLen will be set in 0.
|
||||
* @param inPostData, the post data
|
||||
* @param the length of inPostData
|
||||
* @param outPostData the buffer.
|
||||
* @param outPostDataLen the length of outPostData
|
||||
**/
|
||||
NS_IMETHOD
|
||||
ParsePostBufferToFixHeaders(const char *inPostData, PRUint32 inPostDataLen,
|
||||
char **outPostData, PRUint32 *outPostDataLen) = 0;
|
||||
/*
|
||||
* To create tmp file with Content len header in, it will use by http POST
|
||||
*/
|
||||
NS_IMETHOD
|
||||
CreateTmpFileToPost(const char *postDataURL, char **pTmpFileName) = 0;
|
||||
};
|
||||
|
||||
#endif /* nsPIPluginHost_h___ */
|
||||
|
|
|
@ -110,93 +110,51 @@ public:
|
|||
* account that it could be binary and full of nulls, see bug 105417. Also, we need
|
||||
* to make a copy of the buffer because the plugin may have allocated it on the stack.
|
||||
* For an example of this, see Shockwave registration or bug 108966
|
||||
* We malloc only for headers here, buffer for data itself is malloced by ParsePostBufferToFixHeaders()
|
||||
*/
|
||||
|
||||
inline nsresult
|
||||
NS_NewPluginPostDataStream(nsIInputStream **result,
|
||||
const char *data,
|
||||
PRUint32 contentLength,
|
||||
PRBool isFile = PR_FALSE,
|
||||
PRBool headers = PR_FALSE)
|
||||
|
||||
{
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
if (!data)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
return rv;
|
||||
|
||||
if (!isFile) { // do raw data case first
|
||||
if (contentLength < 1)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
char * buf = nsnull;
|
||||
|
||||
/**
|
||||
* makes the buffer correct according to the assumption of nsHTTPRequest.cpp
|
||||
* that postData include "\r\n\r\n".
|
||||
* This will search for "\r\n\n", which indicates the end of
|
||||
* the last header. It will then search for the first non-whitespace
|
||||
* character after the last header. It will then create a new buffer
|
||||
* with the existing headers, a correct "\r\n\r\n", then the post data.
|
||||
* If no "\r\n" is found, the data does not contain headers, and a simple
|
||||
* "\r\n\r\n" is prepended to the buffer. See bug 60228 for more info.
|
||||
* ...but not for headers!
|
||||
*/
|
||||
|
||||
if (!headers && !PL_strnstr(data, "\r\n\r\n", contentLength)) {
|
||||
const char *crlf = nsnull;
|
||||
const char *crlfcrlf = "\r\n\r\n";
|
||||
const char *t;
|
||||
char *newBuf;
|
||||
PRInt32 headersLen = 0, dataLen = 0;
|
||||
|
||||
if (!(newBuf = (char*)nsMemory::Alloc(contentLength + 4))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
nsCRT::memset(newBuf, 0, contentLength + 4);
|
||||
|
||||
if (!(crlf = PL_strnstr(data, "\r\n\n", contentLength))) {
|
||||
nsMemory::Free(newBuf);
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
headersLen = crlf - data;
|
||||
|
||||
// find the next non-whitespace char
|
||||
t = crlf + 3;
|
||||
while (*t == '\r' || *t == '\n' || *t == '\t' || *t == ' ' && *t) {
|
||||
t++;
|
||||
}
|
||||
if (*t) {
|
||||
// copy the headers
|
||||
memcpy(newBuf, data, headersLen);
|
||||
// copy the correct crlfcrlf
|
||||
memcpy(newBuf + headersLen, crlfcrlf, 4);
|
||||
// copy the rest of the postData
|
||||
dataLen = contentLength - (t - data);
|
||||
memcpy(newBuf + headersLen + 4, t, dataLen);
|
||||
contentLength = headersLen + 4 + dataLen;
|
||||
buf = newBuf;
|
||||
} else {
|
||||
nsMemory::Free(newBuf);
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
} else {
|
||||
|
||||
// We got correctly formated data passed in!
|
||||
|
||||
return rv;
|
||||
|
||||
char *buf = (char*) data;
|
||||
if (headers) {
|
||||
// in assumption we got correctly formated headers just passed in
|
||||
if (!(buf = (char*)nsMemory::Alloc(contentLength)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
memcpy(buf, data, contentLength);
|
||||
}
|
||||
nsCOMPtr<nsIStringInputStream> sis = do_CreateInstance("@mozilla.org/io/string-input-stream;1",&rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
sis->AdoptData(buf, contentLength); // let the string stream manage our data
|
||||
|
||||
rv = CallQueryInterface(sis, result);
|
||||
}
|
||||
} else
|
||||
rv = NS_NewPostDataStream(result, isFile, data, 0); // used only for disk data
|
||||
|
||||
} else {
|
||||
nsCOMPtr<nsILocalFile> file; // tmp file will be deleted on release of stream
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
if (NS_SUCCEEDED(rv = NS_NewLocalFile(data, PR_FALSE, getter_AddRefs(file))) &&
|
||||
NS_SUCCEEDED(rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream),
|
||||
file,
|
||||
PR_RDONLY,
|
||||
0600,
|
||||
PR_TRUE))
|
||||
)
|
||||
{
|
||||
// wrap the file stream with a buffered input stream
|
||||
return NS_NewBufferedInputStream(result, fileStream, 8192);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -2799,14 +2799,30 @@ NS_IMETHODIMP nsPluginHostImpl::PostURL(nsISupports* pluginInst,
|
|||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
rv = pluginInst->QueryInterface(kIPluginInstanceIID, (void **)&instance);
|
||||
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsPluginInstancePeerImpl *peer;
|
||||
char *dataToPost;
|
||||
if (isFile) {
|
||||
rv = CreateTmpFileToPost(postData, &dataToPost);
|
||||
if (NS_FAILED(rv) || !dataToPost) return rv;
|
||||
|
||||
} else {
|
||||
PRUint32 newDataToPostLen;
|
||||
ParsePostBufferToFixHeaders(postData, postDataLen, &dataToPost, &newDataToPostLen);
|
||||
if (!dataToPost)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// we use nsIStringInputStream::adoptDataa()
|
||||
// in NS_NewPluginPostDataStream to set the stream
|
||||
// all new data alloced in ParsePostBufferToFixHeaders()
|
||||
// well be nsMemory::Free()d on destroy the stream
|
||||
postDataLen = newDataToPostLen;
|
||||
}
|
||||
|
||||
if (nsnull != target)
|
||||
{
|
||||
|
||||
nsPluginInstancePeerImpl *peer;
|
||||
rv = instance->GetPeer(NS_REINTERPRET_CAST(nsIPluginInstancePeer **, &peer));
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
|
@ -2827,8 +2843,8 @@ NS_IMETHODIMP nsPluginHostImpl::PostURL(nsISupports* pluginInst,
|
|||
else if (0 == PL_strcmp(target, "_current"))
|
||||
target = "_self";
|
||||
}
|
||||
|
||||
rv = owner->GetURL(url, target, (void*)postData, postDataLen,
|
||||
|
||||
rv = owner->GetURL(url, target, (void*)dataToPost, postDataLen,
|
||||
(void*) postHeaders, postHeadersLength, isFile);
|
||||
}
|
||||
|
||||
|
@ -2840,9 +2856,13 @@ NS_IMETHODIMP nsPluginHostImpl::PostURL(nsISupports* pluginInst,
|
|||
// NS_OpenURI()!
|
||||
if (streamListener != nsnull)
|
||||
rv = NewPluginURLStream(string, instance, streamListener,
|
||||
postData, isFile, postDataLen,
|
||||
(const char*)dataToPost, isFile, postDataLen,
|
||||
postHeaders, postHeadersLength);
|
||||
|
||||
NS_RELEASE(instance);
|
||||
if (isFile) {
|
||||
nsCRT::free(dataToPost);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -5287,8 +5307,6 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL,
|
|||
nsCOMPtr<nsIURI> url;
|
||||
nsAutoString absUrl;
|
||||
nsresult rv;
|
||||
char *newPostData = nsnull;
|
||||
PRUint32 newPostDataLen = 0;
|
||||
|
||||
if (aURL.Length() <= 0)
|
||||
return NS_OK;
|
||||
|
@ -5372,21 +5390,7 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL,
|
|||
if (aPostData) {
|
||||
|
||||
nsCOMPtr<nsIInputStream> postDataStream;
|
||||
const char * dataToPost = aPostData;
|
||||
nsXPIDLCString filename;
|
||||
|
||||
if (aIsFile) {
|
||||
// convert file:///c:/ to c:
|
||||
nsCOMPtr<nsILocalFile> aFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
if (NS_SUCCEEDED(NS_InitFileFromURLSpec(aFile,dataToPost)))
|
||||
if (NS_SUCCEEDED(aFile->GetPath(getter_Copies(filename)))) {
|
||||
// tell the listener about it so it will delete the file later
|
||||
listenerPeer->SetLocalFile(filename);
|
||||
dataToPost = filename;
|
||||
}
|
||||
}
|
||||
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), dataToPost,
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), (const char*)aPostData,
|
||||
aPostDataLen, aIsFile);
|
||||
|
||||
if (!postDataStream)
|
||||
|
@ -5407,12 +5411,6 @@ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL,
|
|||
NS_ASSERTION(uploadChannel, "http must support nsIUploadChannel");
|
||||
|
||||
uploadChannel->SetUploadStream(postDataStream, nsnull, -1);
|
||||
|
||||
if (newPostData)
|
||||
{
|
||||
delete [] (char *)newPostData;
|
||||
newPostData = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
if (aHeadersData)
|
||||
|
@ -5777,24 +5775,6 @@ NS_IMETHODIMP nsPluginHostImpl::Observe(nsISupports *aSubject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
NS_IMETHODIMP
|
||||
nsPluginHostImpl::SetIsScriptableInstance(nsCOMPtr<nsIPluginInstance> aPluginInstance,
|
||||
PRBool aScriptable)
|
||||
{
|
||||
nsActivePlugin * p = mActivePluginList.find(aPluginInstance.get());
|
||||
if(p == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
p->mXPConnected = aScriptable;
|
||||
if(p->mPluginTag)
|
||||
p->mPluginTag->mXPConnected = aScriptable;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
NS_IMETHODIMP nsPluginHostImpl::HandleBadPlugin(PRLibrary* aLibrary)
|
||||
{
|
||||
|
@ -5878,3 +5858,246 @@ NS_IMETHODIMP nsPluginHostImpl::HandleBadPlugin(PRLibrary* aLibrary)
|
|||
nsMemory::Free((void *)checkboxMessage);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// nsPIPluginHost interface
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
NS_IMETHODIMP
|
||||
nsPluginHostImpl::SetIsScriptableInstance(nsCOMPtr<nsIPluginInstance> aPluginInstance,
|
||||
PRBool aScriptable)
|
||||
{
|
||||
nsActivePlugin * p = mActivePluginList.find(aPluginInstance.get());
|
||||
if(p == nsnull)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
p->mXPConnected = aScriptable;
|
||||
if(p->mPluginTag)
|
||||
p->mPluginTag->mXPConnected = aScriptable;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
NS_IMETHODIMP
|
||||
nsPluginHostImpl::ParsePostBufferToFixHeaders(
|
||||
const char *inPostData, PRUint32 inPostDataLen,
|
||||
char **outPostData, PRUint32 *outPostDataLen)
|
||||
{
|
||||
if (!inPostData || !outPostData || !outPostDataLen)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*outPostData = 0;
|
||||
*outPostDataLen = 0;
|
||||
|
||||
const char CR = '\r';
|
||||
const char LF = '\n';
|
||||
const char CRLFCRLF[] = {CR,LF,CR,LF,'\0'}; // C string"\r\n\r\n"
|
||||
const char ContentLenHeader[] = "Content-length";
|
||||
|
||||
nsAutoVoidArray singleLF;
|
||||
const char *pSCntlh = 0;// pointer to start of ContentLenHeader in inPostData
|
||||
const char *pSod = 0; // pointer to start of data in inPostData
|
||||
const char *pEoh = 0; // pointer to end of headers in inPostData
|
||||
const char *pEod = inPostData + inPostDataLen; // pointer to end of inPostData
|
||||
if (*inPostData == LF) {
|
||||
// from 4.x spec http://developer.netscape.com/docs/manuals/communicator/plugin/pgfn2.htm#1007754
|
||||
// If no custom headers are required, simply add a blank
|
||||
// line ('\n') to the beginning of the file or buffer.
|
||||
// so *inPostData == '\n' is valid
|
||||
pSod = inPostData + 1;
|
||||
} else {
|
||||
const char *s = inPostData; //tmp pointer to sourse inPostData
|
||||
while (s < pEod) {
|
||||
if (!pSCntlh &&
|
||||
(*s == 'C' || *s == 'c') &&
|
||||
(s + sizeof(ContentLenHeader) - 1 < pEod) &&
|
||||
(!PL_strncasecmp(s, ContentLenHeader, sizeof(ContentLenHeader) - 1)))
|
||||
{
|
||||
// lets assume this is ContentLenHeader for now
|
||||
const char *p = pSCntlh = s;
|
||||
p += sizeof(ContentLenHeader) - 1;
|
||||
// search for first CR or LF == end of ContentLenHeader
|
||||
for (; p < pEod; p++) {
|
||||
if (*p == CR || *p == LF) {
|
||||
// got delimiter,
|
||||
// one more check; if previous char is a digit
|
||||
// most likely pSCntlh points to the start of ContentLenHeader
|
||||
if (*(p-1) >= '0' && *(p-1) <= '9') {
|
||||
s = p;
|
||||
}
|
||||
break; //for loop
|
||||
}
|
||||
}
|
||||
if (pSCntlh == s) { // curret ptr is the same
|
||||
pSCntlh = 0; // that was not ContentLenHeader
|
||||
break; // there is nothing to parse, break *WHILE LOOP* here
|
||||
}
|
||||
}
|
||||
|
||||
if (*s == CR) {
|
||||
if (pSCntlh && // only if ContentLenHeader is found we are looking for end of headers
|
||||
((s + sizeof(CRLFCRLF)-1) <= pEod) &&
|
||||
!memcmp(s, CRLFCRLF, sizeof(CRLFCRLF)-1))
|
||||
{
|
||||
s += sizeof(CRLFCRLF)-1;
|
||||
pEoh = pSod = s; // data stars here
|
||||
break;
|
||||
}
|
||||
} else if (*s == LF) {
|
||||
if (*(s-1) != CR) {
|
||||
singleLF.AppendElement((void*)s);
|
||||
}
|
||||
if (pSCntlh && (s+1 < pEod) && (*(s+1) == LF)) {
|
||||
s++;
|
||||
singleLF.AppendElement((void*)s);
|
||||
s++;
|
||||
pEoh = pSod = s; // data stars here
|
||||
break;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
// deal with output buffer
|
||||
if (!pSod) { // lets assume whole buffer is a data
|
||||
pSod = inPostData;
|
||||
}
|
||||
|
||||
PRUint32 newBufferLen = 0;
|
||||
PRUint32 dataLen = pEod - pSod;
|
||||
PRUint32 headersLen = pEoh ? pSod - inPostData : 0;
|
||||
|
||||
char *p; // tmp ptr into new output buf
|
||||
if (headersLen) { // we got a headers
|
||||
// this function does not make any assumption on correctness
|
||||
// of ContentLenHeader value in this case.
|
||||
|
||||
newBufferLen = dataLen + newBufferLen;
|
||||
// in case there were single LFs in headers
|
||||
// reserve an extra space for CR will be added before each single LF
|
||||
int cntSingleLF = singleLF.Count();
|
||||
newBufferLen += cntSingleLF;
|
||||
|
||||
if (!(*outPostData = p = (char*)nsMemory::Alloc(newBufferLen)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// deal with single LF
|
||||
const char *s = inPostData;
|
||||
if (cntSingleLF) {
|
||||
for (int i=0; i<cntSingleLF; i++) {
|
||||
const char *plf = (const char*) singleLF.ElementAt(i); // ptr to single LF in headers
|
||||
int n = plf - s; // bytes to copy
|
||||
if (n) { // for '\n\n' there is nothing to memcpy
|
||||
memcpy(p, s, n);
|
||||
p += n;
|
||||
}
|
||||
*p++ = CR;
|
||||
s = plf;
|
||||
*p++ = *s++;
|
||||
}
|
||||
}
|
||||
// are we done with headers?
|
||||
headersLen = pEoh - s;
|
||||
if (headersLen) { // not yet
|
||||
memcpy(p, s, headersLen); // copy the rest
|
||||
p += headersLen;
|
||||
}
|
||||
} else if (dataLen) { // no ContentLenHeader is found but there is a data
|
||||
// make new output buffer big enough
|
||||
// to keep ContentLenHeader+value followed by data
|
||||
PRUint32 l = sizeof(ContentLenHeader) + sizeof(CRLFCRLF) + 32;
|
||||
newBufferLen = dataLen + l;
|
||||
if (!(*outPostData = p = (char*)nsMemory::Alloc(newBufferLen)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
headersLen = PR_snprintf(p, l,"%s: %ld%s", ContentLenHeader, dataLen, CRLFCRLF);
|
||||
if (headersLen == l) { // if PR_snprintf has ate all extra space consider this as an error
|
||||
nsMemory::Free(p);
|
||||
*outPostData = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
p += headersLen;
|
||||
}
|
||||
// at this point we've done with headers.
|
||||
// there is a possibility that input buffer has only headers info in it
|
||||
// which already parsed and copied into output buffer.
|
||||
// copy the data
|
||||
if (dataLen) {
|
||||
memcpy(p, pSod, dataLen);
|
||||
}
|
||||
|
||||
*outPostDataLen = newBufferLen;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
NS_IMETHODIMP
|
||||
nsPluginHostImpl::CreateTmpFileToPost(const char *postDataURL, char **pTmpFileName)
|
||||
{
|
||||
*pTmpFileName = 0;
|
||||
nsresult rv;
|
||||
PRInt64 fileSize;
|
||||
nsXPIDLCString filename;
|
||||
// stat file == get size & convert file:///c:/ to c: if needed
|
||||
nsCOMPtr<nsILocalFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv) ||
|
||||
(NS_FAILED(rv = NS_InitFileFromURLSpec(file, postDataURL)) && NS_FAILED(rv = file->InitWithPath(postDataURL))) ||
|
||||
NS_FAILED(rv = file->GetFileSize(&fileSize)) ||
|
||||
NS_FAILED(rv = file->GetPath(getter_Copies(filename)))
|
||||
)
|
||||
return rv;
|
||||
if (!LL_IS_ZERO(fileSize)) {
|
||||
nsCOMPtr<nsIInputStream> inStream;
|
||||
rv = NS_NewLocalFileInputStream(getter_AddRefs(inStream), file);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Create a temporary file to write the http Content-length: %ld\r\n\" header
|
||||
// and "\r\n" == end of headers for post data to
|
||||
nsCOMPtr<nsIFile> tempFile;
|
||||
nsresult rv;
|
||||
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempFile));
|
||||
if (tempFile) {
|
||||
tempFile->Append("pluginpost");
|
||||
// mode is 0600 so that it's not world-readable
|
||||
rv = tempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
||||
}
|
||||
nsCOMPtr<nsIOutputStream> outStream;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream),
|
||||
tempFile,
|
||||
(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE),
|
||||
0600); // 600 so others can't read our form data
|
||||
}
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Post data file couldn't be created!");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char p[128];
|
||||
sprintf(p, "Content-length: %ld\r\n\r\n",fileSize);
|
||||
PRUint32 bw = 0, br= 0;
|
||||
rv = outStream->Write(p, bw = PL_strlen(p), &br) ||
|
||||
bw != br ? NS_ERROR_FAILURE : NS_OK;
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to write Post data into tmp file!");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRInt32 size = 1;
|
||||
char buf[1024];
|
||||
while (1) {
|
||||
// Read() mallocs if buffer is null
|
||||
rv = inStream->Read(buf, 1024, &br);
|
||||
if (NS_FAILED(rv) || (PRInt32)br <= 0) break;
|
||||
bw = br;
|
||||
rv = outStream->Write(buf, bw, &br);
|
||||
if (NS_FAILED(rv) || (bw != br)) break;
|
||||
}
|
||||
inStream->Close();
|
||||
outStream->Close();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsXPIDLCString tempFileName;
|
||||
tempFile->GetPath(getter_Copies(tempFileName));
|
||||
*pTmpFileName = PL_strdup(tempFileName);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -365,6 +365,13 @@ public:
|
|||
NS_IMETHOD
|
||||
SetIsScriptableInstance(nsCOMPtr<nsIPluginInstance> aPluginInstance, PRBool aScriptable);
|
||||
|
||||
NS_IMETHOD
|
||||
ParsePostBufferToFixHeaders(const char *inPostData, PRUint32 inPostDataLen,
|
||||
char **outPostData, PRUint32 *outPostDataLen);
|
||||
|
||||
NS_IMETHOD
|
||||
CreateTmpFileToPost(const char *postDataURL, char **pTmpFileName);
|
||||
|
||||
/* Called by GetURL and PostURL */
|
||||
|
||||
NS_IMETHOD
|
||||
|
|
|
@ -1075,18 +1075,9 @@ NS_IMETHODIMP pluginInstanceOwner::GetURL(const char *aURL, const char *aTarget,
|
|||
|
||||
// deal with post data, either in a file or raw data, and any headers
|
||||
if (aPostData) {
|
||||
const char * dataToPost = (const char *)aPostData; // default to raw data
|
||||
nsXPIDLCString filename;
|
||||
|
||||
if (isFile) {
|
||||
// convert file:///c:/ to c: if needed
|
||||
nsCOMPtr<nsILocalFile> aFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
if (NS_SUCCEEDED(NS_InitFileFromURLSpec(aFile,dataToPost)) &&
|
||||
NS_SUCCEEDED(aFile->GetPath(getter_Copies(filename))))
|
||||
dataToPost = filename;
|
||||
}
|
||||
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), dataToPost, aPostDataLen, isFile);
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), (const char *)aPostData, aPostDataLen, isFile);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin post data stream");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aHeadersData) {
|
||||
rv = NS_NewPluginPostDataStream(getter_AddRefs(headersDataStream),
|
||||
|
@ -1095,6 +1086,7 @@ NS_IMETHODIMP pluginInstanceOwner::GetURL(const char *aURL, const char *aTarget,
|
|||
PR_FALSE,
|
||||
PR_TRUE); // last arg says we are headers
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin header data stream");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче