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.
 
 
 
 
 
 

782 lines
18 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. #define CPPCMS_SOURCE
  9. #include <cppcms/capi/session.h>
  10. #include <cppcms/session_pool.h>
  11. #include <cppcms/session_interface.h>
  12. #include <cppcms/http_cookie.h>
  13. #include <cppcms/json.h>
  14. #include <set>
  15. #include <list>
  16. #include <string>
  17. #include <stdexcept>
  18. #include <booster/hold_ptr.h>
  19. #include <booster/nowide/fstream.h>
  20. #include <stdio.h>
  21. #include <typeinfo>
  22. extern "C" {
  23. struct cppcms_capi_exception {
  24. int code;
  25. char const *msg;
  26. std::string s_msg;
  27. char c_msg[64];
  28. cppcms_capi_exception() : code(0), msg("ok")
  29. {
  30. memset(c_msg,0,sizeof(c_msg));
  31. }
  32. };
  33. struct cppcms_capi_session_pool {
  34. cppcms_capi_exception e;
  35. booster::hold_ptr<cppcms::session_pool> p;
  36. };
  37. struct cppcms_capi_session {
  38. cppcms_capi_exception e;
  39. void check() {
  40. if(!p.get())
  41. throw std::logic_error("Session is not initialized");
  42. }
  43. void check_loaded()
  44. {
  45. check();
  46. if(!loaded)
  47. throw std::logic_error("Session is not loaded");
  48. }
  49. void check_loaded_unsaved()
  50. {
  51. check();
  52. if(!loaded)
  53. throw std::logic_error("Session is not loaded");
  54. if(saved)
  55. throw std::logic_error("Session is already saved - no changes allowed");
  56. }
  57. void check_saved()
  58. {
  59. if(!saved)
  60. throw std::logic_error("Session is not saved");
  61. }
  62. bool loaded;
  63. bool saved;
  64. booster::hold_ptr<cppcms::session_interface> p;
  65. std::set<std::string> key_set;
  66. std::set<std::string>::const_iterator key_set_ptr;
  67. std::string returned_value;
  68. struct cookie_adapter : public cppcms::session_interface_cookie_adapter {
  69. std::map<std::string,cppcms::http::cookie> cookies;
  70. std::map<std::string,cppcms::http::cookie>::const_iterator cookies_ptr;
  71. std::string value;
  72. std::set<std::string> keys;
  73. virtual void set_cookie(cppcms::http::cookie const &updated_cookie) {
  74. cookies[updated_cookie.name()]=updated_cookie;
  75. }
  76. virtual std::string get_session_cookie(std::string const &) {
  77. return value;
  78. }
  79. virtual std::set<std::string> get_cookie_names()
  80. {
  81. return keys;
  82. }
  83. } adapter;
  84. cppcms_capi_session() {
  85. key_set_ptr = key_set.begin();
  86. loaded = false;
  87. saved = false;
  88. }
  89. };
  90. struct cppcms_capi_cookie {
  91. cppcms_capi_exception e;
  92. std::string name;
  93. std::string value;
  94. std::string path;
  95. std::string domain;
  96. bool secure;
  97. bool httponly;
  98. bool has_samesite_none;
  99. bool has_samesite_lax;
  100. bool has_samesite_strict;
  101. bool has_expires;
  102. bool has_max_age;
  103. time_t expires;
  104. unsigned max_age;
  105. std::string header;
  106. std::string header_content;
  107. cppcms_capi_cookie(cppcms::http::cookie const &c) :
  108. name(c.name()),
  109. value(c.value()),
  110. path(c.path()),
  111. domain(c.domain()),
  112. secure(c.secure()),
  113. httponly(c.httponly()),
  114. has_samesite_none(c.samesite_none()),
  115. has_samesite_lax(c.samesite_lax()),
  116. has_samesite_strict(c.samesite_strict()),
  117. has_expires(c.expires_defined()),
  118. has_max_age(c.max_age_defined()),
  119. expires(c.expires()),
  120. max_age(c.max_age())
  121. {
  122. std::ostringstream ss;
  123. ss << c;
  124. header=ss.str();
  125. size_t pos = header.find(':');
  126. if(pos!=std::string::npos)
  127. header_content=header.substr(pos+1);
  128. }
  129. };
  130. } // extern C
  131. namespace {
  132. void seterror(cppcms_capi_exception &c,int code,std::exception const &e)
  133. {
  134. if(c.code)
  135. return;
  136. c.code = code;
  137. try {
  138. c.s_msg = e.what();
  139. c.msg = c.s_msg.c_str();
  140. }
  141. catch(...) {
  142. strncpy(c.c_msg,e.what(),sizeof(c.c_msg)-1);
  143. c.msg = c.c_msg;
  144. }
  145. }
  146. void seterror(cppcms_capi_exception &c,int code,char const *msg)
  147. {
  148. if(c.code)
  149. return;
  150. c.code = code;
  151. c.msg=msg;
  152. }
  153. template<typename C>
  154. void handle(C *ptr)
  155. {
  156. if(!ptr)
  157. return;
  158. try {
  159. try {
  160. throw;
  161. }
  162. catch(std::runtime_error const &e) {
  163. seterror(ptr->e,CPPCMS_CAPI_ERROR_RUNTIME,e);
  164. }
  165. catch(std::invalid_argument const &e) {
  166. seterror(ptr->e,CPPCMS_CAPI_ERROR_INVALID_ARGUMENT,e);
  167. }
  168. catch(std::logic_error const &e) {
  169. seterror(ptr->e,CPPCMS_CAPI_ERROR_LOGIC,e);
  170. }
  171. catch(std::bad_alloc const &e) {
  172. seterror(ptr->e,CPPCMS_CAPI_ERROR_ALLOC,"memory allocation error");
  173. }
  174. catch(std::exception const &e) {
  175. seterror(ptr->e,CPPCMS_CAPI_ERROR_GENERAL,e);
  176. }
  177. catch(...) {
  178. seterror(ptr->e,CPPCMS_CAPI_ERROR_GENERAL,"unknown error");
  179. }
  180. }
  181. catch(...) {
  182. seterror(ptr->e,CPPCMS_CAPI_ERROR_GENERAL,"unknown error");
  183. }
  184. }
  185. void check_str(char const *str)
  186. {
  187. if(!str)
  188. throw std::invalid_argument("String is null");
  189. }
  190. unsigned char hex_to_digit(char c)
  191. {
  192. if('0' <= c && c<='9')
  193. return c - '0';
  194. if('a' <= c && c<= 'f')
  195. return c - 'a' + 10;
  196. if('A' <= c && c<= 'F')
  197. return c - 'A' + 10;
  198. throw std::invalid_argument("Non hexadecimal digit detected");
  199. }
  200. } // namespace
  201. extern "C" {
  202. #define TRY try
  203. #define CATCH(x,ok,error) catch(...) { handle(x); return error; } return ok
  204. int cppcms_capi_error(cppcms_capi_object obj)
  205. {
  206. if(!obj)
  207. return 0;
  208. cppcms_capi_exception *e=static_cast<cppcms_capi_exception *>(obj);
  209. return e->code;
  210. }
  211. char const *cppcms_capi_error_message(cppcms_capi_object obj)
  212. {
  213. if(!obj)
  214. return "ok";
  215. cppcms_capi_exception *e=static_cast<cppcms_capi_exception *>(obj);
  216. if(e->code == 0)
  217. return "ok";
  218. else
  219. return e->msg;
  220. }
  221. char const *cppcms_capi_error_clear(cppcms_capi_object obj)
  222. {
  223. char const *r=cppcms_capi_error_message(obj);
  224. if(obj) {
  225. static_cast<cppcms_capi_exception *>(obj)->code = 0;
  226. }
  227. return r;
  228. }
  229. cppcms_capi_session_pool *cppcms_capi_session_pool_new()
  230. {
  231. try {
  232. return new cppcms_capi_session_pool();
  233. }catch(...) { return 0; }
  234. }
  235. void cppcms_capi_session_pool_delete(cppcms_capi_session_pool *pool)
  236. {
  237. if(pool)
  238. delete pool;
  239. }
  240. int cppcms_capi_session_pool_init(cppcms_capi_session_pool *pool,char const *config_file)
  241. {
  242. TRY {
  243. if(!pool)
  244. return -1;
  245. check_str(config_file);
  246. cppcms::json::value v;
  247. booster::nowide::ifstream f(config_file);
  248. if(!f)
  249. throw std::runtime_error(std::string("Failed to open file ") + config_file);
  250. int line = 0;
  251. if(!v.load(f,true,&line)) {
  252. std::ostringstream ss;
  253. ss << "Failed to parse " << config_file << " syntax error in line " << line;
  254. throw std::runtime_error(ss.str());
  255. }
  256. pool->p.reset(new cppcms::session_pool(v));
  257. pool->p->init();
  258. } CATCH(pool,0,-1);
  259. }
  260. int cppcms_capi_session_pool_init_from_json(cppcms_capi_session_pool *pool,char const *json)
  261. {
  262. try {
  263. if(!pool)
  264. return -1;
  265. check_str(json);
  266. cppcms::json::value v;
  267. std::istringstream f(json);
  268. int line = 0;
  269. if(!v.load(f,true,&line)) {
  270. std::ostringstream ss;
  271. ss << "Failed to parse json syntax error in line " << line;
  272. throw std::runtime_error(ss.str());
  273. }
  274. pool->p.reset(new cppcms::session_pool(v));
  275. pool->p->init();
  276. } CATCH(pool,0,-1);
  277. }
  278. cppcms_capi_session *cppcms_capi_session_new()
  279. {
  280. try {
  281. return new cppcms_capi_session();
  282. }
  283. catch(...) { return 0; }
  284. }
  285. void cppcms_capi_session_delete(cppcms_capi_session *session)
  286. {
  287. if(session) delete session;
  288. }
  289. int cppcms_capi_session_init(cppcms_capi_session *session,cppcms_capi_session_pool *pool)
  290. {
  291. TRY {
  292. if(!session)
  293. return -1;
  294. if(!pool)
  295. throw std::logic_error("pool is NULL");
  296. if(!pool->p.get()) {
  297. throw std::logic_error("Session pool is not initialized");
  298. }
  299. session->p.reset(new cppcms::session_interface(*pool->p,session->adapter));
  300. }
  301. CATCH(session,0,-1);
  302. }
  303. int cppcms_capi_session_clear(cppcms_capi_session *session)
  304. {
  305. TRY {
  306. if(!session)
  307. return -1;
  308. session->check_loaded_unsaved();
  309. session->p->clear();
  310. }CATCH(session,0,-1);
  311. }
  312. int cppcms_capi_session_is_set(cppcms_capi_session *session,char const *key)
  313. {
  314. TRY {
  315. if(!session)
  316. return -1;
  317. check_str(key);
  318. session->check_loaded();
  319. return session->p->is_set(key);
  320. }CATCH(session,0,-1);
  321. }
  322. int cppcms_capi_session_erase(cppcms_capi_session *session,char const *key)
  323. {
  324. TRY {
  325. if(!session)
  326. return -1;
  327. check_str(key);
  328. session->check_loaded_unsaved();
  329. session->p->erase(key);
  330. }CATCH(session,0,-1);
  331. }
  332. int cppcms_capi_session_get_exposed(cppcms_capi_session *session,char const *key)
  333. {
  334. TRY {
  335. if(!session)
  336. return -1;
  337. check_str(key);
  338. session->check_loaded();
  339. return session->p->is_exposed(key);
  340. }CATCH(session,0,-1);
  341. }
  342. int cppcms_capi_session_set_exposed(cppcms_capi_session *session,char const *key,int is_exposed)
  343. {
  344. TRY {
  345. if(!session)
  346. return -1;
  347. check_str(key);
  348. session->check_loaded_unsaved();
  349. session->p->expose(key,is_exposed);
  350. }CATCH(session,0,-1);
  351. }
  352. char const *cppcms_capi_session_get_first_key(cppcms_capi_session *session)
  353. {
  354. TRY {
  355. if(!session)
  356. return 0;
  357. session->check_loaded();
  358. session->key_set = session->p->key_set();
  359. session->key_set_ptr = session->key_set.begin();
  360. if(session->key_set_ptr != session->key_set.end()) {
  361. char const *r=session->key_set_ptr->c_str();
  362. ++session->key_set_ptr;
  363. return r;
  364. }
  365. }CATCH(session,0,0);
  366. }
  367. char const *cppcms_capi_session_get_next_key(cppcms_capi_session *session)
  368. {
  369. TRY {
  370. if(!session)
  371. return 0;
  372. session->check_loaded();
  373. if(session->key_set_ptr != session->key_set.end()) {
  374. char const *r=session->key_set_ptr->c_str();
  375. ++session->key_set_ptr;
  376. return r;
  377. }
  378. }
  379. CATCH(session,0,0);
  380. }
  381. char const *cppcms_capi_session_get_csrf_token(cppcms_capi_session *session)
  382. {
  383. TRY {
  384. if(!session)
  385. return 0;
  386. session->check_loaded();
  387. session->returned_value = session->p->get_csrf_token();
  388. return session->returned_value.c_str();
  389. }
  390. CATCH(session,0,0);
  391. }
  392. int cppcms_capi_session_set(cppcms_capi_session *session,char const *key,char const *value)
  393. {
  394. TRY {
  395. if(!session)
  396. return -1;
  397. check_str(key);
  398. check_str(value);
  399. session->check_loaded_unsaved();
  400. (*(session->p))[key]=value;
  401. }CATCH(session,0,-1);
  402. }
  403. char const *cppcms_capi_session_get(cppcms_capi_session *session,char const *key)
  404. {
  405. TRY {
  406. if(!session)
  407. return 0;
  408. check_str(key);
  409. session->check_loaded();
  410. if(!session->p->is_set(key))
  411. return 0;
  412. session->returned_value = session->p->get(key);
  413. return session->returned_value.c_str();
  414. }CATCH(session,0,0);
  415. }
  416. int cppcms_capi_session_get_binary_len(cppcms_capi_session *session,char const *key)
  417. {
  418. TRY {
  419. if(!session)
  420. return -1;
  421. check_str(key);
  422. session->check_loaded();
  423. if(!session->p->is_set(key))
  424. return 0;
  425. return (*(session->p))[key].size();
  426. }CATCH(session,0,-1);
  427. }
  428. int cppcms_capi_session_set_binary(cppcms_capi_session *session,char const *key,void const *value,int length)
  429. {
  430. TRY {
  431. if(!session)
  432. return -1;
  433. check_str(key);
  434. if(!value)
  435. throw std::invalid_argument("value is null");
  436. if(length < 0)
  437. throw std::invalid_argument("length is negative");
  438. session->check_loaded_unsaved();
  439. (*(session->p))[key].assign(static_cast<char const *>(value),size_t(length));
  440. }CATCH(session,0,-1);
  441. }
  442. int cppcms_capi_session_get_binary(cppcms_capi_session *session,char const *key,void *buf,int buffer_size)
  443. {
  444. TRY {
  445. if(!session)
  446. return -1;
  447. check_str(key);
  448. if(buffer_size < 0)
  449. throw std::invalid_argument("buffer size is negative");
  450. if(!buf)
  451. throw std::invalid_argument("buffer is null");
  452. session->check_loaded();
  453. if(!session->p->is_set(key))
  454. return 0;
  455. std::string &value = (*(session->p))[key];
  456. int copy_size = value.size();
  457. if(copy_size > buffer_size)
  458. throw std::invalid_argument("Output buffer is too small");
  459. memcpy(buf,value.c_str(),copy_size);
  460. return copy_size;
  461. }CATCH(session,0,-1);
  462. }
  463. int cppcms_capi_session_set_binary_as_hex(cppcms_capi_session *session,char const *key,char const *value)
  464. {
  465. TRY {
  466. if(!session)
  467. return -1;
  468. check_str(key);
  469. check_str(value);
  470. int len = strlen(value);
  471. if(len % 2 != 0)
  472. throw std::invalid_argument("value lengths is odd");
  473. std::string tmp;
  474. tmp.reserve(len / 2);
  475. for(int i=0;i<len;i+=2) {
  476. unsigned char h=hex_to_digit(value[i]);
  477. unsigned char l=hex_to_digit(value[i+1]);
  478. unsigned char b = h * 16u + l;
  479. tmp+=char(b);
  480. }
  481. session->check_loaded_unsaved();
  482. (*(session->p))[key].swap(tmp);
  483. }CATCH(session,0,-1);
  484. }
  485. char const *cppcms_capi_session_get_binary_as_hex(cppcms_capi_session *session,char const *key)
  486. {
  487. TRY {
  488. if(!session)
  489. return 0;
  490. check_str(key);
  491. session->check_loaded();
  492. if(!session->p->is_set(key))
  493. return 0;
  494. std::string const &value = (*(session->p))[key];
  495. std::string tmp;
  496. int len = value.size();
  497. tmp.reserve(len*2);
  498. for(int i=0;i<len;i++) {
  499. static char const *digits="0123456789abcdef";
  500. unsigned char c=value[i];
  501. tmp+=digits[(c >> 4u & 0xFu)];
  502. tmp+=digits[(c & 0xFu)];
  503. }
  504. session->returned_value.swap(tmp);
  505. return session->returned_value.c_str();
  506. }CATCH(session,0,0);
  507. }
  508. int cppcms_capi_session_reset_session(cppcms_capi_session *session)
  509. {
  510. TRY {
  511. if(!session)
  512. return -1;
  513. session->check_loaded_unsaved();
  514. session->p->reset_session();
  515. }
  516. CATCH(session,0,-1);
  517. }
  518. int cppcms_capi_session_set_default_age(cppcms_capi_session *session)
  519. {
  520. TRY {
  521. if(!session)
  522. return -1;
  523. session->check_loaded_unsaved();
  524. session->p->default_age();
  525. }
  526. CATCH(session,0,-1);
  527. }
  528. int cppcms_capi_session_set_age(cppcms_capi_session *session,int t)
  529. {
  530. TRY {
  531. if(!session)
  532. return -1;
  533. session->check_loaded_unsaved();
  534. session->p->age(t);
  535. }
  536. CATCH(session,0,-1);
  537. }
  538. int cppcms_capi_session_get_age(cppcms_capi_session *session)
  539. {
  540. TRY {
  541. if(!session)
  542. return -1;
  543. session->check_loaded();
  544. return session->p->age();
  545. }
  546. CATCH(session,0,-1);
  547. }
  548. int cppcms_capi_session_set_default_expiration(cppcms_capi_session *session)
  549. {
  550. TRY {
  551. if(!session)
  552. return -1;
  553. session->check_loaded_unsaved();
  554. session->p->default_expiration();
  555. }
  556. CATCH(session,0,-1);
  557. }
  558. int cppcms_capi_session_set_expiration(cppcms_capi_session *session,int t)
  559. {
  560. TRY {
  561. if(!session)
  562. return -1;
  563. session->check_loaded_unsaved();
  564. session->p->expiration(t);
  565. }
  566. CATCH(session,0,-1);
  567. }
  568. int cppcms_capi_session_get_expiration(cppcms_capi_session *session)
  569. {
  570. TRY {
  571. if(!session)
  572. return -1;
  573. session->check_loaded();
  574. return session->p->expiration();
  575. }
  576. CATCH(session,0,-1);
  577. }
  578. int cppcms_capi_session_set_on_server(cppcms_capi_session *session,int is_on_server)
  579. {
  580. TRY {
  581. if(!session)
  582. return -1;
  583. session->check_loaded_unsaved();
  584. session->p->on_server(is_on_server);
  585. }
  586. CATCH(session,0,-1);
  587. }
  588. int cppcms_capi_session_get_on_server(cppcms_capi_session *session)
  589. {
  590. TRY {
  591. if(!session)
  592. return -1;
  593. session->check_loaded();
  594. return session->p->on_server();
  595. }
  596. CATCH(session,0,-1);
  597. }
  598. char const *cppcms_capi_session_get_session_cookie_name(cppcms_capi_session *session)
  599. {
  600. TRY {
  601. if(!session)
  602. return 0;
  603. session->check();
  604. session->returned_value = session->p->session_cookie_name();
  605. return session->returned_value.c_str();
  606. }
  607. CATCH(session,0,0);
  608. }
  609. int cppcms_capi_session_set_session_cookie(cppcms_capi_session *session,char const *session_cookie_value)
  610. {
  611. TRY {
  612. if(!session)
  613. return -1;
  614. check_str(session_cookie_value);
  615. session->check();
  616. session->adapter.value = session_cookie_value;
  617. }
  618. CATCH(session,0,-1);
  619. }
  620. int cppcms_capi_session_add_cookie_name(cppcms_capi_session *session,char const *name)
  621. {
  622. TRY {
  623. if(!session)
  624. return -1;
  625. check_str(name);
  626. session->check();
  627. session->adapter.keys.insert(name);
  628. }
  629. CATCH(session,0,-1);
  630. }
  631. int cppcms_capi_session_load(cppcms_capi_session *session)
  632. {
  633. TRY {
  634. if(!session)
  635. return -1;
  636. session->check();
  637. if(session->loaded) {
  638. throw std::logic_error("Session is already loaded");
  639. }
  640. session->p->load();
  641. session->loaded = true;
  642. }
  643. CATCH(session,0,-1);
  644. }
  645. int cppcms_capi_session_save(cppcms_capi_session *session)
  646. {
  647. TRY {
  648. if(!session)
  649. return -1;
  650. session->check_loaded_unsaved();
  651. session->p->save();
  652. session->saved = true;
  653. session->adapter.cookies_ptr=session->adapter.cookies.begin();
  654. }
  655. CATCH(session,0,-1);
  656. }
  657. cppcms_capi_cookie *cppcms_capi_session_cookie_first(cppcms_capi_session *session)
  658. {
  659. TRY {
  660. if(!session)
  661. return 0;
  662. session->check_saved();
  663. session->adapter.cookies_ptr=session->adapter.cookies.begin();
  664. if(session->adapter.cookies_ptr == session->adapter.cookies.end())
  665. return 0;
  666. cppcms_capi_cookie *r=new cppcms_capi_cookie(session->adapter.cookies_ptr->second);
  667. ++session->adapter.cookies_ptr;
  668. return r;
  669. }
  670. CATCH(session,0,0);
  671. }
  672. cppcms_capi_cookie *cppcms_capi_session_cookie_next(cppcms_capi_session *session)
  673. {
  674. TRY {
  675. if(!session)
  676. return 0;
  677. session->check_saved();
  678. if(session->adapter.cookies_ptr == session->adapter.cookies.end())
  679. return 0;
  680. cppcms_capi_cookie *r=new cppcms_capi_cookie(session->adapter.cookies_ptr->second);
  681. ++session->adapter.cookies_ptr;
  682. return r;
  683. }
  684. CATCH(session,0,0);
  685. }
  686. void cppcms_capi_cookie_delete(cppcms_capi_cookie *cookie) { if(cookie) delete cookie; }
  687. char const *cppcms_capi_cookie_header(cppcms_capi_cookie const *cookie) { return cookie ? cookie->header.c_str() : 0; }
  688. char const *cppcms_capi_cookie_header_content(cppcms_capi_cookie const *cookie) { return cookie ? cookie->header_content.c_str() : 0; }
  689. char const *cppcms_capi_cookie_name(cppcms_capi_cookie const *cookie) { return cookie ? cookie->name.c_str(): 0 ; }
  690. char const *cppcms_capi_cookie_value(cppcms_capi_cookie const *cookie) { return cookie ? cookie->value.c_str(): 0; }
  691. char const *cppcms_capi_cookie_path(cppcms_capi_cookie const *cookie) { return cookie ? cookie->path.c_str(): 0; }
  692. char const *cppcms_capi_cookie_domain(cppcms_capi_cookie const *cookie) { return cookie ? cookie->domain.c_str() : 0; }
  693. int cppcms_capi_cookie_max_age_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_max_age : -1; }
  694. unsigned cppcms_capi_cookie_max_age(cppcms_capi_cookie const *cookie) { return cookie ? cookie->max_age: 0; }
  695. int cppcms_capi_cookie_expires_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_expires: -1; }
  696. long long cppcms_capi_cookie_expires(cppcms_capi_cookie const *cookie) { return cookie ? cookie->expires: -1; }
  697. int cppcms_capi_cookie_is_secure(cppcms_capi_cookie const *cookie) { return cookie ? cookie->secure: -1; }
  698. int cppcms_capi_cookie_is_httponly(cppcms_capi_cookie const *cookie) { return cookie ? cookie->httponly: -1; }
  699. int cppcms_capi_cookie_samesite_none_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_samesite_none: -1; }
  700. int cppcms_capi_cookie_samesite_lax_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_samesite_lax: -1; }
  701. int cppcms_capi_cookie_samesite_strict_defined(cppcms_capi_cookie const *cookie) { return cookie ? cookie->has_samesite_strict: -1; }
  702. } // extern "C"