Skip to content

Commit

Permalink
Bug 1210302 - Add a NS_ParseRequestContentType API; ba=al, r=mcmanus,…
Browse files Browse the repository at this point in the history
… r=sicking, a=al

--HG--
extra : amend_source : d93021b626709b03f6499029dc3d1813cccba386
  • Loading branch information
ehsan committed Oct 20, 2015
1 parent a538b24 commit d135e3b
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 20 deletions.
2 changes: 1 addition & 1 deletion docshell/base/nsDocShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13519,7 +13519,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
anchor->GetType(typeHint);
NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
nsAutoCString type, dummy;
NS_ParseContentType(utf8Hint, type, dummy);
NS_ParseRequestContentType(utf8Hint, type, dummy);
CopyUTF8toUTF16(type, typeHint);
}

Expand Down
4 changes: 2 additions & 2 deletions dom/base/Navigator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1221,9 +1221,9 @@ Navigator::SendBeacon(const nsAString& aUrl,
rv = secMan->CheckSameOriginURI(documentURI, uri, false);
bool crossOrigin = NS_FAILED(rv);
nsAutoCString contentType, parsedCharset;
rv = NS_ParseContentType(mimeType, contentType, parsedCharset);
rv = NS_ParseRequestContentType(mimeType, contentType, parsedCharset);
if (crossOrigin &&
contentType.Length() > 0 &&
mimeType.Length() > 0 &&
!contentType.Equals(APPLICATION_WWW_FORM_URLENCODED) &&
!contentType.Equals(MULTIPART_FORM_DATA) &&
!contentType.Equals(TEXT_PLAIN)) {
Expand Down
2 changes: 1 addition & 1 deletion dom/base/nsContentUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7001,7 +7001,7 @@ nsContentUtils::IsAllowedNonCorsContentType(const nsACString& aHeaderValue)
nsAutoCString contentType;
nsAutoCString unused;

nsresult rv = NS_ParseContentType(aHeaderValue, contentType, unused);
nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
if (NS_FAILED(rv)) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion dom/html/nsHTMLDocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,7 @@ nsHTMLDocument::Open(JSContext* cx,
nsAutoString type;
nsContentUtils::ASCIIToLower(aType, type);
nsAutoCString actualType, dummy;
NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
NS_ParseRequestContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
if (!actualType.EqualsLiteral("text/html") &&
!type.EqualsLiteral("replace")) {
contentType.AssignLiteral("text/plain");
Expand Down
6 changes: 3 additions & 3 deletions dom/manifest/ManifestProcessor.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const imports = {};
Cu.import('resource://gre/modules/Services.jsm', imports);
Cu.importGlobalProperties(['URL']);
const securityManager = imports.Services.scriptSecurityManager;
const netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil);
const netutil = Cc['@mozilla.org/network/util;1'].getService(Ci.nsINetUtil_ESR_38);
const defaultDisplayMode = 'browser';
const displayModes = new Set([
'fullscreen',
Expand Down Expand Up @@ -258,7 +258,7 @@ this.ManifestProcessor.prototype.process = function({
};
let value = extractValue(obj),
isParsable = (typeof value === 'string' && value.length > 0);
value = (isParsable) ? netutil.parseContentType(value.trim(), charset, hadCharset) : undefined;
value = (isParsable) ? netutil.parseRequestContentType(value.trim(), charset, hadCharset) : undefined;
return (value === '') ? undefined : value;
}

Expand Down Expand Up @@ -354,4 +354,4 @@ this.ManifestProcessor.prototype.process = function({
};
processedManifest.scope = processScopeMember(manifest, manifestURL, docURL, processedManifest.start_url);
return processedManifest;
};
};
1 change: 1 addition & 0 deletions netwerk/base/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ XPIDL_SOURCES += [
'nsINestedURI.idl',
'nsINetAddr.idl',
'nsINetUtil.idl',
'nsINetUtil_ESR_38.idl',
'nsINetworkInterceptController.idl',
'nsINetworkLinkService.idl',
'nsINetworkPredictor.idl',
Expand Down
14 changes: 14 additions & 0 deletions netwerk/base/nsINetUtil_ESR_38.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"

[scriptable, uuid(e82f2b9d-8bac-48bb-ade7-26a7cd4fb894)]
interface nsINetUtil_ESR_38 : nsISupports
{
AUTF8String parseRequestContentType(in AUTF8String aTypeHeader,
out AUTF8String aCharset,
out boolean aHadCharset);
};
12 changes: 12 additions & 0 deletions netwerk/base/nsIOService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ NS_IMPL_ISUPPORTS(nsIOService,
nsIIOService,
nsIIOService2,
nsINetUtil,
nsINetUtil_ESR_38,
nsISpeculativeConnect,
nsIObserver,
nsISupportsWeakReference)
Expand Down Expand Up @@ -1278,6 +1279,17 @@ nsIOService::Observe(nsISupports *subject,
return NS_OK;
}

// nsINetUtil interface
NS_IMETHODIMP
nsIOService::ParseRequestContentType(const nsACString &aTypeHeader,
nsACString &aCharset,
bool *aHadCharset,
nsACString &aContentType)
{
net_ParseRequestContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
return NS_OK;
}

// nsINetUtil interface
NS_IMETHODIMP
nsIOService::ParseContentType(const nsACString &aTypeHeader,
Expand Down
3 changes: 3 additions & 0 deletions netwerk/base/nsIOService.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "nsINetUtil.h"
#include "nsINetUtil_ESR_38.h"
#include "nsIChannelEventSink.h"
#include "nsCategoryCache.h"
#include "nsISpeculativeConnect.h"
Expand Down Expand Up @@ -47,6 +48,7 @@ namespace net {
class nsIOService final : public nsIIOService2
, public nsIObserver
, public nsINetUtil
, public nsINetUtil_ESR_38
, public nsISpeculativeConnect
, public nsSupportsWeakReference
{
Expand All @@ -56,6 +58,7 @@ class nsIOService final : public nsIIOService2
NS_DECL_NSIIOSERVICE2
NS_DECL_NSIOBSERVER
NS_DECL_NSINETUTIL
NS_DECL_NSINETUTIL_ESR_38
NS_DECL_NSISPECULATIVECONNECT

// Gets the singleton instance of the IO Service, creating it as needed
Expand Down
21 changes: 21 additions & 0 deletions netwerk/base/nsNetUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include "nsISyncStreamListener.h"
#include "nsInterfaceRequestorAgg.h"
#include "nsINetUtil.h"
#include "nsINetUtil_ESR_38.h"
#include "nsIURIWithPrincipal.h"
#include "nsIAuthPrompt.h"
#include "nsIAuthPrompt2.h"
Expand Down Expand Up @@ -1227,6 +1228,26 @@ NS_GetReferrerFromChannel(nsIChannel *channel,
return rv;
}

inline nsresult
NS_ParseRequestContentType(const nsACString &rawContentType,
nsCString &contentType,
nsCString &contentCharset)
{
// contentCharset is left untouched if not present in rawContentType
nsresult rv;
nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINetUtil_ESR_38> utilESR38 = do_QueryInterface(util, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCString charset;
bool hadCharset;
rv = utilESR38->ParseRequestContentType(rawContentType, charset, &hadCharset,
contentType);
if (NS_SUCCEEDED(rv) && hadCharset)
contentCharset = charset;
return rv;
}

inline nsresult
NS_ParseContentType(const nsACString &rawContentType,
nsCString &contentType,
Expand Down
60 changes: 56 additions & 4 deletions netwerk/base/nsURLHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,8 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
int32_t aOffset,
bool *aHadCharset,
int32_t *aCharsetStart,
int32_t *aCharsetEnd)
int32_t *aCharsetEnd,
bool aStrict)
{
const nsCString& flatStr = PromiseFlatCString(aMediaTypeStr);
const char* start = flatStr.get();
Expand All @@ -820,6 +821,8 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
int32_t charsetParamStart = 0;
int32_t charsetParamEnd = 0;

uint32_t consumed = typeEnd - type;

// Iterate over parameters
bool typeHasCharset = false;
uint32_t paramStart = flatStr.FindChar(';', typeEnd - start);
Expand All @@ -843,6 +846,7 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
charsetParamEnd = curParamEnd;
}

consumed = curParamEnd;
curParamStart = curParamEnd + 1;
} while (curParamStart < flatStr.Length());
}
Expand Down Expand Up @@ -872,8 +876,10 @@ net_ParseMediaType(const nsACString &aMediaTypeStr,
// some servers give junk after the charset parameter, which may
// include a comma, so this check makes us a bit more tolerant.

if (type != typeEnd && strncmp(type, "*/*", typeEnd - type) != 0 &&
memchr(type, '/', typeEnd - type) != nullptr) {
if (type != typeEnd &&
memchr(type, '/', typeEnd - type) != nullptr &&
(aStrict ? (net_FindCharNotInSet(start + consumed, end, HTTP_LWS) == end) :
(strncmp(type, "*/*", typeEnd - type) != 0))) {
// Common case here is that aContentType is empty
bool eq = !aContentType.IsEmpty() &&
aContentType.Equals(Substring(type, typeEnd),
Expand Down Expand Up @@ -980,13 +986,59 @@ net_ParseContentType(const nsACString &aHeaderStr,
net_ParseMediaType(Substring(flatStr, curTypeStart,
curTypeEnd - curTypeStart),
aContentType, aContentCharset, curTypeStart,
aHadCharset, aCharsetStart, aCharsetEnd);
aHadCharset, aCharsetStart, aCharsetEnd, false);

// And let's move on to the next media-type
curTypeStart = curTypeEnd + 1;
} while (curTypeStart < flatStr.Length());
}

void
net_ParseRequestContentType(const nsACString &aHeaderStr,
nsACString &aContentType,
nsACString &aContentCharset,
bool *aHadCharset)
{
//
// Augmented BNF (from RFC 7231 section 3.1.1.1):
//
// media-type = type "/" subtype *( OWS ";" OWS parameter )
// type = token
// subtype = token
// parameter = token "=" ( token / quoted-string )
//
// Examples:
//
// text/html
// text/html; charset=ISO-8859-1
// text/html; charset="ISO-8859-1"
// application/octet-stream
//

aContentType.Truncate();
aContentCharset.Truncate();
*aHadCharset = false;
const nsCString& flatStr = PromiseFlatCString(aHeaderStr);

// At this point curTypeEnd points to the spot where the media-type
// starting at curTypeEnd ends. Time to parse that!
nsAutoCString contentType, contentCharset;
bool hadCharset = false;
int32_t dummy1, dummy2;
uint32_t typeEnd = net_FindMediaDelimiter(flatStr, 0, ',');
if (typeEnd != flatStr.Length()) {
// We have some stuff left at the end, so this is not a valid
// request Content-Type header.
return;
}
net_ParseMediaType(flatStr, contentType, contentCharset, 0,
&hadCharset, &dummy1, &dummy2, true);

aContentType = contentType;
aContentCharset = contentCharset;
*aHadCharset = hadCharset;
}

bool
net_IsValidHostName(const nsCSubstring &host)
{
Expand Down
32 changes: 24 additions & 8 deletions netwerk/base/nsURLHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,22 @@ char * net_FindCharNotInSet(const char *str, const char *end, const char *set);
*/
char * net_RFindCharNotInSet(const char *str, const char *end, const char *set);

/**
* Parses a content-type header and returns the content type and
* charset (if any). aCharset is not modified if no charset is
* specified in anywhere in aHeaderStr. In that case (no charset
* specified), aHadCharset is set to false. Otherwise, it's set to
* true. Note that aContentCharset can be empty even if aHadCharset
* is true.
*
* This parsing is suitable for HTTP request. Use net_ParseContentType
* for parsing this header in HTTP responses.
*/
void net_ParseRequestContentType(const nsACString &aHeaderStr,
nsACString &aContentType,
nsACString &aContentCharset,
bool* aHadCharset);

/**
* Parses a content-type header and returns the content type and
* charset (if any). aCharset is not modified if no charset is
Expand All @@ -174,9 +190,9 @@ char * net_RFindCharNotInSet(const char *str, const char *end, const char *set);
* is true.
*/
void net_ParseContentType(const nsACString &aHeaderStr,
nsACString &aContentType,
nsACString &aContentCharset,
bool* aHadCharset);
nsACString &aContentType,
nsACString &aContentCharset,
bool* aHadCharset);
/**
* As above, but also returns the start and end indexes for the charset
* parameter in aHeaderStr. These are indices for the entire parameter, NOT
Expand All @@ -187,11 +203,11 @@ void net_ParseContentType(const nsACString &aHeaderStr,
* *aCharsetStart is nonnegative; this corresponds to charset="".
*/
void net_ParseContentType(const nsACString &aHeaderStr,
nsACString &aContentType,
nsACString &aContentCharset,
bool *aHadCharset,
int32_t *aCharsetStart,
int32_t *aCharsetEnd);
nsACString &aContentType,
nsACString &aContentCharset,
bool *aHadCharset,
int32_t *aCharsetStart,
int32_t *aCharsetEnd);

/* inline versions */

Expand Down

0 comments on commit d135e3b

Please sign in to comment.