Backed out changeset f82fd05e7699 (bug 1333899)

This commit is contained in:
Sebastian Hengst 2017-02-22 09:59:57 +01:00
Родитель eba24aae1e
Коммит 10a6e4f120
2 изменённых файлов: 72 добавлений и 131 удалений

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

@ -7,7 +7,6 @@
#include "nsDataHandler.h"
#include "nsNetCID.h"
#include "nsError.h"
#include "nsIOService.h"
#include "DataChannelChild.h"
#include "plstr.h"
@ -158,104 +157,6 @@ nsDataHandler::AllowPort(int32_t port, const char *scheme, bool *_retval) {
#define BASE64_EXTENSION ";base64"
/**
* Helper that performs a case insensitive match to find the offset of a given
* pattern in a nsACString.
*/
bool
FindOffsetOf(const nsACString& aPattern, const nsACString& aSrc,
nsACString::size_type& aOffset)
{
static const nsCaseInsensitiveCStringComparator kComparator;
nsACString::const_iterator begin, end;
aSrc.BeginReading(begin);
aSrc.EndReading(end);
if (!FindInReadable(aPattern, begin, end, kComparator)) {
return false;
}
// FindInReadable updates |begin| and |end| to the match coordinates.
aOffset = nsACString::size_type(begin.get() - aSrc.Data());
return true;
}
nsresult
nsDataHandler::ParsePathWithoutRef(
const nsACString& aPath,
nsCString& aContentType,
nsCString* aContentCharset,
bool& aIsBase64,
nsDependentCSubstring* aDataBuffer)
{
static NS_NAMED_LITERAL_CSTRING(kBase64Ext, BASE64_EXTENSION);
static NS_NAMED_LITERAL_CSTRING(kCharset, "charset=");
aIsBase64 = false;
// First, find the start of the data
int32_t commaIdx = aPath.FindChar(',');
if (commaIdx == kNotFound) {
return NS_ERROR_MALFORMED_URI;
}
if (commaIdx == 0) {
// Nothing but data.
aContentType.AssignLiteral("text/plain");
if (aContentCharset) {
aContentCharset->AssignLiteral("US-ASCII");
}
} else {
auto mediaType = Substring(aPath, 0, commaIdx);
// Determine if the data is base64 encoded.
nsACString::size_type base64;
if (FindOffsetOf(kBase64Ext, mediaType, base64)) {
nsACString::size_type offset = base64 + kBase64Ext.Length();
// Per the RFC 2397 grammar, "base64" MUST be at the end of the
// non-data part.
//
// But we also allow it in between parameters so a subsequent ";"
// is ok as well (this deals with *broken* data URIs, see bug
// 781693 for an example). Anything after "base64" in the non-data
// part will be discarded in this case, however.
if (offset == mediaType.Length() || mediaType[offset] == ';') {
aIsBase64 = true;
// Trim the base64 part off.
mediaType.Rebind(aPath, 0, base64);
}
}
// Everything else is content type.
int32_t semiColon = mediaType.FindChar(';');
if (semiColon == 0 || mediaType.IsEmpty()) {
// There is no content type, but there are other parameters.
aContentType.AssignLiteral("text/plain");
} else {
aContentType = Substring(mediaType, 0, semiColon);
ToLowerCase(aContentType);
aContentType.StripWhitespace();
}
if (semiColon != kNotFound && aContentCharset) {
auto afterSemi = Substring(mediaType, semiColon + 1);
nsACString::size_type charset;
if (FindOffsetOf(kCharset, afterSemi, charset)) {
*aContentCharset =
Substring(afterSemi, charset + kCharset.Length());
aContentCharset->StripWhitespace();
}
}
}
if (aDataBuffer) {
aDataBuffer->Rebind(aPath, commaIdx + 1);
}
return NS_OK;
}
nsresult
nsDataHandler::ParseURI(nsCString& spec,
nsCString& contentType,
@ -263,30 +164,87 @@ nsDataHandler::ParseURI(nsCString& spec,
bool& isBase64,
nsCString* dataBuffer)
{
static NS_NAMED_LITERAL_CSTRING(kDataScheme, "data:");
isBase64 = false;
// move past "data:"
int32_t scheme = spec.Find(kDataScheme, /* aIgnoreCase = */ true);
if (scheme == kNotFound) {
const char* roBuffer = (const char*) PL_strcasestr(spec.get(), "data:");
if (!roBuffer) {
// malformed uri
return NS_ERROR_MALFORMED_URI;
}
roBuffer += sizeof("data:") - 1;
scheme += kDataScheme.Length();
// First, find the start of the data
const char* roComma = strchr(roBuffer, ',');
const char* roHash = strchr(roBuffer, '#');
if (!roComma || (roHash && roHash < roComma)) {
return NS_ERROR_MALFORMED_URI;
}
// Find the start of the hash ref if present.
int32_t hash = spec.FindChar('#', scheme);
if (roComma == roBuffer) {
// nothing but data
contentType.AssignLiteral("text/plain");
if (contentCharset) {
contentCharset->AssignLiteral("US-ASCII");
}
} else {
// Make a copy of the non-data part so we can null out parts of it as
// we go. This copy will be a small number of chars, in contrast to the
// data which may be large.
char* buffer = PL_strndup(roBuffer, roComma - roBuffer);
auto pathWithoutRef = Substring(spec, scheme,
hash != kNotFound ? hash : -1);
nsDependentCSubstring dataRange;
nsresult rv = ParsePathWithoutRef(pathWithoutRef, contentType,
contentCharset, isBase64, &dataRange);
if (NS_SUCCEEDED(rv) && dataBuffer) {
if (!dataBuffer->Assign(dataRange, mozilla::fallible)) {
rv = NS_ERROR_OUT_OF_MEMORY;
// determine if the data is base64 encoded.
char* base64 = PL_strcasestr(buffer, BASE64_EXTENSION);
if (base64) {
char *beyond = base64 + sizeof(BASE64_EXTENSION) - 1;
// Per the RFC 2397 grammar, "base64" MUST be at the end of the
// non-data part.
//
// But we also allow it in between parameters so a subsequent ";"
// is ok as well (this deals with *broken* data URIs, see bug
// 781693 for an example). Anything after "base64" in the non-data
// part will be discarded in this case, however.
if (*beyond == '\0' || *beyond == ';') {
isBase64 = true;
*base64 = '\0';
}
}
// everything else is content type
char *semiColon = (char *) strchr(buffer, ';');
if (semiColon)
*semiColon = '\0';
if (semiColon == buffer || base64 == buffer) {
// there is no content type, but there are other parameters
contentType.AssignLiteral("text/plain");
} else {
contentType.Assign(buffer);
ToLowerCase(contentType);
contentType.StripWhitespace();
}
if (semiColon && contentCharset) {
char *charset = PL_strcasestr(semiColon + 1, "charset=");
if (charset) {
contentCharset->Assign(charset + sizeof("charset=") - 1);
contentCharset->StripWhitespace();
}
}
free(buffer);
}
if (dataBuffer) {
// Split encoded data from terminal "#ref" (if present)
const char* roData = roComma + 1;
bool ok = !roHash
? dataBuffer->Assign(roData, mozilla::fallible)
: dataBuffer->Assign(roData, roHash - roData, mozilla::fallible);
if (!ok) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
return rv;
return NS_OK;
}

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

@ -36,23 +36,6 @@ public:
nsCString* contentCharset,
bool& isBase64,
nsCString* dataBuffer);
// Parse the path portion of a data: URI and return the individual parts.
//
// Note: The path is assumed *not* to have a ref portion.
//
// @arg aPath The path portion of the spec. Must not have ref portion.
// @arg aContentType Out param, will hold the parsed content type.
// @arg aContentCharset Optional, will hold the charset if specified.
// @arg aIsBase64 Out param, indicates if the data is base64 encoded.
// @arg aDataBuffer Optional, will reference the substring in |aPath| that
// contains the data portion of the path. No copy is made.
static MOZ_MUST_USE nsresult ParsePathWithoutRef(
const nsACString& aPath,
nsCString& aContentType,
nsCString* aContentCharset,
bool& aIsBase64,
nsDependentCSubstring* aDataBuffer);
};
#endif /* nsDataHandler_h___ */