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.
 
 
 
 
 
 

941 lines
35 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_URL_DISPATCHER_H
  9. #define CPPCMS_URL_DISPATCHER_H
  10. #include <booster/noncopyable.h>
  11. #include <cppcms/defs.h>
  12. #include <booster/function.h>
  13. #include <booster/hold_ptr.h>
  14. #include <booster/traits/enable_if.h>
  15. #include <booster/traits/is_base_of.h>
  16. #include <booster/traits/type_traits.h>
  17. #include <booster/regex.h>
  18. #include <cppcms/application.h>
  19. #include <cppcms/steal_buf.h>
  20. #include <string>
  21. #include <list>
  22. namespace cppcms {
  23. ///
  24. /// Sets the content of parameter to output
  25. ///
  26. /// \ver{v1_2}
  27. inline bool parse_url_parameter(util::const_char_istream &parameter,std::string &output)
  28. {
  29. output.assign(parameter.begin(),parameter.end());
  30. return true;
  31. }
  32. ///
  33. /// Parses general value
  34. ///
  35. /// \ver{v1_2}
  36. template<typename ParamType>
  37. bool parse_url_parameter(util::const_char_istream &parameter,ParamType &value)
  38. {
  39. parameter >> value;
  40. if(!parameter || !parameter.eof())
  41. return false;
  42. return true;
  43. }
  44. ///
  45. /// \brief This class is used to glue between member function of application class and urls
  46. ///
  47. /// This class is used in context of \a cppcms::application with its \a url member function.
  48. /// It uses regular expression to bind between url and callbacks that actually process the
  49. /// request. It also allows mount sub-applications to the root of
  50. /// the primary application.
  51. ///
  52. /// There are two families of functions, assign and map.
  53. /// Older `assign` interface allows matching only URL against regular expression.
  54. /// and passes std::string as parameter. All the validation must be
  55. /// performed by regular expression or the code that was called.
  56. ///
  57. /// Newer `map` interface allows both matching an URL and an HTTP request method.
  58. /// Parameters are parsed using `bool parse_url_parameter(util::const_char_istream &parameter,Type &param)`
  59. /// that by default uses std::istream to perform casting.
  60. ///
  61. /// Additionally every matched parameter is checked to contain valid text encoding
  62. ///
  63. /// Newer API uses map member functions family that was introduced in CppCMS 1.1.
  64. ///
  65. /// For example:
  66. ///
  67. /// \code
  68. /// class my_web_project : public cppcms::application {
  69. /// users_app users_;
  70. /// /* Older Handlers */
  71. /// void display_page(std::string)
  72. /// ...
  73. /// /* Newer CppCMS 1.1 handlers */
  74. /// void get_resource(int id);
  75. /// void update_resource(int id);
  76. /// void new_resource();
  77. /// void id_by_name(std::string const &name); /* name checked for valid encoding */
  78. /// void display_page_by_id(int id)
  79. /// public:
  80. /// my_web_project() {
  81. /// /* Older API */
  82. /// dispatcher().assign("/page/(\\d+)/?",&my_web_project::display_page,this,1);
  83. ///
  84. /// /* New API - CppCMS 1.1 and above */
  85. ///
  86. /// dispatcher().map("GET","/resource/(\\d+)",&my_web_project::get_resource,this,1);
  87. /// dispatcher().map("PUT","/resource/(\\d+)",&my_web_project::update_resource,this,1);
  88. /// dispatcher().map("POST","/resources",&my_web_project::new_resource,this);
  89. /// dispatcher().map("GET"."/id_by_name/(.*)",&my_web_project::id_by_name,this,1);
  90. /// dispatcher().map("/page/(\\d+)",&my_web_project::display_page_by_id,this,1); /* any method */
  91. /// ...
  92. /// \endcode
  93. ///
  94. ///
  95. class CPPCMS_API url_dispatcher : public booster::noncopyable {
  96. public:
  97. ///
  98. /// \brief RESTful API Handler that validates parameters and executes a method.
  99. ///
  100. /// If validation fails it should return false and thus the matching would continue to next handler
  101. ///
  102. /// \ver{v1_2}
  103. typedef booster::function<bool(cppcms::application &,booster::cmatch const &)> generic_handler;
  104. // Handlers
  105. typedef booster::function<void()> handler;
  106. typedef booster::function<void(booster::cmatch const &)> rhandler;
  107. typedef booster::function<void(std::string)> handler1;
  108. typedef booster::function<void(std::string,std::string)> handler2;
  109. typedef booster::function<void(std::string,std::string,std::string)> handler3;
  110. typedef booster::function<void(std::string,std::string,std::string,std::string)> handler4;
  111. typedef booster::function<void(std::string,std::string,std::string,std::string,std::string)> handler5;
  112. typedef booster::function<void(std::string,std::string,std::string,std::string,std::string,std::string)> handler6;
  113. ///
  114. /// Map a callback \a h to a URL matching regular expression \a re and an HTTP \a method
  115. ///
  116. /// \param method - HTTP method to match like GET, POST, note regular expression can be used as well, for example "(POST|PUT)"
  117. /// \param re - regular expression to match the URL
  118. /// \param h - handler to execute
  119. ///
  120. /// \ver{v1_2}
  121. void map_generic(std::string const &method,booster::regex const &re,generic_handler const &h);
  122. ///
  123. /// Map a callback \a h to a URL matching regular expression \a re
  124. ///
  125. /// \param re - regular expression to match the URL
  126. /// \param h - handler to execute
  127. ///
  128. /// \ver{v1_2}
  129. void map_generic(booster::regex const &re,generic_handler const &h);
  130. #ifdef CPPCMS_DOXYGEN_DOCS
  131. ///
  132. /// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re and HTTP method \a method
  133. ///
  134. /// \param method - HTTP method to match like GET, POST, note regular expression can be used as well, for example "(POST|PUT)"
  135. /// \param re - regular expression to match the URL
  136. /// \param member - member function of application \a app
  137. /// \param app - application that its \a member is called
  138. /// \param groups - matched groups converted to ApplicationMemberArgs
  139. ///
  140. /// Note:
  141. ///
  142. /// - number of integers in \a groups should match the number of arguments of \a member
  143. /// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
  144. ///
  145. /// For exaample
  146. /// \code
  147. /// class foo : public cppcms::application {
  148. /// ...
  149. /// void page(int x,std::string const &name);
  150. /// void update(int x);
  151. /// foo(...)
  152. /// {
  153. /// dispatcher().map("GET","/page/(\\d+)(/(.*))?",&foo::page,this,1,3);
  154. /// dispatcher().map("POST","/update/(\\d+)",&foo::update,this,1);
  155. /// }
  156. /// \endcode
  157. ///
  158. /// When the reuqest matches the \a method and regualr expression \a re, \a member of \a app is called, For case of `page` that has two
  159. /// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
  160. ///
  161. /// In case of `update` - that has only 1 parameter, a single integer should be passed
  162. ///
  163. /// In addition to calling \a member function it calls app->init() before call
  164. /// and app->clean() after the call if Application is derived from cppcms::application
  165. ///
  166. ///
  167. /// \ver{v1_2}
  168. template<typename Application,typename... ApplicationMemberArgs>
  169. void map(std::string const &method,std::string const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );
  170. ///
  171. /// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re
  172. ///
  173. /// \param re - regular expression to match the URL
  174. /// \param member - member function of application \a app
  175. /// \param app - application that its \a member is called
  176. /// \param groups - matched groups converted to ApplicationMemberArgs
  177. ///
  178. /// Note:
  179. ///
  180. /// - number of integers in \a groups should match the number of arguments of \a member
  181. /// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
  182. ///
  183. /// For exaample
  184. /// \code
  185. /// class foo : public cppcms::application {
  186. /// ...
  187. /// void page(int x,std::string const &name);
  188. /// void update(int x);
  189. /// foo(...)
  190. /// {
  191. /// dispatcher().map("/page/(\\d+)(/(.*))?",&foo::page,this,1,3);
  192. /// dispatcher().map("/update/(\\d+)",&foo::update,this,1);
  193. /// }
  194. /// \endcode
  195. ///
  196. /// When the reuqest URL the regualr expression \a re, \a member of \a app is called, For case of `page` that has two
  197. /// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
  198. ///
  199. /// In case of `update` - that has only 1 parameter, a single integer should be passed
  200. ///
  201. /// In addition to calling \a member function it calls app->init() before call
  202. /// and app->clean() after the call if Application is derived from cppcms::application
  203. ///
  204. ///
  205. /// \ver{v1_2}
  206. template<typename Application,typename... ApplicationMemberArgs>
  207. void map(std::string const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );
  208. ///
  209. /// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re and HTTP method \a method
  210. ///
  211. /// \param method - HTTP method to match like GET, POST, note regular expression can be used as well, for example "(POST|PUT)"
  212. /// \param re - regular expression to match the URL
  213. /// \param member - member function of application \a app
  214. /// \param app - application that its \a member is called
  215. /// \param groups - matched groups converted to ApplicationMemberArgs
  216. ///
  217. /// Note:
  218. ///
  219. /// - number of integers in \a groups should match the number of arguments of \a member
  220. /// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
  221. ///
  222. /// For exaample
  223. /// \code
  224. /// class foo : public cppcms::application {
  225. /// ...
  226. /// void page(int x,std::string const &name);
  227. /// void update(int x);
  228. /// foo(...)
  229. /// {
  230. /// using booster::regex;
  231. /// dispatcher().map(regex("/page/(\\d+)(/(.*))?",regex::icase),&foo::page,this,1,3);
  232. /// dispatcher().map("POST","/update/(\\d+)",&foo::update,this,1);
  233. /// }
  234. /// \endcode
  235. ///
  236. /// When the reuqest matches the \a method and regualr expression \a re, \a member of \a app is called, For case of `page` that has two
  237. /// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
  238. ///
  239. /// In case of `update` - that has only 1 parameter, a single integer should be passed
  240. ///
  241. /// In addition to calling \a member function it calls app->init() before call
  242. /// and app->clean() after the call if Application is derived from cppcms::application
  243. ///
  244. ///
  245. /// \ver{v1_2}
  246. template<typename Application,typename... ApplicationMemberArgs>
  247. void map(std::string const &method,booster::regex const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );
  248. ///
  249. /// \brief Map \a member of \a app as a URL handler that matches regualr expression \a re
  250. ///
  251. /// \param re - regular expression to match the URL
  252. /// \param member - member function of application \a app
  253. /// \param app - application that its \a member is called
  254. /// \param groups - matched groups converted to ApplicationMemberArgs
  255. ///
  256. /// Note:
  257. ///
  258. /// - number of integers in \a groups should match the number of arguments of \a member
  259. /// - \a member can have up to 8 arguments MemberArgs and the function should receive same number of integer parameters representing matched groups
  260. ///
  261. /// For exaample
  262. /// \code
  263. /// class foo : public cppcms::application {
  264. /// ...
  265. /// void page(int x,std::string const &name);
  266. /// void update(int x);
  267. /// foo(...)
  268. /// {
  269. /// using booster::regex;
  270. /// dispatcher().map(regex("/page/(\\d+)(/(.*))?",regex::icase),&foo::page,this,1,3);
  271. /// dispatcher().map("/update/(\\d+)",&foo::update,this,1);
  272. /// }
  273. /// \endcode
  274. ///
  275. /// When the reuqest URL the regualr expression \a re, \a member of \a app is called, For case of `page` that has two
  276. /// parameters the first matched group is converted to integer and passed to as first parameter and 3rd group is passed as string to 2nd parameter
  277. ///
  278. /// In case of `update` - that has only 1 parameter, a single integer should be passed
  279. ///
  280. /// In addition to calling \a member function it calls app->init() before call
  281. /// and app->clean() after the call if Application is derived from cppcms::application
  282. ///
  283. ///
  284. /// \ver{v1_2}
  285. template<typename Application,typename... ApplicationMemberArgs>
  286. void map(booster::regex const &re,void (Application::*member)(ApplicationMemberArgs...),Application *app, int ... groups );
  287. #endif
  288. ///
  289. /// Assign \a handler to pattern \a regex thus if URL that matches
  290. /// this pattern requested, \a handler is called with matched results
  291. ///
  292. void assign_generic(std::string const &regex,rhandler handler);
  293. ///
  294. /// Assign \a handler to pattern \a regex thus if URL that matches
  295. /// this pattern requested, \a handler is called
  296. ///
  297. void assign(std::string const &regex,handler handler);
  298. ///
  299. /// Assign \a handler to pattern \a regex thus if URL that matches
  300. /// this pattern requested, \a handler is called with first parameters
  301. /// the string that was matched at position \a exp1.
  302. ///
  303. /// For example: if
  304. /// regular expression is "^/page/(\\d+)/(\\w+)$" , exp1=2, and the url is
  305. /// "/page/13/to_be_or_not", then handler would be called with "to_be_or_not"
  306. /// as its first parameter
  307. ///
  308. void assign(std::string const &regex,handler1 handler,int exp1);
  309. ///
  310. /// Assign \a handler to pattern \a regex thus if URL that matches
  311. /// this pattern requested, \a handler is called with 1st and 2nd parameters
  312. /// the string that was matched at position \a exp1 and \a exp2
  313. ///
  314. void assign(std::string const &regex,handler2 handler,int exp1,int exp2);
  315. ///
  316. /// Assign \a handler to pattern \a regex thus if URL that matches
  317. /// this pattern requested, \a handler is called with 1st, 2nd and 3rd parameters
  318. /// the string that was matched at position \a exp1, \a exp2 and \a exp2
  319. ///
  320. void assign(std::string const &regex,handler3 handler,int exp1,int exp2,int exp3);
  321. ///
  322. /// Assign \a handler to pattern \a regex thus if URL that matches
  323. /// this pattern requested, \a handler is called with 1st, 2nd, 3rd and 4th parameters
  324. /// the string that was matched at position \a exp1, \a exp2, \a exp3 and \a exp4
  325. ///
  326. void assign(std::string const &regex,handler4 handler,int exp1,int exp2,int exp3,int exp4);
  327. ///
  328. /// Assign \a handler to pattern \a regex thus if URL that matches
  329. /// this pattern requested, \a handler is called with 1st, 2nd, 3rd, 4th and 5th parameters
  330. /// the string that was matched at position \a exp1, \a exp2, \a exp3, \a exp4 and \a exp5
  331. ///
  332. /// \ver{v1_2}
  333. void assign(std::string const &regex,handler5 handler,int exp1,int exp2,int exp3,int exp4,int exp5);
  334. ///
  335. /// Assign \a handler to pattern \a regex thus if URL that matches
  336. /// this pattern requested, \a handler is called with 1st, 2nd, 3rd, 4th, 5th and 6th parameters
  337. /// the string that was matched at position \a exp1, \a exp2, \a exp3, \a exp4, \a exp 5 and \a exp6
  338. ///
  339. /// \ver{v1_2}
  340. void assign(std::string const &regex,handler6 handler,int exp1,int exp2,int exp3,int exp4,int exp5,int exp6);
  341. ///
  342. /// Try to find match between \a url and registered handlers and applications.
  343. /// If the match was found, it returns the method, how handler should bd dispatched
  344. /// synchronous or asynchronous, meaning the handler would be executed in thread pool
  345. /// or in the main non-blocking loop
  346. ///
  347. bool dispatch(std::string url);
  348. /// \cond INTERNAL
  349. url_dispatcher(application *app);
  350. url_dispatcher();
  351. ~url_dispatcher();
  352. /// \endcond
  353. ///
  354. /// This template function is a shortcut to assign(regex,callback). It allows
  355. /// assignment of \a member function of an \a object with signature void handler()
  356. /// as simple as assign(expr,&bar::foo,this);
  357. ///
  358. /// In addition to calling \a member function it calls object->init() before call
  359. /// and object->clean() after the call of the C is derived from cppcms::application
  360. ///
  361. template<typename C>
  362. void assign(std::string const &regex,void (C::*member)(),C *object)
  363. {
  364. assign(regex,binder0<C>(member,object));
  365. }
  366. ///
  367. /// This template function is a shortcut to assign_generic(regex,rhandler). It allows
  368. /// assignment of \a member function of an \a object with signature void handler(booster::cmatch const &)
  369. ///
  370. /// In addition to calling \a member function it calls object->init() before call
  371. /// and object->clean() after the call of the C is derived from cppcms::application
  372. ///
  373. /// \ver{v1_2}
  374. template<typename C>
  375. void assign_generic(std::string const &regex,void (C::*member)(booster::cmatch const &),C *object)
  376. {
  377. assign_generic(regex,rbinder<C>(member,object));
  378. }
  379. ///
  380. /// This template function is a shortcut to assign(regex,callback,int). It allows
  381. /// assignment of \a member function of an \a object with signature void handler(string)
  382. ///
  383. /// In addition to calling \a member function it calls object->init() before call
  384. /// and object->clean() after the call of the C is derived from cppcms::application
  385. ///
  386. template<typename C>
  387. void assign(std::string const &regex,void (C::*member)(std::string),C *object,int e1)
  388. {
  389. assign(regex,binder1<C>(member,object),e1);
  390. }
  391. ///
  392. /// This template function is a shortcut to assign(regex,callback,int,int). It allows
  393. /// assignment of \a member function of an \a object with signature void handler(string,string)
  394. ///
  395. /// In addition to calling \a member function it calls object->init() before call
  396. /// and object->clean() after the call of the C is derived from cppcms::application
  397. ///
  398. template<typename C>
  399. void assign(std::string const &regex,void (C::*member)(std::string,std::string),C *object,int e1,int e2)
  400. {
  401. assign(regex,binder2<C>(member,object),e1,e2);
  402. }
  403. template<typename C>
  404. ///
  405. /// This template function is a shortcut to assign(regex,callback,int,int,int). It allows
  406. /// assignment of \a member function of an \a object with signature void handler(string,string,string)
  407. ///
  408. /// In addition to calling \a member function it calls object->init() before call
  409. /// and object->clean() after the call of the C is derived from cppcms::application
  410. ///
  411. void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string),C *object,int e1,int e2,int e3)
  412. {
  413. assign(regex,binder3<C>(member,object),e1,e2,e3);
  414. }
  415. ///
  416. /// This template function is a shortcut to assign(regex,callback,int,int,int,int). It allows
  417. /// assignment of \a member function of an \a object with signature void handler(string,string,string,string)
  418. ///
  419. /// In addition to calling \a member function it calls object->init() before call
  420. /// and object->clean() after the call of the C is derived from cppcms::application
  421. ///
  422. template<typename C>
  423. void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string,std::string),C *object,int e1,int e2,int e3,int e4)
  424. {
  425. assign(regex,binder4<C>(member,object),e1,e2,e3,e4);
  426. }
  427. ///
  428. /// This template function is a shortcut to assign(regex,callback,int,int,int,int,int). It allows
  429. /// assignment of \a member function of an \a object with signature void handler(string,string,string,string,string)
  430. ///
  431. /// In addition to calling \a member function it calls object->init() before call
  432. /// and object->clean() after the call of the C is derived from cppcms::application
  433. ///
  434. /// \ver{v1_2}
  435. template<typename C>
  436. void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string,std::string,std::string),C *object,int e1,int e2,int e3,int e4,int e5)
  437. {
  438. assign(regex,binder5<C>(member,object),e1,e2,e3,e4,e5);
  439. }
  440. ///
  441. /// This template function is a shortcut to assign(regex,callback,int,int,int,int,int,int). It allows
  442. /// assignment of \a member function of an \a object with signature void handler(string,string,string,string,string,string)
  443. ///
  444. /// In addition to calling \a member function it calls object->init() before call
  445. /// and object->clean() after the call of the C is derived from cppcms::application
  446. ///
  447. /// \ver{v1_2}
  448. template<typename C>
  449. void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string,std::string,std::string,std::string),C *object,int e1,int e2,int e3,int e4,int e5,int e6)
  450. {
  451. assign(regex,binder6<C>(member,object),e1,e2,e3,e4,e5,e6);
  452. }
  453. ///
  454. /// Mount a sub application \a app to the URL dispatcher, using regular expression match.
  455. ///
  456. /// When mounted the URL is checked against match expression and then calls app.main(substr) where
  457. /// substr is the matched subexpression part. For example:
  458. ///
  459. /// \code
  460. /// dispatcher().mount("/formums((/.*)?)",forums,1);
  461. /// \endcode
  462. ///
  463. /// For example: for url /forums/page/3 it would call \c forums::main with value "/page/3"
  464. ///
  465. void mount(std::string const &match,application &app,int part);
  466. private:
  467. template<typename C,typename Enable = void>
  468. class page_guard {
  469. public:
  470. page_guard(C * /*o*/) {}
  471. page_guard(C * /*o*/,std::istream &) {}
  472. application *app() { return 0; }
  473. };
  474. template<typename C>
  475. class page_guard<C,typename booster::enable_if<booster::is_base_of< cppcms::application,C> >::type > {
  476. public:
  477. page_guard(C *o) :
  478. object_(o)
  479. {
  480. object_->init();
  481. }
  482. application *app() { return object_; }
  483. ~page_guard()
  484. {
  485. object_->clear();
  486. }
  487. private:
  488. application *object_;
  489. };
  490. template<typename C>
  491. struct binder0{
  492. typedef void (C::*member_type)();
  493. member_type member;
  494. C *object;
  495. binder0(member_type m,C *o) :
  496. member(m),
  497. object(o)
  498. {
  499. }
  500. void operator()() const
  501. {
  502. page_guard<C> guard(object);
  503. (object->*member)();
  504. }
  505. };
  506. template<typename C>
  507. struct rbinder{
  508. typedef void (C::*member_type)(booster::cmatch const &);
  509. member_type member;
  510. C *object;
  511. rbinder(member_type m,C *o) :
  512. member(m),
  513. object(o)
  514. {
  515. }
  516. void operator()(booster::cmatch const &p1) const
  517. {
  518. page_guard<C> guard(object);
  519. (object->*member)(p1);
  520. }
  521. };
  522. template<typename C>
  523. struct binder1{
  524. typedef void (C::*member_type)(std::string);
  525. member_type member;
  526. C *object;
  527. binder1(member_type m,C *o) :
  528. member(m),
  529. object(o)
  530. {
  531. }
  532. void operator()(std::string p1) const
  533. {
  534. page_guard<C> guard(object);
  535. (object->*member)(p1);
  536. }
  537. };
  538. template<typename C>
  539. struct binder2{
  540. typedef void (C::*member_type)(std::string,std::string);
  541. member_type member;
  542. C *object;
  543. binder2(member_type m,C *o) :
  544. member(m),
  545. object(o)
  546. {
  547. }
  548. void operator()(std::string p1,std::string p2) const
  549. {
  550. page_guard<C> guard(object);
  551. (object->*member)(p1,p2);
  552. }
  553. };
  554. template<typename C>
  555. struct binder3{
  556. typedef void (C::*member_type)(std::string,std::string,std::string);
  557. member_type member;
  558. C *object;
  559. binder3(member_type m,C *o) :
  560. member(m),
  561. object(o)
  562. {
  563. }
  564. void operator()(std::string p1,std::string p2,std::string p3) const
  565. {
  566. page_guard<C> guard(object);
  567. (object->*member)(p1,p2,p3);
  568. }
  569. };
  570. template<typename C>
  571. struct binder4{
  572. typedef void (C::*member_type)(std::string,std::string,std::string,std::string);
  573. member_type member;
  574. C *object;
  575. binder4(member_type m,C *o) :
  576. member(m),
  577. object(o)
  578. {
  579. }
  580. void operator()(std::string p1,std::string p2,std::string p3,std::string p4) const
  581. {
  582. page_guard<C> guard(object);
  583. (object->*member)(p1,p2,p3,p4);
  584. }
  585. };
  586. template<typename C>
  587. struct binder5{
  588. typedef void (C::*member_type)(std::string,std::string,std::string,std::string,std::string);
  589. member_type member;
  590. C *object;
  591. binder5(member_type m,C *o) :
  592. member(m),
  593. object(o)
  594. {
  595. }
  596. void operator()(std::string p1,std::string p2,std::string p3,std::string p4,std::string p5) const
  597. {
  598. page_guard<C> guard(object);
  599. (object->*member)(p1,p2,p3,p4,p5);
  600. }
  601. };
  602. static bool validate_encoding(application &app,char const *begin,char const *end);
  603. static void setup_stream(application &app,std::istream &s);
  604. template<typename C>
  605. struct binder6{
  606. typedef void (C::*member_type)(std::string,std::string,std::string,std::string,std::string,std::string);
  607. member_type member;
  608. C *object;
  609. binder6(member_type m,C *o) :
  610. member(m),
  611. object(o)
  612. {
  613. }
  614. void operator()(std::string p1,std::string p2,std::string p3,std::string p4,std::string p5,std::string p6) const
  615. {
  616. page_guard<C> guard(object);
  617. (object->*member)(p1,p2,p3,p4,p5,p6);
  618. }
  619. };
  620. template<typename T>
  621. static bool parse(application &app,util::const_char_istream &p,booster::cmatch const &m,int group,T &v)
  622. {
  623. if(!validate_encoding(app,m[group].first,m[group].second))
  624. return false;
  625. p.range(m[group].first,m[group].second);
  626. return parse_url_parameter(p,v);
  627. }
  628. template<typename F>
  629. struct url_binder;
  630. #define CPPCMS_DEFANDPARSE(N) typename booster::remove_const_reference<P##N>::type p##N; \
  631. if(!parse(app,s,m,g##N,p##N)) return false;
  632. #define CPPCMS_DEFANDPARSE2(N1,N2) CPPCMS_DEFANDPARSE(N1) CPPCMS_DEFANDPARSE(N2)
  633. #define CPPCMS_DEFANDPARSE3(N1,N2,N3) CPPCMS_DEFANDPARSE(N1) CPPCMS_DEFANDPARSE2(N2,N3)
  634. #define CPPCMS_DEFANDPARSE4(N1,N2,N3,N4) CPPCMS_DEFANDPARSE2(N1,N2) CPPCMS_DEFANDPARSE2(N3,N4)
  635. #define CPPCMS_DEFANDPARSE5(N1,N2,N3,N4,N5) CPPCMS_DEFANDPARSE2(N1,N2) CPPCMS_DEFANDPARSE3(N3,N4,N5)
  636. #define CPPCMS_URLBINDER \
  637. private: \
  638. template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
  639. struct url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> { \
  640. typedef void (C::*member_type)(CPPCMS_URLBINDER_MPAR); \
  641. member_type member; C *self; \
  642. CPPCMS_URLBINDER_GPAR \
  643. url_binder( \
  644. member_type m,C *s CPPCMS_URLBINDER_PRD \
  645. CPPCMS_URLBINDER_IPAR \
  646. ) : member(m), \
  647. self(s) CPPCMS_URLBINDER_PRD \
  648. CPPCMS_URLBINDER_CPAR \
  649. {} \
  650. bool operator()(application &CPPCMS_URLBINDER_P1,booster::cmatch const &CPPCMS_URLBINDER_P2) { \
  651. CPPCMS_URLBINDER_INIT CPPCMS_URLBINDER_PARSE \
  652. page_guard<C> guard(self); \
  653. (self->*member)(CPPCMS_URLBINDER_PPAR); \
  654. return true; \
  655. } \
  656. }; \
  657. public: \
  658. template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
  659. void map(std::string const &me,std::string const &re, \
  660. void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
  661. CPPCMS_URLBINDER_IPAR) \
  662. { \
  663. typedef url_binder<void(C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
  664. map_generic(me,re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
  665. } \
  666. template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
  667. void map(std::string const &re, \
  668. void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
  669. CPPCMS_URLBINDER_IPAR) \
  670. { \
  671. typedef url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
  672. map_generic(re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
  673. } \
  674. template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
  675. void map(std::string const &me,booster::regex const &re, \
  676. void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
  677. CPPCMS_URLBINDER_IPAR) \
  678. { \
  679. typedef url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
  680. map_generic(me,re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
  681. } \
  682. template<typename C CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_TPAR> \
  683. void map(booster::regex const &re, \
  684. void (C::*mb)(CPPCMS_URLBINDER_MPAR),C *app CPPCMS_URLBINDER_PRD \
  685. CPPCMS_URLBINDER_IPAR) \
  686. { \
  687. typedef url_binder<void (C::*)(CPPCMS_URLBINDER_MPAR)> btype; \
  688. map_generic(re,btype(mb,app CPPCMS_URLBINDER_PRD CPPCMS_URLBINDER_PPAR)); \
  689. } \
  690. private:
  691. #define CPPCMS_URLBINDER_PRD
  692. #define CPPCMS_URLBINDER_INIT
  693. #define CPPCMS_URLBINDER_TPAR
  694. #define CPPCMS_URLBINDER_MPAR
  695. #define CPPCMS_URLBINDER_PPAR
  696. #define CPPCMS_URLBINDER_GPAR
  697. #define CPPCMS_URLBINDER_IPAR
  698. #define CPPCMS_URLBINDER_CPAR
  699. #define CPPCMS_URLBINDER_PARSE
  700. #define CPPCMS_URLBINDER_P1
  701. #define CPPCMS_URLBINDER_P2
  702. CPPCMS_URLBINDER
  703. #undef CPPCMS_URLBINDER_TPAR
  704. #undef CPPCMS_URLBINDER_MPAR
  705. #undef CPPCMS_URLBINDER_PPAR
  706. #undef CPPCMS_URLBINDER_GPAR
  707. #undef CPPCMS_URLBINDER_IPAR
  708. #undef CPPCMS_URLBINDER_CPAR
  709. #undef CPPCMS_URLBINDER_PARSE
  710. #undef CPPCMS_URLBINDER_INIT
  711. #undef CPPCMS_URLBINDER_PRD
  712. #undef CPPCMS_URLBINDER_P1
  713. #undef CPPCMS_URLBINDER_P2
  714. #define CPPCMS_URLBINDER_PRD ,
  715. #define CPPCMS_URLBINDER_INIT util::const_char_istream s; setup_stream(app,s);
  716. #define CPPCMS_URLBINDER_P1 app
  717. #define CPPCMS_URLBINDER_P2 m
  718. #define CPPCMS_URLBINDER_TPAR typename P1
  719. #define CPPCMS_URLBINDER_MPAR P1
  720. #define CPPCMS_URLBINDER_PPAR p1
  721. #define CPPCMS_URLBINDER_GPAR int g1;
  722. #define CPPCMS_URLBINDER_IPAR int p1
  723. #define CPPCMS_URLBINDER_CPAR g1(p1)
  724. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE(1)
  725. CPPCMS_URLBINDER
  726. #undef CPPCMS_URLBINDER_TPAR
  727. #undef CPPCMS_URLBINDER_MPAR
  728. #undef CPPCMS_URLBINDER_PPAR
  729. #undef CPPCMS_URLBINDER_GPAR
  730. #undef CPPCMS_URLBINDER_IPAR
  731. #undef CPPCMS_URLBINDER_CPAR
  732. #undef CPPCMS_URLBINDER_PARSE
  733. #define CPPCMS_URLBINDER_TPAR typename P1,typename P2
  734. #define CPPCMS_URLBINDER_MPAR P1,P2
  735. #define CPPCMS_URLBINDER_PPAR p1,p2
  736. #define CPPCMS_URLBINDER_GPAR int g1,g2;
  737. #define CPPCMS_URLBINDER_IPAR int p1,int p2
  738. #define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2)
  739. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE2(1,2)
  740. CPPCMS_URLBINDER
  741. #undef CPPCMS_URLBINDER_TPAR
  742. #undef CPPCMS_URLBINDER_MPAR
  743. #undef CPPCMS_URLBINDER_PPAR
  744. #undef CPPCMS_URLBINDER_GPAR
  745. #undef CPPCMS_URLBINDER_IPAR
  746. #undef CPPCMS_URLBINDER_CPAR
  747. #undef CPPCMS_URLBINDER_PARSE
  748. #define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3
  749. #define CPPCMS_URLBINDER_MPAR P1,P2,P3
  750. #define CPPCMS_URLBINDER_PPAR p1,p2,p3
  751. #define CPPCMS_URLBINDER_GPAR int g1,g2,g3;
  752. #define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3
  753. #define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3)
  754. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE3(1,2,3)
  755. CPPCMS_URLBINDER
  756. #undef CPPCMS_URLBINDER_TPAR
  757. #undef CPPCMS_URLBINDER_MPAR
  758. #undef CPPCMS_URLBINDER_PPAR
  759. #undef CPPCMS_URLBINDER_GPAR
  760. #undef CPPCMS_URLBINDER_IPAR
  761. #undef CPPCMS_URLBINDER_CPAR
  762. #undef CPPCMS_URLBINDER_PARSE
  763. #define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4
  764. #define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4
  765. #define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4
  766. #define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4;
  767. #define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4
  768. #define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4)
  769. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE4(1,2,3,4)
  770. CPPCMS_URLBINDER
  771. #undef CPPCMS_URLBINDER_TPAR
  772. #undef CPPCMS_URLBINDER_MPAR
  773. #undef CPPCMS_URLBINDER_PPAR
  774. #undef CPPCMS_URLBINDER_GPAR
  775. #undef CPPCMS_URLBINDER_IPAR
  776. #undef CPPCMS_URLBINDER_CPAR
  777. #undef CPPCMS_URLBINDER_PARSE
  778. #define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5
  779. #define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5
  780. #define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5
  781. #define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5;
  782. #define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5
  783. #define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5)
  784. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5)
  785. CPPCMS_URLBINDER
  786. #undef CPPCMS_URLBINDER_TPAR
  787. #undef CPPCMS_URLBINDER_MPAR
  788. #undef CPPCMS_URLBINDER_PPAR
  789. #undef CPPCMS_URLBINDER_GPAR
  790. #undef CPPCMS_URLBINDER_IPAR
  791. #undef CPPCMS_URLBINDER_CPAR
  792. #undef CPPCMS_URLBINDER_PARSE
  793. #define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5,typename P6
  794. #define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5,P6
  795. #define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5,p6
  796. #define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5,g6;
  797. #define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5,int p6
  798. #define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5),g6(p6)
  799. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5) CPPCMS_DEFANDPARSE(6)
  800. CPPCMS_URLBINDER
  801. #undef CPPCMS_URLBINDER_TPAR
  802. #undef CPPCMS_URLBINDER_MPAR
  803. #undef CPPCMS_URLBINDER_PPAR
  804. #undef CPPCMS_URLBINDER_GPAR
  805. #undef CPPCMS_URLBINDER_IPAR
  806. #undef CPPCMS_URLBINDER_CPAR
  807. #undef CPPCMS_URLBINDER_PARSE
  808. #define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7
  809. #define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5,P6,P7
  810. #define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5,p6,p7
  811. #define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5,g6,g7;
  812. #define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5,int p6,int p7
  813. #define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5),g6(p6),g7(p7)
  814. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5) CPPCMS_DEFANDPARSE2(6,7)
  815. CPPCMS_URLBINDER
  816. #undef CPPCMS_URLBINDER_TPAR
  817. #undef CPPCMS_URLBINDER_MPAR
  818. #undef CPPCMS_URLBINDER_PPAR
  819. #undef CPPCMS_URLBINDER_GPAR
  820. #undef CPPCMS_URLBINDER_IPAR
  821. #undef CPPCMS_URLBINDER_CPAR
  822. #undef CPPCMS_URLBINDER_PARSE
  823. #define CPPCMS_URLBINDER_TPAR typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8
  824. #define CPPCMS_URLBINDER_MPAR P1,P2,P3,P4,P5,P6,P7,P8
  825. #define CPPCMS_URLBINDER_PPAR p1,p2,p3,p4,p5,p6,p7,p8
  826. #define CPPCMS_URLBINDER_GPAR int g1,g2,g3,g4,g5,g6,g7,g8;
  827. #define CPPCMS_URLBINDER_IPAR int p1,int p2,int p3,int p4,int p5,int p6,int p7,int p8
  828. #define CPPCMS_URLBINDER_CPAR g1(p1),g2(p2),g3(p3),g4(p4),g5(p5),g6(p6),g7(p7),g8(p8)
  829. #define CPPCMS_URLBINDER_PARSE CPPCMS_DEFANDPARSE5(1,2,3,4,5) CPPCMS_DEFANDPARSE3(6,7,8)
  830. CPPCMS_URLBINDER
  831. #undef CPPCMS_URLBINDER_TPAR
  832. #undef CPPCMS_URLBINDER_MPAR
  833. #undef CPPCMS_URLBINDER_PPAR
  834. #undef CPPCMS_URLBINDER_GPAR
  835. #undef CPPCMS_URLBINDER_IPAR
  836. #undef CPPCMS_URLBINDER_CPAR
  837. #undef CPPCMS_URLBINDER_PARSE
  838. #undef CPPCMS_URLBINDER
  839. #undef CPPCMS_URLBINDER_INIT
  840. #undef CPPCMS_URLBINDER_PRD
  841. #undef CPPCMS_URLBINDER_P1
  842. #undef CPPCMS_URLBINDER_P2
  843. struct _data;
  844. booster::hold_ptr<_data> d;
  845. };
  846. } // cppcms
  847. #endif