#include "config.h"
#include "HTTPParsers.h"
#include "ResourceResponseBase.h"
#include "PlatformString.h"
#include <wtf/text/CString.h>
#include <wtf/DateMath.h>
using namespace WTF;
namespace WebCore {
static inline bool skipWhiteSpace(const String& str, int& pos, bool fromHttpEquivMeta)
{
int len = str.length();
if (fromHttpEquivMeta) {
while (pos != len && str[pos] <= ' ')
++pos;
} else {
while (pos != len && (str[pos] == '\t' || str[pos] == ' '))
++pos;
}
return pos != len;
}
static inline bool skipToken(const String& str, int& pos, const char* token)
{
int len = str.length();
while (pos != len && *token) {
if (toASCIILower(str[pos]) != *token++)
return false;
++pos;
}
return true;
}
ContentDispositionType contentDispositionType(const String& contentDisposition)
{
if (contentDisposition.isEmpty())
return ContentDispositionNone;
if (contentDisposition.startsWith(";"))
return ContentDispositionNone;
if (contentDisposition.startsWith("inline", false))
return ContentDispositionInline;
if (contentDisposition.startsWith("filename", false))
return ContentDispositionNone;
if (contentDisposition.startsWith("name", false))
return ContentDispositionNone;
return ContentDispositionAttachment;
}
bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url)
{
int len = refresh.length();
int pos = 0;
if (!skipWhiteSpace(refresh, pos, fromHttpEquivMeta))
return false;
while (pos != len && refresh[pos] != ',' && refresh[pos] != ';')
++pos;
if (pos == len) { url = String();
bool ok;
delay = refresh.stripWhiteSpace().toDouble(&ok);
return ok;
} else {
bool ok;
delay = refresh.left(pos).stripWhiteSpace().toDouble(&ok);
if (!ok)
return false;
++pos;
skipWhiteSpace(refresh, pos, fromHttpEquivMeta);
int urlStartPos = pos;
if (refresh.find("url", urlStartPos, false) == urlStartPos) {
urlStartPos += 3;
skipWhiteSpace(refresh, urlStartPos, fromHttpEquivMeta);
if (refresh[urlStartPos] == '=') {
++urlStartPos;
skipWhiteSpace(refresh, urlStartPos, fromHttpEquivMeta);
} else
urlStartPos = pos; }
int urlEndPos = len;
if (refresh[urlStartPos] == '"' || refresh[urlStartPos] == '\'') {
UChar quotationMark = refresh[urlStartPos];
urlStartPos++;
while (urlEndPos > urlStartPos) {
urlEndPos--;
if (refresh[urlEndPos] == quotationMark)
break;
}
if (urlEndPos == urlStartPos)
urlEndPos = len;
}
url = refresh.substring(urlStartPos, urlEndPos - urlStartPos).stripWhiteSpace();
return true;
}
}
double parseDate(const String& value)
{
return parseDateFromNullTerminatedCharacters(value.utf8().data());
}
String filenameFromHTTPContentDisposition(const String& value)
{
Vector<String> keyValuePairs;
value.split(';', keyValuePairs);
unsigned length = keyValuePairs.size();
for (unsigned i = 0; i < length; i++) {
int valueStartPos = keyValuePairs[i].find('=');
if (valueStartPos < 0)
continue;
String key = keyValuePairs[i].left(valueStartPos).stripWhiteSpace();
if (key.isEmpty() || key != "filename")
continue;
String value = keyValuePairs[i].substring(valueStartPos + 1).stripWhiteSpace();
if (value[0] == '\"')
value = value.substring(1, value.length() - 2);
return value;
}
return String();
}
String extractMIMETypeFromMediaType(const String& mediaType)
{
Vector<UChar, 64> mimeType;
unsigned length = mediaType.length();
mimeType.reserveCapacity(length);
for (unsigned i = 0; i < length; i++) {
UChar c = mediaType[i];
if (c == ';')
break;
if (c == ',')
break;
if (isSpaceOrNewline(c))
continue;
mimeType.append(c);
}
if (mimeType.size() == length)
return mediaType;
return String(mimeType.data(), mimeType.size());
}
String extractCharsetFromMediaType(const String& mediaType)
{
unsigned int pos, len;
findCharsetInMediaType(mediaType, pos, len);
return mediaType.substring(pos, len);
}
void findCharsetInMediaType(const String& mediaType, unsigned int& charsetPos, unsigned int& charsetLen, unsigned int start)
{
charsetPos = start;
charsetLen = 0;
int pos = start;
int length = (int)mediaType.length();
while (pos < length) {
pos = mediaType.find("charset", pos, false);
if (pos <= 0) {
charsetLen = 0;
return;
}
if (mediaType[pos-1] > ' ' && mediaType[pos-1] != ';') {
pos += 7;
continue;
}
pos += 7;
while (pos != length && mediaType[pos] <= ' ')
++pos;
if (mediaType[pos++] != '=') continue;
while (pos != length && (mediaType[pos] <= ' ' || mediaType[pos] == '"' || mediaType[pos] == '\''))
++pos;
int endpos = pos;
while (pos != length && mediaType[endpos] > ' ' && mediaType[endpos] != '"' && mediaType[endpos] != '\'' && mediaType[endpos] != ';')
++endpos;
charsetPos = pos;
charsetLen = endpos - pos;
return;
}
}
XSSProtectionDisposition parseXSSProtectionHeader(const String& header)
{
String stippedHeader = header.stripWhiteSpace();
if (stippedHeader.isEmpty())
return XSSProtectionEnabled;
if (stippedHeader[0] == '0')
return XSSProtectionDisabled;
int length = (int)header.length();
int pos = 0;
if (stippedHeader[pos++] == '1'
&& skipWhiteSpace(stippedHeader, pos, false)
&& stippedHeader[pos++] == ';'
&& skipWhiteSpace(stippedHeader, pos, false)
&& skipToken(stippedHeader, pos, "mode")
&& skipWhiteSpace(stippedHeader, pos, false)
&& stippedHeader[pos++] == '='
&& skipWhiteSpace(stippedHeader, pos, false)
&& skipToken(stippedHeader, pos, "block")
&& pos == length)
return XSSProtectionBlockEnabled;
return XSSProtectionEnabled;
}
String extractReasonPhraseFromHTTPStatusLine(const String& statusLine)
{
int spacePos = statusLine.find(' ');
spacePos = statusLine.find(' ', spacePos + 1);
return statusLine.substring(spacePos + 1);
}
}