Guest User

Untitled

a guest
Feb 21st, 2018
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.08 KB | None | 0 0
  1. // checks if `c' is a space or a h-tab (see RFC 2616 chapter 2.2)
  2. inline bool isspht(char c) {
  3. return c == ' ' || c == '\t';
  4. }
  5.  
  6. template<class Source, typename Char>
  7. bool expect(Source &in, Char c) {
  8. int t = boost::iostreams::get(in);
  9. if(t == c)
  10. return true;
  11. else if(t == EOF)
  12. throw remote_close();
  13.  
  14. boost::iostreams::putback(in, t);
  15. return false;
  16. }
  17.  
  18. template<class Source>
  19. int remove_spaces(Source &in) {
  20. int c;
  21. do {
  22. c = boost::iostreams::get(in);
  23. } while(isspht(c));
  24. boost::iostreams::putback(in, c);
  25. return c;
  26. }
  27.  
  28. typedef boost::tuple<std::string, std::string, std::string> request_line;
  29. enum { REQUEST_METHOD, REQUEST_URI, REQUEST_HTTP_VERSION };
  30.  
  31. template<class Source>
  32. void get_until(char end, Source &in, std::string &ret,
  33. bool allow_cr_or_lf = false,
  34. std::size_t max_length = 0) {
  35. int t;
  36. while ((t = boost::iostreams::get(in)) != end) {
  37. if(t == EOF)
  38. throw remote_close();
  39. if (!allow_cr_or_lf && (t == '\r' || t == '\n'))
  40. throw bad_format();
  41. if (max_length != 0 && ret.size() >= max_length)
  42. throw bad_format();
  43. ret += t;
  44. }
  45. }
  46.  
  47. #define REST_RESERVE_LIKE(x, s) \
  48. (x).reserve(sizeof(s) - 1)
  49.  
  50. template<class Source>
  51. request_line get_request_line(
  52. Source &in,
  53. boost::tuple<std::size_t, std::size_t, std::size_t> const &max_sizes =
  54. boost::make_tuple(0, 0, 0))
  55. {
  56. while (expect(in, '\r'))
  57. if (!expect(in, '\n'))
  58. throw bad_format();
  59.  
  60. request_line x;
  61.  
  62. REST_RESERVE_LIKE(x.get<REQUEST_METHOD>(), "OPTIONS");
  63. get_until(' ', in, x.get<REQUEST_METHOD>(), false,
  64. max_sizes.get<REQUEST_METHOD>());
  65. if (x.get<REQUEST_METHOD>().empty())
  66. throw bad_format();
  67.  
  68. get_until(' ', in, x.get<REQUEST_URI>(), false,
  69. max_sizes.get<REQUEST_URI>());
  70. if (x.get<REQUEST_URI>().empty())
  71. throw bad_format();
  72.  
  73. REST_RESERVE_LIKE(x.get<REQUEST_HTTP_VERSION>(), "HTTP/1.0");
  74. get_until('\r', in, x.get<REQUEST_HTTP_VERSION>(), false,
  75. max_sizes.get<REQUEST_HTTP_VERSION>());
  76. if (x.get<REQUEST_HTTP_VERSION>().empty())
  77. throw bad_format();
  78.  
  79. if (!expect(in, '\n'))
  80. throw bad_format();
  81.  
  82. return x;
  83. }
  84.  
  85. // reads a header field from `in' and adds it to `fields'
  86. // see RFC 2616 chapter 4.2
  87. // Warning: Field names are converted to all lower-case!
  88. template<class Source, class HeaderFields>
  89. void get_header_field(
  90. Source &in,
  91. HeaderFields &fields,
  92. std::size_t max_name_length,
  93. std::size_t max_value_length)
  94. {
  95. namespace io = boost::iostreams;
  96.  
  97. std::string name;
  98. REST_RESERVE_LIKE(name, "If-Unmodified-Since");
  99. get_until(':', in, name, false, max_name_length);
  100. boost::algorithm::to_lower(name);
  101.  
  102. remove_spaces(in);
  103.  
  104. std::string &value = fields[name];
  105. if (!value.empty())
  106. value += ", ";
  107.  
  108. for (;;) {
  109. int t;
  110. if ((t = io::get(in)) == EOF)
  111. throw remote_close();
  112. if (t == '\n' || t == '\r') {
  113. // Newlines in header fields are allowed when followed
  114. // by an SP (space or horizontal tab)
  115. if (t == '\r')
  116. expect(in, '\n');
  117. t = io::get(in);
  118. if (!isspht(t)) {
  119. io::putback(in, t);
  120. break;
  121. }
  122. remove_spaces(in);
  123. value += ' ';
  124. } else {
  125. if (max_value_length != 0 && value.size() >= max_value_length)
  126. throw bad_format();
  127. value += t;
  128. }
  129. }
  130.  
  131. std::string::reverse_iterator xend = value.rbegin();
  132. while (isspht(*xend))
  133. ++xend;
  134. value.erase(xend.base(), value.end());
  135. }
  136.  
  137. #undef REST_RESERVE_LIKE
  138.  
  139. template<class Source, class HeaderFields>
  140. void read_headers(
  141. Source &source,
  142. HeaderFields &fields,
  143. std::size_t max_name_length = 0,
  144. std::size_t max_value_length = 0,
  145. std::size_t max_header_count = 0)
  146. {
  147. std::size_t n = 0;
  148. for (;;) {
  149. if (expect(source, '\r')) {
  150. if (!expect(source, '\n'))
  151. throw bad_format();
  152. return;
  153. }
  154. if (max_header_count != 0 && ++n > max_header_count)
  155. throw bad_format();
  156. get_header_field(source, fields, max_name_length, max_value_length);
  157. }
  158. }
Add Comment
Please, Sign In to add comment