mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
4e6138a54f
- remove PM alertTime custom (911dd825ec) - Bug 1208346 - Alert service Do Not Disturb backend. r=jaws (0047051b4e) - Bug 1208346 - Fix manualDoNotDisturb build bustage on Android. r=bustage (39275a49bd) - Add some shadow warnings back (64eb2adf55) - some window fixes by Roy (72e6a9b98e) - remove parameter of DoesD3D11DeviceWork (243dfb24f4) - Bug 1197296. Check the error code of Map. r=bas (9debd274fd) - Bug 1221348 - Part 1: Unify crash signatures. r=jrmuizel (80763d326d) - Bug 1221348 - Part 2: Fix texture sharing detection code on Intel. r=jrmuizel (fb0390850d) - Bug 1097321 - Add layers.amd-switchable-gfx.enabled pref. r=jrmuizel (3963a35cbc) - Bug 720589 - mMatchCounts may be accessed with a nonexisting index. r=neil (fdbdd7e228) - Bug 1224975 - add telemetry for font loading. r=m_kato (013a6e8fc7) - Bug 1188376: Split Hello Telemetry values from general WebRTC r=jib (3887cc3201) - Bug 1198883 - Part 1: Improve ICE candidates telemetry probes. r=bwc (2d02a3d752) - Bug 1198883 - Part 2: Added WebRTC ICE candidates to Telemetry. r+vladan (fa8032043f) - Bug 1201926 - Add support for keyed histograms to Fennec's Telemetry module, r=nalexander (8b96ebf026) - Bug 1213780 - Fix Telemetry reporting repeated hang annotations for Chrome hangs. r=aklotz (afde812b08) - Bug 1128768: Part 4 - Update telemetry to serialize BHR hang annotations; r=gfritzsche (7c1b8f5fa5) - Bug 1215540 - Fix Telemetry reporting repeated hang annotations for Thread hangs. r=aklotz (afed35f06f) - Bug 896740 - Limit the number of chrome-hangs reported to Telemetry. r=vladan (a37ba72225) - missing bits of Bug 932865 - Expose thread hang stats (c19c41ae06) - Bug 1187138 (part 1) - Replace nsBaseHashtable::Enumerate() calls in toolkit/ with iterators. r=froydnj. (ba92a8464f) - Bug 1121040 - Don't send RETURN keypresses to content while a satchel autocomplete entry is selected. r=Gijs,smaug (762efd7cc8) - Bug 1145146 - Remove offensive comment from nsFormFillController r=mak (7a6b0eb4e1) - Bug 1136085 - Part 1 - Don't store & collect subsession histograms on mobile. r=vladan (911084001c) - missing bits of Bug 1023461 - Add HangStack class to support internal string buffer; r=vladan (599bee2150) - Bug 1196381 - Eliminate breakpad dependency in ThreadStackHelper; r=nfroyd r=snorp (ff8a632975) - fix misspatch of 1157282 and 1198883 (9a216ab188) - Bug 1034138 - a. Get native stack for permahangs in BHM; r=snorp (772970d0e0) - Bug 1211411 - Limit the number of thread hang stats reported to Telemetry. r=vladan (fd72bc8b62) - Bug 1219751 - Change the the depth limit of the thread hangs stack to use the 99th percentile. r=gfritzsche (fc59bd7598) - Bug 1133521 - Enable BHR on Beta. r=vladan (2501c6a0ff) - Bug 1219216 - Fix a wrong comment in BackgroundHangMonitor.h. r=gfritzsche (e974320361) - bits of Bug 1134279 - Change Telemetry data producers to use the correct (d00e84b7f3) - bits of Bug 977026 - Part 2: B2G loader (bf1208a73a) - bug 1198450 - Firefox fails to load about:home if Firefox was installed to a folder with non-Latin name r=jimm (c4df06a69e) - Bug 1222167 - fix initialization order in GeckoChildProcessHost; r=jld (6bad274479) - Bug 1141693 - Build and use a PIE plugin-container on Android 5.0+. Based on a patch by Mike Hommey. r=me,glandium (78dc877aec) - Bug 1187533 - Change how Gtk+2 plugin-container is started on Gtk+3 builds. r=billm (93c2b8a1b0) - Bug 1063359 - Unconditionally use -Wl,--no-as-needed when building with GNU ld/gold. r=mshal (643e92ca49) - Bug 971811 - Don't prepend an empty existing DYLD_INSERT_LIBRARIES path when launching the plugin. r=smichaud (c72df0073c) - Bug 1189352: Fix NSPR_LOG_FILE with absolute paths for sandboxed child on Windows. r=bbondy (f4bb51c123) - Bug 1189967 - Be slightly more explicit about some conversions to std::wstring. r=nfroyd (7bec611359) - Bug 1201438: Add non-sandboxed Windows content processes as target peers for handle duplication. r=bbondy (1ca7f499e9) - Bug 1201438 - Fixup for builds with disabled sandbox. (de125d156e) - Bug 1165895: Add NPAPI sandbox rule for the crash server pipe and x64 Temp dir write access. r=bbondy (e9f601912d) - Bug 1202988 - Don't use GetTempPath for flash's mms.cfg hack for low integrity. r=aklotz (b4a0d7f856) - Bug 1225023: Allow Flash Player to create Adobe\Flash Player and Macromedia\Flash Player directories. r=bbondy (c5120afc1d) - Bug 1218681 - add plugin-container standalone process code. The Code associate with ARCH. r=hev (03dfb21776) - bug 1130976 - Flash context menu causes CPOW deadlock with AdBlock Plus, plugins should spin even loop in content process instead of the chrome process r=billm (52f4d33633) - Bug 1157237: Move invocation of async NPP_New to an async task; r=jimm (7b6c1a577e) - Bug 1175147 - Don't do threadsafety asserts for NPN_MemAlloc and friends, r=jimm (b4ce5b33ce) - fix strange misspatch (8a96a61819) - Bug 1219244 - use UniquePtr instead of nsAutoArrayPtr in dom/plugins/; r=aklotz (19fabc55b5) - Bug 1155503: BrowserStreamParent should null out its NPStream pointer and we should check for it; r=jimm (eddb82b8b4) - some crashrep stuff (bb2b046090) - Bug 1192077 - Convert AndroidBridge JNIEnv calls; r=esawin (821453089e) - Bug 554171 - Add plugin thread checks to functions that must only be called on the main thread. r=jimm (f2eb3822da) - Bug 1149358: Ensure that plugin streams are not manipulated by PluginAsyncSurrogate if plugin destruction is imminent; r=jimm (6dd99c94ee) - Bug 1198302 - Ensure that PluginAsyncSurrogate::NotifyAsyncInitFailed properly aborts any PluginAsyncSurrogate::WaitForInit calls. r=jimm (23c1fbfcfe) - Bug 1201239 - Add a proper null check in PluginAsyncSurrogate::NotifyAsyncInitFailed; r=jimm (5d8ff9f8aa) - Bug 1208059: Make nsNPAPIPluginInstance support WeakPtr and modify PluginAsyncSurrogate to use it; r=jimm (174a3166b1) - Bug 1171453: Make ParentNPObjects aware of AsyncNPObject wrappers; r=jimm (92e608831d) - Bug 1217726 - Fix -Wimplicit-fallthrough warnings in dom/plugins. r=jimm (32db26ede8) - Bug 1167720 - Fix invalid window ID provided to GTK3 plugin container children. r=karlt (d8c2de0c19) - Remove Windows-specific synchronous plugin drawing code. (bug 1218688 part 1, r=jimm) (5e4b60ea33) - Remove Linux-specific synchronous plugin drawing code. (bug 1218688 part 2, r=jimm) (edb29f27b8) - Remove Mac-specific synchronous plugin drawing code. (bug 1218688 part 3, r=benwa) (acc6b57b23) - Assert that we do not attempt synchronous painting of windowless Desktop plugins. (bug 1218688 part 4, r=bsmedberg) (c34094b038) - Bug 1195472 - Call Show after Enable on puppet widgets to avoid an assertion when running crash tests. r=aklotz (405ed2c1d1) - Add explicit keyword to AsyncScrollBase constructor to fix static analysis build (bug 1139220 part 6, r=shu) (4cc37b9a3b) - Bug 1146561 - Add back the visibility check for Mac plugins. r=jmuizelaar (91a4a5a8e9) - namespace (9b4919f8fa) - Bug 1217307 - Remove some unnecessary null checks in rest of dom/. r=njn (de5d69880a) - Bug 1225137 - Avoid crash on some platforms if scrollbar fading is enabled and the duration is set to zero. r=spohl (a16954de2f) - Bug 1114554 - Disable NotificationStorage debug logging. r=dholbert (c2722fa4ed) - Bug 1073551 - fix doorhangers to not steal focus unless explicitly opened using mouse or keyboard, r=jaws (be6109cf6d) - Bug 1169629: Add-on install confirmation notification appears anchored to older dismissed anchors. r=dao (684535c7cc) - Bug 1194706: make sure that the notification icons and doorhangers are shown in undocked chat windows too. r=Mossop (68e0ced913) - Bug 1207089 - Telemetry for permission notifications. r=MattN,vladan (ff421236ea) - Bug 1215526 - part 4 - make preprocess-tab-svgs.py report extra dependencies; r=glandium (98b64b5c45)
854 lines
26 KiB
C++
854 lines
26 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsFormSubmission.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIForm.h"
|
|
#include "nsILinkHandler.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsIFormControl.h"
|
|
#include "nsIDOMHTMLFormElement.h"
|
|
#include "nsError.h"
|
|
#include "nsGenericHTMLElement.h"
|
|
#include "nsAttrValueInlines.h"
|
|
#include "nsISaveAsCharset.h"
|
|
#include "nsIFile.h"
|
|
#include "nsDirectoryServiceDefs.h"
|
|
#include "nsStringStream.h"
|
|
#include "nsIURI.h"
|
|
#include "nsIURL.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsLinebreakConverter.h"
|
|
#include "nsEscape.h"
|
|
#include "nsUnicharUtils.h"
|
|
#include "nsIMultiplexInputStream.h"
|
|
#include "nsIMIMEInputStream.h"
|
|
#include "nsIMIMEService.h"
|
|
#include "nsIConsoleService.h"
|
|
#include "nsIScriptError.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsCExternalHandlerService.h"
|
|
#include "nsIFileStreams.h"
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "mozilla/dom/EncodingUtils.h"
|
|
#include "mozilla/dom/File.h"
|
|
|
|
using namespace mozilla;
|
|
using mozilla::dom::EncodingUtils;
|
|
|
|
static void
|
|
SendJSWarning(nsIDocument* aDocument,
|
|
const char* aWarningName,
|
|
const char16_t** aWarningArgs, uint32_t aWarningArgsLen)
|
|
{
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
NS_LITERAL_CSTRING("HTML"), aDocument,
|
|
nsContentUtils::eFORMS_PROPERTIES,
|
|
aWarningName,
|
|
aWarningArgs, aWarningArgsLen);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
class nsFSURLEncoded : public nsEncodingFormSubmission
|
|
{
|
|
public:
|
|
/**
|
|
* @param aCharset the charset of the form as a string
|
|
* @param aMethod the method of the submit (either NS_FORM_METHOD_GET or
|
|
* NS_FORM_METHOD_POST).
|
|
*/
|
|
nsFSURLEncoded(const nsACString& aCharset,
|
|
int32_t aMethod,
|
|
nsIDocument* aDocument,
|
|
nsIContent* aOriginatingElement)
|
|
: nsEncodingFormSubmission(aCharset, aOriginatingElement),
|
|
mMethod(aMethod),
|
|
mDocument(aDocument),
|
|
mWarnedFileControl(false)
|
|
{
|
|
}
|
|
|
|
virtual nsresult AddNameValuePair(const nsAString& aName,
|
|
const nsAString& aValue) override;
|
|
virtual nsresult AddNameFilePair(const nsAString& aName,
|
|
mozilla::dom::File* aFile) override;
|
|
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
|
|
nsIInputStream** aPostDataStream)
|
|
override;
|
|
|
|
virtual bool SupportsIsindexSubmission() override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual nsresult AddIsindex(const nsAString& aValue) override;
|
|
|
|
protected:
|
|
|
|
/**
|
|
* URL encode a Unicode string by encoding it to bytes, converting linebreaks
|
|
* properly, and then escaping many bytes as %xx.
|
|
*
|
|
* @param aStr the string to encode
|
|
* @param aEncoded the encoded string [OUT]
|
|
* @throws NS_ERROR_OUT_OF_MEMORY if we run out of memory
|
|
*/
|
|
nsresult URLEncode(const nsAString& aStr, nsCString& aEncoded);
|
|
|
|
private:
|
|
/**
|
|
* The method of the submit (either NS_FORM_METHOD_GET or
|
|
* NS_FORM_METHOD_POST).
|
|
*/
|
|
int32_t mMethod;
|
|
|
|
/** The query string so far (the part after the ?) */
|
|
nsCString mQueryString;
|
|
|
|
/** The document whose URI to use when reporting errors */
|
|
nsCOMPtr<nsIDocument> mDocument;
|
|
|
|
/** Whether or not we have warned about a file control not being submitted */
|
|
bool mWarnedFileControl;
|
|
};
|
|
|
|
nsresult
|
|
nsFSURLEncoded::AddNameValuePair(const nsAString& aName,
|
|
const nsAString& aValue)
|
|
{
|
|
// Encode value
|
|
nsCString convValue;
|
|
nsresult rv = URLEncode(aValue, convValue);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Encode name
|
|
nsAutoCString convName;
|
|
rv = URLEncode(aName, convName);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
// Append data to string
|
|
if (mQueryString.IsEmpty()) {
|
|
mQueryString += convName + NS_LITERAL_CSTRING("=") + convValue;
|
|
} else {
|
|
mQueryString += NS_LITERAL_CSTRING("&") + convName
|
|
+ NS_LITERAL_CSTRING("=") + convValue;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsFSURLEncoded::AddIsindex(const nsAString& aValue)
|
|
{
|
|
// Encode value
|
|
nsCString convValue;
|
|
nsresult rv = URLEncode(aValue, convValue);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Append data to string
|
|
if (mQueryString.IsEmpty()) {
|
|
mQueryString.Assign(convValue);
|
|
} else {
|
|
mQueryString += NS_LITERAL_CSTRING("&isindex=") + convValue;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsFSURLEncoded::AddNameFilePair(const nsAString& aName,
|
|
mozilla::dom::File* aFile)
|
|
{
|
|
if (!mWarnedFileControl) {
|
|
SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0);
|
|
mWarnedFileControl = true;
|
|
}
|
|
|
|
nsAutoString filename;
|
|
if (aFile) {
|
|
aFile->GetName(filename);
|
|
}
|
|
|
|
return AddNameValuePair(aName, filename);
|
|
}
|
|
|
|
static void
|
|
HandleMailtoSubject(nsCString& aPath) {
|
|
|
|
// Walk through the string and see if we have a subject already.
|
|
bool hasSubject = false;
|
|
bool hasParams = false;
|
|
int32_t paramSep = aPath.FindChar('?');
|
|
while (paramSep != kNotFound && paramSep < (int32_t)aPath.Length()) {
|
|
hasParams = true;
|
|
|
|
// Get the end of the name at the = op. If it is *after* the next &,
|
|
// assume that someone made a parameter without an = in it
|
|
int32_t nameEnd = aPath.FindChar('=', paramSep+1);
|
|
int32_t nextParamSep = aPath.FindChar('&', paramSep+1);
|
|
if (nextParamSep == kNotFound) {
|
|
nextParamSep = aPath.Length();
|
|
}
|
|
|
|
// If the = op is after the &, this parameter is a name without value.
|
|
// If there is no = op, same thing.
|
|
if (nameEnd == kNotFound || nextParamSep < nameEnd) {
|
|
nameEnd = nextParamSep;
|
|
}
|
|
|
|
if (nameEnd != kNotFound) {
|
|
if (Substring(aPath, paramSep+1, nameEnd-(paramSep+1)).
|
|
LowerCaseEqualsLiteral("subject")) {
|
|
hasSubject = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
paramSep = nextParamSep;
|
|
}
|
|
|
|
// If there is no subject, append a preformed subject to the mailto line
|
|
if (!hasSubject) {
|
|
if (hasParams) {
|
|
aPath.Append('&');
|
|
} else {
|
|
aPath.Append('?');
|
|
}
|
|
|
|
// Get the default subject
|
|
nsXPIDLString brandName;
|
|
nsresult rv =
|
|
nsContentUtils::GetLocalizedString(nsContentUtils::eBRAND_PROPERTIES,
|
|
"brandShortName", brandName);
|
|
if (NS_FAILED(rv))
|
|
return;
|
|
const char16_t *formatStrings[] = { brandName.get() };
|
|
nsXPIDLString subjectStr;
|
|
rv = nsContentUtils::FormatLocalizedString(
|
|
nsContentUtils::eFORMS_PROPERTIES,
|
|
"DefaultFormSubject",
|
|
formatStrings,
|
|
subjectStr);
|
|
if (NS_FAILED(rv))
|
|
return;
|
|
aPath.AppendLiteral("subject=");
|
|
nsCString subjectStrEscaped;
|
|
aPath.Append(NS_EscapeURL(NS_ConvertUTF16toUTF8(subjectStr), esc_Query,
|
|
subjectStrEscaped));
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
nsFSURLEncoded::GetEncodedSubmission(nsIURI* aURI,
|
|
nsIInputStream** aPostDataStream)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
*aPostDataStream = nullptr;
|
|
|
|
if (mMethod == NS_FORM_METHOD_POST) {
|
|
|
|
bool isMailto = false;
|
|
aURI->SchemeIs("mailto", &isMailto);
|
|
if (isMailto) {
|
|
|
|
nsAutoCString path;
|
|
rv = aURI->GetPath(path);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
HandleMailtoSubject(path);
|
|
|
|
// Append the body to and force-plain-text args to the mailto line
|
|
nsCString escapedBody;
|
|
escapedBody.Adopt(nsEscape(mQueryString.get(), url_XAlphas));
|
|
|
|
path += NS_LITERAL_CSTRING("&force-plain-text=Y&body=") + escapedBody;
|
|
|
|
rv = aURI->SetPath(path);
|
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIInputStream> dataStream;
|
|
// XXX We *really* need to either get the string to disown its data (and
|
|
// not destroy it), or make a string input stream that owns the CString
|
|
// that is passed to it. Right now this operation does a copy.
|
|
rv = NS_NewCStringInputStream(getter_AddRefs(dataStream), mQueryString);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIMIMEInputStream> mimeStream(
|
|
do_CreateInstance("@mozilla.org/network/mime-input-stream;1", &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
#ifdef SPECIFY_CHARSET_IN_CONTENT_TYPE
|
|
mimeStream->AddHeader("Content-Type",
|
|
PromiseFlatString(
|
|
"application/x-www-form-urlencoded; charset="
|
|
+ mCharset
|
|
).get());
|
|
#else
|
|
mimeStream->AddHeader("Content-Type",
|
|
"application/x-www-form-urlencoded");
|
|
#endif
|
|
mimeStream->SetAddContentLength(true);
|
|
mimeStream->SetData(dataStream);
|
|
|
|
*aPostDataStream = mimeStream;
|
|
NS_ADDREF(*aPostDataStream);
|
|
}
|
|
|
|
} else {
|
|
// Get the full query string
|
|
bool schemeIsJavaScript;
|
|
rv = aURI->SchemeIs("javascript", &schemeIsJavaScript);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
if (schemeIsJavaScript) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
|
|
if (url) {
|
|
url->SetQuery(mQueryString);
|
|
}
|
|
else {
|
|
nsAutoCString path;
|
|
rv = aURI->GetPath(path);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
// Bug 42616: Trim off named anchor and save it to add later
|
|
int32_t namedAnchorPos = path.FindChar('#');
|
|
nsAutoCString namedAnchor;
|
|
if (kNotFound != namedAnchorPos) {
|
|
path.Right(namedAnchor, (path.Length() - namedAnchorPos));
|
|
path.Truncate(namedAnchorPos);
|
|
}
|
|
|
|
// Chop off old query string (bug 25330, 57333)
|
|
// Only do this for GET not POST (bug 41585)
|
|
int32_t queryStart = path.FindChar('?');
|
|
if (kNotFound != queryStart) {
|
|
path.Truncate(queryStart);
|
|
}
|
|
|
|
path.Append('?');
|
|
// Bug 42616: Add named anchor to end after query string
|
|
path.Append(mQueryString + namedAnchor);
|
|
|
|
aURI->SetPath(path);
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
// i18n helper routines
|
|
nsresult
|
|
nsFSURLEncoded::URLEncode(const nsAString& aStr, nsCString& aEncoded)
|
|
{
|
|
// convert to CRLF breaks
|
|
char16_t* convertedBuf =
|
|
nsLinebreakConverter::ConvertUnicharLineBreaks(PromiseFlatString(aStr).get(),
|
|
nsLinebreakConverter::eLinebreakAny,
|
|
nsLinebreakConverter::eLinebreakNet);
|
|
NS_ENSURE_TRUE(convertedBuf, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
nsAutoCString encodedBuf;
|
|
nsresult rv = EncodeVal(nsDependentString(convertedBuf), encodedBuf, false);
|
|
free(convertedBuf);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
char* escapedBuf = nsEscape(encodedBuf.get(), url_XPAlphas);
|
|
NS_ENSURE_TRUE(escapedBuf, NS_ERROR_OUT_OF_MEMORY);
|
|
aEncoded.Adopt(escapedBuf);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
nsFSMultipartFormData::nsFSMultipartFormData(const nsACString& aCharset,
|
|
nsIContent* aOriginatingElement)
|
|
: nsEncodingFormSubmission(aCharset, aOriginatingElement)
|
|
{
|
|
mPostDataStream =
|
|
do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
|
|
mTotalLength = 0;
|
|
|
|
mBoundary.AssignLiteral("---------------------------");
|
|
mBoundary.AppendInt(rand());
|
|
mBoundary.AppendInt(rand());
|
|
mBoundary.AppendInt(rand());
|
|
}
|
|
|
|
nsFSMultipartFormData::~nsFSMultipartFormData()
|
|
{
|
|
NS_ASSERTION(mPostDataChunk.IsEmpty(), "Left unsubmitted data");
|
|
}
|
|
|
|
nsIInputStream*
|
|
nsFSMultipartFormData::GetSubmissionBody(uint64_t* aContentLength)
|
|
{
|
|
// Finish data
|
|
mPostDataChunk += NS_LITERAL_CSTRING("--") + mBoundary
|
|
+ NS_LITERAL_CSTRING("--" CRLF);
|
|
|
|
// Add final data input stream
|
|
AddPostDataStream();
|
|
|
|
*aContentLength = mTotalLength;
|
|
return mPostDataStream;
|
|
}
|
|
|
|
nsresult
|
|
nsFSMultipartFormData::AddNameValuePair(const nsAString& aName,
|
|
const nsAString& aValue)
|
|
{
|
|
nsCString valueStr;
|
|
nsAutoCString encodedVal;
|
|
nsresult rv = EncodeVal(aValue, encodedVal, false);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
valueStr.Adopt(nsLinebreakConverter::
|
|
ConvertLineBreaks(encodedVal.get(),
|
|
nsLinebreakConverter::eLinebreakAny,
|
|
nsLinebreakConverter::eLinebreakNet));
|
|
|
|
nsAutoCString nameStr;
|
|
rv = EncodeVal(aName, nameStr, true);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Make MIME block for name/value pair
|
|
|
|
// XXX: name parameter should be encoded per RFC 2231
|
|
// RFC 2388 specifies that RFC 2047 be used, but I think it's not
|
|
// consistent with MIME standard.
|
|
mPostDataChunk += NS_LITERAL_CSTRING("--") + mBoundary
|
|
+ NS_LITERAL_CSTRING(CRLF)
|
|
+ NS_LITERAL_CSTRING("Content-Disposition: form-data; name=\"")
|
|
+ nameStr + NS_LITERAL_CSTRING("\"" CRLF CRLF)
|
|
+ valueStr + NS_LITERAL_CSTRING(CRLF);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
|
|
mozilla::dom::File* aFile)
|
|
{
|
|
// Encode the control name
|
|
nsAutoCString nameStr;
|
|
nsresult rv = EncodeVal(aName, nameStr, true);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCString filename, contentType;
|
|
nsCOMPtr<nsIInputStream> fileStream;
|
|
if (aFile) {
|
|
nsAutoString filename16;
|
|
aFile->GetName(filename16);
|
|
|
|
ErrorResult error;
|
|
nsAutoString filepath16;
|
|
aFile->GetPath(filepath16, error);
|
|
if (NS_WARN_IF(error.Failed())) {
|
|
return error.StealNSResult();
|
|
}
|
|
|
|
if (!filepath16.IsEmpty()) {
|
|
// File.path includes trailing "/"
|
|
filename16 = filepath16 + filename16;
|
|
}
|
|
|
|
rv = EncodeVal(filename16, filename, true);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Get content type
|
|
nsAutoString contentType16;
|
|
aFile->GetType(contentType16);
|
|
if (contentType16.IsEmpty()) {
|
|
contentType16.AssignLiteral("application/octet-stream");
|
|
}
|
|
contentType.Adopt(nsLinebreakConverter::
|
|
ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
|
|
nsLinebreakConverter::eLinebreakAny,
|
|
nsLinebreakConverter::eLinebreakSpace));
|
|
|
|
// Get input stream
|
|
aFile->GetInternalStream(getter_AddRefs(fileStream), error);
|
|
if (NS_WARN_IF(error.Failed())) {
|
|
return error.StealNSResult();
|
|
}
|
|
|
|
if (fileStream) {
|
|
// Create buffered stream (for efficiency)
|
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
|
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
|
fileStream, 8192);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
fileStream = bufferedStream;
|
|
}
|
|
}
|
|
else {
|
|
contentType.AssignLiteral("application/octet-stream");
|
|
}
|
|
|
|
//
|
|
// Make MIME block for name/value pair
|
|
//
|
|
// more appropriate than always using binary?
|
|
mPostDataChunk += NS_LITERAL_CSTRING("--") + mBoundary
|
|
+ NS_LITERAL_CSTRING(CRLF);
|
|
// XXX: name/filename parameter should be encoded per RFC 2231
|
|
// RFC 2388 specifies that RFC 2047 be used, but I think it's not
|
|
// consistent with the MIME standard.
|
|
mPostDataChunk +=
|
|
NS_LITERAL_CSTRING("Content-Disposition: form-data; name=\"")
|
|
+ nameStr + NS_LITERAL_CSTRING("\"; filename=\"")
|
|
+ filename + NS_LITERAL_CSTRING("\"" CRLF)
|
|
+ NS_LITERAL_CSTRING("Content-Type: ")
|
|
+ contentType + NS_LITERAL_CSTRING(CRLF CRLF);
|
|
|
|
// We should not try to append an invalid stream. That will happen for example
|
|
// if we try to update a file that actually do not exist.
|
|
if (fileStream) {
|
|
ErrorResult error;
|
|
uint64_t size = aFile->GetSize(error);
|
|
if (error.Failed()) {
|
|
error.SuppressException();
|
|
} else {
|
|
// We need to dump the data up to this point into the POST data stream
|
|
// here, since we're about to add the file input stream
|
|
AddPostDataStream();
|
|
|
|
mPostDataStream->AppendStream(fileStream);
|
|
mTotalLength += size;
|
|
}
|
|
}
|
|
|
|
// CRLF after file
|
|
mPostDataChunk.AppendLiteral(CRLF);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsFSMultipartFormData::GetEncodedSubmission(nsIURI* aURI,
|
|
nsIInputStream** aPostDataStream)
|
|
{
|
|
nsresult rv;
|
|
|
|
// Make header
|
|
nsCOMPtr<nsIMIMEInputStream> mimeStream
|
|
= do_CreateInstance("@mozilla.org/network/mime-input-stream;1", &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString contentType;
|
|
GetContentType(contentType);
|
|
mimeStream->AddHeader("Content-Type", contentType.get());
|
|
mimeStream->SetAddContentLength(true);
|
|
uint64_t unused;
|
|
mimeStream->SetData(GetSubmissionBody(&unused));
|
|
|
|
mimeStream.forget(aPostDataStream);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsFSMultipartFormData::AddPostDataStream()
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
nsCOMPtr<nsIInputStream> postDataChunkStream;
|
|
rv = NS_NewCStringInputStream(getter_AddRefs(postDataChunkStream),
|
|
mPostDataChunk);
|
|
NS_ASSERTION(postDataChunkStream, "Could not open a stream for POST!");
|
|
if (postDataChunkStream) {
|
|
mPostDataStream->AppendStream(postDataChunkStream);
|
|
mTotalLength += mPostDataChunk.Length();
|
|
}
|
|
|
|
mPostDataChunk.Truncate();
|
|
|
|
return rv;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
class nsFSTextPlain : public nsEncodingFormSubmission
|
|
{
|
|
public:
|
|
nsFSTextPlain(const nsACString& aCharset, nsIContent* aOriginatingElement)
|
|
: nsEncodingFormSubmission(aCharset, aOriginatingElement)
|
|
{
|
|
}
|
|
|
|
virtual nsresult AddNameValuePair(const nsAString& aName,
|
|
const nsAString& aValue) override;
|
|
virtual nsresult AddNameFilePair(const nsAString& aName,
|
|
mozilla::dom::File* aFile) override;
|
|
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
|
|
nsIInputStream** aPostDataStream)
|
|
override;
|
|
|
|
private:
|
|
nsString mBody;
|
|
};
|
|
|
|
nsresult
|
|
nsFSTextPlain::AddNameValuePair(const nsAString& aName,
|
|
const nsAString& aValue)
|
|
{
|
|
// XXX This won't work well with a name like "a=b" or "a\nb" but I suppose
|
|
// text/plain doesn't care about that. Parsers aren't built for escaped
|
|
// values so we'll have to live with it.
|
|
mBody.Append(aName + NS_LITERAL_STRING("=") + aValue +
|
|
NS_LITERAL_STRING(CRLF));
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsFSTextPlain::AddNameFilePair(const nsAString& aName,
|
|
mozilla::dom::File* aFile)
|
|
{
|
|
nsAutoString filename;
|
|
if (aFile) {
|
|
aFile->GetName(filename);
|
|
}
|
|
|
|
AddNameValuePair(aName, filename);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsFSTextPlain::GetEncodedSubmission(nsIURI* aURI,
|
|
nsIInputStream** aPostDataStream)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
// XXX HACK We are using the standard URL mechanism to give the body to the
|
|
// mailer instead of passing the post data stream to it, since that sounds
|
|
// hard.
|
|
bool isMailto = false;
|
|
aURI->SchemeIs("mailto", &isMailto);
|
|
if (isMailto) {
|
|
nsAutoCString path;
|
|
rv = aURI->GetPath(path);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
HandleMailtoSubject(path);
|
|
|
|
// Append the body to and force-plain-text args to the mailto line
|
|
char* escapedBuf = nsEscape(NS_ConvertUTF16toUTF8(mBody).get(),
|
|
url_XAlphas);
|
|
NS_ENSURE_TRUE(escapedBuf, NS_ERROR_OUT_OF_MEMORY);
|
|
nsCString escapedBody;
|
|
escapedBody.Adopt(escapedBuf);
|
|
|
|
path += NS_LITERAL_CSTRING("&force-plain-text=Y&body=") + escapedBody;
|
|
|
|
rv = aURI->SetPath(path);
|
|
|
|
} else {
|
|
// Create data stream.
|
|
// We do want to send the data through the charset encoder and we want to
|
|
// normalize linebreaks to use the "standard net" format (\r\n), but we
|
|
// don't want to perform any other encoding. This means that names and
|
|
// values which contains '=' or newlines are potentially ambigiously
|
|
// encoded, but that how text/plain is specced.
|
|
nsCString cbody;
|
|
EncodeVal(mBody, cbody, false);
|
|
cbody.Adopt(nsLinebreakConverter::
|
|
ConvertLineBreaks(cbody.get(),
|
|
nsLinebreakConverter::eLinebreakAny,
|
|
nsLinebreakConverter::eLinebreakNet));
|
|
nsCOMPtr<nsIInputStream> bodyStream;
|
|
rv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), cbody);
|
|
if (!bodyStream) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
// Create mime stream with headers and such
|
|
nsCOMPtr<nsIMIMEInputStream> mimeStream
|
|
= do_CreateInstance("@mozilla.org/network/mime-input-stream;1", &rv);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
mimeStream->AddHeader("Content-Type", "text/plain");
|
|
mimeStream->SetAddContentLength(true);
|
|
mimeStream->SetData(bodyStream);
|
|
CallQueryInterface(mimeStream, aPostDataStream);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
nsEncodingFormSubmission::nsEncodingFormSubmission(const nsACString& aCharset,
|
|
nsIContent* aOriginatingElement)
|
|
: nsFormSubmission(aCharset, aOriginatingElement)
|
|
, mEncoder(aCharset)
|
|
{
|
|
if (!(aCharset.EqualsLiteral("UTF-8") || aCharset.EqualsLiteral("gb18030"))) {
|
|
NS_ConvertUTF8toUTF16 charsetUtf16(aCharset);
|
|
const char16_t* charsetPtr = charsetUtf16.get();
|
|
SendJSWarning(aOriginatingElement ? aOriginatingElement->GetOwnerDocument()
|
|
: nullptr,
|
|
"CannotEncodeAllUnicode",
|
|
&charsetPtr,
|
|
1);
|
|
}
|
|
}
|
|
|
|
nsEncodingFormSubmission::~nsEncodingFormSubmission()
|
|
{
|
|
}
|
|
|
|
// i18n helper routines
|
|
nsresult
|
|
nsEncodingFormSubmission::EncodeVal(const nsAString& aStr, nsCString& aOut,
|
|
bool aHeaderEncode)
|
|
{
|
|
if (!mEncoder.Encode(aStr, aOut)) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (aHeaderEncode) {
|
|
aOut.Adopt(nsLinebreakConverter::
|
|
ConvertLineBreaks(aOut.get(),
|
|
nsLinebreakConverter::eLinebreakAny,
|
|
nsLinebreakConverter::eLinebreakSpace));
|
|
aOut.ReplaceSubstring(NS_LITERAL_CSTRING("\""),
|
|
NS_LITERAL_CSTRING("\\\""));
|
|
}
|
|
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
static void
|
|
GetSubmitCharset(nsGenericHTMLElement* aForm,
|
|
nsACString& oCharset)
|
|
{
|
|
oCharset.AssignLiteral("UTF-8"); // default to utf-8
|
|
|
|
nsAutoString acceptCharsetValue;
|
|
aForm->GetAttr(kNameSpaceID_None, nsGkAtoms::acceptcharset,
|
|
acceptCharsetValue);
|
|
|
|
int32_t charsetLen = acceptCharsetValue.Length();
|
|
if (charsetLen > 0) {
|
|
int32_t offset=0;
|
|
int32_t spPos=0;
|
|
// get charset from charsets one by one
|
|
do {
|
|
spPos = acceptCharsetValue.FindChar(char16_t(' '), offset);
|
|
int32_t cnt = ((-1==spPos)?(charsetLen-offset):(spPos-offset));
|
|
if (cnt > 0) {
|
|
nsAutoString uCharset;
|
|
acceptCharsetValue.Mid(uCharset, offset, cnt);
|
|
|
|
if (EncodingUtils::FindEncodingForLabel(uCharset, oCharset))
|
|
return;
|
|
}
|
|
offset = spPos + 1;
|
|
} while (spPos != -1);
|
|
}
|
|
// if there are no accept-charset or all the charset are not supported
|
|
// Get the charset from document
|
|
nsIDocument* doc = aForm->GetComposedDoc();
|
|
if (doc) {
|
|
oCharset = doc->GetDocumentCharacterSet();
|
|
}
|
|
}
|
|
|
|
static void
|
|
GetEnumAttr(nsGenericHTMLElement* aContent,
|
|
nsIAtom* atom, int32_t* aValue)
|
|
{
|
|
const nsAttrValue* value = aContent->GetParsedAttr(atom);
|
|
if (value && value->Type() == nsAttrValue::eEnum) {
|
|
*aValue = value->GetEnumValue();
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
GetSubmissionFromForm(nsGenericHTMLElement* aForm,
|
|
nsGenericHTMLElement* aOriginatingElement,
|
|
nsFormSubmission** aFormSubmission)
|
|
{
|
|
// Get all the information necessary to encode the form data
|
|
NS_ASSERTION(aForm->GetComposedDoc(),
|
|
"Should have doc if we're building submission!");
|
|
|
|
// Get encoding type (default: urlencoded)
|
|
int32_t enctype = NS_FORM_ENCTYPE_URLENCODED;
|
|
if (aOriginatingElement &&
|
|
aOriginatingElement->HasAttr(kNameSpaceID_None, nsGkAtoms::formenctype)) {
|
|
GetEnumAttr(aOriginatingElement, nsGkAtoms::formenctype, &enctype);
|
|
} else {
|
|
GetEnumAttr(aForm, nsGkAtoms::enctype, &enctype);
|
|
}
|
|
|
|
// Get method (default: GET)
|
|
int32_t method = NS_FORM_METHOD_GET;
|
|
if (aOriginatingElement &&
|
|
aOriginatingElement->HasAttr(kNameSpaceID_None, nsGkAtoms::formmethod)) {
|
|
GetEnumAttr(aOriginatingElement, nsGkAtoms::formmethod, &method);
|
|
} else {
|
|
GetEnumAttr(aForm, nsGkAtoms::method, &method);
|
|
}
|
|
|
|
// Get charset
|
|
nsAutoCString charset;
|
|
GetSubmitCharset(aForm, charset);
|
|
|
|
// We now have a canonical charset name, so we only have to check it
|
|
// against canonical names.
|
|
|
|
// use UTF-8 for UTF-16* (per WHATWG and existing practice of
|
|
// MS IE/Opera).
|
|
if (StringBeginsWith(charset, NS_LITERAL_CSTRING("UTF-16"))) {
|
|
charset.AssignLiteral("UTF-8");
|
|
}
|
|
|
|
// Choose encoder
|
|
if (method == NS_FORM_METHOD_POST &&
|
|
enctype == NS_FORM_ENCTYPE_MULTIPART) {
|
|
*aFormSubmission = new nsFSMultipartFormData(charset, aOriginatingElement);
|
|
} else if (method == NS_FORM_METHOD_POST &&
|
|
enctype == NS_FORM_ENCTYPE_TEXTPLAIN) {
|
|
*aFormSubmission = new nsFSTextPlain(charset, aOriginatingElement);
|
|
} else {
|
|
nsIDocument* doc = aForm->OwnerDoc();
|
|
if (enctype == NS_FORM_ENCTYPE_MULTIPART ||
|
|
enctype == NS_FORM_ENCTYPE_TEXTPLAIN) {
|
|
nsAutoString enctypeStr;
|
|
if (aOriginatingElement &&
|
|
aOriginatingElement->HasAttr(kNameSpaceID_None,
|
|
nsGkAtoms::formenctype)) {
|
|
aOriginatingElement->GetAttr(kNameSpaceID_None, nsGkAtoms::formenctype,
|
|
enctypeStr);
|
|
} else {
|
|
aForm->GetAttr(kNameSpaceID_None, nsGkAtoms::enctype, enctypeStr);
|
|
}
|
|
const char16_t* enctypeStrPtr = enctypeStr.get();
|
|
SendJSWarning(doc, "ForgotPostWarning",
|
|
&enctypeStrPtr, 1);
|
|
}
|
|
*aFormSubmission = new nsFSURLEncoded(charset, method, doc,
|
|
aOriginatingElement);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|