15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) /*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Google Inc. All rights reserved.
3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2012 Intel Corporation. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/network/ParsedContentType.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/text/CString.h"
367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/text/StringBuilder.h"
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
38c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)class DummyParsedContentType {
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)public:
42926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    void setContentType(const SubstringRange&) const { }
43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    void setContentTypeParameter(const SubstringRange&, const SubstringRange&) const { }
44926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)};
45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static void skipSpaces(const String& input, unsigned& startIndex)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (startIndex < input.length() && input[startIndex] == ' ')
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++startIndex;
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)static SubstringRange parseParameterPart(const String& input, unsigned& startIndex)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
54926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned inputLength = input.length();
55926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned tokenStart = startIndex;
56926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned& tokenEnd = startIndex;
57926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (tokenEnd >= inputLength)
59926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return SubstringRange();
60926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
6106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    bool quoted = input[tokenStart] == '\"';
6206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    bool escape = false;
6306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    while (tokenEnd < inputLength) {
6506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        UChar c = input[tokenEnd];
6606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (quoted && tokenStart != tokenEnd && c == '\"' && !escape)
6706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            return SubstringRange(tokenStart + 1, tokenEnd++ - tokenStart - 1);
6806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (!quoted && (c == ';' || c == '='))
69926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return SubstringRange(tokenStart, tokenEnd - tokenStart);
7006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        escape = !escape && c == '\\';
71926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ++tokenEnd;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
7406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (quoted)
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return SubstringRange();
7606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    return SubstringRange(tokenStart, tokenEnd - tokenStart);
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static String substringForRange(const String& string, const SubstringRange& range)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return string.substring(range.first, range.second);
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// From http://tools.ietf.org/html/rfc2045#section-5.1:
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// content := "Content-Type" ":" type "/" subtype
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//            *(";" parameter)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//            ; Matching of media type and subtype
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//            ; is ALWAYS case-insensitive.
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// type := discrete-type / composite-type
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// discrete-type := "text" / "image" / "audio" / "video" /
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                  "application" / extension-token
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// composite-type := "message" / "multipart" / extension-token
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// extension-token := ietf-token / x-token
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// ietf-token := <An extension token defined by a
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                standards-track RFC and registered
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                with IANA.>
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// x-token := <The two characters "X-" or "x-" followed, with
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//             no intervening white space, by any token>
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// subtype := extension-token / iana-token
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// iana-token := <A publicly-defined extension token. Tokens
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                of this form must be registered with IANA
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//                as specified in RFC 2048.>
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// parameter := attribute "=" value
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// attribute := token
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//              ; Matching of attributes
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//              ; is ALWAYS case-insensitive.
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// value := token / quoted-string
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//             or tspecials>
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// tspecials :=  "(" / ")" / "<" / ">" / "@" /
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//               "," / ";" / ":" / "\" / <">
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//               "/" / "[" / "]" / "?" / "="
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//               ; Must be in quoted-string,
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//               ; to use within parameter values
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)template <class ReceiverType>
131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool parseContentType(const String& contentType, ReceiverType& receiver)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned index = 0;
134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned contentTypeLength = contentType.length();
135926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    skipSpaces(contentType, index);
136926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (index >= contentTypeLength)  {
137a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        WTF_LOG_ERROR("Invalid Content-Type string '%s'", contentType.ascii().data());
138926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // There should not be any quoted strings until we reach the parameters.
142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    size_t semiColonIndex = contentType.find(';', index);
14306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    if (semiColonIndex == kNotFound) {
144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        receiver.setContentType(SubstringRange(index, contentTypeLength - index));
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return true;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    receiver.setContentType(SubstringRange(index, semiColonIndex - index));
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    index = semiColonIndex + 1;
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        skipSpaces(contentType, index);
15206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        SubstringRange keyRange = parseParameterPart(contentType, index);
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!keyRange.second || index >= contentTypeLength) {
154a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            WTF_LOG_ERROR("Invalid Content-Type parameter name. (at %i)", index);
155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return false;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
157926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Should we tolerate spaces here?
159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (contentType[index++] != '=' || index >= contentTypeLength) {
160a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            WTF_LOG_ERROR("Invalid Content-Type malformed parameter (at %i).", index);
161926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return false;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Should we tolerate spaces here?
16506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        SubstringRange valueRange = parseParameterPart(contentType, index);
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!valueRange.second) {
168a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            WTF_LOG_ERROR("Invalid Content-Type, invalid parameter value (at %i, for '%s').", index, substringForRange(contentType, keyRange).stripWhiteSpace().ascii().data());
169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return false;
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Should we tolerate spaces here?
173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (index < contentTypeLength && contentType[index++] != ';') {
174a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            WTF_LOG_ERROR("Invalid Content-Type, invalid character at the end of key/value parameter (at %i).", index);
175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return false;
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        receiver.setContentTypeParameter(keyRange, valueRange);
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (index >= contentTypeLength)
181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return true;
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return true;
185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
186926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)bool isValidContentType(const String& contentType)
188926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (contentType.contains('\r') || contentType.contains('\n'))
190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return false;
191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DummyParsedContentType parsedContentType = DummyParsedContentType();
193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return parseContentType<DummyParsedContentType>(contentType, parsedContentType);
194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
196926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ParsedContentType::ParsedContentType(const String& contentType)
197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    : m_contentType(contentType.stripWhiteSpace())
198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    parseContentType<ParsedContentType>(m_contentType, *this);
200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)String ParsedContentType::charset() const
203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return parameterValueForName("charset");
205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)String ParsedContentType::parameterValueForName(const String& name) const
208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return m_parameters.get(name);
210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)size_t ParsedContentType::parameterCount() const
213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return m_parameters.size();
215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void ParsedContentType::setContentType(const SubstringRange& contentRange)
218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_mimeType = substringForRange(m_contentType, contentRange).stripWhiteSpace();
220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void ParsedContentType::setContentTypeParameter(const SubstringRange& key, const SubstringRange& value)
223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    m_parameters.set(substringForRange(m_contentType, key), substringForRange(m_contentType, value));
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
228