Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: Source/core/platform/network/ParsedContentType.cpp

Issue 23043002: Relax Content-Type parameter parsing (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Test fixes Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « LayoutTests/mhtml/relaxed-content-type-parameters-expected.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Corporation. All rights reserved. 3 * Copyright (C) 2012 Intel Corporation. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 void setContentType(const SubstringRange&) const { } 42 void setContentType(const SubstringRange&) const { }
43 void setContentTypeParameter(const SubstringRange&, const SubstringRange&) c onst { } 43 void setContentTypeParameter(const SubstringRange&, const SubstringRange&) c onst { }
44 }; 44 };
45 45
46 static void skipSpaces(const String& input, unsigned& startIndex) 46 static void skipSpaces(const String& input, unsigned& startIndex)
47 { 47 {
48 while (startIndex < input.length() && input[startIndex] == ' ') 48 while (startIndex < input.length() && input[startIndex] == ' ')
49 ++startIndex; 49 ++startIndex;
50 } 50 }
51 51
52 static bool isTokenCharacter(char c) 52 static SubstringRange parseParameterPart(const String& input, unsigned& startInd ex)
53 {
54 return isASCII(c) && c > ' ' && c != '"' && c != '(' && c != ')' && c != ',' && c != '/' && (c < ':' || c > '@') && (c < '[' || c > ']');
55 }
56
57 static SubstringRange parseToken(const String& input, unsigned& startIndex)
58 { 53 {
59 unsigned inputLength = input.length(); 54 unsigned inputLength = input.length();
60 unsigned tokenStart = startIndex; 55 unsigned tokenStart = startIndex;
61 unsigned& tokenEnd = startIndex; 56 unsigned& tokenEnd = startIndex;
62 57
63 if (tokenEnd >= inputLength) 58 if (tokenEnd >= inputLength)
64 return SubstringRange(); 59 return SubstringRange();
65 60
61 bool quoted = input[tokenStart] == '\"';
62 bool escape = false;
63
66 while (tokenEnd < inputLength) { 64 while (tokenEnd < inputLength) {
67 if (!isTokenCharacter(input[tokenEnd])) 65 UChar c = input[tokenEnd];
66 if (quoted && tokenStart != tokenEnd && c == '\"' && !escape)
67 return SubstringRange(tokenStart + 1, tokenEnd++ - tokenStart - 1);
68 if (!quoted && (c == ';' || c == '='))
68 return SubstringRange(tokenStart, tokenEnd - tokenStart); 69 return SubstringRange(tokenStart, tokenEnd - tokenStart);
70 escape = !escape && c == '\\';
69 ++tokenEnd; 71 ++tokenEnd;
70 } 72 }
71 73
74 if (quoted)
75 return SubstringRange();
72 return SubstringRange(tokenStart, tokenEnd - tokenStart); 76 return SubstringRange(tokenStart, tokenEnd - tokenStart);
73 } 77 }
74 78
75 static SubstringRange parseQuotedString(const String& input, unsigned& startInde x)
76 {
77 unsigned inputLength = input.length();
78 unsigned quotedStringStart = startIndex + 1;
79 unsigned& quotedStringEnd = startIndex;
80
81 if (quotedStringEnd >= inputLength)
82 return SubstringRange();
83
84 if (input[quotedStringEnd++] != '"' || quotedStringEnd >= inputLength)
85 return SubstringRange();
86
87 bool lastCharacterWasBackslash = false;
88 char currentCharacter;
89 while ((currentCharacter = input[quotedStringEnd++]) != '"' || lastCharacter WasBackslash) {
90 if (quotedStringEnd >= inputLength)
91 return SubstringRange();
92 if (currentCharacter == '\\' && !lastCharacterWasBackslash) {
93 lastCharacterWasBackslash = true;
94 continue;
95 }
96 if (lastCharacterWasBackslash)
97 lastCharacterWasBackslash = false;
98 }
99 return SubstringRange(quotedStringStart, quotedStringEnd - quotedStringStart - 1);
100 }
101
102 static String substringForRange(const String& string, const SubstringRange& rang e) 79 static String substringForRange(const String& string, const SubstringRange& rang e)
103 { 80 {
104 return string.substring(range.first, range.second); 81 return string.substring(range.first, range.second);
105 } 82 }
106 83
107 // From http://tools.ietf.org/html/rfc2045#section-5.1: 84 // From http://tools.ietf.org/html/rfc2045#section-5.1:
108 // 85 //
109 // content := "Content-Type" ":" type "/" subtype 86 // content := "Content-Type" ":" type "/" subtype
110 // *(";" parameter) 87 // *(";" parameter)
111 // ; Matching of media type and subtype 88 // ; Matching of media type and subtype
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 size_t semiColonIndex = contentType.find(';', index); 142 size_t semiColonIndex = contentType.find(';', index);
166 if (semiColonIndex == notFound) { 143 if (semiColonIndex == notFound) {
167 receiver.setContentType(SubstringRange(index, contentTypeLength - index) ); 144 receiver.setContentType(SubstringRange(index, contentTypeLength - index) );
168 return true; 145 return true;
169 } 146 }
170 147
171 receiver.setContentType(SubstringRange(index, semiColonIndex - index)); 148 receiver.setContentType(SubstringRange(index, semiColonIndex - index));
172 index = semiColonIndex + 1; 149 index = semiColonIndex + 1;
173 while (true) { 150 while (true) {
174 skipSpaces(contentType, index); 151 skipSpaces(contentType, index);
175 SubstringRange keyRange = parseToken(contentType, index); 152 SubstringRange keyRange = parseParameterPart(contentType, index);
176 if (!keyRange.second || index >= contentTypeLength) { 153 if (!keyRange.second || index >= contentTypeLength) {
177 LOG_ERROR("Invalid Content-Type parameter name."); 154 LOG_ERROR("Invalid Content-Type parameter name. (at %i)", index);
178 return false; 155 return false;
179 } 156 }
180 157
181 // Should we tolerate spaces here? 158 // Should we tolerate spaces here?
182 if (contentType[index++] != '=' || index >= contentTypeLength) { 159 if (contentType[index++] != '=' || index >= contentTypeLength) {
183 LOG_ERROR("Invalid Content-Type malformed parameter."); 160 LOG_ERROR("Invalid Content-Type malformed parameter (at %i).", index );
184 return false; 161 return false;
185 } 162 }
186 163
187 // Should we tolerate spaces here? 164 // Should we tolerate spaces here?
188 String value; 165 SubstringRange valueRange = parseParameterPart(contentType, index);
189 SubstringRange valueRange;
190 if (contentType[index] == '"')
191 valueRange = parseQuotedString(contentType, index);
192 else
193 valueRange = parseToken(contentType, index);
194 166
195 if (!valueRange.second) { 167 if (!valueRange.second) {
196 LOG_ERROR("Invalid Content-Type, invalid parameter value."); 168 LOG_ERROR("Invalid Content-Type, invalid parameter value (at %i, for '%s').", index, substringForRange(contentType, keyRange).stripWhiteSpace().asci i().data());
197 return false; 169 return false;
198 } 170 }
199 171
200 // Should we tolerate spaces here? 172 // Should we tolerate spaces here?
201 if (index < contentTypeLength && contentType[index++] != ';') { 173 if (index < contentTypeLength && contentType[index++] != ';') {
202 LOG_ERROR("Invalid Content-Type, invalid character at the end of key /value parameter."); 174 LOG_ERROR("Invalid Content-Type, invalid character at the end of key /value parameter (at %i).", index);
203 return false; 175 return false;
204 } 176 }
205 177
206 receiver.setContentTypeParameter(keyRange, valueRange); 178 receiver.setContentTypeParameter(keyRange, valueRange);
207 179
208 if (index >= contentTypeLength) 180 if (index >= contentTypeLength)
209 return true; 181 return true;
210 } 182 }
211 183
212 return true; 184 return true;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 { 218 {
247 m_mimeType = substringForRange(m_contentType, contentRange).stripWhiteSpace( ); 219 m_mimeType = substringForRange(m_contentType, contentRange).stripWhiteSpace( );
248 } 220 }
249 221
250 void ParsedContentType::setContentTypeParameter(const SubstringRange& key, const SubstringRange& value) 222 void ParsedContentType::setContentTypeParameter(const SubstringRange& key, const SubstringRange& value)
251 { 223 {
252 m_parameters.set(substringForRange(m_contentType, key), substringForRange(m_ contentType, value)); 224 m_parameters.set(substringForRange(m_contentType, key), substringForRange(m_ contentType, value));
253 } 225 }
254 226
255 } 227 }
OLDNEW
« no previous file with comments | « LayoutTests/mhtml/relaxed-content-type-parameters-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698