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.
 
 
 
 
 
 

541 lines
14 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. #include <cppcms/application.h>
  9. #include <cppcms/url_dispatcher.h>
  10. #include <cppcms/applications_pool.h>
  11. #include <cppcms/service.h>
  12. #include <cppcms/http_response.h>
  13. #include <cppcms/http_request.h>
  14. #include <cppcms/http_cookie.h>
  15. #include <cppcms/localization.h>
  16. #include <cppcms/http_context.h>
  17. #include <cppcms/filters.h>
  18. #include <booster/intrusive_ptr.h>
  19. #include <cppcms/form.h>
  20. #include <cppcms/cache_interface.h>
  21. #include <cppcms/session_interface.h>
  22. #include <cppcms/mount_point.h>
  23. #include <sstream>
  24. #include <stdexcept>
  25. #include <stdlib.h>
  26. #include <set>
  27. #include <cppcms/config.h>
  28. #include <cppcms/mem_bind.h>
  29. #include <fstream>
  30. #include "hello_world_view.h"
  31. #include <booster/aio/deadline_timer.h>
  32. #include <booster/callback.h>
  33. #include <booster/posix_time.h>
  34. #include <booster/system_error.h>
  35. #include <booster/log.h>
  36. class chat : public cppcms::application {
  37. public:
  38. chat(cppcms::service &srv) : cppcms::application(srv)
  39. {
  40. dispatcher().assign("^/post$",&chat::post,this);
  41. dispatcher().assign("^/get/(\\d+)$",&chat::get,this,1);
  42. }
  43. void post()
  44. {
  45. if(request().request_method()=="POST") {
  46. if(request().post().find("message")!=request().post().end()) {
  47. messages_.push_back(request().post().find("message")->second);
  48. broadcast();
  49. }
  50. }
  51. response().finalize();
  52. release_context()->async_complete_response();
  53. }
  54. struct binder {
  55. chat *self;
  56. booster::shared_ptr<cppcms::http::context> context;
  57. void operator()() {
  58. self->remove_context(context);
  59. }
  60. };
  61. void get(std::string no)
  62. {
  63. std::cerr<<"Get:"<<waiters_.size()<<std::endl;
  64. unsigned pos=atoi(no.c_str());
  65. if(pos < messages_.size()) {
  66. response().set_plain_text_header();
  67. response().out()<<messages_[pos];
  68. release_context()->async_complete_response();
  69. }
  70. else if(pos == messages_.size()) {
  71. booster::shared_ptr<cppcms::http::context> context=release_context();
  72. waiters_.insert(context);
  73. binder bd = { this, context };
  74. context->async_on_peer_reset(bd);
  75. }
  76. else {
  77. response().status(404);
  78. release_context()->async_complete_response();
  79. }
  80. }
  81. void remove_context(booster::shared_ptr<cppcms::http::context> context)
  82. {
  83. std::cerr<<"Connection closed"<<std::endl;
  84. waiters_.erase(context);
  85. }
  86. void broadcast()
  87. {
  88. for(waiters_type::iterator waiter=waiters_.begin();waiter!=waiters_.end();++waiter) {
  89. (*waiter)->response().set_plain_text_header();
  90. (*waiter)->response().out() << messages_.back();
  91. (*waiter)->async_complete_response();
  92. }
  93. waiters_.clear();
  94. }
  95. private:
  96. std::vector<std::string> messages_;
  97. typedef std::set<booster::shared_ptr<cppcms::http::context> > waiters_type;
  98. waiters_type waiters_;
  99. };
  100. class stock : public cppcms::application {
  101. public:
  102. stock(cppcms::service &srv) : cppcms::application(srv),timer_(srv.get_io_service())
  103. {
  104. dispatcher().assign("^/price$",&stock::get,this);
  105. dispatcher().assign("^/update$",&stock::update,this);
  106. price_=10.3;
  107. counter_=0;
  108. async_run();
  109. }
  110. ~stock()
  111. {
  112. }
  113. void async_run()
  114. {
  115. on_timeout(booster::system::error_code());
  116. }
  117. private:
  118. void on_timeout(booster::system::error_code const &/*e*/)
  119. {
  120. broadcast();
  121. timer_.expires_from_now(booster::ptime(100));
  122. timer_.async_wait(cppcms::util::mem_bind(&stock::on_timeout,booster::intrusive_ptr<stock>(this)));
  123. }
  124. void get()
  125. {
  126. response().set_plain_text_header();
  127. cppcms::http::request::form_type::const_iterator p=request().get().find("from"),
  128. e=request().get().end();
  129. if(p==e || atoi(p->second.c_str()) < counter_) {
  130. response().out() << price_<<std::endl;
  131. release_context()->async_complete_response();
  132. return;
  133. }
  134. all_.push_back(release_context());
  135. }
  136. void broadcast()
  137. {
  138. for(unsigned i=0;i<all_.size();i++) {
  139. all_[i]->response().out() << counter_<<":"<<price_ << std::endl;
  140. all_[i]->async_complete_response();
  141. }
  142. all_.clear();
  143. }
  144. void update()
  145. {
  146. if(request().request_method()=="POST") {
  147. cppcms::http::request::form_type::const_iterator p=request().post().find("price"),
  148. e=request().post().end();
  149. if(p!=e) {
  150. price_ = atof(p->second.c_str());
  151. counter_ ++ ;
  152. for(unsigned i=0;i<all_.size();i++) {
  153. all_[i]->response().out() << price_ << std::endl;
  154. all_[i]->async_complete_response();
  155. }
  156. all_.clear();
  157. }
  158. }
  159. response().out() <<
  160. "<html>"
  161. "<body><form action='/stock/update' method='post'> "
  162. "<input type='text' name='price' /><br/>"
  163. "<input type='submit' value='Update Price' name='submit' />"
  164. "</form></body></html>"<<std::endl;
  165. release_context()->async_complete_response();
  166. }
  167. int counter_;
  168. double price_;
  169. std::vector<booster::shared_ptr<cppcms::http::context> > all_;
  170. booster::aio::deadline_timer timer_;
  171. };
  172. class my_form : public cppcms::form
  173. {
  174. public:
  175. cppcms::widgets::text name;
  176. cppcms::widgets::numeric<double> age;
  177. cppcms::widgets::password p1;
  178. cppcms::widgets::password p2;
  179. cppcms::widgets::textarea description;
  180. cppcms::widgets::select_multiple sel;
  181. cppcms::widgets::radio sel1;
  182. cppcms::widgets::select sel2;
  183. cppcms::widgets::file gif;
  184. cppcms::widgets::file text;
  185. cppcms::widgets::hidden secret;
  186. my_form()
  187. {
  188. name.message("Your Name");
  189. name.limits(2,30);
  190. age.message("Your Age");
  191. age.range(0,120);
  192. description.message("Describe Yourself");
  193. p1.message("Password");
  194. p2.message("Confirm");
  195. p1.check_equal(p2);
  196. p1.non_empty();
  197. sel.message(cppcms::locale::translate("Files:"));
  198. sel.add("Foo");
  199. sel.add("Bar");
  200. sel.add("Bee");
  201. sel.add("Car");
  202. sel1.message(cppcms::locale::translate("Fruit"));
  203. sel1.add("Apple");
  204. sel1.add("Orange");
  205. sel2.message(cppcms::locale::translate("Sex"));
  206. sel2.add("Male");
  207. sel2.add("Femail");
  208. sel2.add("You are sexist");
  209. sel.at_least(2);
  210. sel1.non_empty();
  211. gif.non_empty();
  212. gif.add_valid_magic("GIF89a");
  213. gif.add_valid_magic("GIF87a");
  214. gif.add_valid_magic("\x89PNG\r\n\x1a\n");
  215. text.mime(booster::regex("text/.*"));
  216. add(name);
  217. add(age);
  218. add(p1);
  219. add(p2);
  220. add(description);
  221. add(sel);
  222. add(sel1);
  223. add(sel2);
  224. add(gif);
  225. add(text);
  226. add(secret);
  227. }
  228. };
  229. struct foo {
  230. void bar() {}
  231. } foo_instance;
  232. class hello : public cppcms::application {
  233. public:
  234. hello(cppcms::service &srv) :
  235. cppcms::application(srv)
  236. {
  237. dispatcher().assign("^/(\\d+)$",&hello::num,this,1);
  238. dispatcher().assign("^/view(/(\\w+))?$",&hello::view_test,this,2);
  239. dispatcher().assign("^/get$",&hello::gform,this);
  240. dispatcher().assign("^/env$",&hello::env,this);
  241. dispatcher().assign("^/post$",&hello::pform,this);
  242. dispatcher().assign("^/err$",&hello::err,this);
  243. dispatcher().assign("^/forward$",&hello::forward,this);
  244. dispatcher().assign("^/form$",&hello::form,this);
  245. dispatcher().assign("^/cache/?$",&hello::cached,this);
  246. dispatcher().assign("^/csrf/?$",&hello::csrf,this);
  247. dispatcher().assign("^/throw/?$",&hello::throw_it,this);
  248. dispatcher().assign("^/foo$",&foo::bar,&foo_instance);
  249. dispatcher().assign("^/session/?$",&hello::session_test,this);
  250. dispatcher().assign("^/verylong/?$",&hello::verylong,this);
  251. dispatcher().assign(".*",&hello::hello_world,this);
  252. }
  253. ~hello()
  254. {
  255. }
  256. void env()
  257. {
  258. std::map<std::string,std::string> m(request().getenv());
  259. for(std::map<std::string,std::string>::const_iterator p = m.begin();p!=m.end();++p) {
  260. response().out() << p->first <<"="<<p->second <<"<br>\n";
  261. }
  262. }
  263. void csrf()
  264. {
  265. session().set("name","me");
  266. view::csrf c;
  267. if(request().request_method() == "POST") {
  268. c.my_form.load(context());
  269. if(c.my_form.validate()) {
  270. c.valid=true;
  271. }
  272. }
  273. render("csrf",c);
  274. }
  275. void verylong()
  276. {
  277. for(int i=0;i<10000000;i++) {
  278. if(!(response().out() << i << '\n')) {
  279. BOOSTER_DEBUG("hello") << "Bad output!";
  280. return;
  281. }
  282. }
  283. }
  284. void throw_it()
  285. {
  286. throw std::runtime_error("This is my secret error message");
  287. }
  288. void session_test()
  289. {
  290. if(!session().is_set("first_visit"))
  291. session().set("first_visit",::time(0));
  292. std::string tmp(rand() % 100,'x');
  293. session().set("foo",tmp);
  294. response().out() << cppcms::locale::format("<html><body> Your first visit was at {1,datetime=l} </body></html>")
  295. % session().get<time_t>("first_visit");
  296. }
  297. void cached()
  298. {
  299. if(cache().fetch_page("test"))
  300. return;
  301. response().out() <<
  302. "<html><body>Time :" << cppcms::locale::format("{1,time=f}") % time(0) << "</body></html>\n";
  303. cache().store_page("test",10);
  304. }
  305. void view_test(std::string skin)
  306. {
  307. view::hello c;
  308. if(!skin.empty())
  309. context().skin(skin);
  310. render("hello",c);
  311. }
  312. #ifndef CPPCMS_DISABLE_ICU_LOCALIZATION
  313. void devide(cppcms::locale::boundary::boundary_type type,std::string const &str,char const *name)
  314. {
  315. response().out()<<name<<":";
  316. using namespace cppcms::locale::boundary;
  317. ssegment_index ind(type,str.begin(),str.end(),context().locale());
  318. ssegment_index::iterator p;
  319. for(p=ind.begin();p!=ind.end();++p) {
  320. response().out()<<"|"<<*p;
  321. }
  322. response().out()<<"|<br>\n";
  323. }
  324. #endif
  325. void form()
  326. {
  327. my_form f;
  328. bool ok=false;
  329. if(request().request_method()=="POST") {
  330. f.load(context());
  331. if(f.validate()) {
  332. ok=true;
  333. }
  334. }
  335. response().out()<<
  336. "<html><body>\n";
  337. std::locale loc = context().locale();
  338. if(f.name.set()) {
  339. using namespace cppcms::locale;
  340. std::string name = f.name.value();
  341. response().out() <<"Upper: "<<to_upper(name,loc)<<"<br>"<<std::endl;
  342. response().out() <<"Lower: "<<to_lower(name,loc)<<"<br>"<<std::endl;
  343. #ifndef CPPCMS_DISABLE_ICU_LOCALIZATION
  344. response().out() <<"Title: "<<to_title(name,loc)<<"<br>"<<std::endl;
  345. response().out() <<"Fold Case: "<<fold_case(name,loc)<<"<br>"<<std::endl;
  346. #endif
  347. }
  348. if(f.description.set()) {
  349. std::string descr = f.description.value();
  350. if(!f.description.valid()) {
  351. std::ofstream tmp("test.txt");
  352. tmp<<descr;
  353. }
  354. #ifndef CPPCMS_DISABLE_ICU_LOCALIZATION
  355. using namespace cppcms::locale;
  356. devide(boundary::character,descr,"code");
  357. devide(boundary::word,descr,"word");
  358. devide(boundary::sentence,descr,"sentence");
  359. devide(boundary::line,descr,"line");
  360. #endif
  361. }
  362. if(ok) {
  363. response().out() << f.name.value() <<" " <<f.age.value();
  364. f.clear();
  365. }
  366. response().out()<<
  367. "<form action='" <<
  368. request().script_name() + request().path_info()
  369. << "' method='post' enctype='multipart/form-data' >\n"
  370. "<table>\n";
  371. cppcms::form_context context(response().out());
  372. f.render(context);
  373. response().out()<<"</table><input type='submit' value='Send' ></form>\n";
  374. response().out()<<"</form></body></html>"<<std::endl;
  375. }
  376. void forward()
  377. {
  378. //response().set_redirect_header("http://127.0.0.1:8080/hello");
  379. response().set_redirect_header("/hello");
  380. }
  381. void err()
  382. {
  383. throw std::runtime_error("Foo<Bar>!!!");
  384. }
  385. void hello_world()
  386. {
  387. using namespace cppcms;
  388. std::ostringstream ss;
  389. ss<<std::time(NULL);
  390. response().set_cookie(cppcms::http::cookie("test",ss.str()));
  391. response().out() <<
  392. "<html><body>\n"
  393. "<h1>Hello World!</h1>\n";
  394. std::string t1="text";
  395. std::string t2="text text";
  396. std::string t3="<text>";
  397. response().out()<<cppcms::filters::date(time(0)) << "<br>\n";
  398. response().out()<<cppcms::filters::time(time(0)) << "<br>\n";
  399. response().out()<<cppcms::filters::datetime(time(0)) << "<br>\n";
  400. response().out()<<cppcms::filters::to_upper(t1) << "<br>\n";
  401. response().out()<<cppcms::filters::to_lower(t1) << "<br>\n";
  402. response().out()<<cppcms::filters::to_title(t1) << "<br>\n";
  403. response().out()<<cppcms::filters::escape(t3) << "<br>\n";
  404. response().out()<<cppcms::filters::urlencode(t2) << "<br>\n";
  405. response().out()<<cppcms::filters::base64_urlencode(t1) << "<br>\n";
  406. response().out()<<locale::format("{1,datetime=f}") % time(0) << "<br>\n";
  407. response().out()<<locale::format("{1,datetime=f}") % cppcms::filters::escape(time(0)) << "<br>\n";
  408. response().out()<<std::use_facet<locale::info>(response().out().getloc()).language()<<"<br>\n";
  409. cppcms::http::request::cookies_type::const_iterator p;
  410. for(p=request().cookies().begin();p!=request().cookies().end();++p) {
  411. response().out()<<p->second<<"<br/>\n";
  412. }
  413. response().out() << filters::date(time(0)) <<std::endl;
  414. response().out() << filters::escape(locale::translate("hello\n")) << "<br>";
  415. for(int i=0;i<30;i++) {
  416. response().out() << locale::format(locale::translate("passed one day","passed {1} days",i)) % i << "<br>\n";
  417. }
  418. response().out()
  419. <<"<body></html>\n";
  420. }
  421. void init()
  422. {
  423. //std::cout << "There" << std::endl;
  424. }
  425. void num(std::string s)
  426. {
  427. response().set_plain_text_header();
  428. response().out() <<
  429. "Number is "<<s;
  430. }
  431. void pform()
  432. {
  433. std::string name;
  434. std::string message;
  435. cppcms::http::request::form_type::const_iterator p=request().post().find("name");
  436. if(p!=request().post().end())
  437. name=p->second;
  438. if((p=request().post().find("message"))!=request().post().end())
  439. message=p->second;
  440. response().out() <<
  441. "<html><body>"
  442. "<form method=\"post\" action=\"/hello/post\" >"
  443. "<input name=\"name\" type=\"text\" /><br/>"
  444. "<textarea name=\"message\"></textarea><br/>"
  445. "<input type=\"Submit\" value=\"Submit\" />"
  446. "</form>"
  447. <<"Name:"<<name<<"<br/>\n"
  448. <<"Text:"<<message<<
  449. "</body></html>";
  450. }
  451. void gform()
  452. {
  453. std::string name;
  454. std::string message;
  455. cppcms::http::request::form_type::const_iterator p=request().get().find("name");
  456. if(p!=request().get().end())
  457. name=p->second;
  458. if((p=request().get().find("message"))!=request().get().end())
  459. message=p->second;
  460. response().out() <<
  461. "<html><body>"
  462. "<form method=\"get\" action=\"/hello/get\" >"
  463. "<input name=\"name\" type=\"text\" /><br/>"
  464. "<textarea name=\"message\"></textarea><br/>"
  465. "<input type=\"Submit\" value=\"Submit\" />"
  466. "</form>"
  467. <<"Name:"<<name<<"<br/>\n"
  468. <<"Text:"<<message<<
  469. "</body></html>";
  470. }
  471. };
  472. int main(int argc,char **argv)
  473. {
  474. try {
  475. cppcms::service service(argc,argv);
  476. booster::intrusive_ptr<chat> c=new chat(service);
  477. service.applications_pool().mount(c,cppcms::mount_point("/chat"));
  478. service.applications_pool().mount(cppcms::applications_factory<hello>(),cppcms::mount_point("/hello"));
  479. service.applications_pool().mount(new stock(service),cppcms::mount_point("/stock"));
  480. service.run();
  481. std::cout<<"Done..."<<std::endl;
  482. }
  483. catch(std::exception const &e) {
  484. std::cerr<<"Caught exception: "<<e.what()<<std::endl;
  485. std::cerr<<booster::trace(e) << std::endl;
  486. return 1;
  487. }
  488. return 0;
  489. }