Commit 0d4968dc authored by tzik's avatar tzik Committed by Commit bot

Drop unused functions in HTTPParsers

Review URL: https://codereview.chromium.org/1460883003

Cr-Commit-Position: refs/heads/master@{#360524}
parent 4d1b80a4
...@@ -158,14 +158,6 @@ bool isValidHTTPToken(const String& characters) ...@@ -158,14 +158,6 @@ bool isValidHTTPToken(const String& characters)
return true; return true;
} }
static const size_t maxInputSampleSize = 128;
static String trimInputSample(const char* p, size_t length)
{
if (length > maxInputSampleSize)
return String(p, maxInputSampleSize) + horizontalEllipsisCharacter;
return String(p, length);
}
ContentDispositionType contentDispositionType(const String& contentDisposition) ContentDispositionType contentDispositionType(const String& contentDisposition)
{ {
if (contentDisposition.isEmpty()) if (contentDisposition.isEmpty())
...@@ -264,39 +256,6 @@ double parseDate(const String& value) ...@@ -264,39 +256,6 @@ double parseDate(const String& value)
return parseDateFromNullTerminatedCharacters(value.utf8().data()); return parseDateFromNullTerminatedCharacters(value.utf8().data());
} }
// FIXME: This function doesn't comply with RFC 6266.
// For example, this function doesn't handle the interaction between " and ;
// that arises from quoted-string, nor does this function properly unquote
// attribute values. Further this function appears to process parameter names
// in a case-sensitive manner. (There are likely other bugs as well.)
String filenameFromHTTPContentDisposition(const String& value)
{
Vector<String> keyValuePairs;
value.split(';', keyValuePairs);
unsigned length = keyValuePairs.size();
for (unsigned i = 0; i < length; i++) {
size_t valueStartPos = keyValuePairs[i].find('=');
if (valueStartPos == kNotFound)
continue;
String key = keyValuePairs[i].left(valueStartPos).stripWhiteSpace();
if (key.isEmpty() || key != "filename")
continue;
String value = keyValuePairs[i].substring(valueStartPos + 1).stripWhiteSpace();
// Remove quotes if there are any
if (value[0] == '\"')
value = value.substring(1, value.length() - 2);
return value;
}
return String();
}
AtomicString extractMIMETypeFromMediaType(const AtomicString& mediaType) AtomicString extractMIMETypeFromMediaType(const AtomicString& mediaType)
{ {
StringBuilder mimeType; StringBuilder mimeType;
...@@ -479,14 +438,6 @@ ContentTypeOptionsDisposition parseContentTypeOptionsHeader(const String& header ...@@ -479,14 +438,6 @@ ContentTypeOptionsDisposition parseContentTypeOptionsHeader(const String& header
return ContentTypeOptionsNone; return ContentTypeOptionsNone;
} }
String extractReasonPhraseFromHTTPStatusLine(const String& statusLine)
{
size_t spacePos = statusLine.find(' ');
// Remove status code from the status line.
spacePos = statusLine.find(' ', spacePos + 1);
return statusLine.substring(spacePos + 1);
}
XFrameOptionsDisposition parseXFrameOptionsHeader(const String& header) XFrameOptionsDisposition parseXFrameOptionsHeader(const String& header)
{ {
XFrameOptionsDisposition result = XFrameOptionsNone; XFrameOptionsDisposition result = XFrameOptionsNone;
...@@ -517,229 +468,6 @@ XFrameOptionsDisposition parseXFrameOptionsHeader(const String& header) ...@@ -517,229 +468,6 @@ XFrameOptionsDisposition parseXFrameOptionsHeader(const String& header)
return result; return result;
} }
bool parseRange(const String& range, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength)
{
// The format of "Range" header is defined in RFC 2616 Section 14.35.1.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
// We don't support multiple range requests.
rangeOffset = rangeEnd = rangeSuffixLength = -1;
// The "bytes" unit identifier should be present.
static const char bytesStart[] = "bytes=";
if (!range.startsWith(bytesStart, TextCaseInsensitive))
return false;
String byteRange = range.substring(sizeof(bytesStart) - 1);
// The '-' character needs to be present.
int index = byteRange.find('-');
if (index == -1)
return false;
// If the '-' character is at the beginning, the suffix length, which specifies the last N bytes, is provided.
// Example:
// -500
if (!index) {
String suffixLengthString = byteRange.substring(index + 1).stripWhiteSpace();
bool ok;
long long value = suffixLengthString.toInt64Strict(&ok);
if (ok)
rangeSuffixLength = value;
return true;
}
// Otherwise, the first-byte-position and the last-byte-position are provied.
// Examples:
// 0-499
// 500-
String firstBytePosStr = byteRange.left(index).stripWhiteSpace();
bool ok;
long long firstBytePos = firstBytePosStr.toInt64Strict(&ok);
if (!ok)
return false;
String lastBytePosStr = byteRange.substring(index + 1).stripWhiteSpace();
long long lastBytePos = -1;
if (!lastBytePosStr.isEmpty()) {
lastBytePos = lastBytePosStr.toInt64Strict(&ok);
if (!ok)
return false;
}
if (firstBytePos < 0 || !(lastBytePos == -1 || lastBytePos >= firstBytePos))
return false;
rangeOffset = firstBytePos;
rangeEnd = lastBytePos;
return true;
}
// HTTP/1.1 - RFC 2616
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF
size_t parseHTTPRequestLine(const char* data, size_t length, String& failureReason, String& method, String& url, HTTPVersion& httpVersion)
{
method = String();
url = String();
httpVersion = Unknown;
const char* space1 = 0;
const char* space2 = 0;
const char* p;
size_t consumedLength;
for (p = data, consumedLength = 0; consumedLength < length; p++, consumedLength++) {
if (*p == ' ') {
if (!space1)
space1 = p;
else if (!space2)
space2 = p;
} else if (*p == '\n') {
break;
}
}
// Haven't finished header line.
if (consumedLength == length) {
failureReason = "Incomplete Request Line";
return 0;
}
// RequestLine does not contain 3 parts.
if (!space1 || !space2) {
failureReason = "Request Line does not appear to contain: <Method> <Url> <HTTPVersion>.";
return 0;
}
// The line must end with "\r\n".
const char* end = p + 1;
if (*(end - 2) != '\r') {
failureReason = "Request line does not end with CRLF";
return 0;
}
// Request Method.
method = String(data, space1 - data); // For length subtract 1 for space, but add 1 for data being the first character.
// Request URI.
url = String(space1 + 1, space2 - space1 - 1); // For length subtract 1 for space.
// HTTP Version.
String httpVersionString(space2 + 1, end - space2 - 3); // For length subtract 1 for space, and 2 for "\r\n".
if (httpVersionString.length() != 8 || !httpVersionString.startsWith("HTTP/1."))
httpVersion = Unknown;
else if (httpVersionString[7] == '0')
httpVersion = HTTP_1_0;
else if (httpVersionString[7] == '1')
httpVersion = HTTP_1_1;
else
httpVersion = Unknown;
return end - data;
}
static bool parseHTTPHeaderName(const char* s, size_t start, size_t size, String& failureReason, size_t* position, AtomicString* name)
{
size_t nameBegin = start;
for (size_t i = start; i < size; ++i) {
switch (s[i]) {
case '\r':
failureReason = "Unexpected CR in name at " + trimInputSample(&s[nameBegin], i - nameBegin);
return false;
case '\n':
failureReason = "Unexpected LF in name at " + trimInputSample(&s[nameBegin], i - nameBegin);
return false;
case ':':
if (i == nameBegin) {
failureReason = "Header name is missing";
return false;
}
*name = AtomicString::fromUTF8(&s[nameBegin], i - nameBegin);
if (name->isNull()) {
failureReason = "Invalid UTF-8 sequence in header name";
return false;
}
*position = i;
return true;
default:
break;
}
}
failureReason = "Unterminated header name";
return false;
}
static bool parseHTTPHeaderValue(const char* s, size_t start, size_t size, String& failureReason, size_t* position, AtomicString* value)
{
size_t i = start;
for (; i < size && s[i] == ' '; ++i) {
}
size_t valueBegin = i;
for (; i < size && s[i] != '\r'; ++i) {
if (s[i] == '\n') {
failureReason = "Unexpected LF in value at " + trimInputSample(&s[valueBegin], i - valueBegin);
return false;
}
}
if (i == size) {
failureReason = "Unterminated header value";
return false;
}
ASSERT(i < size && s[i] == '\r');
if (i + 1 >= size || s[i + 1] != '\n') {
failureReason = "LF doesn't follow CR after value at " + trimInputSample(&s[i + 1], size - i - 1);
return false;
}
*value = AtomicString::fromUTF8(&s[valueBegin], i - valueBegin);
if (i != valueBegin && value->isNull()) {
failureReason = "Invalid UTF-8 sequence in header value";
return false;
}
// 2 for strlen("\r\n")
*position = i + 2;
return true;
}
// Note that the header is already parsed and re-formatted in chromium side.
// We assume that the input is more restricted than RFC2616.
size_t parseHTTPHeader(const char* s, size_t size, String& failureReason, AtomicString& name, AtomicString& value)
{
name = nullAtom;
value = nullAtom;
if (size >= 1 && s[0] == '\r') {
if (size >= 2 && s[1] == '\n') {
// Skip an empty line.
return 2;
}
failureReason = "LF doesn't follow CR at " + trimInputSample(0, size);
return 0;
}
size_t current = 0;
if (!parseHTTPHeaderName(s, current, size, failureReason, &current, &name)) {
return 0;
}
ASSERT(s[current] == ':');
++current;
if (!parseHTTPHeaderValue(s, current, size, failureReason, &current, &value)) {
return 0;
}
return current;
}
size_t parseHTTPRequestBody(const char* data, size_t length, Vector<unsigned char>& body)
{
body.clear();
body.append(data, length);
return length;
}
static bool isCacheHeaderSeparator(UChar c) static bool isCacheHeaderSeparator(UChar c)
{ {
// See RFC 2616, Section 2.2 // See RFC 2616, Section 2.2
......
...@@ -96,27 +96,16 @@ PLATFORM_EXPORT bool isValidHTTPFieldContentRFC7230(const String&); ...@@ -96,27 +96,16 @@ PLATFORM_EXPORT bool isValidHTTPFieldContentRFC7230(const String&);
PLATFORM_EXPORT bool isValidHTTPToken(const String&); PLATFORM_EXPORT bool isValidHTTPToken(const String&);
PLATFORM_EXPORT bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url); PLATFORM_EXPORT bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url);
PLATFORM_EXPORT double parseDate(const String&); PLATFORM_EXPORT double parseDate(const String&);
PLATFORM_EXPORT String filenameFromHTTPContentDisposition(const String&);
PLATFORM_EXPORT AtomicString extractMIMETypeFromMediaType(const AtomicString&); PLATFORM_EXPORT AtomicString extractMIMETypeFromMediaType(const AtomicString&);
PLATFORM_EXPORT String extractCharsetFromMediaType(const String&); PLATFORM_EXPORT String extractCharsetFromMediaType(const String&);
PLATFORM_EXPORT void findCharsetInMediaType(const String& mediaType, unsigned& charsetPos, unsigned& charsetLen, unsigned start = 0); PLATFORM_EXPORT void findCharsetInMediaType(const String& mediaType, unsigned& charsetPos, unsigned& charsetLen, unsigned start = 0);
PLATFORM_EXPORT ReflectedXSSDisposition parseXSSProtectionHeader(const String& header, String& failureReason, unsigned& failurePosition, String& reportURL); PLATFORM_EXPORT ReflectedXSSDisposition parseXSSProtectionHeader(const String& header, String& failureReason, unsigned& failurePosition, String& reportURL);
PLATFORM_EXPORT String extractReasonPhraseFromHTTPStatusLine(const String&);
PLATFORM_EXPORT XFrameOptionsDisposition parseXFrameOptionsHeader(const String&); PLATFORM_EXPORT XFrameOptionsDisposition parseXFrameOptionsHeader(const String&);
PLATFORM_EXPORT CacheControlHeader parseCacheControlDirectives(const AtomicString& cacheControlHeader, const AtomicString& pragmaHeader); PLATFORM_EXPORT CacheControlHeader parseCacheControlDirectives(const AtomicString& cacheControlHeader, const AtomicString& pragmaHeader);
PLATFORM_EXPORT void parseCommaDelimitedHeader(const String& headerValue, CommaDelimitedHeaderSet&); PLATFORM_EXPORT void parseCommaDelimitedHeader(const String& headerValue, CommaDelimitedHeaderSet&);
// -1 could be set to one of the return parameters to indicate the value is not specified.
PLATFORM_EXPORT bool parseRange(const String&, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength);
PLATFORM_EXPORT ContentTypeOptionsDisposition parseContentTypeOptionsHeader(const String& header); PLATFORM_EXPORT ContentTypeOptionsDisposition parseContentTypeOptionsHeader(const String& header);
// Parsing Complete HTTP Messages.
enum HTTPVersion { Unknown, HTTP_1_0, HTTP_1_1 };
PLATFORM_EXPORT size_t parseHTTPRequestLine(const char* data, size_t length, String& failureReason, String& method, String& url, HTTPVersion&);
PLATFORM_EXPORT size_t parseHTTPHeader(const char* data, size_t length, String& failureReason, AtomicString& nameStr, AtomicString& valueStr);
PLATFORM_EXPORT size_t parseHTTPRequestBody(const char* data, size_t length, Vector<unsigned char>& body);
} }
#endif #endif
...@@ -11,15 +11,6 @@ ...@@ -11,15 +11,6 @@
namespace blink { namespace blink {
namespace {
size_t parseHTTPHeader(const char* data, String& failureReason, AtomicString& nameStr, AtomicString& valueStr)
{
return blink::parseHTTPHeader(data, strlen(data), failureReason, nameStr, valueStr);
}
} // namespace
TEST(HTTPParsersTest, ParseCacheControl) TEST(HTTPParsersTest, ParseCacheControl)
{ {
CacheControlHeader header; CacheControlHeader header;
...@@ -102,125 +93,6 @@ TEST(HTTPParsersTest, ParseCacheControl) ...@@ -102,125 +93,6 @@ TEST(HTTPParsersTest, ParseCacheControl)
EXPECT_TRUE(std::isnan(header.maxAge)); EXPECT_TRUE(std::isnan(header.maxAge));
} }
TEST(HTTPParsersTest, parseHTTPHeaderSimple)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(12u, parseHTTPHeader("foo: bar\r\notherdata", failureReason, name, value));
EXPECT_TRUE(failureReason.isEmpty());
EXPECT_EQ("foo", name.string());
EXPECT_EQ("bar", value.string());
}
TEST(HTTPParsersTest, parseHTTPHeaderEmptyName)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader(": bar\r\notherdata", failureReason, name, value));
EXPECT_EQ("Header name is missing", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderEmptyValue)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(7u, parseHTTPHeader("foo: \r\notherdata", failureReason, name, value));
EXPECT_TRUE(failureReason.isEmpty());
EXPECT_EQ("foo", name.string());
EXPECT_TRUE(value.isEmpty());
}
TEST(HTTPParsersTest, parseHTTPHeaderInvalidName)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("\xfa: \r\notherdata", failureReason, name, value));
EXPECT_EQ("Invalid UTF-8 sequence in header name", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderInvalidValue)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("foo: \xfa\r\notherdata", failureReason, name, value));
EXPECT_EQ("Invalid UTF-8 sequence in header value", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderEmpty)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("", failureReason, name, value));
EXPECT_EQ("Unterminated header name", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderEmptyLine)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(2u, parseHTTPHeader("\r\notherdata", failureReason, name, value));
EXPECT_TRUE(failureReason.isEmpty());
EXPECT_TRUE(name.isNull());
EXPECT_TRUE(value.isNull());
}
TEST(HTTPParsersTest, parseHTTPHeaderUnexpectedCRinName)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("foo\rotherdata\n", failureReason, name, value));
EXPECT_EQ("Unexpected CR in name at foo", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderUnexpectedLFinName)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("foo\notherdata\n", failureReason, name, value));
EXPECT_EQ("Unexpected LF in name at foo", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderUnexpectedLFinValue)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("foo: bar\notherdata\n", failureReason, name, value));
EXPECT_EQ("Unexpected LF in value at bar", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderNoLFAtEndOfLine)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("foo: bar\r", failureReason, name, value));
EXPECT_EQ("LF doesn't follow CR after value at ", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderNoLF)
{
String failureReason;
AtomicString name, value;
EXPECT_EQ(0u, parseHTTPHeader("foo: bar\rhoge\r\n", failureReason, name, value));
EXPECT_EQ("LF doesn't follow CR after value at hoge\r\n", failureReason);
}
TEST(HTTPParsersTest, parseHTTPHeaderTwoLines)
{
const char data[] = "foo: bar\r\nhoge: fuga\r\nxxx";
String failureReason;
AtomicString name, value;
EXPECT_EQ(10u, parseHTTPHeader(data, failureReason, name, value));
EXPECT_TRUE(failureReason.isEmpty());
EXPECT_EQ("foo", name.string());
EXPECT_EQ("bar", value.string());
EXPECT_EQ(12u, parseHTTPHeader(data + 10, failureReason, name, value));
EXPECT_TRUE(failureReason.isEmpty());
EXPECT_EQ("hoge", name.string());
EXPECT_EQ("fuga", value.string());
}
TEST(HTTPParsersTest, CommaDelimitedHeaderSet) TEST(HTTPParsersTest, CommaDelimitedHeaderSet)
{ {
CommaDelimitedHeaderSet set1; CommaDelimitedHeaderSet set1;
...@@ -263,4 +135,3 @@ TEST(HTTPParsersTest, HTTPFieldContent) ...@@ -263,4 +135,3 @@ TEST(HTTPParsersTest, HTTPFieldContent)
} }
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment