| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "config.h" | 5 #include "config.h" |
| 6 #include "FetchHeaderList.h" | 6 #include "FetchHeaderList.h" |
| 7 | 7 |
| 8 #include "core/fetch/CrossOriginAccessControl.h" | 8 #include "core/fetch/CrossOriginAccessControl.h" |
| 9 #include "core/xml/XMLHttpRequest.h" | 9 #include "core/xml/XMLHttpRequest.h" |
| 10 #include "platform/network/HTTPParsers.h" | 10 #include "platform/network/HTTPParsers.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 { | 21 { |
| 22 } | 22 } |
| 23 | 23 |
| 24 FetchHeaderList::~FetchHeaderList() | 24 FetchHeaderList::~FetchHeaderList() |
| 25 { | 25 { |
| 26 } | 26 } |
| 27 | 27 |
| 28 void FetchHeaderList::append(const String& name, const String& value) | 28 void FetchHeaderList::append(const String& name, const String& value) |
| 29 { | 29 { |
| 30 // "To append a name/value (|name|/|value|) pair to a header list (|list|), | 30 // "To append a name/value (|name|/|value|) pair to a header list (|list|), |
| 31 // append a new header whose name is |name| and value is |value|, to | 31 // append a new header whose name is |name|, byte lowercased, and value is |
| 32 // |list|." | 32 // |value|, to |list|." |
| 33 m_headerList.append(adoptPtr(new Header(name, value))); | 33 m_headerList.append(adoptPtr(new Header(name.lower(), value))); |
| 34 } | 34 } |
| 35 | 35 |
| 36 void FetchHeaderList::set(const String& name, const String& value) | 36 void FetchHeaderList::set(const String& name, const String& value) |
| 37 { | 37 { |
| 38 // "To set a name/value (|name|/|value|) pair in a header list (|list|), run | 38 // "To set a name/value (|name|/|value|) pair in a header list (|list|), run |
| 39 // these steps: | 39 // these steps: |
| 40 // 1. If there are any headers in |list| whose name is |name|, set the value | 40 // 1. Byte lowercase |name|. |
| 41 // 2. If there are any headers in |list| whose name is |name|, set the value |
| 41 // of the first such header to |value| and remove the others. | 42 // of the first such header to |value| and remove the others. |
| 42 // 2. Otherwise, append a new header whose name is |name| and value is | 43 // 3. Otherwise, append a new header whose name is |name| and value is |
| 43 // |value|, to |list|." | 44 // |value|, to |list|." |
| 45 const String lowercasedName = name.lower(); |
| 44 for (size_t i = 0; i < m_headerList.size(); ++i) { | 46 for (size_t i = 0; i < m_headerList.size(); ++i) { |
| 45 if (m_headerList[i]->first == name) { | 47 if (m_headerList[i]->first == lowercasedName) { |
| 46 m_headerList[i]->second = value; | 48 m_headerList[i]->second = value; |
| 47 for (size_t j = i + 1; j < m_headerList.size(); ) { | 49 for (size_t j = i + 1; j < m_headerList.size(); ) { |
| 48 if (m_headerList[j]->first == name) | 50 if (m_headerList[j]->first == lowercasedName) |
| 49 m_headerList.remove(j); | 51 m_headerList.remove(j); |
| 50 else | 52 else |
| 51 ++j; | 53 ++j; |
| 52 } | 54 } |
| 53 return; | 55 return; |
| 54 } | 56 } |
| 55 } | 57 } |
| 56 m_headerList.append(adoptPtr(new Header(name, value))); | 58 m_headerList.append(adoptPtr(new Header(lowercasedName, value))); |
| 57 } | 59 } |
| 58 | 60 |
| 59 size_t FetchHeaderList::size() const | 61 size_t FetchHeaderList::size() const |
| 60 { | 62 { |
| 61 return m_headerList.size(); | 63 return m_headerList.size(); |
| 62 } | 64 } |
| 63 | 65 |
| 64 void FetchHeaderList::remove(const String& name) | 66 void FetchHeaderList::remove(const String& name) |
| 65 { | 67 { |
| 68 // "To delete a name (|name|) from a header list (|list|), remove all header
s |
| 69 // whose name is |name|, byte lowercased, from |list|." |
| 70 const String lowercasedName = name.lower(); |
| 66 for (size_t i = 0; i < m_headerList.size(); ) { | 71 for (size_t i = 0; i < m_headerList.size(); ) { |
| 67 if (m_headerList[i]->first == name) | 72 if (m_headerList[i]->first == lowercasedName) |
| 68 m_headerList.remove(i); | 73 m_headerList.remove(i); |
| 69 else | 74 else |
| 70 ++i; | 75 ++i; |
| 71 } | 76 } |
| 72 } | 77 } |
| 73 | 78 |
| 74 bool FetchHeaderList::get(const String& name, String& result) const | 79 bool FetchHeaderList::get(const String& name, String& result) const |
| 75 { | 80 { |
| 81 const String lowercasedName = name.lower(); |
| 76 for (size_t i = 0; i < m_headerList.size(); ++i) { | 82 for (size_t i = 0; i < m_headerList.size(); ++i) { |
| 77 if (m_headerList[i]->first == name) { | 83 if (m_headerList[i]->first == lowercasedName) { |
| 78 result = m_headerList[i]->second; | 84 result = m_headerList[i]->second; |
| 79 return true; | 85 return true; |
| 80 } | 86 } |
| 81 } | 87 } |
| 82 return false; | 88 return false; |
| 83 } | 89 } |
| 84 | 90 |
| 85 void FetchHeaderList::getAll(const String& name, Vector<String>& result) const | 91 void FetchHeaderList::getAll(const String& name, Vector<String>& result) const |
| 86 { | 92 { |
| 93 const String lowercasedName = name.lower(); |
| 87 result.clear(); | 94 result.clear(); |
| 88 for (size_t i = 0; i < m_headerList.size(); ++i) { | 95 for (size_t i = 0; i < m_headerList.size(); ++i) { |
| 89 if (m_headerList[i]->first == name) | 96 if (m_headerList[i]->first == lowercasedName) |
| 90 result.append(m_headerList[i]->second); | 97 result.append(m_headerList[i]->second); |
| 91 } | 98 } |
| 92 } | 99 } |
| 93 | 100 |
| 94 bool FetchHeaderList::has(const String& name) const | 101 bool FetchHeaderList::has(const String& name) const |
| 95 { | 102 { |
| 103 const String lowercasedName = name.lower(); |
| 96 for (size_t i = 0; i < m_headerList.size(); ++i) { | 104 for (size_t i = 0; i < m_headerList.size(); ++i) { |
| 97 if (m_headerList[i]->first == name) | 105 if (m_headerList[i]->first == lowercasedName) |
| 98 return true; | 106 return true; |
| 99 } | 107 } |
| 100 return false; | 108 return false; |
| 101 } | 109 } |
| 102 | 110 |
| 103 void FetchHeaderList::clearList() | 111 void FetchHeaderList::clearList() |
| 104 { | 112 { |
| 105 m_headerList.clear(); | 113 m_headerList.clear(); |
| 106 } | 114 } |
| 107 | 115 |
| 108 bool FetchHeaderList::isValidHeaderName(const String& name) | 116 bool FetchHeaderList::isValidHeaderName(const String& name) |
| 109 { | 117 { |
| 110 // FIXME: According to the spec (http://fetch.spec.whatwg.org/) should we | 118 // "A name is a case-insensitive byte sequence that matches the field-name |
| 111 // accept all characters in the range 0x00 to 0x7F? | 119 // token production." |
| 112 return isValidHTTPToken(name); | 120 return isValidHTTPToken(name); |
| 113 } | 121 } |
| 114 | 122 |
| 115 bool FetchHeaderList::isValidHeaderValue(const String& value) | 123 bool FetchHeaderList::isValidHeaderValue(const String& value) |
| 116 { | 124 { |
| 117 // "A value is a byte sequence that matches the field-value token production | 125 // "A value is a byte sequence that matches the field-value token production |
| 118 // and contains no 0x0A or 0x0D bytes." | 126 // and contains no 0x0A or 0x0D bytes." |
| 119 return (value.find('\r') == kNotFound) && (value.find('\n') == kNotFound); | 127 return isValidHTTPHeaderValue(value); |
| 120 } | 128 } |
| 121 | 129 |
| 122 bool FetchHeaderList::isSimpleHeader(const String& name, const String& value) | 130 bool FetchHeaderList::isSimpleHeader(const String& name, const String& value) |
| 123 { | 131 { |
| 124 // "A simple header is a header whose name is either one of `Accept`, | 132 // "A simple header is a header whose name is either one of `Accept`, |
| 125 // `Accept-Language`, and `Content-Language`, or whose name is | 133 // `Accept-Language`, and `Content-Language`, or whose name is |
| 126 // `Content-Type` and value, once parsed, is one of | 134 // `Content-Type` and value, once parsed, is one of |
| 127 // `application/x-www-form-urlencoded`, `multipart/form-data`, and | 135 // `application/x-www-form-urlencoded`, `multipart/form-data`, and |
| 128 // `text/plain`." | 136 // `text/plain`." |
| 129 if (equalIgnoringCase(name, "accept") | 137 if (equalIgnoringCase(name, "accept") |
| (...skipping 25 matching lines...) Expand all Loading... |
| 155 } | 163 } |
| 156 | 164 |
| 157 bool FetchHeaderList::isForbiddenResponseHeaderName(const String& name) | 165 bool FetchHeaderList::isForbiddenResponseHeaderName(const String& name) |
| 158 { | 166 { |
| 159 // "A forbidden response header name is a header name that is one of: | 167 // "A forbidden response header name is a header name that is one of: |
| 160 // `Set-Cookie`, `Set-Cookie2`" | 168 // `Set-Cookie`, `Set-Cookie2`" |
| 161 return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set
-cookie2"); | 169 return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set
-cookie2"); |
| 162 } | 170 } |
| 163 | 171 |
| 164 } // namespace WebCore | 172 } // namespace WebCore |
| OLD | NEW |