| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/tools/balsa/balsa_headers_token_utils.h" | |
| 6 #include "net/tools/balsa/string_piece_utils.h" | |
| 7 | |
| 8 namespace net { | |
| 9 | |
| 10 inline void BalsaHeadersTokenUtils::TokenizeHeaderLine( | |
| 11 const BalsaHeaders& headers, | |
| 12 const BalsaHeaders::HeaderLineDescription& header_line, | |
| 13 BalsaHeaders::HeaderTokenList* tokens) { | |
| 14 CHECK(tokens); | |
| 15 | |
| 16 // Find where this line is stored | |
| 17 const char* stream_begin = headers.GetPtr(header_line.buffer_base_idx); | |
| 18 | |
| 19 // Determine the boundaries of the value | |
| 20 const char* value_begin = stream_begin + header_line.value_begin_idx; | |
| 21 const char* line_end = stream_begin + header_line.last_char_idx; | |
| 22 | |
| 23 // Tokenize | |
| 24 ParseTokenList(value_begin, line_end, tokens); | |
| 25 } | |
| 26 | |
| 27 void BalsaHeadersTokenUtils::RemoveLastTokenFromHeaderValue( | |
| 28 const base::StringPiece& key, BalsaHeaders* headers) { | |
| 29 BalsaHeaders::HeaderLines::iterator it = | |
| 30 headers->GetHeaderLinesIterator(key, headers->header_lines_.begin()); | |
| 31 if (it == headers->header_lines_.end()) { | |
| 32 DLOG(WARNING) << "Attempting to remove last token from a non-existent " | |
| 33 << "header \"" << key << "\""; | |
| 34 return; | |
| 35 } | |
| 36 | |
| 37 // Find the last line with that key. | |
| 38 BalsaHeaders::HeaderLines::iterator header_line; | |
| 39 do { | |
| 40 header_line = it; | |
| 41 it = headers->GetHeaderLinesIterator(key, it + 1); | |
| 42 } | |
| 43 while (it != headers->header_lines_.end()); | |
| 44 | |
| 45 // Tokenize just that line. | |
| 46 BalsaHeaders::HeaderTokenList tokens; | |
| 47 TokenizeHeaderLine(*headers, *header_line, &tokens); | |
| 48 | |
| 49 if (tokens.empty()) { | |
| 50 DLOG(WARNING) << "Attempting to remove a token from an empty header value " | |
| 51 << "for header \"" << key << "\""; | |
| 52 header_line->skip = true; // remove the whole line | |
| 53 } else if (tokens.size() == 1) { | |
| 54 header_line->skip = true; // remove the whole line | |
| 55 } else { | |
| 56 // Shrink the line size and leave the extra data in the buffer. | |
| 57 const base::StringPiece& new_last_token = tokens[tokens.size() - 2]; | |
| 58 const char* last_char_address = | |
| 59 new_last_token.data() + new_last_token.size() - 1; | |
| 60 const char* stream_begin = headers->GetPtr(header_line->buffer_base_idx); | |
| 61 | |
| 62 header_line->last_char_idx = last_char_address - stream_begin + 1; | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 bool BalsaHeadersTokenUtils::CheckHeaderForLastToken( | |
| 67 const BalsaHeaders& headers, | |
| 68 const base::StringPiece& key, | |
| 69 const base::StringPiece& token) { | |
| 70 BalsaHeaders::const_header_lines_key_iterator it = | |
| 71 headers.GetIteratorForKey(key); | |
| 72 if (it == headers.header_lines_key_end()) | |
| 73 return false; | |
| 74 | |
| 75 // Find the last line | |
| 76 BalsaHeaders::const_header_lines_key_iterator header_line = it; | |
| 77 do { | |
| 78 header_line = it; | |
| 79 ++it; | |
| 80 } | |
| 81 while (it != headers.header_lines_key_end()); | |
| 82 | |
| 83 // Tokenize just that line | |
| 84 BalsaHeaders::HeaderTokenList tokens; | |
| 85 ParseTokenList(header_line->second.begin(), header_line->second.end(), | |
| 86 &tokens); | |
| 87 | |
| 88 return !tokens.empty() && | |
| 89 StringPieceUtils::StartsWithIgnoreCase(tokens.back(), token); | |
| 90 } | |
| 91 | |
| 92 void BalsaHeadersTokenUtils::TokenizeHeaderValue( | |
| 93 const BalsaHeaders& headers, | |
| 94 const base::StringPiece& key, | |
| 95 BalsaHeaders::HeaderTokenList* tokens) { | |
| 96 CHECK(tokens); | |
| 97 tokens->clear(); | |
| 98 | |
| 99 // We may have more then 1 line with the same header key. Tokenize them all | |
| 100 // and stick all the tokens into the same list. | |
| 101 for (BalsaHeaders::const_header_lines_key_iterator header_line = | |
| 102 headers.GetIteratorForKey(key); | |
| 103 header_line != headers.header_lines_key_end(); ++header_line) { | |
| 104 ParseTokenList(header_line->second.begin(), header_line->second.end(), | |
| 105 tokens); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 void BalsaHeadersTokenUtils::ParseTokenList( | |
| 110 const char* start, | |
| 111 const char* end, | |
| 112 BalsaHeaders::HeaderTokenList* tokens) { | |
| 113 if (start == end) { | |
| 114 return; | |
| 115 } | |
| 116 while (true) { | |
| 117 // search for first nonwhitespace, non separator char. | |
| 118 while (*start == ',' || *start <= ' ') { | |
| 119 ++start; | |
| 120 if (start == end) { | |
| 121 return; | |
| 122 } | |
| 123 } | |
| 124 // found. marked. | |
| 125 const char* nws = start; | |
| 126 | |
| 127 // search for next whitspace or separator char. | |
| 128 while (*start != ',' && *start > ' ') { | |
| 129 ++start; | |
| 130 if (start == end) { | |
| 131 if (nws != start) { | |
| 132 tokens->push_back(base::StringPiece(nws, start - nws)); | |
| 133 } | |
| 134 return; | |
| 135 } | |
| 136 } | |
| 137 tokens->push_back(base::StringPiece(nws, start - nws)); | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 } // namespace net | |
| 142 | |
| OLD | NEW |