Closed Bug 115308 Opened 23 years ago Closed 23 years ago

[viewpoint] HTTP POST does not handle binary data

Categories

(Core Graveyard :: Plug-ins, defect, P1)

x86
Windows 2000
defect

Tracking

(Not tracked)

VERIFIED FIXED
mozilla0.9.9

People

(Reporter: sdreier, Assigned: srgchrpv)

References

Details

(Whiteboard: ETA: 01/14/02; on the trunk)

Attachments

(6 files, 4 obsolete files)

491.31 KB, application/x-zip-compressed
Details
364.91 KB, application/x-zip-compressed
Details
379.83 KB, application/x-zip-compressed
Details
24.36 KB, patch
bnesse
: review+
Details | Diff | Splinter Review
24.83 KB, patch
bnesse
: review+
darin.moz
: superreview+
Details | Diff | Splinter Review
2.67 KB, text/plain
Details
From Bugzilla Helper: User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; YUBC VeXi; T312461) BuildID: Mozilla 5.0 Gecko/20011019 When using NPN_PostURLNotify() and sending "\x0Hello World" as content, the content is not sent. This works fine on other browsers (ie5.0,ie5.5,ie6.0, NS4.x). If I ommit the leading 0, it works fine, but then it's not binary data anymore. Reproducible: Always Steps to Reproduce: 1.Set up a capture program to view TCP/IP transactions 2.Send some binary POST data. 3.
Status: UNCONFIRMED → NEW
Ever confirmed: true
OK, there's something to this bug, and since it's a blocker for Flash, I'm adding all the keywords. NPN_PostURLNotify( ) is NPAPI stuff -- Darin, if you rule out Necko, then we ought to hand this one off. But I'm slapping an edt0.9.4 and a mozilla0.9.7 since the importance of this bug warrants the keywords.
Argh, I'm also nsbranching this one. Shoot me if nsbranch is a relic.
Keywords: nsbranch
this is a problem in the plugins code... over to plugins.
Assignee: darin → av
Component: Networking: HTTP → Plug-ins
QA Contact: tever → shrir
Scott, I just fixed this in bug 108966. Please try a build from this afternoon or Monday morning. *** This bug has been marked as a duplicate of 108966 ***
Status: NEW → RESOLVED
Closed: 23 years ago
Resolution: --- → DUPLICATE
v d
Status: RESOLVED → VERIFIED
minusing, this was fixed elsewhere.
Keywords: edt0.9.4edt0.9.4-
After talking with Shrirang, since this (115308) was marked dup of 108966, 108966 got fixed,but this one still doesn't work, so this is not duplicated with 108966. I try to post http requests to Jrun server, didn't see any requests through tcpmon, so reopen it. Thanks. Jody
Status: VERIFIED → REOPENED
Resolution: DUPLICATE → ---
Jody, can you post a link to your testcase or attach it here? It seems to be working for me but there may have been a quirk in 4.x that I missed... I've attached a testcase with two tester plugins showing us POSTing binary data. Use only one at a time.
a testcase showing no http request is post.
-->peterl and renominating....
Assignee: av → peterl
Status: REOPENED → NEW
Keywords: edt0.9.4-edt0.9.4
missed mozilla0.9.7 but still edt0.9.4
Status: NEW → ASSIGNED
Will plus 094 once fixed and verified om the trunk.
Severity: major → critical
Keywords: testcase
Priority: -- → P1
Jody, The zip file you attached was missing the movie file (bug.swf) and I saw no NPN_PostURL calls. Could you double check the testcase to make sure everything is there. Also, it possible, it would really help if you could look in the debugger and take note of the values of the arguments being passed to NPN_PostURL. Knowing that the exact arguments would really help in reproducing. Thanks!
Keywords: testcaseqawanted
-->av
Assignee: peterl → av
Status: ASSIGNED → NEW
with test case from attachment 63128 [details] when I stop into _posturlnotify(_NPP * 0x01057750, const char * 0x00186c38, const char * 0x00000000, unsigned long 402, const char * 0x03ce2110, unsigned char 0, void * 0x00000003) line 765 + 56 bytes NPSWF32_6! NP_Shutdown + 185 bytes NPSWF32_6! NP_Shutdown + 9683 bytes NPSWF32_6! native_ShockwaveFlash_TCallFrame + -41978 bytes NPSWF32_6! native_ShockwaveFlash_TCallFrame + -42229 bytes .... I got len == unsigned long 402 const char *buf ==: 03CE2110 43 6F 6E 74 65 6E 74 2D 74 79 70 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 78 2D 6D 6D 2D 66 Content-type: application/x-mm-f 03CE2130 6D 66 0A 43 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 33 34 34 0A 0A 00 00 00 00 00 02 00 30 mf.Content-length: 344.........0 which is incomplete header and NS_NewPluginPostDataStream() fails on 157 if (!(crlf = PL_strnstr(data, "\r\n\n", contentLength))) { 158 nsMemory::Free(newBuf); 159 return NS_ERROR_NULL_POINTER; 160 } ... there is no "\x0Hello World" in there, did I miss something, what is the content?
Should we be looking for \n\n as the marker for the end of the header instead of \r\n\n? See bug 60228 for the orrignal source of that code.
Serge has a hand on it. Reassigning, please feel free to bounce it back to me.
Assignee: av → serge
according to the 4.x spec http://developer.netscape.com/docs/manuals/communicator/plugin/pgfn2.htm#1007763 >NPN_PostURLNotify supports specifying headers when posting a memory buffer. below line #1007754 >For protocols in which the headers must be distinguished from the body, such as >HTTP, the buffer or file should >contain the headers, followed by a blank line, then the body. If no custom >headers are required, simply add a blank >line ('\n') to the beginning of the file or buffer. So do we have to check for single '\n', "\n\n" or "\r\n\n"?
From HTTP1.1 spec: generic-message = start-line *(message-header CRLF) CRLF [ message-body ] start-line = Request-Line | Status-Line So, looks like each header should be terminated with CRLF. In addition, one more CRLF should be added to the end of the last header. So, I see it like this: 1. if we see '\n' and some char following, that means there is no header. We should replace it with "\r\n" 2. if we see "\r\n\n" or "\n\n" this probably means somebody wrongfully indicated the end of the headers, and we should fix it with "\r\n\r\n" again 3. I think we also should fix all previous occurences of a single '\n' between headers Serge, can you try this and if it fixes the problem?
...and SEE if it fixes the problem? I can imaging why this is happenning. The Plugin doc says "\n" so people do just that. The HTTP spec says "\r\n" and Necko probably expects it exactly in this form. Does it make sense to anybody?
it's good to use \r\n, but traditionaly \n is okay too. mixing them can be problematic and probably confuses more than just a couple servers out there.
Wow, we really need to do a lot of fix up on the raw headers before passing them to Necko. I wonder if something else can already do this for us, Darin? If not, |NS_NewPluginPostDataStream| will need to be smart enough fix up the stream like Andrei says in comment #20. The NPAPI spec says one thing and the HTTP sepc says another and we need to be prepared for all kinds of input.
Attached patch patch v1 (obsolete) — Splinter Review
Serge, would you please explain what the patch does? This will be useful for those who just wants to know what we are doing not going into implementation details.
Well, I've just slightly changed peter's implementation (attachment 62115 [details] [diff] [review] for bug #108966) of NS_NewPluginPostDataStream(), it does handle "\n\n" as end of http headers and first single '\n' as buffer w/o headers. Peter, could you take a look on the patch, please?
Comment on attachment 63929 [details] [diff] [review] patch v1 r=peterl
Attachment #63929 - Flags: review+
peter: AFAIK there aren't any utility functions in the code base that you can use to perform this fixup.
Comment on attachment 63929 [details] [diff] [review] patch v1 sr=darin but, this function should really be added as a method on some service. NS_NewPluginPostDataStream should really be a lightweight wrapper function instead.
Attachment #63929 - Flags: superreview+
We are having a related plugin with our viewpoint windowless plugin. I am not sure if it should be a different bug. I post using NPN_PostURLNotify. I applied the patch mentioned in this bug. I am posting data- just some text (eg abcdefg). I prepend it with \n, so the data I put in is "\nabcdefg". The data gets posted to the server, which responds with a 400. I look using a TCP peek program, and the problem seems to be that NONE of the http headers are there. There is no POST, no http 1.1, no url. Is there anything obvious that comes to mind? I will put together a test case ASAP. I am working on the .9.4 branch.
Ari, you are right, without Content-length: header POST request is not going to work. We have to add that header if there is no one, that is easy, but what about Content-type: do we have to add it as "text/html" if it's missing? Darin what do you think? Thanks.
I had an impression that Necko should care of this if the |postHeaders| is null.
it's important that the content-length be specified. otherwise, the server won't know the length of the http request and therefore won't know when the request has been completely sent. the content-type header on the other hand is probably not so essential. does the plugin API even provide a way for the plugin to specify the content-type? i think it's probably safe to leave out a content-type header if the plugin fails to provide one in the plugin data stream.
The code eventualy calls nsILinkHandler::OnLinkClick(..., postDataStream, postHeadersStream) Here is my vision of how it works. Before it comes to it a plugin can tell us that it has a header in a separate buffer (e.g. Java plugin). In this case we create two streams: for the raw data and the headers and pass them to the link handler. Legacy plugins however do not have this kind of access, well they actualy do, but they cannot do this via NPAPI, so they give us a buffer which may or may not content headers. In the code which is being fixed in this bug we try to find the headers and fix them if they are not up to the spec. Whether there are headers or not we now create only one stream -- |postDataStream|, which will include headers in itself and pass |null| in place of |postHeadersStream| If all this is correct, it does not look right to me. I would expect |OnLinkClick| to create headers for me if the |postHeadersData| is |null|. This is OK if the data from the plugin is just a raw data but we don't want more headers if the data already contain them. Looks like the logic in |nsPluginInstanceOwner::PostURL| should be rewritten. We shuold probably separate the headers (if found) from the data and pass them separately to the link handler. If not found, the link handler will create some default headers for us (should it?). Darin, does it make sense?
The last two paragraphs in my last comment are probably not quite accurate. The standard header should be added by Necko in any case. Any additional headers the plugin wants to add can be done either as a separate buffer or as a part of the data buffer. We just need to make sure all CR and LF chars are in appropriate places.
That is right, I'm writing data buffer parser, which should be smart enough to figure out end of headers, if header separator is LF change it to CRLF, because our standard headers use it, and if there is no content-length header add it to the stream. Definitely this parser should be implemented as a method of some service, the question is which one, av, peterl any suggestions? BTW: in current implementation every thing work fine when content-length header is present, headers separator is CRLF and end of headers is CRLFCRLF.
As folks like chofmann and others are looking to plan some embedding stuff off of the branch, they need eta data.
Whiteboard: need eta
I'm going to post new patch probably tomorrow, so ETA: 01/14/02
Whiteboard: need eta → ETA: 01/14/02
I run into some discrepancy for POST url as file, I have not figure out how we add content len header and CRLFCRLF as end of http headers to the post data stream. Does it work before? Investigating...
Files go down a different code path, through NS_NewPostDataStream which creates an instance of the LocalFileInputStream component so it may be harder to do the fixup, if needed?
Summary: HTTP POST does not handle binary data → [viewpoint] HTTP POST does not handle binary data
av, peter would you please take a look on this, thanks.
Attachment #63929 - Attachment is obsolete: true
Darin, who should be responsible for adding content-length header? I think we should be consistent on this. I talked to gagan and he said that there was a discussion that Necko side should evaluate the length of the data and take care of the header. What is the latest? Another question. |nsILinkHandler::OnLinkClick| takes post data stream and headers stream. Post data may or may not contain headers, headers stream may or may not be present at all. Are all of those cases accounted for?
take a look at the implementation in nsHttpChannel::SetUploadStream. necko doesn't know if the given nsIInputStream contains headers or not, so if in the call to: SetUploadStream(in nsIInputStream, in string contentType, in long contentLength) contentType is null, necko will assume that the input stream contains all necessary headers as well as the required header/body line break. if contentType is not-null, then necko will assume that the input stream contains only the message body (w/o any headers). then necko will use the specified contentType and contentLength to set appropriate request headers.
> contentType is null, necko will assume that the input stream contains all > necessary headers By 'all' -- do you mean ALL, even standard headers?
i mean that the stream must contain at least Content-Type and Content-Length headers. the usual request headers will be automatically sent first.
well, the patches for bugs 112479 119625 (with implementation Darin described) are not on the 0.9.4 branch, we can't use it in there anyway.
Attachment #64910 - Attachment is obsolete: true
Whiteboard: ETA: 01/14/02 → ETA: 01/14/02; have a patch, needs review
Blocks: 119979
Attachment #64950 - Attachment is obsolete: true
can we get r/sr on this?
In nsPluginHostImpl::PostURL() it appears that the incoming argument |postData| is replaced with either |tmpFileName| or |newDataToPost| at the bottom, if |isFile| is true, this is freed. This seems prone to a) leaking the original contents of |postData| and b) returning a deleted pointer... both concern me. In ParsePostBufferToFixHeaders() + const char *pEod = inPostData + inPostDataLen; + while (s <= pEod) { Is the buffer 0 terminated (i.e. 1 byte longer than inPostDataLen?) if not, you could read past the end of the buffer here... + if (!pSCntlh && + (*s == 'C' || *s == 'c') && + (s + sizeof(ContentLenHeader) - 1 <= pEod) && [snipped] + s += sizeof(ContentLenHeader); This seems dangerous also, if size - 1 == pEod s + size is past the buffer end. In CreateTmpFileToPost() + nsCOMPtr<nsILocalFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); + if (NS_FAILED(rv) || + (NS_FAILED(rv = file->SetURL(postDataURL)) && NS_FAILED(rv = file->InitWithPath(postDataURL))) || This doesn't compile on the Mac... I don't think SetURL is a member of nsILocalFile...
Thank you Brain for quick review. >This seems prone to a) leaking the original >contents of |postData| and b) returning a deleted pointer... both concern me I do free only memory I've alloced in rv = CreateTmpFileToPost(postData, &tmpFileName) call original contents of |postData| is (const char*) and we cannot modify it. >+ while (s <= pEod) { You are right, probably I wa plaing with '\n' case at start of buffer, or something..:( I'll chahge all <= pEod to < pEod >+ s += sizeof(ContentLenHeader); it's going to be + s += sizeof(ContentLenHeader) -1; >This doesn't compile on the Mac... I don't think SetURL is a member of nsILocalFile the patch (attachment 64164 [details] [diff] [review]) for bug 100212 remove "URL" attribute from nsIFile.idl I'm going to change it for the trunk, but it should be still valid in 0.9.4 branch
>I do free only memory I've alloced in rv = CreateTmpFileToPost(postData, >&tmpFileName) call original contents of |postData| is (const char*) and we >cannot modify it. This is true, but the memory allocated by this call (in the !isFile case) + ParsePostBufferToFixHeaders(postData, postDataLen, &newDataToPost, &newDataToPostLen); is not freed because: + if (isFile && postData) { + nsCRT::free((char*)postData); + } It seems to me that the code would more readable if you simply got the new name into a common local variable in both cases instead of trying to reuse the input argument.
we are using nsIStringInputStream::adoptData(char *data, int length) to set the stream, on destroy stream calls nsMemory::Freei() for data. >It seems to me that the code would more readable if you simply got the new >name... I agree.
Ok, I think I see it... that is absolutely screaming for some comments to explain why we appear to be not releasing memory, etc. Thanks for clearing it up for me.
Attachment #64967 - Attachment is obsolete: true
Comment on attachment 65125 [details] [diff] [review] v4 for 01-15-02 trunk, which addresses all Brain's comments + PRInt64 fileSize; [snip] + if (fileSize != 0) { You should use the LL_ macros (i.e. LL_IS_ZERO(fileSize)) when using 64 bit ints to insure no XP issues. With that fix. r=bnesse.
Attachment #65125 - Flags: review+
>You should use the LL_ macros (i.e. LL_IS_ZERO(fileSize)) will do so, thanks Brian.
Three minor things after I looked at the patch briefly (sorry, had absolutely no chance to do it earlier): 1. |newDataToPost| should be primed with null. The parser function can be rewritten later and somebody may forget to assign null there. 2. instead of doing if (!something) return NS_ERROR_NULL_POINTER; we should go NS_ENSURE_ARG_POINTER(something); 3. if (isFile && tmpFileName) { nsCRT::free(tmpFileName); why to check |isFile|? All those maybe fine for the branch check in but would be nice to fix on the trunk.
ok, so i looked over the patch... it's rough, but seems accurate to me. for example, the uses of sprintf should be replaced with PR_snprintf... please never ever use sprintf. it makes code very fragile. also there is an indentation problem in the PostURL() method. at any rate, sr=darin
on the 0.9.4 branch: Checking in modules/plugin/base/src/nsPluginHostImpl.cpp; new revision: 1.288.2.16; previous revision: 1.288.2.15 -- Checking in modules/plugin/base/src/nsPluginHostImpl.h; new revision: 1.55.14.6; previous revision: 1.55.14.5 -- Checking in modules/plugin/base/src/nsIPluginHost.h; new revision: 1.20.116.2; previous revision: 1.20.116.1 -- Checking in modules/plugin/base/src/nsPluginViewer.cpp; new revision: 1.74.2.7; previous revision: 1.74.2.6 -- Checking in modules/plugin/base/public/nsPIPluginHost.h; new revision: 1.1.64.1; previous revision: 1.1 -- Checking in layout/html/base/src/nsObjectFrame.cpp; new revision: 1.248.2.23; previous revision: 1.248.2.22
Well, I don't post binary data, so I can't verify that part. But I have verified that I no longer need to prepend the content-length header. Works for me.
Thx for the help, Ari !
Keywords: verified0.9.4
It appears that this may be working as expected with CS/Talon 112a Launch CS/Talon Go to http://lxr.mozilla.org/mozilla/source/modules/plugin/tools/tester Select "Click here to launch the tester" I set the following parameters: API call = NPN_PostURL URL = http://www.mozilla.gr.jp:4321 Target = _npapi_Display (default) buf = "Hello World" file = FALSE (default) Select GO button Results: len = 11 (sets itself automatically) Top frame contains: HTTP Client Net Debugger Server: Tokyo.Mozilla.Gr.JP/210.160.137.138, Port: 4321 Client: x98A3A5C2.pix.aol.com/152.163.165.194, Port: 3138 ---------------- HTTP Request & Body POST / HTTP/1.1 Host: www.mozilla.gr.jp:4321 User-Agent: Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.4.2) Gecko/20020120 CS 2000 7.0/7.0 Accept: text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, image/png, image/jpeg, image/gif;q=0.2, text/plain;q=0.8, text/css, */*;q=0.1 Accept-Language: en-us Accept-Encoding: gzip, deflate, compress;q=0.9 Keep-Alive: 300 Connection: keep-alive Referer: http://lxr.mozilla.org/mozilla/source/modules/plugin/tools/tester/testcase/teste r.html Content-length: 11 Hello World ----------------------------------------------- HTTP Response (Content-Length omitted) ======================================================================== The Lower Frame Contains: NPN_PostURL(0x01e87eb4, 0x0065f418("http://www.mozilla.gr.jp:4321/"), 0x0065f398("_npapi_Display"), 11, 0x0065f318("Hello World"), FALSE) Returns: NPERR_NO_ERROR Time: 91243 91243 (0)
Comment on attachment 66065 [details] [diff] [review] v5 the same as v4, with PR_snprintf, and manor changes in nsPluginHostImpl::ParsePostBufferToFixHeaders() Additional changes appear ok. r=bnesse.
Attachment #66065 - Flags: review+
Comment on attachment 66065 [details] [diff] [review] v5 the same as v4, with PR_snprintf, and manor changes in nsPluginHostImpl::ParsePostBufferToFixHeaders() sr=darin
Attachment #66065 - Flags: superreview+
Thanks all. Checked into the trunk. Nominating for 0.9.8 branch.
Keywords: mozilla0.9.8
Whiteboard: ETA: 01/14/02; have a patch, needs review → ETA: 01/14/02; on the trunk
Target Milestone: --- → mozilla0.9.8
resolved as fixed
Status: NEW → RESOLVED
Closed: 23 years ago23 years ago
Resolution: --- → FIXED
Target Milestone: mozilla0.9.8 → mozilla0.9.9
this did not land for 0.9.8 so anyone working with the 0.9.8 branch who needs this will want to patch their tree.
.
Status: RESOLVED → VERIFIED
Keywords: qawanted
Keywords: fixed0.9.4
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: