OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |