Make our content-type header parsing closer to spec (it wasn't allowing some

perfectly valid things), and have only one function for doing said parsing
instead of two separate functions.  Bug 244964, r+sr=darin, a=bsmedberg
This commit is contained in:
bzbarsky%mit.edu 2005-07-25 20:27:04 +00:00
Родитель 38277d1324
Коммит b0179fc5c7
19 изменённых файлов: 491 добавлений и 120 удалений

Просмотреть файл

@ -114,6 +114,7 @@ XPIDLSRCS = \
nsPIProtocolProxyService.idl \
nsPISocketTransportService.idl \
nsIChannelEventSink.idl \
nsINetUtil.idl \
$(NULL)
EXPORTS = \

Просмотреть файл

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
/**
* nsINetUtil provides various network-related utility methods.
*/
[scriptable, uuid(f0c5dddb-4713-4603-af2d-bf671838996b)]
interface nsINetUtil : nsISupports
{
/**
* Parse a content-type header and return the content type and
* charset (if any).
*
* @param aTypeHeader the header string to parse
* @param [out] aCharset the charset parameter specified in the
* header, if any.
* @param [out] aHadCharset whether a charset was explicitly specified.
* @return the MIME type specified in the header, in lower-case.
*/
AUTF8String parseContentType(in AUTF8String aTypeHeader,
out AUTF8String aCharset,
out boolean aHadCharset);
};

Просмотреть файл

