Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // checks if `c' is a space or a h-tab (see RFC 2616 chapter 2.2)
- inline bool isspht(char c) {
- return c == ' ' || c == '\t';
- }
- template<class Source, typename Char>
- bool expect(Source &in, Char c) {
- int t = boost::iostreams::get(in);
- if(t == c)
- return true;
- else if(t == EOF)
- throw remote_close();
- boost::iostreams::putback(in, t);
- return false;
- }
- template<class Source>
- int remove_spaces(Source &in) {
- int c;
- do {
- c = boost::iostreams::get(in);
- } while(isspht(c));
- boost::iostreams::putback(in, c);
- return c;
- }
- typedef boost::tuple<std::string, std::string, std::string> request_line;
- enum { REQUEST_METHOD, REQUEST_URI, REQUEST_HTTP_VERSION };
- template<class Source>
- void get_until(char end, Source &in, std::string &ret,
- bool allow_cr_or_lf = false,
- std::size_t max_length = 0) {
- int t;
- while ((t = boost::iostreams::get(in)) != end) {
- if(t == EOF)
- throw remote_close();
- if (!allow_cr_or_lf && (t == '\r' || t == '\n'))
- throw bad_format();
- if (max_length != 0 && ret.size() >= max_length)
- throw bad_format();
- ret += t;
- }
- }
- #define REST_RESERVE_LIKE(x, s) \
- (x).reserve(sizeof(s) - 1)
- template<class Source>
- request_line get_request_line(
- Source &in,
- boost::tuple<std::size_t, std::size_t, std::size_t> const &max_sizes =
- boost::make_tuple(0, 0, 0))
- {
- while (expect(in, '\r'))
- if (!expect(in, '\n'))
- throw bad_format();
- request_line x;
- REST_RESERVE_LIKE(x.get<REQUEST_METHOD>(), "OPTIONS");
- get_until(' ', in, x.get<REQUEST_METHOD>(), false,
- max_sizes.get<REQUEST_METHOD>());
- if (x.get<REQUEST_METHOD>().empty())
- throw bad_format();
- get_until(' ', in, x.get<REQUEST_URI>(), false,
- max_sizes.get<REQUEST_URI>());
- if (x.get<REQUEST_URI>().empty())
- throw bad_format();
- REST_RESERVE_LIKE(x.get<REQUEST_HTTP_VERSION>(), "HTTP/1.0");
- get_until('\r', in, x.get<REQUEST_HTTP_VERSION>(), false,
- max_sizes.get<REQUEST_HTTP_VERSION>());
- if (x.get<REQUEST_HTTP_VERSION>().empty())
- throw bad_format();
- if (!expect(in, '\n'))
- throw bad_format();
- return x;
- }
- // reads a header field from `in' and adds it to `fields'
- // see RFC 2616 chapter 4.2
- // Warning: Field names are converted to all lower-case!
- template<class Source, class HeaderFields>
- void get_header_field(
- Source &in,
- HeaderFields &fields,
- std::size_t max_name_length,
- std::size_t max_value_length)
- {
- namespace io = boost::iostreams;
- std::string name;
- REST_RESERVE_LIKE(name, "If-Unmodified-Since");
- get_until(':', in, name, false, max_name_length);
- boost::algorithm::to_lower(name);
- remove_spaces(in);
- std::string &value = fields[name];
- if (!value.empty())
- value += ", ";
- for (;;) {
- int t;
- if ((t = io::get(in)) == EOF)
- throw remote_close();
- if (t == '\n' || t == '\r') {
- // Newlines in header fields are allowed when followed
- // by an SP (space or horizontal tab)
- if (t == '\r')
- expect(in, '\n');
- t = io::get(in);
- if (!isspht(t)) {
- io::putback(in, t);
- break;
- }
- remove_spaces(in);
- value += ' ';
- } else {
- if (max_value_length != 0 && value.size() >= max_value_length)
- throw bad_format();
- value += t;
- }
- }
- std::string::reverse_iterator xend = value.rbegin();
- while (isspht(*xend))
- ++xend;
- value.erase(xend.base(), value.end());
- }
- #undef REST_RESERVE_LIKE
- template<class Source, class HeaderFields>
- void read_headers(
- Source &source,
- HeaderFields &fields,
- std::size_t max_name_length = 0,
- std::size_t max_value_length = 0,
- std::size_t max_header_count = 0)
- {
- std::size_t n = 0;
- for (;;) {
- if (expect(source, '\r')) {
- if (!expect(source, '\n'))
- throw bad_format();
- return;
- }
- if (max_header_count != 0 && ++n > max_header_count)
- throw bad_format();
- get_header_field(source, fields, max_name_length, max_value_length);
- }
- }
Add Comment
Please, Sign In to add comment