1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// Copyright (c) 2009 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/flip_server/balsa_headers_token_utils.h"
#include "net/tools/flip_server/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
|