@ -86,6 +86,7 @@
#include "nsISyncStreamListener.h"
#include "nsInterfaceRequestorAgg.h"
#include "nsInt64.h"
#include "nsINetUtil.h"
// Helper, to simplify getting the I/O service.
inline const nsGetServiceByCIDWithError
@ -682,24 +683,16 @@ NS_ParseContentType(const nsACString &rawContentType,
nsCString &contentCharset)
{
// contentCharset is left untouched if not present in rawContentType
nsACString::const_iterator begin, it, end;
it = rawContentType.BeginReading(begin);
rawContentType.EndReading(end);
if (FindCharInReadable(';', it, end)) {
contentType = Substring(begin, it);
// now look for "charset=FOO" and extract "FOO"
begin = ++it;
if (FindInReadable(NS_LITERAL_CSTRING("charset="), begin, it = end,
nsCaseInsensitiveCStringComparator())) {
contentCharset = Substring(it, end);
contentCharset.StripWhitespace();
}
}
else
contentType = rawContentType;
ToLowerCase(contentType);
contentType.StripWhitespace();
return NS_OK;
nsresult rv;
nsCOMPtr<nsINetUtil> util = do_GetIOService(&rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCString charset;
PRBool hadCharset;
rv = util->ParseContentType(rawContentType, charset, &hadCharset,
contentType);
if (NS_SUCCEEDED(rv) && hadCharset)
contentCharset = charset;
return rv;
}
inline nsresult

Просмотреть файл

@ -237,8 +237,9 @@ nsIOService::~nsIOService()
{
}
NS_IMPL_THREADSAFE_ISUPPORTS3(nsIOService,
NS_IMPL_THREADSAFE_ISUPPORTS4(nsIOService,
nsIIOService,
nsINetUtil,
nsIObserver,
nsISupportsWeakReference)
@ -707,3 +708,14 @@ nsIOService::Observe(nsISupports *subject,
}
return NS_OK;
}
// nsINetUtil interface
NS_IMETHODIMP
nsIOService::ParseContentType(const nsACString &aTypeHeader,
nsACString &aCharset,
PRBool *aHadCharset,
nsACString &aContentType)
{
net_ParseContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
return NS_OK;
}

Просмотреть файл

@ -54,6 +54,7 @@
#include "nsSupportsArray.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "nsINetUtil.h"
#define NS_N(x) (sizeof(x)/sizeof(*x))
@ -71,12 +72,14 @@ class nsIPrefBranch2;
class nsIOService : public nsIIOService
, public nsIObserver
, public nsINetUtil
, public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIIOSERVICE
NS_DECL_NSIOBSERVER
NS_DECL_NSINETUTIL
nsIOService() NS_HIDDEN;
~nsIOService() NS_HIDDEN;

Просмотреть файл

@ -675,3 +675,220 @@ repeat:
}
return (char *) iter;
}
#define HTTP_LWS " \t"
// Return the index of the closing quote of the string, if any
static PRUint32
net_FindStringEnd(const nsCString& flatStr,
PRUint32 stringStart,
char stringDelim)
{
NS_ASSERTION(stringStart < flatStr.Length() &&
flatStr.CharAt(stringStart) == stringDelim &&
(stringDelim == '"' || stringDelim == '\''),
"Invalid stringStart");
const char set[] = { stringDelim, '\\', '\0' };
do {
// stringStart points to either the start quote or the last
// escaped char (the char following a '\\')
// Write to searchStart here, so that when we get back to the
// top of the loop right outside this one we search from the
// right place.
PRUint32 stringEnd = flatStr.FindCharInSet(set, stringStart + 1);
if (stringEnd == PRUint32(kNotFound))
return flatStr.Length();
if (flatStr.CharAt(stringEnd) == '\\') {
// Hit a backslash-escaped char. Need to skip over it.
stringStart = stringEnd + 1;
if (stringStart == flatStr.Length())
return stringStart;
// Go back to looking for the next escape or the string end
continue;
}
return stringEnd;
} while (PR_TRUE);
NS_NOTREACHED("How did we get here?");
return flatStr.Length();
}
static PRUint32
net_FindMediaDelimiter(const nsCString& flatStr,
PRUint32 searchStart,
char delimiter)
{
do {
// searchStart points to the spot from which we should start looking
// for the delimiter.
const char delimStr[] = { delimiter, '"', '\'', '\0' };
PRUint32 curDelimPos = flatStr.FindCharInSet(delimStr, searchStart);
if (curDelimPos == PRUint32(kNotFound))
return flatStr.Length();
char ch = flatStr.CharAt(curDelimPos);
if (ch == delimiter) {
// Found delimiter
return curDelimPos;
}
// We hit the start of a quoted string. Look for its end.
searchStart = net_FindStringEnd(flatStr, curDelimPos, ch);
if (searchStart == flatStr.Length())
return searchStart;
++searchStart;
// searchStart now points to the first char after the end of the
// string, so just go back to the top of the loop and look for
// |delimiter| again.
} while (PR_TRUE);
NS_NOTREACHED("How did we get here?");
return flatStr.Length();
}
static void
net_ParseMediaType(const nsACString &aMediaTypeStr,
nsACString &aContentType,
nsACString &aContentCharset,
PRBool *aHadCharset)
{
const nsCString& flatStr = PromiseFlatCString(aMediaTypeStr);
const char* start = flatStr.get();
const char* end = start + flatStr.Length();
// Trim LWS leading and trailing whitespace from type. We include '(' in
// the trailing trim set to catch media-type comments, which are not at all
// standard, but may occur in rare cases.
const char* type = net_FindCharNotInSet(start, end, HTTP_LWS);
const char* typeEnd = net_FindCharInSet(type, end, HTTP_LWS ";(");
const char* charset = "";
const char* charsetEnd = charset;
// Iterate over parameters
PRBool typeHasCharset = PR_FALSE;
PRUint32 paramStart = flatStr.FindChar(';', typeEnd - start);
if (paramStart != PRUint32(kNotFound)) {
// We have parameters. Iterate over them.
PRUint32 curParamStart = paramStart + 1;
do {
PRUint32 curParamEnd =
net_FindMediaDelimiter(flatStr, curParamStart, ';');
const char* paramName = net_FindCharNotInSet(start + curParamStart,
start + curParamEnd,
HTTP_LWS);
static const char charsetStr[] = "charset=";
if (PL_strncasecmp(paramName, charsetStr,
sizeof(charsetStr) - 1) == 0) {
charset = paramName + sizeof(charsetStr) - 1;
charsetEnd = start + curParamEnd;
typeHasCharset = PR_TRUE;
}
curParamStart = curParamEnd + 1;
} while (curParamStart < flatStr.Length());
}
if (typeHasCharset) {
// Trim LWS leading and trailing whitespace from charset. We include
// '(' in the trailing trim set to catch media-type comments, which are
// not at all standard, but may occur in rare cases.
charset = net_FindCharNotInSet(charset, charsetEnd, HTTP_LWS);
if (*charset == '"' || *charset == '\'') {
charsetEnd =
start + net_FindStringEnd(flatStr, charset - start, *charset);
charset++;
NS_ASSERTION(charsetEnd >= charset, "Bad charset parsing");
} else {
charsetEnd = net_FindCharInSet(charset, charsetEnd, HTTP_LWS ";(");
}
}
// if the server sent "*/*", it is meaningless, so do not store it.
// also, if type is the same as aContentType, then just update the
// charset. however, if charset is empty and aContentType hasn't
// changed, then don't wipe-out an existing aContentCharset. We
// also want to reject a mime-type if it does not include a slash.
// 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) != NULL) {
// Common case here is that aContentType is empty
PRBool eq = !aContentType.IsEmpty() &&
aContentType.Equals(Substring(type, typeEnd),
nsCaseInsensitiveCStringComparator());
if (!eq) {
aContentType.Assign(type, typeEnd - type);
ToLowerCase(aContentType);
}
if ((!eq && *aHadCharset) || typeHasCharset) {
*aHadCharset = PR_TRUE;
aContentCharset.Assign(charset, charsetEnd - charset);
}
}
}
#undef HTTP_LWS
void
net_ParseContentType(const nsACString &aHeaderStr,
nsACString &aContentType,
nsACString &aContentCharset,
PRBool *aHadCharset)
{
//
// Augmented BNF (from RFC 2616 section 3.7):
//
// header-value = media-type *( LWS "," LWS media-type )
// media-type = type "/" subtype *( LWS ";" LWS parameter )
// type = token
// subtype = token
// parameter = attribute "=" value
// attribute = token
// value = token | quoted-string
//
//
// Examples:
//
// text/html
// text/html, text/html
// text/html,text/html; charset=ISO-8859-1
// text/html,text/html; charset="ISO-8859-1"
// text/html;charset=ISO-8859-1, text/html
// text/html;charset='ISO-8859-1', text/html
// application/octet-stream
//
*aHadCharset = PR_FALSE;
const nsCString& flatStr = PromiseFlatCString(aHeaderStr);
// iterate over media-types. Note that ',' characters can happen
// inside quoted strings, so we need to watch out for that.
PRUint32 curTypeStart = 0;
do {
// curTypeStart points to the start of the current media-type. We want
// to look for its end.
PRUint32 curTypeEnd =
net_FindMediaDelimiter(flatStr, curTypeStart, ',');
// At this point curTypeEnd points to the spot where the media-type
// starting at curTypeEnd ends. Time to parse that!
net_ParseMediaType(Substring(flatStr, curTypeStart,
curTypeEnd - curTypeStart),
aContentType, aContentCharset, aHadCharset);
// And let's move on to the next media-type
curTypeStart = curTypeEnd + 1;
} while (curTypeStart < flatStr.Length());
}

