зеркало из 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 "nsDataHandler.h"
|
||||||
#include "nsNetCID.h"
|
#include "nsNetCID.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
#include "nsIOService.h"
|
|
||||||
#include "DataChannelChild.h"
|
#include "DataChannelChild.h"
|
||||||
#include "plstr.h"
|
#include "plstr.h"
|
||||||
|
|
||||||
|
@ -158,104 +157,6 @@ nsDataHandler::AllowPort(int32_t port, const char *scheme, bool *_retval) {
|
||||||
|
|
||||||
#define BASE64_EXTENSION ";base64"
|
#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
|
nsresult
|
||||||
nsDataHandler::ParseURI(nsCString& spec,
|
nsDataHandler::ParseURI(nsCString& spec,
|
||||||
nsCString& contentType,
|
nsCString& contentType,
|
||||||
|
@ -263,30 +164,87 @@ nsDataHandler::ParseURI(nsCString& spec,
|
||||||
bool& isBase64,
|
bool& isBase64,
|
||||||
nsCString* dataBuffer)
|
nsCString* dataBuffer)
|
||||||
{
|
{
|
||||||
static NS_NAMED_LITERAL_CSTRING(kDataScheme, "data:");
|
isBase64 = false;
|
||||||
|
|
||||||
// move past "data:"
|
// move past "data:"
|
||||||
int32_t scheme = spec.Find(kDataScheme, /* aIgnoreCase = */ true);
|
const char* roBuffer = (const char*) PL_strcasestr(spec.get(), "data:");
|
||||||
if (scheme == kNotFound) {
|
if (!roBuffer) {
|
||||||
// malformed uri
|
// malformed uri
|
||||||
return NS_ERROR_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.
|
if (roComma == roBuffer) {
|
||||||
int32_t hash = spec.FindChar('#', scheme);
|
// 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,
|
// determine if the data is base64 encoded.
|
||||||
hash != kNotFound ? hash : -1);
|
char* base64 = PL_strcasestr(buffer, BASE64_EXTENSION);
|
||||||
nsDependentCSubstring dataRange;
|
if (base64) {
|
||||||
nsresult rv = ParsePathWithoutRef(pathWithoutRef, contentType,
|
char *beyond = base64 + sizeof(BASE64_EXTENSION) - 1;
|
||||||
contentCharset, isBase64, &dataRange);
|
// Per the RFC 2397 grammar, "base64" MUST be at the end of the
|
||||||
if (NS_SUCCEEDED(rv) && dataBuffer) {
|
// non-data part.
|
||||||
if (!dataBuffer->Assign(dataRange, mozilla::fallible)) {
|
//
|
||||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
// 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,
|
nsCString* contentCharset,
|
||||||
bool& isBase64,
|
bool& isBase64,
|
||||||
nsCString* dataBuffer);
|
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___ */
|
#endif /* nsDataHandler_h___ */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче