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

Side by Side Diff: src/url_parse.cc

Issue 115748: url_parse: Segment partially-typed IPv6 literals.... (Closed) Base URL: http://google-url.googlecode.com/svn/trunk/
Patch Set: '' Created 11 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/url_parse_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Based on nsURLParsers.cc from Mozilla 1 /* Based on nsURLParsers.cc from Mozilla
2 * ------------------------------------- 2 * -------------------------------------
3 * The contents of this file are subject to the Mozilla Public License Version 3 * The contents of this file are subject to the Mozilla Public License Version
4 * 1.1 (the "License"); you may not use this file except in compliance with 4 * 1.1 (the "License"); you may not use this file except in compliance with
5 * the License. You may obtain a copy of the License at 5 * the License. You may obtain a copy of the License at
6 * http://www.mozilla.org/MPL/ 6 * http://www.mozilla.org/MPL/
7 * 7 *
8 * Software distributed under the License is distributed on an "AS IS" basis, 8 * Software distributed under the License is distributed on an "AS IS" basis,
9 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 9 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10 * for the specific language governing rights and limitations under the 10 * for the specific language governing rights and limitations under the
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 const Component& serverinfo, 140 const Component& serverinfo,
141 Component* hostname, 141 Component* hostname,
142 Component* port_num) { 142 Component* port_num) {
143 if (serverinfo.len == 0) { 143 if (serverinfo.len == 0) {
144 // No server info, host name is empty. 144 // No server info, host name is empty.
145 hostname->reset(); 145 hostname->reset();
146 port_num->reset(); 146 port_num->reset();
147 return; 147 return;
148 } 148 }
149 149
150 // Search backwards for a ':' but stop on ']' (IPv6 address literal 150 // If the host starts with a left-bracket, assume the entire host is an
151 // delimiter). 151 // IPv6 literal. Otherwise, assume none of the host is an IPv6 literal.
152 int i = serverinfo.begin + serverinfo.len - 1; 152 // This assumption will be overridden if we find a right-bracket.
153 int colon = -1, bracket = -1; 153 //
154 while (i >= serverinfo.begin && colon < 0) { 154 // Our IPv6 address canonicalization code requires both brackets to exist,
155 // but the ability to locate an incomplete address can still be useful.
156 int ipv6_terminator = spec[serverinfo.begin] == '[' ? serverinfo.end() : -1;
157 int colon = -1;
158
159 // Find the last right-bracket, and the last colon.
160 for (int i = serverinfo.begin; i < serverinfo.end(); i++) {
155 switch (spec[i]) { 161 switch (spec[i]) {
156 case ']': 162 case ']':
157 bracket = i; 163 ipv6_terminator = i;
158 break; 164 break;
159 case ':': 165 case ':':
160 if (bracket < 0) 166 colon = i;
161 colon = i; // Will cause loop to terminate.
162 break; 167 break;
163 } 168 }
164 i--;
165 } 169 }
166 170
167 if (colon >= 0) { 171 if (colon > ipv6_terminator) {
168 // Found a port number: <hostname>:<port> 172 // Found a port number: <hostname>:<port>
169 int host_len = colon - serverinfo.begin; 173 *hostname = MakeRange(serverinfo.begin, colon);
170 if (host_len) 174 if (hostname->len == 0)
171 *hostname = MakeRange(serverinfo.begin, colon);
172 else
173 hostname->reset(); 175 hostname->reset();
174 *port_num = MakeRange(colon + 1, serverinfo.begin + serverinfo.len); 176 *port_num = MakeRange(colon + 1, serverinfo.end());
175 } else { 177 } else {
176 // No port: <hostname> 178 // No port: <hostname>
177 *hostname = serverinfo; 179 *hostname = serverinfo;
178 port_num->reset(); 180 port_num->reset();
179 } 181 }
180 } 182 }
181 183
182 // Given an already-identified auth section, breaks it into its consituent 184 // Given an already-identified auth section, breaks it into its consituent
183 // parts. The port number will be parsed and the resulting integer will be 185 // parts. The port number will be parsed and the resulting integer will be
184 // filled into the given *port variable, or -1 if there is no port number or it 186 // filled into the given *port variable, or -1 if there is no port number or it
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 void DoParseMailtoURL(const CHAR* spec, int spec_len, Parsed* parsed) { 381 void DoParseMailtoURL(const CHAR* spec, int spec_len, Parsed* parsed) {
380 DCHECK(spec_len >= 0); 382 DCHECK(spec_len >= 0);
381 383
382 // Get the non-path and non-scheme parts of the URL out of the way, we never 384 // Get the non-path and non-scheme parts of the URL out of the way, we never
383 // use them. 385 // use them.
384 parsed->username.reset(); 386 parsed->username.reset();
385 parsed->password.reset(); 387 parsed->password.reset();
386 parsed->host.reset(); 388 parsed->host.reset();
387 parsed->port.reset(); 389 parsed->port.reset();
388 parsed->ref.reset(); 390 parsed->ref.reset();
389 parsed->query.reset(); // May use this; reset for convenience. 391 parsed->query.reset(); // May use this; reset for convenience.
390 392
391 // Strip leading & trailing spaces and control characters. 393 // Strip leading & trailing spaces and control characters.
392 int begin = 0; 394 int begin = 0;
393 TrimURL(spec, &begin, &spec_len); 395 TrimURL(spec, &begin, &spec_len);
394 396
395 // Handle empty specs or ones that contain only whitespace or control chars. 397 // Handle empty specs or ones that contain only whitespace or control chars.
396 if (begin == spec_len) { 398 if (begin == spec_len) {
397 parsed->scheme.reset(); 399 parsed->scheme.reset();
398 parsed->path.reset(); 400 parsed->path.reset();
399 return; 401 return;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 } 439 }
438 } 440 }
439 441
440 // Converts a port number in a string to an integer. We'd like to just call 442 // Converts a port number in a string to an integer. We'd like to just call
441 // sscanf but our input is not NULL-terminated, which sscanf requires. Instead, 443 // sscanf but our input is not NULL-terminated, which sscanf requires. Instead,
442 // we copy the digits to a small stack buffer (since we know the maximum number 444 // we copy the digits to a small stack buffer (since we know the maximum number
443 // of digits in a valid port number) that we can NULL terminate. 445 // of digits in a valid port number) that we can NULL terminate.
444 template<typename CHAR> 446 template<typename CHAR>
445 int DoParsePort(const CHAR* spec, const Component& component) { 447 int DoParsePort(const CHAR* spec, const Component& component) {
446 // Easy success case when there is no port. 448 // Easy success case when there is no port.
447 const int max_digits = 5; 449 const int kMaxDigits = 5;
448 if (!component.is_nonempty()) 450 if (!component.is_nonempty())
449 return PORT_UNSPECIFIED; 451 return PORT_UNSPECIFIED;
450 452
451 // Skip over any leading 0s. 453 // Skip over any leading 0s.
452 Component digits_comp(component.end(), 0); 454 Component digits_comp(component.end(), 0);
453 for (int i = 0; i < component.len; i++) { 455 for (int i = 0; i < component.len; i++) {
454 if (spec[component.begin + i] != '0') { 456 if (spec[component.begin + i] != '0') {
455 digits_comp = MakeRange(component.begin + i, component.end()); 457 digits_comp = MakeRange(component.begin + i, component.end());
456 break; 458 break;
457 } 459 }
458 } 460 }
459 if (digits_comp.len == 0) 461 if (digits_comp.len == 0)
460 return 0; // All digits were 0. 462 return 0; // All digits were 0.
461 463
462 // Verify we don't have too many digits (we'll be copying to our buffer so 464 // Verify we don't have too many digits (we'll be copying to our buffer so
463 // we need to double-check). 465 // we need to double-check).
464 if (digits_comp.len > max_digits) 466 if (digits_comp.len > kMaxDigits)
465 return PORT_INVALID; 467 return PORT_INVALID;
466 468
467 // Copy valid digits to the buffer. 469 // Copy valid digits to the buffer.
468 char digits[max_digits + 1]; // +1 for null terminator 470 char digits[kMaxDigits + 1]; // +1 for null terminator
469 for (int i = 0; i < digits_comp.len; i++) { 471 for (int i = 0; i < digits_comp.len; i++) {
470 CHAR ch = spec[digits_comp.begin + i]; 472 CHAR ch = spec[digits_comp.begin + i];
471 if (!IsPortDigit(ch)) { 473 if (!IsPortDigit(ch)) {
472 // Invalid port digit, fail. 474 // Invalid port digit, fail.
473 return PORT_INVALID; 475 return PORT_INVALID;
474 } 476 }
475 digits[i] = static_cast<char>(ch); 477 digits[i] = static_cast<char>(ch);
476 } 478 }
477 479
478 // Null-terminate the string and convert to integer. Since we guarantee 480 // Null-terminate the string and convert to integer. Since we guarantee
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 } 748 }
747 749
748 void ParseAfterScheme(const char16* spec, 750 void ParseAfterScheme(const char16* spec,
749 int spec_len, 751 int spec_len,
750 int after_scheme, 752 int after_scheme,
751 Parsed* parsed) { 753 Parsed* parsed) {
752 DoParseAfterScheme(spec, spec_len, after_scheme, parsed); 754 DoParseAfterScheme(spec, spec_len, after_scheme, parsed);
753 } 755 }
754 756
755 } // namespace url_parse 757 } // namespace url_parse
OLDNEW
« no previous file with comments | « no previous file | src/url_parse_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698