Bug 1433624 - Use rust-url's form-urlencoded parser; r?bz
That parser is already in rust-url, and will not copy into any intermediate
string the contents of the form-urlencoded input, as long as it doesn't
encounter percent-encoded bytes or malformed UTF-8 byte sequences.
MozReview-Commit-ID: 9UYMNy7NQNP
--- a/netwerk/base/MozURL.cpp
+++ b/netwerk/base/MozURL.cpp
@@ -2,16 +2,34 @@
* 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 "MozURL.h"
#include "mozilla/Encoding.h"
#include "nsReadableUtils.h"
#include "rust-url-capi/src/rust-url-capi.h"
+extern "C" {
+struct ForEachWrapper
+{
+ nsAutoString& mName;
+ nsAutoString& mValue;
+ mozilla::MozURL::ForEachFormUrlencoded& mProcessor;
+};
+
+static bool
+CallForEach(const nsACString* aName, const nsACString* aValue, void* aContext)
+{
+ auto wrapper = static_cast<ForEachWrapper*>(aContext);
+ CopyUTF8toUTF16(*aName, wrapper->mName);
+ CopyUTF8toUTF16(*aValue, wrapper->mValue);
+ return wrapper->mProcessor.Process(wrapper->mName, wrapper->mValue);
+}
+}
+
namespace mozilla {
namespace net {
NS_IMPL_ADDREF(MozURL)
NS_IMPL_RELEASE(MozURL)
/* static */ nsresult
MozURL::Init(MozURL** aURL, const nsACString& aSpec, const MozURL* aBaseURL)
@@ -103,133 +121,28 @@ MozURL::GetRef(nsACString& aRef)
}
nsresult
MozURL::GetOrigin(nsACString& aOrigin)
{
return rusturl_get_origin(mURL.get(), &aOrigin);
}
-static void
-ConvertString(const nsACString& aInput, nsAString& aOutput)
-{
- if (NS_FAILED(UTF_8_ENCODING->DecodeWithoutBOMHandling(aInput, aOutput))) {
- MOZ_CRASH("Out of memory when converting URL params.");
- }
-}
-
-static void
-DecodeString(const nsACString& aInput, nsAString& aOutput)
-{
- nsACString::const_iterator start, end;
- aInput.BeginReading(start);
- aInput.EndReading(end);
-
- nsCString unescaped;
-
- while (start != end) {
- // replace '+' with U+0020
- if (*start == '+') {
- unescaped.Append(' ');
- ++start;
- continue;
- }
-
- // Percent decode algorithm
- if (*start == '%') {
- nsACString::const_iterator first(start);
- ++first;
-
- nsACString::const_iterator second(first);
- ++second;
-
-#define ASCII_HEX_DIGIT( x ) \
- ((x >= 0x41 && x <= 0x46) || \
- (x >= 0x61 && x <= 0x66) || \
- (x >= 0x30 && x <= 0x39))
-
-#define HEX_DIGIT( x ) \
- (*x >= 0x30 && *x <= 0x39 \
- ? *x - 0x30 \
- : (*x >= 0x41 && *x <= 0x46 \
- ? *x - 0x37 \
- : *x - 0x57))
-
- if (first != end && second != end &&
- ASCII_HEX_DIGIT(*first) && ASCII_HEX_DIGIT(*second)) {
- unescaped.Append(HEX_DIGIT(first) * 16 + HEX_DIGIT(second));
- start = ++second;
- continue;
-
- } else {
- unescaped.Append('%');
- ++start;
- continue;
- }
- }
-
- unescaped.Append(*start);
- ++start;
- }
-
- ConvertString(unescaped, aOutput);
-}
-
/* static */ bool
MozURL::ParseFormUrlencoded(const nsACString& aInput,
ForEachFormUrlencoded& aProcessor)
{
- nsACString::const_iterator start, end;
- aInput.BeginReading(start);
- aInput.EndReading(end);
- nsACString::const_iterator iter(start);
-
- while (start != end) {
- nsAutoCString string;
-
- if (FindCharInReadable('&', iter, end)) {
- string.Assign(Substring(start, iter));
- start = ++iter;
- } else {
- string.Assign(Substring(start, end));
- start = end;
- }
-
- if (string.IsEmpty()) {
- continue;
- }
-
- nsACString::const_iterator eqStart, eqEnd;
- string.BeginReading(eqStart);
- string.EndReading(eqEnd);
- nsACString::const_iterator eqIter(eqStart);
-
- nsAutoCString name;
- nsAutoCString value;
-
- if (FindCharInReadable('=', eqIter, eqEnd)) {
- name.Assign(Substring(eqStart, eqIter));
-
- ++eqIter;
- value.Assign(Substring(eqIter, eqEnd));
- } else {
- name.Assign(string);
- }
-
- nsAutoString decodedName;
- DecodeString(name, decodedName);
-
- nsAutoString decodedValue;
- DecodeString(value, decodedValue);
-
- if (!aProcessor.Process(decodedName, decodedValue)) {
- return false;
- }
- }
- return true;
+ nsAutoString name;
+ nsAutoString value;
+ ForEachWrapper wrapper = {
+ name,
+ value,
+ aProcessor
+ };
+ return rusturl_parse_form_urlencoded(&aInput, CallForEach, &wrapper);
}
class MOZ_STACK_CLASS ExtractURLParam final
: public MozURL::ForEachFormUrlencoded
{
public:
explicit ExtractURLParam(const nsAString& aName, nsAString& aValue)
: mName(aName)
--- a/netwerk/base/rust-url-capi/src/lib.rs
+++ b/netwerk/base/rust-url-capi/src/lib.rs
@@ -3,20 +3,20 @@
* 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/. */
extern crate url;
use url::{Url, ParseOptions, Position};
use url::quirks;
extern crate libc;
-use libc::size_t;
+use libc::{c_void, size_t};
extern crate nsstring;
-use nsstring::nsACString;
+use nsstring::{nsACString, nsCStr};
extern crate nserror;
use nserror::*;
use std::mem;
use std::str;
use std::ptr;
@@ -604,8 +604,22 @@ pub extern "C" fn rusturl_parse_ipv6addr
Ok(host) => host,
// XXX: Do we want to change our error message based on the error type?
Err(_) => return NS_ERROR_MALFORMED_URI,
};
cont.assign(&h.to_string());
NS_OK
}
+
+#[no_mangle]
+pub extern "C" fn rusturl_parse_form_urlencoded(
+ input: &nsACString,
+ callback: extern "C" fn(&nsACString, &nsACString, *mut c_void) -> bool,
+ context: *mut c_void,
+) -> bool {
+ for (name, value) in url::form_urlencoded::parse(input) {
+ if !callback(&nsCStr::from(&*name), &nsCStr::from(&*value), context) {
+ return false;
+ }
+ }
+ true
+}
--- a/netwerk/base/rust-url-capi/src/rust-url-capi.h
+++ b/netwerk/base/rust-url-capi/src/rust-url-capi.h
@@ -49,13 +49,17 @@ nsresult rusturl_set_query(rusturl* url,
nsresult rusturl_set_fragment(rusturl* url, const nsACString* fragment);
nsresult rusturl_resolve(const rusturl* url, const nsACString* relative, nsACString* cont);
nsresult rusturl_common_base_spec(const rusturl* url1, const rusturl* url2, nsACString* cont);
nsresult rusturl_relative_spec(const rusturl* url1, const rusturl* url2, nsACString* cont);
nsresult rusturl_parse_ipv6addr(const nsACString* input, nsACString* cont);
+bool rusturl_parse_form_urlencoded(const nsACString* input,
+ bool callback(const nsACString* key, const nsACString* value, void* ctx),
+ void *ctx);
+
size_t sizeof_rusturl();
}
#endif // __RUST_URL_CAPI