| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // The rules for parsing content-types were borrowed from Firefox: | 5 // The rules for parsing content-types were borrowed from Firefox: |
| 6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 | 6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 |
| 7 | 7 |
| 8 #include "net/http/http_util.h" | 8 #include "net/http/http_util.h" |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 return line.length(); | 50 return line.length(); |
| 51 } | 51 } |
| 52 | 52 |
| 53 //----------------------------------------------------------------------------- | 53 //----------------------------------------------------------------------------- |
| 54 | 54 |
| 55 // static | 55 // static |
| 56 std::string HttpUtil::PathForRequest(const GURL& url) { | 56 std::string HttpUtil::PathForRequest(const GURL& url) { |
| 57 DCHECK(url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https"))); | 57 DCHECK(url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https"))); |
| 58 if (url.has_query()) | 58 if (url.has_query()) |
| 59 return url.path() + "?" + url.query(); | 59 return url.path() + "?" + url.query(); |
| 60 return url.path(); | 60 return url.path(); |
| 61 } | 61 } |
| 62 | 62 |
| 63 // static | 63 // static |
| 64 std::string HttpUtil::SpecForRequest(const GURL& url) { | 64 std::string HttpUtil::SpecForRequest(const GURL& url) { |
| 65 DCHECK(url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https"))); | 65 DCHECK(url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https"))); |
| 66 GURL::Replacements replacements; | 66 GURL::Replacements replacements; |
| 67 replacements.ClearUsername(); | 67 replacements.ClearUsername(); |
| 68 replacements.ClearPassword(); | 68 replacements.ClearPassword(); |
| 69 replacements.ClearRef(); | 69 replacements.ClearRef(); |
| 70 return url.ReplaceComponents(replacements).spec(); | 70 return url.ReplaceComponents(replacements).spec(); |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 | 423 |
| 424 // TODO(ericroman): is this too permissive? (delimits on [\r\n]+) | 424 // TODO(ericroman): is this too permissive? (delimits on [\r\n]+) |
| 425 CStringTokenizer lines(status_line_end, input_end, "\r\n"); | 425 CStringTokenizer lines(status_line_end, input_end, "\r\n"); |
| 426 | 426 |
| 427 // This variable is true when the previous line was continuable. | 427 // This variable is true when the previous line was continuable. |
| 428 bool prev_line_continuable = false; | 428 bool prev_line_continuable = false; |
| 429 | 429 |
| 430 while (lines.GetNext()) { | 430 while (lines.GetNext()) { |
| 431 const char* line_begin = lines.token_begin(); | 431 const char* line_begin = lines.token_begin(); |
| 432 const char* line_end = lines.token_end(); | 432 const char* line_end = lines.token_end(); |
| 433 | 433 |
| 434 if (prev_line_continuable && IsLWS(*line_begin)) { | 434 if (prev_line_continuable && IsLWS(*line_begin)) { |
| 435 // Join continuation; reduce the leading LWS to a single SP. | 435 // Join continuation; reduce the leading LWS to a single SP. |
| 436 raw_headers.push_back(' '); | 436 raw_headers.push_back(' '); |
| 437 raw_headers.append(FindFirstNonLWS(line_begin, line_end), line_end); | 437 raw_headers.append(FindFirstNonLWS(line_begin, line_end), line_end); |
| 438 } else { | 438 } else { |
| 439 // Terminate the previous line. | 439 // Terminate the previous line. |
| 440 raw_headers.push_back('\0'); | 440 raw_headers.push_back('\0'); |
| 441 | 441 |
| 442 // Copy the raw data to output. | 442 // Copy the raw data to output. |
| 443 raw_headers.append(line_begin, line_end); | 443 raw_headers.append(line_begin, line_end); |
| 444 | 444 |
| 445 // Check if the current line can be continued. | 445 // Check if the current line can be continued. |
| 446 prev_line_continuable = IsLineSegmentContinuable(line_begin, line_end); | 446 prev_line_continuable = IsLineSegmentContinuable(line_begin, line_end); |
| 447 } | 447 } |
| 448 } | 448 } |
| 449 | 449 |
| 450 raw_headers.append("\0\0", 2); | 450 raw_headers.append("\0\0", 2); |
| 451 return raw_headers; | 451 return raw_headers; |
| 452 } | 452 } |
| 453 | 453 |
| 454 // TODO(jungshik): 1. If the list is 'fr-CA,fr-FR,en,de', we have to add |
| 455 // 'fr' after 'fr-CA' with the same q-value as 'fr-CA' because |
| 456 // web servers, in general, do not fall back to 'fr' and may end up picking |
| 457 // 'en' which has a lower preference than 'fr-CA' and 'fr-FR'. |
| 458 // 2. This function assumes that the input is a comma separated list |
| 459 // without any whitespace. As long as it comes from the preference and |
| 460 // a user does not manually edit the preference file, it's the case. Still, |
| 461 // we may have to make it more robust. |
| 462 std::string HttpUtil::GenerateAcceptLanguageHeader( |
| 463 const std::string& raw_language_list) { |
| 464 // We use integers for qvalue and qvalue decrement that are 10 times |
| 465 // larger than actual values to avoid a problem with comparing |
| 466 // two floating point numbers. |
| 467 const unsigned int kQvalueDecrement10 = 2; |
| 468 unsigned int qvalue10 = 10; |
| 469 StringTokenizer t(raw_language_list, ","); |
| 470 std::string lang_list_with_q; |
| 471 while (t.GetNext()) { |
| 472 std::string language = t.token(); |
| 473 if (qvalue10 == 10) { |
| 474 // q=1.0 is implicit. |
| 475 lang_list_with_q = language; |
| 476 } else { |
| 477 DCHECK(qvalue10 >= 0 && qvalue10 < 10); |
| 478 StringAppendF(&lang_list_with_q, ",%s;q=0.%d", language.c_str(), |
| 479 qvalue10); |
| 480 } |
| 481 // It does not make sense to have 'q=0'. |
| 482 if (qvalue10 > kQvalueDecrement10) |
| 483 qvalue10 -= kQvalueDecrement10; |
| 484 } |
| 485 return lang_list_with_q; |
| 486 } |
| 487 |
| 488 std::string HttpUtil::GenerateAcceptCharsetHeader(const std::string& charset) { |
| 489 std::string charset_with_q = charset; |
| 490 if (LowerCaseEqualsASCII(charset, "utf-8")) { |
| 491 charset_with_q += ",*;q=0.5"; |
| 492 } else { |
| 493 charset_with_q += ",utf-8;q=0.7,*;q=0.3"; |
| 494 } |
| 495 return charset_with_q; |
| 496 } |
| 497 |
| 454 // BNF from section 4.2 of RFC 2616: | 498 // BNF from section 4.2 of RFC 2616: |
| 455 // | 499 // |
| 456 // message-header = field-name ":" [ field-value ] | 500 // message-header = field-name ":" [ field-value ] |
| 457 // field-name = token | 501 // field-name = token |
| 458 // field-value = *( field-content | LWS ) | 502 // field-value = *( field-content | LWS ) |
| 459 // field-content = <the OCTETs making up the field-value | 503 // field-content = <the OCTETs making up the field-value |
| 460 // and consisting of either *TEXT or combinations | 504 // and consisting of either *TEXT or combinations |
| 461 // of token, separators, and quoted-string> | 505 // of token, separators, and quoted-string> |
| 462 // | 506 // |
| 463 | 507 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 | 557 |
| 514 // bypass empty values. | 558 // bypass empty values. |
| 515 if (value_begin_ != value_end_) | 559 if (value_begin_ != value_end_) |
| 516 return true; | 560 return true; |
| 517 } | 561 } |
| 518 return false; | 562 return false; |
| 519 } | 563 } |
| 520 | 564 |
| 521 } // namespace net | 565 } // namespace net |
| 522 | 566 |
| OLD | NEW |