summaryrefslogtreecommitdiff
path: root/chromium/net/tools/balsa/balsa_headers_token_utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/tools/balsa/balsa_headers_token_utils.cc')
-rw-r--r--chromium/net/tools/balsa/balsa_headers_token_utils.cc142
1 files changed, 142 insertions, 0 deletions
diff --git a/chromium/net/tools/balsa/balsa_headers_token_utils.cc b/chromium/net/tools/balsa/balsa_headers_token_utils.cc
new file mode 100644
index 00000000000..c807e05c9ab
--- /dev/null
+++ b/chromium/net/tools/balsa/balsa_headers_token_utils.cc
@@ -0,0 +1,142 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/balsa/balsa_headers_token_utils.h"
+#include "net/tools/balsa/string_piece_utils.h"
+
+namespace net {
+
+inline void BalsaHeadersTokenUtils::TokenizeHeaderLine(
+ const BalsaHeaders& headers,
+ const BalsaHeaders::HeaderLineDescription& header_line,
+ BalsaHeaders::HeaderTokenList* tokens) {
+ CHECK(tokens);
+
+ // Find where this line is stored
+ const char* stream_begin = headers.GetPtr(header_line.buffer_base_idx);
+
+ // Determine the boundaries of the value
+ const char* value_begin = stream_begin + header_line.value_begin_idx;
+ const char* line_end = stream_begin + header_line.last_char_idx;
+
+ // Tokenize
+ ParseTokenList(value_begin, line_end, tokens);
+}
+
+void BalsaHeadersTokenUtils::RemoveLastTokenFromHeaderValue(
+ const base::StringPiece& key, BalsaHeaders* headers) {
+ BalsaHeaders::HeaderLines::iterator it =
+ headers->GetHeaderLinesIterator(key, headers->header_lines_.begin());
+ if (it == headers->header_lines_.end()) {
+ DLOG(WARNING) << "Attempting to remove last token from a non-existent "
+ << "header \"" << key << "\"";
+ return;
+ }
+
+ // Find the last line with that key.
+ BalsaHeaders::HeaderLines::iterator header_line;
+ do {
+ header_line = it;
+ it = headers->GetHeaderLinesIterator(key, it + 1);
+ }
+ while (it != headers->header_lines_.end());
+
+ // Tokenize just that line.
+ BalsaHeaders::HeaderTokenList tokens;
+ TokenizeHeaderLine(*headers, *header_line, &tokens);
+
+ if (tokens.empty()) {
+ DLOG(WARNING) << "Attempting to remove a token from an empty header value "
+ << "for header \"" << key << "\"";
+ header_line->skip = true; // remove the whole line
+ } else if (tokens.size() == 1) {
+ header_line->skip = true; // remove the whole line
+ } else {
+ // Shrink the line size and leave the extra data in the buffer.
+ const base::StringPiece& new_last_token = tokens[tokens.size() - 2];
+ const char* last_char_address =
+ new_last_token.data() + new_last_token.size() - 1;
+ const char* stream_begin = headers->GetPtr(header_line->buffer_base_idx);
+
+ header_line->last_char_idx = last_char_address - stream_begin + 1;
+ }
+}
+
+bool BalsaHeadersTokenUtils::CheckHeaderForLastToken(
+ const BalsaHeaders& headers,
+ const base::StringPiece& key,
+ const base::StringPiece& token) {
+ BalsaHeaders::const_header_lines_key_iterator it =
+ headers.GetIteratorForKey(key);
+ if (it == headers.header_lines_key_end())
+ return false;
+
+ // Find the last line
+ BalsaHeaders::const_header_lines_key_iterator header_line = it;
+ do {
+ header_line = it;
+ ++it;
+ }
+ while (it != headers.header_lines_key_end());
+
+ // Tokenize just that line
+ BalsaHeaders::HeaderTokenList tokens;
+ ParseTokenList(header_line->second.begin(), header_line->second.end(),
+ &tokens);
+
+ return !tokens.empty() &&
+ StringPieceUtils::StartsWithIgnoreCase(tokens.back(), token);
+}
+
+void BalsaHeadersTokenUtils::TokenizeHeaderValue(
+ const BalsaHeaders& headers,
+ const base::StringPiece& key,
+ BalsaHeaders::HeaderTokenList* tokens) {
+ CHECK(tokens);
+ tokens->clear();
+
+ // We may have more then 1 line with the same header key. Tokenize them all
+ // and stick all the tokens into the same list.
+ for (BalsaHeaders::const_header_lines_key_iterator header_line =
+ headers.GetIteratorForKey(key);
+ header_line != headers.header_lines_key_end(); ++header_line) {
+ ParseTokenList(header_line->second.begin(), header_line->second.end(),
+ tokens);
+ }
+}
+
+void BalsaHeadersTokenUtils::ParseTokenList(
+ const char* start,
+ const char* end,
+ BalsaHeaders::HeaderTokenList* tokens) {
+ if (start == end) {
+ return;
+ }
+ while (true) {
+ // search for first nonwhitespace, non separator char.
+ while (*start == ',' || *start <= ' ') {
+ ++start;
+ if (start == end) {
+ return;
+ }
+ }
+ // found. marked.
+ const char* nws = start;
+
+ // search for next whitspace or separator char.
+ while (*start != ',' && *start > ' ') {
+ ++start;
+ if (start == end) {
+ if (nws != start) {
+ tokens->push_back(base::StringPiece(nws, start - nws));
+ }
+ return;
+ }
+ }
+ tokens->push_back(base::StringPiece(nws, start - nws));
+ }
+}
+
+} // namespace net
+