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

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