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

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: Adding tests (I've heard this might work now) 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
66 while (tokenEnd < inputLength) { 63 while (tokenEnd < inputLength) {
67 if (!isTokenCharacter(input[tokenEnd])) 64 if (quoted && tokenStart != tokenEnd && input[tokenEnd] == '\"' && input [tokenEnd - 1] != '\\')
abarth-chromium 2013/09/12 18:16:11 I see. The key is that you're trying to lift this
abarth-chromium 2013/09/12 18:16:11 I don't think this is correct. Consider the follo
65 return SubstringRange(tokenStart + 1, tokenEnd++ - tokenStart - 1);
66 if (!quoted && (input[tokenEnd] == ';' || input[tokenEnd] == '='))
68 return SubstringRange(tokenStart, tokenEnd - tokenStart); 67 return SubstringRange(tokenStart, tokenEnd - tokenStart);
69 ++tokenEnd; 68 ++tokenEnd;
70 } 69 }
71 70
72 return SubstringRange(tokenStart, tokenEnd - tokenStart); 71 return SubstringRange(tokenStart, tokenEnd - tokenStart);
73 } 72 }
74 73
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) 74 static String substringForRange(const String& string, const SubstringRange& rang e)
103 { 75 {
104 return string.substring(range.first, range.second); 76 return string.substring(range.first, range.second);
105 } 77 }
106 78
107 // From http://tools.ietf.org/html/rfc2045#section-5.1: 79 // From http://tools.ietf.org/html/rfc2045#section-5.1:
108 // 80 //
109 // content := "Content-Type" ":" type "/" subtype 81 // content := "Content-Type" ":" type "/" subtype
110 // *(";" parameter) 82 // *(";" parameter)
111 // ; Matching of media type and subtype 83 // ; 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); 137 size_t semiColonIndex = contentType.find(';', index);
166 if (semiColonIndex == notFound) { 138 if (semiColonIndex == notFound) {
167 receiver.setContentType(SubstringRange(index, contentTypeLength - index) ); 139 receiver.setContentType(SubstringRange(index, contentTypeLength - index) );
168 return true; 140 return true;
169 } 141 }
170 142
171 receiver.setContentType(SubstringRange(index, semiColonIndex - index)); 143 receiver.setContentType(SubstringRange(index, semiColonIndex - index));
172 index = semiColonIndex + 1; 144 index = semiColonIndex + 1;
173 while (true) { 145 while (true) {
174 skipSpaces(contentType, index); 146 skipSpaces(contentType, index);
175 SubstringRange keyRange = parseToken(contentType, index); 147 SubstringRange keyRange = parseParameterPart(contentType, index);
176 if (!keyRange.second || index >= contentTypeLength) { 148 if (!keyRange.second || index >= contentTypeLength) {
177 LOG_ERROR("Invalid Content-Type parameter name."); 149 LOG_ERROR("Invalid Content-Type parameter name. (at %i)", index);
178 return false; 150 return false;
179 } 151 }
180 152
181 // Should we tolerate spaces here? 153 // Should we tolerate spaces here?
182 if (contentType[index++] != '=' || index >= contentTypeLength) { 154 if (contentType[index++] != '=' || index >= contentTypeLength) {
183 LOG_ERROR("Invalid Content-Type malformed parameter."); 155 LOG_ERROR("Invalid Content-Type malformed parameter (at %i).", index );
184 return false; 156 return false;
185 } 157 }
186 158
187 // Should we tolerate spaces here? 159 // Should we tolerate spaces here?
188 String value; 160 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 161
195 if (!valueRange.second) { 162 if (!valueRange.second) {
196 LOG_ERROR("Invalid Content-Type, invalid parameter value."); 163 LOG_ERROR("Invalid Content-Type, invalid parameter value (at %i, for '%s').", index, substringForRange(contentType, keyRange).stripWhiteSpace().asci i().data());
197 return false; 164 return false;
198 } 165 }
199 166
200 // Should we tolerate spaces here? 167 // Should we tolerate spaces here?
201 if (index < contentTypeLength && contentType[index++] != ';') { 168 if (index < contentTypeLength && contentType[index++] != ';') {
202 LOG_ERROR("Invalid Content-Type, invalid character at the end of key /value parameter."); 169 LOG_ERROR("Invalid Content-Type, invalid character at the end of key /value parameter (at %i).", index);
203 return false; 170 return false;
204 } 171 }
205 172
206 receiver.setContentTypeParameter(keyRange, valueRange); 173 receiver.setContentTypeParameter(keyRange, valueRange);
207 174
208 if (index >= contentTypeLength) 175 if (index >= contentTypeLength)
209 return true; 176 return true;
210 } 177 }
211 178
212 return true; 179 return true;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 { 213 {
247 m_mimeType = substringForRange(m_contentType, contentRange).stripWhiteSpace( ); 214 m_mimeType = substringForRange(m_contentType, contentRange).stripWhiteSpace( );
248 } 215 }
249 216
250 void ParsedContentType::setContentTypeParameter(const SubstringRange& key, const SubstringRange& value) 217 void ParsedContentType::setContentTypeParameter(const SubstringRange& key, const SubstringRange& value)
251 { 218 {
252 m_parameters.set(substringForRange(m_contentType, key), substringForRange(m_ contentType, value)); 219 m_parameters.set(substringForRange(m_contentType, key), substringForRange(m_ contentType, value));
253 } 220 }
254 221
255 } 222 }
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