ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

277 lines
5.4 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #ifndef CPPCMS_HTTP_PARSER_H
  9. #define CPPCMS_HTTP_PARSER_H
  10. #include "http_protocol.h"
  11. #include <vector>
  12. #include <string>
  13. #include <stack>
  14. #ifdef getc
  15. #undef getc
  16. #endif
  17. namespace cppcms {
  18. namespace http {
  19. namespace impl {
  20. class parser {
  21. enum {
  22. idle,
  23. input_observed,
  24. last_lf_exptected,
  25. lf_exptected,
  26. space_or_other_exptected,
  27. quote_expected,
  28. pass_quote_exptected,
  29. closing_bracket_expected,
  30. pass_closing_bracket_expected
  31. } state_;
  32. unsigned bracket_counter_;
  33. std::vector<char> *body_;
  34. unsigned *body_ptr_;
  35. char const **pbase_,**pptr_,**epptr_;
  36. std::stack<char> ungot_;
  37. // Non copyable
  38. parser(parser const &);
  39. parser const &operator=(parser const &);
  40. protected:
  41. inline int getc()
  42. {
  43. if(!ungot_.empty()) {
  44. unsigned char r=ungot_.top();
  45. ungot_.pop();
  46. return r;
  47. }
  48. if(body_) {
  49. if(*body_ptr_ < body_->size()) {
  50. return (unsigned char)(*body_)[(*body_ptr_)++];
  51. }
  52. else {
  53. body_->clear();
  54. *body_ptr_=0;
  55. return -1;
  56. }
  57. }
  58. else {
  59. if(*pptr_ != *epptr_) {
  60. unsigned char c = *(*pptr_)++;
  61. return c;
  62. }
  63. else {
  64. return -1;
  65. }
  66. }
  67. }
  68. inline void ungetc(int c)
  69. {
  70. if(body_) {
  71. if(*body_ptr_ > 0)
  72. (*body_ptr_)--;
  73. else
  74. ungot_.push(c);
  75. }
  76. else {
  77. if(*pbase_!=*pptr_)
  78. (*pptr_)--;
  79. else
  80. ungot_.push(c);
  81. }
  82. }
  83. public:
  84. std::string header_;
  85. parser(std::vector<char> &body,unsigned &body_ptr) :
  86. state_(idle),
  87. bracket_counter_(0),
  88. body_(&body),
  89. body_ptr_(&body_ptr),
  90. pbase_(0),
  91. pptr_(0),
  92. epptr_(0)
  93. {
  94. header_.reserve(32);
  95. }
  96. parser(char const *&pbase,char const *&pptr,char const *&epptr) :
  97. state_(idle),
  98. bracket_counter_(0),
  99. body_(0),
  100. body_ptr_(0),
  101. pbase_(&pbase),
  102. pptr_(&pptr),
  103. epptr_(&epptr)
  104. {
  105. header_.reserve(32);
  106. }
  107. void reset()
  108. {
  109. state_ = idle;
  110. bracket_counter_ = 0;
  111. header_.clear();
  112. }
  113. enum { more_data, got_header, end_of_headers , error_observerd };
  114. int step()
  115. {
  116. #ifdef DEBUG_HTTP_PARSER
  117. static char const *states[]= {
  118. "idle",
  119. "input_observed",
  120. "last_lf_exptected",
  121. "lf_exptected",
  122. "space_or_other_exptected",
  123. "quote_expected",
  124. "pass_quote_exptected",
  125. "closing_bracket_expected",
  126. "pass_closing_bracket_expected"
  127. };
  128. #endif
  129. for(;;) {
  130. int c=getc();
  131. #if defined DEBUG_HTTP_PARSER
  132. std::cerr<<"Step("<<body_ptr_<<":"<<body_.size()<<": "<<std::flush;
  133. if(c>=32)
  134. std::cerr<<"["<<char(c)<<"] "<<states[state_]<<std::endl;
  135. else
  136. std::cerr<<c<<" "<<states[state_]<<std::endl;
  137. #endif
  138. if(c<0)
  139. return more_data;
  140. switch(state_) {
  141. case idle:
  142. header_.clear();
  143. switch(c) {
  144. case '\r':
  145. state_=last_lf_exptected;
  146. break;
  147. case '"':
  148. state_=quote_expected;
  149. break;
  150. case '(':
  151. state_=closing_bracket_expected;
  152. bracket_counter_++;
  153. break;
  154. default:
  155. state_=input_observed;
  156. }
  157. break;
  158. case last_lf_exptected:
  159. if(c!='\n') return error_observerd;
  160. header_.clear();
  161. return end_of_headers;
  162. case lf_exptected:
  163. if(c!='\n') return error_observerd;
  164. state_=space_or_other_exptected;
  165. break;
  166. case space_or_other_exptected:
  167. if(c==' ' || c=='\t') {
  168. // Convert LWS to space as required by
  169. // RFC, so remove last CRLF
  170. header_.resize(header_.size() - 2);
  171. state_=input_observed;
  172. break;
  173. }
  174. ungetc(c);
  175. header_.resize(header_.size()-2);
  176. state_=idle;
  177. #ifdef DEBUG_HTTP_PARSER
  178. std::cerr<<"["<<header_<<"]"<<std::endl;
  179. #endif
  180. return got_header;
  181. case input_observed:
  182. switch(c) {
  183. case '\r':
  184. state_=lf_exptected;
  185. break;
  186. case '"':
  187. state_=quote_expected;
  188. break;
  189. case '(':
  190. state_=closing_bracket_expected;
  191. bracket_counter_++;
  192. break;
  193. default:
  194. state_=input_observed;
  195. }
  196. break;
  197. case quote_expected:
  198. switch(c) {
  199. case '"':
  200. state_=input_observed;
  201. break;
  202. case '\\':
  203. state_=pass_quote_exptected;
  204. break;
  205. }
  206. break;
  207. case pass_quote_exptected:
  208. if(c < 0 || c >=127)
  209. return error_observerd;
  210. state_=quote_expected;
  211. break;
  212. case closing_bracket_expected:
  213. switch(c) {
  214. case ')':
  215. bracket_counter_--;
  216. if(bracket_counter_==0)
  217. state_=input_observed;
  218. break;
  219. case '\\':
  220. state_=pass_closing_bracket_expected;
  221. break;
  222. }
  223. break;
  224. case pass_closing_bracket_expected:
  225. if(c < 0 || c >=127)
  226. return error_observerd;
  227. state_=closing_bracket_expected;
  228. break;
  229. }
  230. header_+=char(c);
  231. /* switch(state_) {
  232. case idle:
  233. case input_observed:
  234. case last_lf_exptected:
  235. case lf_exptected:
  236. case space_or_other_exptected:
  237. if(separator(c)) {
  238. parsed_.push_back(element_type(c,std::string()));
  239. }
  240. else if(0x20 <= c && c<=0x7E) {
  241. if(parsed_.empty() || parsed_.back().first != token_element) {
  242. parsed.push_back(element_type(token_element,std::string()));
  243. }
  244. parsed.back().second+=c;
  245. }
  246. break;
  247. default:
  248. ; // Nothing
  249. }*/
  250. }
  251. }
  252. }; // class parser
  253. }}} // cppcms::http::impl
  254. #endif