#include "config.h"
#include "MIMEHeader.h"
#include "ParsedContentType.h"
#include "SharedBufferChunkReader.h"
#include <wtf/HashMap.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringConcatenate.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
typedef HashMap<String, String> KeyValueMap;
static KeyValueMap retrieveKeyValuePairs(WebCore::SharedBufferChunkReader* buffer)
{
KeyValueMap keyValuePairs;
String line;
String key;
StringBuilder value;
while (!(line = buffer->nextChunkAsUTF8StringWithLatin1Fallback()).isNull()) {
if (line.isEmpty())
break; if (line[0] == '\t') {
ASSERT(!key.isEmpty());
value.append(line.substring(1));
continue;
}
if (!key.isEmpty()) {
if (keyValuePairs.find(key) != keyValuePairs.end())
LOG_ERROR("Key duplicate found in MIME header. Key is '%s', previous value replaced.", key.ascii().data());
keyValuePairs.add(key, value.toString().stripWhiteSpace());
key = String();
value.clear();
}
size_t semiColonIndex = line.find(':');
if (semiColonIndex == notFound) {
continue;
}
key = line.substring(0, semiColonIndex).lower().stripWhiteSpace();
value.append(line.substring(semiColonIndex + 1));
}
if (!key.isEmpty())
keyValuePairs.set(key, value.toString().stripWhiteSpace());
return keyValuePairs;
}
PassRefPtr<MIMEHeader> MIMEHeader::parseHeader(SharedBufferChunkReader* buffer)
{
RefPtr<MIMEHeader> mimeHeader = adoptRef(new MIMEHeader);
KeyValueMap keyValuePairs = retrieveKeyValuePairs(buffer);
KeyValueMap::iterator mimeParametersIterator = keyValuePairs.find("content-type");
if (mimeParametersIterator != keyValuePairs.end()) {
ParsedContentType parsedContentType(mimeParametersIterator->value);
mimeHeader->m_contentType = parsedContentType.mimeType();
if (!mimeHeader->isMultipart())
mimeHeader->m_charset = parsedContentType.charset().stripWhiteSpace();
else {
mimeHeader->m_multipartType = parsedContentType.parameterValueForName("type");
mimeHeader->m_endOfPartBoundary = parsedContentType.parameterValueForName("boundary");
if (mimeHeader->m_endOfPartBoundary.isNull()) {
LOG_ERROR("No boundary found in multipart MIME header.");
return 0;
}
mimeHeader->m_endOfPartBoundary.insert("--", 0);
mimeHeader->m_endOfDocumentBoundary = mimeHeader->m_endOfPartBoundary;
mimeHeader->m_endOfDocumentBoundary.append("--");
}
}
mimeParametersIterator = keyValuePairs.find("content-transfer-encoding");
if (mimeParametersIterator != keyValuePairs.end())
mimeHeader->m_contentTransferEncoding = parseContentTransferEncoding(mimeParametersIterator->value);
mimeParametersIterator = keyValuePairs.find("content-location");
if (mimeParametersIterator != keyValuePairs.end())
mimeHeader->m_contentLocation = mimeParametersIterator->value;
return mimeHeader.release();
}
MIMEHeader::Encoding MIMEHeader::parseContentTransferEncoding(const String& text)
{
String encoding = text.stripWhiteSpace().lower();
if (encoding == "base64")
return Base64;
if (encoding == "quoted-printable")
return QuotedPrintable;
if (encoding == "7bit")
return SevenBit;
if (encoding == "binary")
return Binary;
LOG_ERROR("Unknown encoding '%s' found in MIME header.", text.ascii().data());
return Unknown;
}
MIMEHeader::MIMEHeader()
: m_contentTransferEncoding(Unknown)
{
}
}