1 // Copyright 2009, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 #include "googleurl/src/url_canon_ip.h" 31 32 #include <stdlib.h> 33 34 #include "base/basictypes.h" 35 #include "base/logging.h" 36 #include "googleurl/src/url_canon_internal.h" 37 38 namespace url_canon { 39 40 namespace { 41 42 // Converts one of the character types that represent a numerical base to the 43 // corresponding base. 44 int BaseForType(SharedCharTypes type) { 45 switch (type) { 46 case CHAR_HEX: 47 return 16; 48 case CHAR_DEC: 49 return 10; 50 case CHAR_OCT: 51 return 8; 52 default: 53 return 0; 54 } 55 } 56 57 template<typename CHAR, typename UCHAR> 58 bool DoFindIPv4Components(const CHAR* spec, 59 const url_parse::Component& host, 60 url_parse::Component components[4]) { 61 if (!host.is_nonempty()) 62 return false; 63 64 int cur_component = 0; // Index of the component we're working on. 65 int cur_component_begin = host.begin; // Start of the current component. 66 int end = host.end(); 67 for (int i = host.begin; /* nothing */; i++) { 68 if (i >= end || spec[i] == '.') { 69 // Found the end of the current component. 70 int component_len = i - cur_component_begin; 71 components[cur_component] = 72 url_parse::Component(cur_component_begin, component_len); 73 74 // The next component starts after the dot. 75 cur_component_begin = i + 1; 76 cur_component++; 77 78 // Don't allow empty components (two dots in a row), except we may 79 // allow an empty component at the end (this would indicate that the 80 // input ends in a dot). We also want to error if the component is 81 // empty and it's the only component (cur_component == 1). 82 if (component_len == 0 && (i < end || cur_component == 1)) 83 return false; 84 85 if (i >= end) 86 break; // End of the input. 87 88 if (cur_component == 4) { 89 // Anything else after the 4th component is an error unless it is a 90 // dot that would otherwise be treated as the end of input. 91 if (spec[i] == '.' && i + 1 == end) 92 break; 93 return false; 94 } 95 } else if (static_cast<UCHAR>(spec[i]) >= 0x80 || 96 !IsIPv4Char(static_cast<unsigned char>(spec[i]))) { 97 // Invalid character for an IPv4 address. 98 return false; 99 } 100 } 101 102 // Fill in any unused components. 103 while (cur_component < 4) 104 components[cur_component++] = url_parse::Component(); 105 return true; 106 } 107 108 // Converts an IPv4 component to a 32-bit number, while checking for overflow. 109 // 110 // Possible return values: 111 // - IPV4 - The number was valid, and did not overflow. 112 // - BROKEN - The input was numeric, but too large for a 32-bit field. 113 // - NEUTRAL - Input was not numeric. 114 // 115 // The input is assumed to be ASCII. FindIPv4Components should have stripped 116 // out any input that is greater than 7 bits. The components are assumed 117 // to be non-empty. 118 template<typename CHAR> 119 CanonHostInfo::Family IPv4ComponentToNumber( 120 const CHAR* spec, 121 const url_parse::Component& component, 122 uint32* number) { 123 // Figure out the base 124 SharedCharTypes base; 125 int base_prefix_len = 0; // Size of the prefix for this base. 126 if (spec[component.begin] == '0') { 127 // Either hex or dec, or a standalone zero. 128 if (component.len == 1) { 129 base = CHAR_DEC; 130 } else if (spec[component.begin + 1] == 'X' || 131 spec[component.begin + 1] == 'x') { 132 base = CHAR_HEX; 133 base_prefix_len = 2; 134 } else { 135 base = CHAR_OCT; 136 base_prefix_len = 1; 137 } 138 } else { 139 base = CHAR_DEC; 140 } 141 142 // Extend the prefix to consume all leading zeros. 143 while (base_prefix_len < component.len && 144 spec[component.begin + base_prefix_len] == '0') 145 base_prefix_len++; 146 147 // Put the component, minus any base prefix, into a NULL-terminated buffer so 148 // we can call the standard library. Because leading zeros have already been 149 // discarded, filling the entire buffer is guaranteed to trigger the 32-bit 150 // overflow check. 151 const int kMaxComponentLen = 16; 152 char buf[kMaxComponentLen + 1]; // digits + '\0' 153 int dest_i = 0; 154 for (int i = component.begin + base_prefix_len; i < component.end(); i++) { 155 // We know the input is 7-bit, so convert to narrow (if this is the wide 156 // version of the template) by casting. 157 char input = static_cast<char>(spec[i]); 158 159 // Validate that this character is OK for the given base. 160 if (!IsCharOfType(input, base)) 161 return CanonHostInfo::NEUTRAL; 162 163 // Fill the buffer, if there's space remaining. This check allows us to 164 // verify that all characters are numeric, even those that don't fit. 165 if (dest_i < kMaxComponentLen) 166 buf[dest_i++] = input; 167 } 168 169 buf[dest_i] = '\0'; 170 171 // Use the 64-bit strtoi so we get a big number (no hex, decimal, or octal 172 // number can overflow a 64-bit number in <= 16 characters). 173 uint64 num = _strtoui64(buf, NULL, BaseForType(base)); 174 175 // Check for 32-bit overflow. 176 if (num > kuint32max) 177 return CanonHostInfo::BROKEN; 178 179 // No overflow. Success! 180 *number = static_cast<uint32>(num); 181 return CanonHostInfo::IPV4; 182 } 183 184 // Writes the given address (with each character representing one dotted 185 // part of an IPv4 address) to the output, and updating |*out_host| to 186 // identify the added portion. 187 void AppendIPv4Address(const unsigned char address[4], 188 CanonOutput* output, 189 url_parse::Component* out_host) { 190 out_host->begin = output->length(); 191 for (int i = 0; i < 4; i++) { 192 char str[16]; 193 _itoa_s(address[i], str, 10); 194 195 for (int ch = 0; str[ch] != 0; ch++) 196 output->push_back(str[ch]); 197 198 if (i != 3) 199 output->push_back('.'); 200 } 201 out_host->len = output->length() - out_host->begin; 202 } 203 204 // See declaration of IPv4AddressToNumber for documentation. 205 template<typename CHAR> 206 CanonHostInfo::Family DoIPv4AddressToNumber(const CHAR* spec, 207 const url_parse::Component& host, 208 unsigned char address[4], 209 int* num_ipv4_components) { 210 // The identified components. Not all may exist. 211 url_parse::Component components[4]; 212 if (!FindIPv4Components(spec, host, components)) 213 return CanonHostInfo::NEUTRAL; 214 215 // Convert existing components to digits. Values up to 216 // |existing_components| will be valid. 217 uint32 component_values[4]; 218 int existing_components = 0; 219 for (int i = 0; i < 4; i++) { 220 if (components[i].len <= 0) 221 continue; 222 CanonHostInfo::Family family = IPv4ComponentToNumber( 223 spec, components[i], &component_values[existing_components]); 224 225 // Stop if we hit an invalid non-empty component. 226 if (family != CanonHostInfo::IPV4) 227 return family; 228 229 existing_components++; 230 } 231 232 // Use that sequence of numbers to fill out the 4-component IP address. 233 234 // First, process all components but the last, while making sure each fits 235 // within an 8-bit field. 236 for (int i = 0; i < existing_components - 1; i++) { 237 if (component_values[i] > kuint8max) 238 return CanonHostInfo::BROKEN; 239 address[i] = static_cast<unsigned char>(component_values[i]); 240 } 241 242 // Next, consume the last component to fill in the remaining bytes. 243 uint32 last_value = component_values[existing_components - 1]; 244 for (int i = 3; i >= existing_components - 1; i--) { 245 address[i] = static_cast<unsigned char>(last_value); 246 last_value >>= 8; 247 } 248 249 // If the last component has residual bits, report overflow. 250 if (last_value != 0) 251 return CanonHostInfo::BROKEN; 252 253 // Tell the caller how many components we saw. 254 *num_ipv4_components = existing_components; 255 256 // Success! 257 return CanonHostInfo::IPV4; 258 } 259 260 // Return true if we've made a final IPV4/BROKEN decision, false if the result 261 // is NEUTRAL, and we could use a second opinion. 262 template<typename CHAR, typename UCHAR> 263 bool DoCanonicalizeIPv4Address(const CHAR* spec, 264 const url_parse::Component& host, 265 CanonOutput* output, 266 CanonHostInfo* host_info) { 267 unsigned char address[4]; 268 host_info->family = IPv4AddressToNumber( 269 spec, host, address, &host_info->num_ipv4_components); 270 271 switch (host_info->family) { 272 case CanonHostInfo::IPV4: 273 // Definitely an IPv4 address. 274 AppendIPv4Address(address, output, &host_info->out_host); 275 return true; 276 case CanonHostInfo::BROKEN: 277 // Definitely broken. 278 return true; 279 default: 280 // Could be IPv6 or a hostname. 281 return false; 282 } 283 } 284 285 // Helper class that describes the main components of an IPv6 input string. 286 // See the following examples to understand how it breaks up an input string: 287 // 288 // [Example 1]: input = "[::aa:bb]" 289 // ==> num_hex_components = 2 290 // ==> hex_components[0] = Component(3,2) "aa" 291 // ==> hex_components[1] = Component(6,2) "bb" 292 // ==> index_of_contraction = 0 293 // ==> ipv4_component = Component(0, -1) 294 // 295 // [Example 2]: input = "[1:2::3:4:5]" 296 // ==> num_hex_components = 5 297 // ==> hex_components[0] = Component(1,1) "1" 298 // ==> hex_components[1] = Component(3,1) "2" 299 // ==> hex_components[2] = Component(6,1) "3" 300 // ==> hex_components[3] = Component(8,1) "4" 301 // ==> hex_components[4] = Component(10,1) "5" 302 // ==> index_of_contraction = 2 303 // ==> ipv4_component = Component(0, -1) 304 // 305 // [Example 3]: input = "[::ffff:192.168.0.1]" 306 // ==> num_hex_components = 1 307 // ==> hex_components[0] = Component(3,4) "ffff" 308 // ==> index_of_contraction = 0 309 // ==> ipv4_component = Component(8, 11) "192.168.0.1" 310 // 311 // [Example 4]: input = "[1::]" 312 // ==> num_hex_components = 1 313 // ==> hex_components[0] = Component(1,1) "1" 314 // ==> index_of_contraction = 1 315 // ==> ipv4_component = Component(0, -1) 316 // 317 // [Example 5]: input = "[::192.168.0.1]" 318 // ==> num_hex_components = 0 319 // ==> index_of_contraction = 0 320 // ==> ipv4_component = Component(8, 11) "192.168.0.1" 321 // 322 struct IPv6Parsed { 323 // Zero-out the parse information. 324 void reset() { 325 num_hex_components = 0; 326 index_of_contraction = -1; 327 ipv4_component.reset(); 328 } 329 330 // There can be up to 8 hex components (colon separated) in the literal. 331 url_parse::Component hex_components[8]; 332 333 // The count of hex components present. Ranges from [0,8]. 334 int num_hex_components; 335 336 // The index of the hex component that the "::" contraction precedes, or 337 // -1 if there is no contraction. 338 int index_of_contraction; 339 340 // The range of characters which are an IPv4 literal. 341 url_parse::Component ipv4_component; 342 }; 343 344 // Parse the IPv6 input string. If parsing succeeded returns true and fills 345 // |parsed| with the information. If parsing failed (because the input is 346 // invalid) returns false. 347 template<typename CHAR, typename UCHAR> 348 bool DoParseIPv6(const CHAR* spec, 349 const url_parse::Component& host, 350 IPv6Parsed* parsed) { 351 // Zero-out the info. 352 parsed->reset(); 353 354 if (!host.is_nonempty()) 355 return false; 356 357 // The index for start and end of address range (no brackets). 358 int begin = host.begin; 359 int end = host.end(); 360 361 int cur_component_begin = begin; // Start of the current component. 362 363 // Scan through the input, searching for hex components, "::" contractions, 364 // and IPv4 components. 365 for (int i = begin; /* i <= end */; i++) { 366 bool is_colon = spec[i] == ':'; 367 bool is_contraction = is_colon && i < end - 1 && spec[i + 1] == ':'; 368 369 // We reached the end of the current component if we encounter a colon 370 // (separator between hex components, or start of a contraction), or end of 371 // input. 372 if (is_colon || i == end) { 373 int component_len = i - cur_component_begin; 374 375 // A component should not have more than 4 hex digits. 376 if (component_len > 4) 377 return false; 378 379 // Don't allow empty components. 380 if (component_len == 0) { 381 // The exception is when contractions appear at beginning of the 382 // input or at the end of the input. 383 if (!((is_contraction && i == begin) || (i == end && 384 parsed->index_of_contraction == parsed->num_hex_components))) 385 return false; 386 } 387 388 // Add the hex component we just found to running list. 389 if (component_len > 0) { 390 // Can't have more than 8 components! 391 if (parsed->num_hex_components >= 8) 392 return false; 393 394 parsed->hex_components[parsed->num_hex_components++] = 395 url_parse::Component(cur_component_begin, component_len); 396 } 397 } 398 399 if (i == end) 400 break; // Reached the end of the input, DONE. 401 402 // We found a "::" contraction. 403 if (is_contraction) { 404 // There can be at most one contraction in the literal. 405 if (parsed->index_of_contraction != -1) 406 return false; 407 parsed->index_of_contraction = parsed->num_hex_components; 408 ++i; // Consume the colon we peeked. 409 } 410 411 if (is_colon) { 412 // Colons are separators between components, keep track of where the 413 // current component started (after this colon). 414 cur_component_begin = i + 1; 415 } else { 416 if (static_cast<UCHAR>(spec[i]) >= 0x80) 417 return false; // Not ASCII. 418 419 if (!IsHexChar(static_cast<unsigned char>(spec[i]))) { 420 // Regular components are hex numbers. It is also possible for 421 // a component to be an IPv4 address in dotted form. 422 if (IsIPv4Char(static_cast<unsigned char>(spec[i]))) { 423 // Since IPv4 address can only appear at the end, assume the rest 424 // of the string is an IPv4 address. (We will parse this separately 425 // later). 426 parsed->ipv4_component = url_parse::Component( 427 cur_component_begin, end - cur_component_begin); 428 break; 429 } else { 430 // The character was neither a hex digit, nor an IPv4 character. 431 return false; 432 } 433 } 434 } 435 } 436 437 return true; 438 } 439 440 // Verifies the parsed IPv6 information, checking that the various components 441 // add up to the right number of bits (hex components are 16 bits, while 442 // embedded IPv4 formats are 32 bits, and contractions are placeholdes for 443 // 16 or more bits). Returns true if sizes match up, false otherwise. On 444 // success writes the length of the contraction (if any) to 445 // |out_num_bytes_of_contraction|. 446 bool CheckIPv6ComponentsSize(const IPv6Parsed& parsed, 447 int* out_num_bytes_of_contraction) { 448 // Each group of four hex digits contributes 16 bits. 449 int num_bytes_without_contraction = parsed.num_hex_components * 2; 450 451 // If an IPv4 address was embedded at the end, it contributes 32 bits. 452 if (parsed.ipv4_component.is_valid()) 453 num_bytes_without_contraction += 4; 454 455 // If there was a "::" contraction, its size is going to be: 456 // MAX([16bits], [128bits] - num_bytes_without_contraction). 457 int num_bytes_of_contraction = 0; 458 if (parsed.index_of_contraction != -1) { 459 num_bytes_of_contraction = 16 - num_bytes_without_contraction; 460 if (num_bytes_of_contraction < 2) 461 num_bytes_of_contraction = 2; 462 } 463 464 // Check that the numbers add up. 465 if (num_bytes_without_contraction + num_bytes_of_contraction != 16) 466 return false; 467 468 *out_num_bytes_of_contraction = num_bytes_of_contraction; 469 return true; 470 } 471 472 // Converts a hex comonent into a number. This cannot fail since the caller has 473 // already verified that each character in the string was a hex digit, and 474 // that there were no more than 4 characters. 475 template<typename CHAR> 476 uint16 IPv6HexComponentToNumber(const CHAR* spec, 477 const url_parse::Component& component) { 478 DCHECK(component.len <= 4); 479 480 // Copy the hex string into a C-string. 481 char buf[5]; 482 for (int i = 0; i < component.len; ++i) 483 buf[i] = static_cast<char>(spec[component.begin + i]); 484 buf[component.len] = '\0'; 485 486 // Convert it to a number (overflow is not possible, since with 4 hex 487 // characters we can at most have a 16 bit number). 488 return static_cast<uint16>(_strtoui64(buf, NULL, 16)); 489 } 490 491 // Converts an IPv6 address to a 128-bit number (network byte order), returning 492 // true on success. False means that the input was not a valid IPv6 address. 493 template<typename CHAR, typename UCHAR> 494 bool DoIPv6AddressToNumber(const CHAR* spec, 495 const url_parse::Component& host, 496 unsigned char address[16]) { 497 // Make sure the component is bounded by '[' and ']'. 498 int end = host.end(); 499 if (!host.is_nonempty() || spec[host.begin] != '[' || spec[end - 1] != ']') 500 return false; 501 502 // Exclude the square brackets. 503 url_parse::Component ipv6_comp(host.begin + 1, host.len - 2); 504 505 // Parse the IPv6 address -- identify where all the colon separated hex 506 // components are, the "::" contraction, and the embedded IPv4 address. 507 IPv6Parsed ipv6_parsed; 508 if (!DoParseIPv6<CHAR, UCHAR>(spec, ipv6_comp, &ipv6_parsed)) 509 return false; 510 511 // Do some basic size checks to make sure that the address doesn't 512 // specify more than 128 bits or fewer than 128 bits. This also resolves 513 // how may zero bytes the "::" contraction represents. 514 int num_bytes_of_contraction; 515 if (!CheckIPv6ComponentsSize(ipv6_parsed, &num_bytes_of_contraction)) 516 return false; 517 518 int cur_index_in_address = 0; 519 520 // Loop through each hex components, and contraction in order. 521 for (int i = 0; i <= ipv6_parsed.num_hex_components; ++i) { 522 // Append the contraction if it appears before this component. 523 if (i == ipv6_parsed.index_of_contraction) { 524 for (int j = 0; j < num_bytes_of_contraction; ++j) 525 address[cur_index_in_address++] = 0; 526 } 527 // Append the hex component's value. 528 if (i != ipv6_parsed.num_hex_components) { 529 // Get the 16-bit value for this hex component. 530 uint16 number = IPv6HexComponentToNumber<CHAR>( 531 spec, ipv6_parsed.hex_components[i]); 532 // Append to |address|, in network byte order. 533 address[cur_index_in_address++] = (number & 0xFF00) >> 8; 534 address[cur_index_in_address++] = (number & 0x00FF); 535 } 536 } 537 538 // If there was an IPv4 section, convert it into a 32-bit number and append 539 // it to |address|. 540 if (ipv6_parsed.ipv4_component.is_valid()) { 541 // We only allow the embedded IPv4 syntax to be used for "compat" and 542 // "mapped" formats: 543 // "mapped" ==> 0:0:0:0:0:ffff:<IPv4-literal> 544 // "compat" ==> 0:0:0:0:0:0000:<IPv4-literal> 545 for (int j = 0; j < 10; ++j) { 546 if (address[j] != 0) 547 return false; 548 } 549 if (!((address[10] == 0 && address[11] == 0) || 550 (address[10] == 0xFF && address[11] == 0xFF))) 551 return false; 552 553 // Append the 32-bit number to |address|. 554 int ignored_num_ipv4_components; 555 if (CanonHostInfo::IPV4 != 556 IPv4AddressToNumber(spec, 557 ipv6_parsed.ipv4_component, 558 &address[cur_index_in_address], 559 &ignored_num_ipv4_components)) 560 return false; 561 } 562 563 return true; 564 } 565 566 // Searches for the longest sequence of zeros in |address|, and writes the 567 // range into |contraction_range|. The run of zeros must be at least 16 bits, 568 // and if there is a tie the first is chosen. 569 void ChooseIPv6ContractionRange(const unsigned char address[16], 570 url_parse::Component* contraction_range) { 571 // The longest run of zeros in |address| seen so far. 572 url_parse::Component max_range; 573 574 // The current run of zeros in |address| being iterated over. 575 url_parse::Component cur_range; 576 577 for (int i = 0; i < 16; i += 2) { 578 // Test for 16 bits worth of zero. 579 bool is_zero = (address[i] == 0 && address[i + 1] == 0); 580 581 if (is_zero) { 582 // Add the zero to the current range (or start a new one). 583 if (!cur_range.is_valid()) 584 cur_range = url_parse::Component(i, 0); 585 cur_range.len += 2; 586 } 587 588 if (!is_zero || i == 14) { 589 // Just completed a run of zeros. If the run is greater than 16 bits, 590 // it is a candidate for the contraction. 591 if (cur_range.len > 2 && cur_range.len > max_range.len) { 592 max_range = cur_range; 593 } 594 cur_range.reset(); 595 } 596 } 597 *contraction_range = max_range; 598 } 599 600 // Return true if we've made a final IPV6/BROKEN decision, false if the result 601 // is NEUTRAL, and we could use a second opinion. 602 template<typename CHAR, typename UCHAR> 603 bool DoCanonicalizeIPv6Address(const CHAR* spec, 604 const url_parse::Component& host, 605 CanonOutput* output, 606 CanonHostInfo* host_info) { 607 // Turn the IP address into a 128 bit number. 608 unsigned char address[16]; 609 if (!IPv6AddressToNumber(spec, host, address)) { 610 // If it's not an IPv6 address, scan for characters that should *only* 611 // exist in an IPv6 address. 612 for (int i = host.begin; i < host.end(); i++) { 613 switch (spec[i]) { 614 case '[': 615 case ']': 616 case ':': 617 host_info->family = CanonHostInfo::BROKEN; 618 return true; 619 } 620 } 621 622 // No invalid characters. Could still be IPv4 or a hostname. 623 host_info->family = CanonHostInfo::NEUTRAL; 624 return false; 625 } 626 627 host_info->out_host.begin = output->length(); 628 output->push_back('['); 629 630 // We will now output the address according to the rules in: 631 // http://tools.ietf.org/html/draft-kawamura-ipv6-text-representation-01#section-4 632 633 // Start by finding where to place the "::" contraction (if any). 634 url_parse::Component contraction_range; 635 ChooseIPv6ContractionRange(address, &contraction_range); 636 637 for (int i = 0; i <= 14;) { 638 // We check 2 bytes at a time, from bytes (0, 1) to (14, 15), inclusive. 639 DCHECK(i % 2 == 0); 640 if (i == contraction_range.begin && contraction_range.len > 0) { 641 // Jump over the contraction. 642 if (i == 0) 643 output->push_back(':'); 644 output->push_back(':'); 645 i = contraction_range.end(); 646 } else { 647 // Consume the next 16 bits from |address|. 648 int x = address[i] << 8 | address[i + 1]; 649 650 i += 2; 651 652 // Stringify the 16 bit number (at most requires 4 hex digits). 653 char str[5]; 654 _itoa_s(x, str, 16); 655 for (int ch = 0; str[ch] != 0; ++ch) 656 output->push_back(str[ch]); 657 658 // Put a colon after each number, except the last. 659 if (i < 16) 660 output->push_back(':'); 661 } 662 } 663 664 output->push_back(']'); 665 host_info->out_host.len = output->length() - host_info->out_host.begin; 666 667 host_info->family = CanonHostInfo::IPV6; 668 return true; 669 } 670 671 } // namespace 672 673 bool FindIPv4Components(const char* spec, 674 const url_parse::Component& host, 675 url_parse::Component components[4]) { 676 return DoFindIPv4Components<char, unsigned char>(spec, host, components); 677 } 678 679 bool FindIPv4Components(const char16* spec, 680 const url_parse::Component& host, 681 url_parse::Component components[4]) { 682 return DoFindIPv4Components<char16, char16>(spec, host, components); 683 } 684 685 void CanonicalizeIPAddress(const char* spec, 686 const url_parse::Component& host, 687 CanonOutput* output, 688 CanonHostInfo* host_info) { 689 if (DoCanonicalizeIPv4Address<char, unsigned char>( 690 spec, host, output, host_info)) 691 return; 692 if (DoCanonicalizeIPv6Address<char, unsigned char>( 693 spec, host, output, host_info)) 694 return; 695 } 696 697 void CanonicalizeIPAddress(const char16* spec, 698 const url_parse::Component& host, 699 CanonOutput* output, 700 CanonHostInfo* host_info) { 701 if (DoCanonicalizeIPv4Address<char16, char16>( 702 spec, host, output, host_info)) 703 return; 704 if (DoCanonicalizeIPv6Address<char16, char16>( 705 spec, host, output, host_info)) 706 return; 707 } 708 709 CanonHostInfo::Family IPv4AddressToNumber(const char* spec, 710 const url_parse::Component& host, 711 unsigned char address[4], 712 int* num_ipv4_components) { 713 return DoIPv4AddressToNumber<char>(spec, host, address, num_ipv4_components); 714 } 715 716 CanonHostInfo::Family IPv4AddressToNumber(const char16* spec, 717 const url_parse::Component& host, 718 unsigned char address[4], 719 int* num_ipv4_components) { 720 return DoIPv4AddressToNumber<char16>( 721 spec, host, address, num_ipv4_components); 722 } 723 724 bool IPv6AddressToNumber(const char* spec, 725 const url_parse::Component& host, 726 unsigned char address[16]) { 727 return DoIPv6AddressToNumber<char, unsigned char>(spec, host, address); 728 } 729 730 bool IPv6AddressToNumber(const char16* spec, 731 const url_parse::Component& host, 732 unsigned char address[16]) { 733 return DoIPv6AddressToNumber<char16, char16>(spec, host, address); 734 } 735 736 737 } // namespace url_canon 738