Просмотреть файл

@ -194,6 +194,19 @@ NS_HIDDEN_(char *) net_RFindCharInSet(const char *str, const char *end, const ch
*/
NS_HIDDEN_(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.
*/
NS_HIDDEN_(void) net_ParseContentType(const nsACString &aHeaderStr,
nsACString &aContentType,
nsACString &aContentCharset,
PRBool* aHadCharset);
/* inline versions */
/* remember the 64-bit platforms ;-) */

Просмотреть файл

@ -57,6 +57,10 @@
{0x93, 0x37, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
}
// service implementing nsINetUtil
#define NS_NETUTIL_CONTRACTID \
"@mozilla.org/network/util;1"
// service implementing nsIEventTarget. events dispatched to this event
// target will be executed on one of necko's background i/o threads.
#define NS_IOTHREADPOOL_CLASSNAME \

Просмотреть файл

@ -621,6 +621,10 @@ static const nsModuleComponentInfo gNetModuleInfo[] = {
NS_IOSERVICE_CID,
NS_IOSERVICE_CONTRACTID,
nsIOServiceConstructor },
{ NS_IOSERVICE_CLASSNAME,
NS_IOSERVICE_CID,
NS_NETUTIL_CONTRACTID,
nsIOServiceConstructor },
{ NS_IOTHREADPOOL_CLASSNAME,
NS_IOTHREADPOOL_CID,
NS_IOTHREADPOOL_CONTRACTID,

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsIMIMEService.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsURLHelper.h"
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
@ -313,8 +314,8 @@ nsFileChannel::SetContentType(const nsACString &aContentType)
// If someone gives us a type hint we should just use that type instead of
// doing our guessing. So we don't care when this is being called.
// mContentCharset is unchanged if not parsed
NS_ParseContentType(aContentType, mContentType, mContentCharset);
PRBool dummy;
net_ParseContentType(aContentType, mContentType, mContentCharset, &dummy);
return NS_OK;
}

Просмотреть файл

@ -68,7 +68,11 @@ MODULE_OPTIMIZE_FLAGS=-O -g
endif
endif
LOCAL_INCLUDES=-I$(topsrcdir)/xpcom/ds
LOCAL_INCLUDES = \
-I$(srcdir)/../../../base/src \
-I$(topsrcdir)/xpcom/ds \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a
# static lib.

Просмотреть файл

@ -48,6 +48,7 @@
#include "nsIPrefBranch.h"
#include "nsIStreamConverterService.h"
#include "nsISocketTransport.h"
#include "nsURLHelper.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gFTPLog;
@ -432,7 +433,8 @@ nsFTPChannel::GetContentType(nsACString &aContentType)
NS_IMETHODIMP
nsFTPChannel::SetContentType(const nsACString &aContentType)
{
NS_ParseContentType(aContentType, mContentType, mContentCharset);
PRBool dummy;
net_ParseContentType(aContentType, mContentType, mContentCharset, &dummy);
return NS_OK;
}

Просмотреть файл

@ -423,6 +423,7 @@ nsGopherChannel::SetContentType(const nsACString &aContentType)
// from the charset part of this.
nsCString *contentType = mIsPending ? &mContentType : &mContentTypeHint;
// Not in libnecko, so can't use net_ParseContentType
NS_ParseContentType(aContentType, *contentType, mContentCharset);
return NS_OK;
}

Просмотреть файл

@ -3161,16 +3161,19 @@ nsHttpChannel::SetContentType(const nsACString &value)
return NS_ERROR_NOT_AVAILABLE;
nsCAutoString contentTypeBuf, charsetBuf;
NS_ParseContentType(value, contentTypeBuf, charsetBuf);
PRBool hadCharset;
net_ParseContentType(value, contentTypeBuf, charsetBuf, &hadCharset);
mResponseHead->SetContentType(contentTypeBuf);
// take care not to stomp on an existing charset
if (!charsetBuf.IsEmpty())
if (hadCharset)
mResponseHead->SetContentCharset(charsetBuf);
} else {
// We are being given a content-type hint.
NS_ParseContentType(value, mContentTypeHint, mContentCharsetHint);
PRBool dummy;
net_ParseContentType(value, mContentTypeHint, mContentCharsetHint,
&dummy);
}
return NS_OK;

