зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset f82fd05e7699 (bug 1333899)
This commit is contained in:
Родитель
eba24aae1e
Коммит
10a6e4f120
|
@ -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___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче