proxygen
StructuredHeadersBuffer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
10 
12 #include <boost/lexical_cast.hpp>
13 #include "StructuredHeadersUtilities.h"// @manual=:utils
14 
15 namespace proxygen {
16 
17 using namespace StructuredHeaders;
18 
20 
21  removeOptionalWhitespace();
22 
23  if (isEmpty()) {
24  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
25  } else {
26  char firstCharacter = peek();
27  if (firstCharacter == '"') {
28  return parseString(result);
29  } else if (firstCharacter == '*') {
30  return parseBinaryContent(result);
31  } else if (std::isdigit(firstCharacter) || firstCharacter == '-') {
32  return parseNumber(result);
33  } else {
34  return handleDecodeError(DecodeError::INVALID_CHARACTER);
35  }
36  }
37 }
38 
41 
42  bool positive = true;
43  std::string input;
44 
45  if (isEmpty()) {
46  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
47  }
48 
49  if (peek() == '-') {
50  advanceCursor();
51  positive = false;
52  input.push_back('-');
53  }
54 
55  if (isEmpty()) {
56  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
57  }
58 
59  if (!std::isdigit(peek())) {
60  return handleDecodeError(DecodeError::INVALID_CHARACTER);
61  }
62 
63  while (!isEmpty()) {
64  char current = peek();
65  if (std::isdigit(current)) {
66  input.push_back(current);
67  advanceCursor();
68  } else if (type == StructuredHeaderItem::Type::INT64 && current == '.') {
70  input.push_back(current);
71  advanceCursor();
72  } else {
73  break;
74  }
75 
76  int numDigits = input.length() - (positive ? 0 : 1);
79  return handleDecodeError(DecodeError::VALUE_TOO_LONG);
82  return handleDecodeError(DecodeError::VALUE_TOO_LONG);
83  }
84  }
85 
87  return parseInteger(input, result);
88  } else if (input.back() == '.') {
89  return handleDecodeError(DecodeError::INVALID_CHARACTER);
90  } else {
91  return parseFloat(input, result);
92  }
93 
94  return DecodeError::OK;
95 }
96 
98  StructuredHeaderItem& result) {
99 
100  std::string outputString;
101  if (isEmpty()) {
102  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
103  }
104 
105  if (peek() != '*') {
106  return handleDecodeError(DecodeError::INVALID_CHARACTER);
107  }
108 
109  advanceCursor();
110 
111  while (!isEmpty()) {
112  char current = peek();
113  advanceCursor();
114  if (current == '*') {
116  outputString)) {
117  return handleDecodeError(DecodeError::UNDECODEABLE_BINARY_CONTENT);
118  }
119 
120  std::string decodedContent = decodeBase64(outputString);
121  if (encodeBase64(decodedContent) != outputString) {
122  return handleDecodeError(DecodeError::UNDECODEABLE_BINARY_CONTENT);
123  }
124 
125  result.value = std::move(decodedContent);
127  return DecodeError::OK;
129  current)) {
130  return handleDecodeError(DecodeError::INVALID_CHARACTER);
131  } else {
132  outputString.push_back(current);
133  }
134  }
135 
136  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
137 }
138 
140  StructuredHeaderItem& result) {
141 
142  std::string outputString;
143 
144  auto err = parseIdentifier(outputString);
145  if (err != DecodeError::OK) {
146  return err;
147  }
148 
149  result.value = outputString;
151 
152  return DecodeError::OK;
153 }
154 
156  std::string& result) {
157 
158  if (isEmpty()) {
159  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
160  }
161 
162  if (!isLcAlpha(peek())) {
163  return handleDecodeError(DecodeError::INVALID_CHARACTER);
164  }
165 
166  while (!isEmpty()) {
167  char current = peek();
168  if (!isValidIdentifierChar(current)) {
169  break;
170  } else {
171  advanceCursor();
172  result.push_back(current);
173  }
174  }
175 
176  return DecodeError::OK;
177 }
178 
180  StructuredHeaderItem& result) {
181 
182  try {
183  result.value = boost::lexical_cast<int64_t>(input);
185  } catch (boost::bad_lexical_cast &) {
186  return handleDecodeError(DecodeError::UNPARSEABLE_NUMERIC_TYPE);
187  }
188  return DecodeError::OK;
189 }
190 
192  StructuredHeaderItem& result) {
193 
194  try {
195  result.value = boost::lexical_cast<double>(input);
197  } catch (boost::bad_lexical_cast &) {
198  return handleDecodeError(DecodeError::UNPARSEABLE_NUMERIC_TYPE);
199  }
200  return DecodeError::OK;
201 }
202 
204 
205  std::string outputString;
206 
207  if (isEmpty()) {
208  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
209  }
210 
211  if (peek() != '"') {
212  return handleDecodeError(DecodeError::INVALID_CHARACTER);
213  }
214 
215  advanceCursor();
216 
217  while (!isEmpty()) {
218  char current = peek();
219  if (current == '\\') {
220  advanceCursor();
221  if (isEmpty()) {
222  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
223  } else {
224  char nextChar = peek();
225  advanceCursor();
226  if (nextChar != '"' && nextChar != '\\') {
227  return handleDecodeError(DecodeError::INVALID_CHARACTER);
228  }
229  outputString.push_back(nextChar);
230  }
231  } else if (current == '"') {
232  advanceCursor();
233  result.value = outputString;
235  return DecodeError::OK;
236  } else if (!isValidStringChar(current)) {
237  return handleDecodeError(DecodeError::INVALID_CHARACTER);
238  } else {
239  advanceCursor();
240  outputString.push_back(current);
241  }
242  }
243 
244  return handleDecodeError(DecodeError::UNEXPECTED_END_OF_BUFFER);
245 }
246 
248  while (peek() == ' ' || peek() == '\t') {
249  advanceCursor();
250  }
251  return DecodeError::OK;
252 }
253 
255  bool strict) {
256 
257  if (content_.startsWith(symbol)) {
258  content_.advance(symbol.length());
259  return DecodeError::OK;
260  } else {
261  if (strict) {
262  // Do some error logging
263  return handleDecodeError(DecodeError::INVALID_CHARACTER);
264  }
266  }
267 }
268 
270  LOG_EVERY_N(ERROR, 1000) << "Error message: " <<
271  decodeErrorDescription.at(err) <<
272  ". Number of characters parsed before error:" <<
273  getNumCharsParsed() << ". Header Content:" << originalContent_.str();
274  return err;
275 }
276 
278  return *content_.begin();
279 }
280 
282  content_.advance(1);
283 }
284 
286  return content_.begin() == content_.end();
287 }
288 
290  return std::distance(originalContent_.begin(), content_.begin());
291 }
292 
293 }
DecodeError removeSymbol(const std::string &symbol, bool strict)
DecodeError parseBinaryContent(StructuredHeaderItem &result)
static const std::map< DecodeError, std::string > decodeErrorDescription
PskType type
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
DecodeError parseFloat(const std::string &input, StructuredHeaderItem &result)
std::string encodeBase64(const std::string &input)
DecodeError parseString(StructuredHeaderItem &result)
int current
constexpr detail::IsEmpty< true > isEmpty
Definition: Base-inl.h:2555
boost::variant< int64_t, double, std::string > value
StructuredHeaders::DecodeError parseItem(StructuredHeaderItem &result)
std::string decodeBase64(const std::string &encoded)
DecodeError handleDecodeError(const DecodeError &err)
DecodeError parseNumber(StructuredHeaderItem &result)
const char * string
Definition: Conv.cpp:212
bool isValidEncodedBinaryContent(const std::string &s)
StructuredHeaders::DecodeError parseIdentifier(StructuredHeaderItem &result)
DecodeError parseInteger(const std::string &input, StructuredHeaderItem &result)