Просмотреть файл

@ -208,8 +208,12 @@ nsHttpResponseHead::ParseHeaderLine(char *line)
// handle some special case headers...
if (hdr == nsHttp::Content_Length)
PR_sscanf(val, "%lld", &mContentLength);
else if (hdr == nsHttp::Content_Type)
ParseContentType(val);
else if (hdr == nsHttp::Content_Type) {
LOG(("ParseContentType [type=%s]\n", val));
PRBool dummy;
net_ParseContentType(nsDependentCString(val),
mContentType, mContentCharset, &dummy);
}
else if (hdr == nsHttp::Cache_Control)
ParseCacheControl(val);
else if (hdr == nsHttp::Pragma)
@ -617,96 +621,6 @@ nsHttpResponseHead::ParseVersion(const char *str)
mVersion = NS_HTTP_VERSION_1_0;
}
void
nsHttpResponseHead::ParseContentType(char *type)
{
LOG(("nsHttpResponseHead::ParseContentType [type=%s]\n", type));
//
// Augmented BNF (from RFC 2616 section 3.7):
//
// header-value = media-type *( LWS "," LWS media-type )
// media-type = type "/" subtype *( LWS ";" LWS parameter )
// type = token
// subtype = token
// parameter = attribute "=" value
// attribute = token
// value = token | quoted-string
//
//
// Examples:
//
// text/html
// text/html, text/html
// text/html,text/html; charset=ISO-8859-1
// text/html;charset=ISO-8859-1, text/html
// application/octet-stream
//
// iterate over media-types
char *nextType;
do {
nextType = (char *) strchr(type, ',');
if (nextType) {
*nextType = '\0';
++nextType;
}
// type points at this media-type; locate first parameter if any
char *charset = "";
char *param = (char *) strchr(type, ';');
if (param) {
*param = '\0';
++param;
// iterate over parameters
char *nextParam;
do {
nextParam = (char *) strchr(param, ';');
if (nextParam) {
*nextParam = '\0';
++nextParam;
}
// param points at this parameter
param = net_FindCharNotInSet(param, HTTP_LWS);
if (PL_strncasecmp(param, "charset=", 8) == 0)
charset = param + 8;
} while ((param = nextParam) != nsnull);
}
// trim LWS leading and trailing whitespace from type and charset.
// charset cannot have leading whitespace. we include '(' in the
// trailing trim set to catch media-type comments, which are not
// at all standard, but may occur in rare cases.
type = net_FindCharNotInSet(type, HTTP_LWS);
char *typeEnd = net_FindCharInSet(type, HTTP_LWS "(");
char *charsetEnd = net_FindCharInSet(charset, HTTP_LWS "(");
// force content-type to be lowercase
net_ToLowerCase(type, typeEnd - type);
// if the server sent "*/*", it is meaningless, so do not store it.
// also, if type is the same as mContentType, then just update the
// charset. however, if charset is empty and mContentType hasn't
// changed, then don't wipe-out an existing mContentCharset. we
// also want to reject a mime-type if it does not include a slash.
// some servers give junk after the charset parameter, which may
// include a comma, so this check makes us a bit more tolerant.
if (*type && strcmp(type, "*/*") != 0 && strchr(type, '/')) {
PRBool eq = mContentType.Equals(Substring(type, typeEnd));
if (!eq)
mContentType.Assign(type, typeEnd - type);
if (!eq || *charset)
mContentCharset.Assign(charset, charsetEnd - charset);
}
} while ((type = nextType) != nsnull);
}
void
nsHttpResponseHead::ParseCacheControl(const char *val)
{

Просмотреть файл

@ -132,7 +132,6 @@ public:
private:
void ParseVersion(const char *);
void ParseContentType(char *);
void ParseCacheControl(const char *);
void ParsePragma(const char *);

Просмотреть файл

@ -48,6 +48,7 @@
#include "nsIMultiPartChannel.h"
#include "nsCRT.h"
#include "nsIHttpChannelInternal.h"
#include "nsURLHelper.h"
//
// Helper function for determining the length of data bytes up to
@ -325,7 +326,8 @@ nsPartChannel::GetContentType(nsACString &aContentType)
NS_IMETHODIMP
nsPartChannel::SetContentType(const nsACString &aContentType)
{
NS_ParseContentType(aContentType, mContentType, mContentCharset);
PRBool dummy;
net_ParseContentType(aContentType, mContentType, mContentCharset, &dummy);
return NS_OK;
}

Просмотреть файл

@ -98,6 +98,7 @@ _UNIT_FILES = unit/test_all.sh \
unit/tail.js \
unit/test_protocolproxyservice.js \
unit/test_http_headers.js \
unit/test_parse_content_type.js \
$(NULL)
libs:: $(_UNIT_FILES)
$(INSTALL) $^ $(DIST)/bin/necko_unit_tests

Просмотреть файл

@ -0,0 +1,137 @@
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Boris Zbarsky <bzbarsky@mit.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var charset = {};
var hadCharset = {};
var type;
function reset() {
delete charset.value;
delete hadCharset.value;
type = undefined;
}
function check(aType, aCharset, aHadCharset) {
do_check_eq(type, aType);
do_check_eq(aCharset, charset.value);
do_check_eq(aHadCharset, hadCharset.value);
reset();
}
function run_test() {
var netutil = Components.classes["@mozilla.org/network/util;1"]
.getService(Components.interfaces.nsINetUtil);
type = netutil.parseContentType("text/html", charset, hadCharset);
check("text/html", "", false);
type = netutil.parseContentType("TEXT/HTML", charset, hadCharset);
check("text/html", "", false);
type = netutil.parseContentType("text/html, text/html", charset, hadCharset);
check("text/html", "", false);
type = netutil.parseContentType("text/html, text/plain",
charset, hadCharset);
check("text/plain", "", false);
type = netutil.parseContentType('text/html, ', charset, hadCharset);
check("text/html", "", false);
type = netutil.parseContentType('text/html, */*', charset, hadCharset);
check("text/html", "", false);
type = netutil.parseContentType('text/html, foo', charset, hadCharset);
check("text/html", "", false);
type = netutil.parseContentType("text/html; charset=ISO-8859-1",
charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType('text/html; charset="ISO-8859-1"',
charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType("text/html; charset='ISO-8859-1'",
charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType("text/html; charset='ISO-8859-1', text/html",
charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType("text/html; charset='ISO-8859-1', text/html; charset=UTF8",
charset, hadCharset);
check("text/html", "UTF8", true);
type = netutil.parseContentType("text/html; charset=ISO-8859-1, TEXT/HTML", charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType("text/html; charset=ISO-8859-1, TEXT/plain", charset, hadCharset);
check("text/plain", "", true);
type = netutil.parseContentType("text/plain, TEXT/HTML; charset='ISO-8859-1', text/html, TEXT/HTML", charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType('text/plain, TEXT/HTML; param="charset=UTF8"; charset=\'ISO-8859-1\'; param2="charset=UTF16", text/html, TEXT/HTML', charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType('text/plain, TEXT/HTML; param=charset=UTF8; charset=\'ISO-8859-1\'; param2=charset=UTF16, text/html, TEXT/HTML', charset, hadCharset);
check("text/html", "ISO-8859-1", true);
type = netutil.parseContentType("text/plain; param= , text/html", charset, hadCharset);
check("text/html", "", false);
type = netutil.parseContentType('text/plain; param=", text/html"', charset, hadCharset);
check("text/plain", "", false);
type = netutil.parseContentType('text/plain; param=", \\" , text/html"', charset, hadCharset);
check("text/plain", "", false);
type = netutil.parseContentType('text/plain; param=", \\" , text/html , "', charset, hadCharset);
check("text/plain", "", false);
type = netutil.parseContentType('text/plain param=", \\" , text/html , "', charset, hadCharset);
check("text/plain", "", false);
type = netutil.parseContentType('text/plain charset=UTF8', charset, hadCharset);
check("text/plain", "", false);
type = netutil.parseContentType('text/plain, TEXT/HTML; param="charset=UTF8"; ; param2="charset=UTF16", text/html, TEXT/HTML', charset, hadCharset);
check("text/html", "", false);
}