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.
 
 
 
 
 
 

1627 lines
39 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_FORM_H
  9. #define CPPCMS_FORM_H
  10. #include <cppcms/defs.h>
  11. #include <booster/noncopyable.h>
  12. #include <string>
  13. #include <set>
  14. #include <map>
  15. #include <list>
  16. #include <vector>
  17. #include <stack>
  18. #include <ostream>
  19. #include <sstream>
  20. #include <cppcms/http_context.h>
  21. #include <cppcms/http_request.h>
  22. #include <cppcms/http_response.h>
  23. #include <booster/copy_ptr.h>
  24. #include <booster/perl_regex.h>
  25. #include <booster/shared_ptr.h>
  26. #include <cppcms/cppcms_error.h>
  27. #include <cppcms/util.h>
  28. #include <cppcms/localization.h>
  29. namespace cppcms {
  30. namespace http {
  31. class file;
  32. }
  33. namespace widgets {
  34. class base_widget;
  35. }
  36. ///
  37. /// \brief This struct holds various flags to control the HTML generation.
  38. ///
  39. struct form_flags {
  40. ///
  41. /// This enum represents the HTML/XHTML switch.
  42. ///
  43. typedef enum {
  44. as_html = 0, ///< render form/widget as ordinary HTML
  45. as_xhtml= 1, ///< render form/widget as XHTML
  46. } html_type;
  47. ///
  48. /// This enum represents the style for the widgets generation.
  49. ///
  50. typedef enum {
  51. as_p = 0 , ///< Render each widget using paragraphs
  52. as_table= 1 , ///< Render each widget using table
  53. as_ul = 2 , ///< Render each widget using unordered list
  54. as_dl = 3 , ///< Render each widget using definitions list
  55. as_space= 4 ///< Render each widget using simple blank space separators
  56. } html_list_type;
  57. ///
  58. /// This special flag is used to partially generate a widget's HTML.
  59. ///
  60. typedef enum {
  61. first_part = 0, ///< Render part 1: HTML attributes can be inserted after it.
  62. second_part = 1 ///< Render part 2: complete part 1.
  63. } widget_part_type;
  64. };
  65. ///
  66. /// \brief This class represents the context required to generate the widgets' HTML.
  67. ///
  68. class CPPCMS_API form_context : public form_flags
  69. {
  70. public:
  71. ///
  72. /// Default constructor.
  73. ///
  74. form_context();
  75. ///
  76. /// Copy-constructor.
  77. ///
  78. form_context(form_context const &other);
  79. ///
  80. /// Assignment.
  81. ///
  82. form_context const &operator = (form_context const &other);
  83. ///
  84. /// Create a rendering context.
  85. ///
  86. /// \param output the std::ostream output to write HTML to.
  87. /// \param ht flags represents the type of HTML that should be generated.
  88. /// \param hlt flag defines the style of widgets generation.
  89. ///
  90. form_context( std::ostream &output,
  91. html_type ht = form_flags::as_html,
  92. html_list_type hlt=form_flags::as_p);
  93. ///
  94. /// Destructor.
  95. ///
  96. ~form_context();
  97. ///
  98. /// Set the HTML/XHTML flag.
  99. ///
  100. void html(html_type t);
  101. ///
  102. /// Set the widgets rendering style.
  103. ///
  104. void html_list(html_list_type t);
  105. ///
  106. /// Set the flag for the partial rendering of the widget.
  107. ///
  108. void widget_part(widget_part_type t);
  109. ///
  110. /// Set the output stream.
  111. ///
  112. void out(std::ostream &out);
  113. ///
  114. /// Set the HTML/XHTML flag. The default is \a as_html.
  115. ///
  116. html_type html() const;
  117. ///
  118. /// Get the widget rendering style. The default is \a as_p.
  119. ///
  120. html_list_type html_list() const;
  121. ///
  122. /// Get the part of the widget that should be generated. See \a widget_part_type. The default is \a first_part.
  123. ///
  124. widget_part_type widget_part() const;
  125. ///
  126. /// Get the output stream.
  127. ///
  128. std::ostream &out() const;
  129. private:
  130. uint32_t html_type_;
  131. uint32_t html_list_type_;
  132. uint32_t widget_part_type_;
  133. std::ostream *output_;
  134. CPPCMS_UNUSED_MEMBER uint32_t reserved_1;
  135. CPPCMS_UNUSED_MEMBER uint32_t reserved_2;
  136. struct _data;
  137. booster::hold_ptr<_data> d;
  138. };
  139. ///
  140. /// \brief This class is the base class for any form or form widget used in CppCMS.
  141. ///
  142. /// It provides basic, abstract operations that every widget or form should implement.
  143. ///
  144. class CPPCMS_API base_form : public form_flags {
  145. public:
  146. ///
  147. /// Render the widget to the output set in \a cppcms::form_context::out()
  148. /// according to the control flags set in \a cppcms::form_flags.
  149. /// Usually this function is called directly by the template rendering functions.
  150. ///
  151. virtual void render(form_context &context) = 0;
  152. ///
  153. /// Load the form information from the provided http::context \a context.
  154. /// A user can call this function to load all information from the raw POST/GET
  155. /// data into the internal widget representation.
  156. ///
  157. virtual void load(http::context &context) = 0;
  158. ///
  159. /// Validate the form according to defined rules. If all checks are OK,
  160. /// true is returned. If some widget or form fails, false is returned.
  161. ///
  162. virtual bool validate() = 0;
  163. ///
  164. /// Clear the form from all user provided data.
  165. ///
  166. virtual void clear() = 0;
  167. ///
  168. /// Set the parent of this form. Used internally. You should not use it.
  169. ///
  170. virtual void parent(base_form *subform) = 0;
  171. ///
  172. /// Get the parent of this form. If this is the topmost form, NULL is returned.
  173. ///
  174. virtual base_form *parent() = 0;
  175. base_form();
  176. virtual ~base_form();
  177. };
  178. ///
  179. /// \brief The \a form is a container used to collect other widgets and forms into a single unit.
  180. ///
  181. /// Generally various widgets and forms are combined into a single form in order to simplify their rendering
  182. /// and validation of the forms that include more than one widget.
  183. ///
  184. class CPPCMS_API form : public booster::noncopyable,
  185. public base_form
  186. {
  187. public:
  188. form();
  189. virtual ~form();
  190. ///
  191. /// Render all the widgets and sub-forms to the \a output, using
  192. /// the flags defined in the \a context.
  193. ///
  194. virtual void render(form_context &context);
  195. ///
  196. /// Load all the widget information from http::context \a cont.
  197. ///
  198. virtual void load(http::context &cont);
  199. ///
  200. /// Validate all subforms and widgets. If at least one of them fails,
  201. /// false is returned. Otherwise, true is returned.
  202. ///
  203. virtual bool validate();
  204. ///
  205. /// Clear all subforms and widgets from all loaded data.
  206. ///
  207. virtual void clear();
  208. ///
  209. /// Add \a subform to form. The ownership is not transferred to
  210. /// the parent.
  211. ///
  212. void add(form &subform);
  213. ///
  214. /// Add \a subform to form. The ownership is transferred to
  215. /// the parent and the subform will be destroyed together with
  216. /// the parent.
  217. ///
  218. void attach(form *subform);
  219. ///
  220. /// Add \a widget to form. The ownership is not transferred to
  221. /// to the parent.
  222. ///
  223. void add(widgets::base_widget &widget);
  224. ///
  225. /// Add \a widget to form. The ownership is transferred to
  226. /// the parent and the widget will be destroyed together with
  227. /// the parent.
  228. ///
  229. void attach(widgets::base_widget *widget);
  230. ///
  231. /// \deprecated Use add(form &) instead
  232. ///
  233. /// Shortcut to \a add.
  234. ///
  235. CPPCMS_DEPRECATED inline form &operator + (form &f)
  236. {
  237. add(f);
  238. return *this;
  239. }
  240. ///
  241. /// \deprecated Use add(widgets::base_widget &) instead
  242. ///
  243. /// Shortcut to \a add.
  244. ///
  245. CPPCMS_DEPRECATED inline form &operator + (widgets::base_widget &f)
  246. {
  247. add(f);
  248. return *this;
  249. }
  250. ///
  251. /// Set the parent of this form. It is used internally; you should not use it. It is called
  252. /// when the form is added or attached to another form.
  253. ///
  254. virtual void parent(base_form *subform);
  255. ///
  256. /// Get the parent of this form. If this is the topmost form, NULL is returned.
  257. /// It is assumed that the parent is always a form.
  258. ///
  259. virtual form *parent();
  260. ///
  261. /// \brief Input iterator used to iterate over all the widgets in a form.
  262. ///
  263. /// This class is mainly used by templates to render widgets. It
  264. /// recursively iterates over all the widgets and subforms.
  265. ///
  266. /// \note it iterates over widgets only and never \ref
  267. /// form objects.
  268. ///
  269. /// \code
  270. /// iterator p=f.begin();
  271. /// if(p!=f.end())
  272. /// if p!=f.end() --> *p is derived from widgets::base_widget.
  273. /// \endcode
  274. ///
  275. class CPPCMS_API iterator : public std::iterator<std::input_iterator_tag,widgets::base_widget>
  276. {
  277. public:
  278. ///
  279. /// End iterator.
  280. ///
  281. iterator();
  282. ///
  283. /// Create a widget iterator.
  284. ///
  285. iterator(form &);
  286. ///
  287. /// Destructor.
  288. ///
  289. ~iterator();
  290. ///
  291. /// Copy the iterator. This operation is not cheap.
  292. ///
  293. iterator(iterator const &other);
  294. ///
  295. /// Assign the iterator. This operation is not cheap.
  296. ///
  297. iterator const &operator = (iterator const &other);
  298. ///
  299. /// Return the underlying widget. Condition: *this!=iterator().
  300. ///
  301. widgets::base_widget *operator->() const
  302. {
  303. return get();
  304. }
  305. ///
  306. /// Return the underlying widget. Condition: *this!=iterator().
  307. ///
  308. widgets::base_widget &operator*() const
  309. {
  310. return *get();
  311. }
  312. ///
  313. /// Check if two iterators point to the same element.
  314. ///
  315. bool operator==(iterator const &other) const
  316. {
  317. return equal(other);
  318. }
  319. ///
  320. /// Check if two iterators point to different elements.
  321. ///
  322. bool operator!=(iterator const &other) const
  323. {
  324. return !equal(other);
  325. }
  326. ///
  327. /// Post increment operator. It forwards the iterator to the next widget.
  328. /// Note it does not point to the higher level form container.
  329. ///
  330. /// Note: it is preferable to use ++i rather than i++ as copying iterators is not cheap.
  331. ///
  332. iterator operator++(int /*unused*/)
  333. {
  334. iterator tmp(*this);
  335. next();
  336. return tmp;
  337. }
  338. ///
  339. /// Increment operator. It forwards the iterator to the next widget.
  340. /// Note it does not point to the higher level form container.
  341. ///
  342. iterator &operator++()
  343. {
  344. next();
  345. return *this;
  346. }
  347. private:
  348. friend class form;
  349. bool equal(iterator const &other) const;
  350. void zero();
  351. void next();
  352. widgets::base_widget *get() const;
  353. std::stack<unsigned> return_positions_;
  354. form *current_;
  355. unsigned offset_;
  356. struct _data;
  357. booster::copy_ptr<_data> d;
  358. };
  359. ///
  360. /// Returns the iterator to the first widget.
  361. ///
  362. iterator begin();
  363. ///
  364. /// Returns the end of the range iterator.
  365. ///
  366. iterator end();
  367. private:
  368. friend class iterator;
  369. struct _data;
  370. // Widget and ownership - true means I own it.
  371. typedef std::pair<base_form *,bool> widget_type;
  372. std::vector<widget_type> elements_;
  373. form *parent_;
  374. booster::hold_ptr<_data> d;
  375. };
  376. ///
  377. /// \brief This namespace includes all the widgets (i.e. parts of HTML forms) supported by cppcms.
  378. ///
  379. namespace widgets {
  380. ///
  381. /// \brief this class is the base class of all renderable widgets which
  382. /// can be used with CppCMS form system.
  383. ///
  384. /// All cppcms widgets are derived from this class. Users who want to create
  385. /// their own custom widgets must derive them from this class.
  386. ///
  387. class CPPCMS_API base_widget :
  388. public base_form,
  389. public booster::noncopyable
  390. {
  391. public:
  392. ///
  393. /// Default constructor.
  394. ///
  395. base_widget();
  396. virtual ~base_widget();
  397. ///
  398. /// Check if a value has been assigned to the widget. It is usually true
  399. /// when the user has assigned a value to the widget or when the widget is loaded.
  400. ///
  401. /// If there is a reasonable default value for the widget
  402. /// then set() should be true. For widgets like file or numeric
  403. /// where explicit parsing is required, the set() value would indicate
  404. /// that user provided some value (i.e. uploaded a file or entered a number).
  405. ///
  406. bool set();
  407. ///
  408. /// After having executed the validation process, each widget can be tested for validity.
  409. ///
  410. bool valid();
  411. ///
  412. /// Get the HTML \a id attribute.
  413. ///
  414. std::string id();
  415. ///
  416. /// Get the HTML \a name attribute.
  417. ///
  418. std::string name();
  419. ///
  420. /// Get the short message that would be displayed near the widget.
  421. ///
  422. locale::message message();
  423. ///
  424. /// Check if a message is set.
  425. ///
  426. bool has_message();
  427. ///
  428. /// Get the error message that would be displayed near the widget
  429. /// if the widget validation failed.
  430. ///
  431. locale::message error_message();
  432. ///
  433. /// Check if an error message is set.
  434. ///
  435. bool has_error_message();
  436. ///
  437. /// Get the eventual long description of the wigget.
  438. ///
  439. locale::message help();
  440. ///
  441. /// Check if a help message is set.
  442. ///
  443. bool has_help();
  444. ///
  445. /// Get the HTML \c disabled attribute.
  446. ///
  447. bool disabled();
  448. ///
  449. /// Set/Unset the HTML \c disabled attribute.
  450. ///
  451. void disabled(bool);
  452. ///
  453. /// Get the HTML \c readonly attribute.
  454. ///
  455. /// \ver{v1_2}
  456. bool readonly();
  457. ///
  458. /// Set/Unset the HTML \c readonly attribute.
  459. ///
  460. /// \ver{v1_2}
  461. void readonly(bool);
  462. ///
  463. /// Get the general user defined attribute string that can be added to the widget.
  464. ///
  465. std::string attributes_string();
  466. ///
  467. /// Set the existence of content for the widget. By default the widget is not set.
  468. /// By convention, trying to fetch a value from a widget that is "unset" will throw an exception.
  469. /// Call set(true) to change the state to "set" and call set(false) to change it to "unset".
  470. ///
  471. void set(bool);
  472. ///
  473. /// Set th validity state of the widget. By default the widget is valid. If it fails to pass
  474. /// the validation, its validity state is changed by calling this function.
  475. ///
  476. /// Note: a widget may be "unset" and still be valid. Conversely, it may be set but be not-valid.
  477. ///
  478. void valid(bool);
  479. ///
  480. /// Set the HTML \c id attribute of the widget.
  481. ///
  482. void id(std::string);
  483. ///
  484. /// Set the HTML \c name attribute of the widget. Note: if this attribute
  485. /// is not set, the widget will not be able to be loaded from the POST/GET
  486. /// data.
  487. ///
  488. void name(std::string);
  489. ///
  490. /// Set a short description for the widget. Generally, it is a good idea to
  491. /// define this value.
  492. ///
  493. /// The short message can also be set using the base_widget constructor.
  494. ///
  495. void message(std::string);
  496. ///
  497. /// Set a short translatable description for the widget. Generally, it is a good idea to
  498. /// define this value.
  499. ///
  500. /// The short message can also be set using the base_widget constructor.
  501. ///
  502. void message(locale::message const &);
  503. ///
  504. /// Set the error message that is displayed for invalid widgets.
  505. ///
  506. /// If it is not set, a simple "*" is shown instead.
  507. ///
  508. void error_message(std::string);
  509. ///
  510. /// Set the translatable error message that is displayed for invalid widgets.
  511. ///
  512. /// If it is not set, a simple "*" is shown instead.
  513. ///
  514. void error_message(locale::message const &);
  515. ///
  516. /// Set a longer help message that describes this widget.
  517. ///
  518. void help(std::string);
  519. ///
  520. /// Set a translatable help message that describes this widget.
  521. ///
  522. void help(locale::message const &msg);
  523. ///
  524. /// Set general HTML attributes that are not directly supported
  525. /// For example:
  526. ///
  527. /// \code
  528. /// my_widget.attributes_string("style='direction:rtl' onclick='return foo()'");
  529. /// \endcode
  530. ///
  531. /// This string is inserted as-is just after render_input_start.
  532. ///
  533. void attributes_string(std::string v);
  534. ///
  535. /// Render the full widget together with error messages and decorations as paragraphs
  536. /// or table elements to the output set in \a cppcms::form_context::out().
  537. ///
  538. virtual void render(form_context &context);
  539. ///
  540. /// This is a virtual member function that should be implemented by each widget.
  541. /// It executes the actual rendering of the HTML form.
  542. ///
  543. virtual void render_input(form_context &context) = 0;
  544. ///
  545. /// Clear the form. It also calls set(false).
  546. ///
  547. virtual void clear();
  548. ///
  549. /// Validate the form. If not overridden, it sets the widget to \a valid.
  550. ///
  551. virtual bool validate();
  552. ///
  553. /// Render standard common attributes like \a id, \a name, \a disabled, etc.
  554. ///
  555. virtual void render_attributes(form_context &context);
  556. ///
  557. /// Set the parent of this widget. It is used internally; you should not use it. It is called
  558. /// when the form is added or attached to another form.
  559. ///
  560. virtual void parent(base_form *subform);
  561. ///
  562. /// Get the parent of this form. If this is the topmost form, NULL is returned.
  563. /// It is assumed that the parent is always a form.
  564. ///
  565. virtual form *parent();
  566. ///
  567. /// This function should be called before actual loading
  568. /// of widgets, it performs cross widgets validation
  569. /// and causes automatic generation of undefined names
  570. ///
  571. void pre_load(http::context &);
  572. protected:
  573. ///
  574. /// This function should be called by overloadeding the load/render methods
  575. /// before the loading/rendering starts.
  576. ///
  577. void auto_generate(form_context *context = 0);
  578. private:
  579. void generate(int position,form_context *context = 0);
  580. std::string id_;
  581. std::string name_;
  582. locale::message message_;
  583. locale::message error_message_;
  584. locale::message help_;
  585. std::string attr_;
  586. form *parent_;
  587. uint32_t is_valid_ : 1;
  588. uint32_t is_set_ : 1;
  589. uint32_t is_disabled_ : 1;
  590. uint32_t is_readonly_ : 1;
  591. uint32_t is_generation_done_ : 1;
  592. uint32_t has_message_ : 1;
  593. uint32_t has_error_ : 1;
  594. uint32_t has_help_ : 1;
  595. CPPCMS_UNUSED_MEMBER uint32_t reserverd_ : 24;
  596. struct _data;
  597. booster::hold_ptr<_data> d;
  598. };
  599. ///
  600. /// \brief This widget is used as base for text input fields.
  601. ///
  602. /// This widget is used as the base class for other widgets that are used for
  603. /// text input like: \ref text, \ref textarea, etc.
  604. ///
  605. /// This widget does much more than reading simple text data from the POST
  606. /// or GET form. It also performs charset validation.
  607. ///
  608. class CPPCMS_API base_text : virtual public base_widget {
  609. public:
  610. base_text();
  611. virtual ~base_text();
  612. ///
  613. /// Get the string that contains the input value of the widget.
  614. ///
  615. std::string value();
  616. ///
  617. /// Set the widget content to the value \a v before rendering.
  618. ///
  619. void value(std::string v);
  620. ///
  621. /// Inform the validator that this text widget should contain some text.
  622. /// It is similar to limits(1,-1).
  623. ///
  624. void non_empty();
  625. ///
  626. /// Set the minimum and maximum limits of the text size. Note: max == -1 indicates that there
  627. /// is no maximum limit; min==0 indicates that there is no minimum limit.
  628. ///
  629. /// Note: these numbers represent the length in Unicode code points (even if the encoding
  630. /// is not Unicode). If the character set validation is disabled, then these numbers represent
  631. /// the number of octets in the string.
  632. ///
  633. void limits(int min,int max);
  634. ///
  635. /// Get the minimum and maximum size limits,
  636. ///
  637. std::pair<int,int> limits();
  638. ///
  639. /// Inform the validator whether it should check the validity of the charset.
  640. /// The default is enabled (true).
  641. ///
  642. /// Generally you should not use this option to disable the charset validation
  643. /// unless you want to load some raw data as
  644. /// form input, or the character set is different from the one defined in the locale.
  645. ///
  646. void validate_charset(bool );
  647. ///
  648. /// Return true if the charset validation is enabled.
  649. ///
  650. bool validate_charset();
  651. ///
  652. /// Validate the widget content according to the rules and to the charset encoding.
  653. ///
  654. /// Notes:
  655. ///
  656. /// - The charset validation is very efficient for variable length UTF-8 encoding as well as
  657. /// for most popular fixed length encodings like ISO-8859-*, windows-125* and koi8*.
  658. /// For other encodings, character set conversion is used for the actual validation.
  659. /// - Special characters (that are not allowed in HTML) are assumed to be forbidden, even if they are
  660. /// valid code points (like NUL = 0 or DEL=127).
  661. ///
  662. virtual bool validate();
  663. ///
  664. /// Load the widget for http::context. It uses the locale given in the context to
  665. /// validate the text.
  666. ///
  667. virtual void load(http::context &);
  668. private:
  669. std::string value_;
  670. int low_;
  671. int high_;
  672. bool validate_charset_;
  673. size_t code_points_;
  674. struct _data;
  675. booster::hold_ptr<_data> d;
  676. };
  677. ///
  678. /// \brief This class represents a basic widget that generates HTML form elements
  679. /// the widgets that use the <input \/> HTML tag.
  680. ///
  681. /// It allows you to create your own widgets more easily. It does most of job required to
  682. /// generate the HTML. The user is only required to generate the actual value like
  683. /// value="10.34" as with a numeric widget.
  684. ///
  685. class CPPCMS_API base_html_input : virtual public base_widget {
  686. public:
  687. ///
  688. /// Create a new instance. \a type is the HTML type tag of the input element, for example "text" or
  689. /// "password".
  690. ///
  691. base_html_input(std::string const &type);
  692. ///
  693. /// Virtual destructor.
  694. ///
  695. virtual ~base_html_input();
  696. ///
  697. /// This function generates the actual HTML. It calls render_value where needed.
  698. ///
  699. virtual void render_input(form_context &context);
  700. protected:
  701. ///
  702. /// Write the actual value of the HTML tag. Derived classes must implement this.
  703. ///
  704. virtual void render_value(form_context &context) = 0;
  705. private:
  706. struct _data;
  707. booster::hold_ptr<_data> d;
  708. std::string type_;
  709. };
  710. ///
  711. /// \brief This class represents an HTML form input element of type text.
  712. ///
  713. class CPPCMS_API text : public base_html_input, public base_text
  714. {
  715. public:
  716. ///
  717. /// Create a text field widget.
  718. ///
  719. text();
  720. ///
  721. /// This constructor is provided for use by derived classes where it is required
  722. /// to change the type of the widget, like text, password, etc.
  723. ///
  724. text(std::string const &type);
  725. ~text();
  726. ///
  727. /// Set the HTML size attribute of the widget.
  728. ///
  729. void size(int n);
  730. ///
  731. /// Get the HTML size attribute size of the widget. It returns -1 if it is undefined.
  732. ///
  733. int size();
  734. virtual void render_attributes(form_context &context);
  735. virtual void render_value(form_context &context);
  736. private:
  737. int size_;
  738. struct _data;
  739. booster::hold_ptr<_data> d;
  740. };
  741. ///
  742. /// \brief This widget represents a hidden input form element. It is used to provide
  743. /// information invisible to the user.
  744. ///
  745. /// I has the same properties as a text widget has but it does not render any HTML
  746. /// for message(), help() and other informational types.
  747. ///
  748. /// When you render the form in templates, it is a good idea to render it separately
  749. /// to make sure that no invalid HTML is created.
  750. ///
  751. class CPPCMS_API hidden : public text
  752. {
  753. public:
  754. hidden();
  755. ~hidden();
  756. ///
  757. /// Render the HTML of the widget. It overrides
  758. /// the default HTML rendering as hidden widget
  759. /// is never displayed.
  760. ///
  761. virtual void render(form_context &context);
  762. private:
  763. struct _data;
  764. booster::hold_ptr<_data> d;
  765. };
  766. ///
  767. /// \brief This text widget behaves similarly to the text widget but uses
  768. /// the \c textarea HTML tag rather than the \c input HTML tag.
  769. ///
  770. class CPPCMS_API textarea : public base_text
  771. {
  772. public:
  773. textarea();
  774. ~textarea();
  775. ///
  776. /// Get the number of rows in the textarea. The default is -1 -- undefined.
  777. ///
  778. int rows();
  779. ///
  780. /// Get the number of columns in the textarea. The default is -1 -- undefined.
  781. ///
  782. int cols();
  783. ///
  784. /// Set the number of rows in the textarea.
  785. ///
  786. void rows(int n);
  787. ///
  788. /// Set the number of columns in the textarea.
  789. ///
  790. void cols(int n);
  791. virtual void render_input(form_context &context);
  792. private:
  793. int rows_,cols_;
  794. struct _data;
  795. booster::hold_ptr<_data> d;
  796. };
  797. ///
  798. /// \brief Widget for number input. It is a template class that assumes that T is a number.
  799. ///
  800. /// This class parses the input and checks if it is input text is a valid
  801. /// numeric value. If it is valid, the set() would return true
  802. /// be true.
  803. ///
  804. /// If the value was not defined, access to value() will throw an exception.
  805. ///
  806. template<typename T>
  807. class numeric: public base_html_input {
  808. public:
  809. numeric() :
  810. base_html_input("text"),
  811. check_low_(false),
  812. check_high_(false),
  813. non_empty_(false)
  814. {
  815. }
  816. ///
  817. /// Inform the validator that this widget should contain some value.
  818. ///
  819. void non_empty()
  820. {
  821. non_empty_=true;
  822. }
  823. ///
  824. /// Get numeric value that was loaded from the POST or
  825. /// GET data.
  826. ///
  827. /// \note if the value was not set (empty field for example)
  828. /// then this function will throw. So it is good idea to
  829. /// check if \ref set() returns true before using this
  830. /// function.
  831. ///
  832. T value()
  833. {
  834. if(!set())
  835. throw cppcms_error("Value not loaded");
  836. return value_;
  837. }
  838. ///
  839. /// Set the value of the widget.
  840. ///
  841. void value(T v)
  842. {
  843. set(true);
  844. value_=v;
  845. }
  846. ///
  847. /// Set the minimum valid value.
  848. ///
  849. void low(T a)
  850. {
  851. min_=a;
  852. check_low_=true;
  853. non_empty();
  854. }
  855. ///
  856. /// Set the maximum valid value.
  857. ///
  858. void high(T b)
  859. {
  860. max_=b;
  861. check_high_=true;
  862. non_empty();
  863. }
  864. ///
  865. /// Same as low(a); high(b);
  866. ///
  867. void range(T a,T b)
  868. {
  869. low(a);
  870. high(b);
  871. }
  872. ///
  873. /// Render the first part of the widget.
  874. ///
  875. virtual void render_value(form_context &context)
  876. {
  877. if(set())
  878. context.out()<<"value=\""<<value_<<"\" ";
  879. else
  880. context.out()<<"value=\""<<util::escape(loaded_string_)<<"\" ";
  881. }
  882. virtual void clear()
  883. {
  884. base_html_input::clear();
  885. loaded_string_.clear();
  886. }
  887. ///
  888. /// Load the widget data.
  889. ///
  890. virtual void load(http::context &context)
  891. {
  892. pre_load(context);
  893. loaded_string_.clear();
  894. set(false);
  895. valid(true);
  896. http::request::form_type::const_iterator p;
  897. http::request::form_type const &request=context.request().post_or_get();
  898. p=request.find(name());
  899. if(p==request.end()) {
  900. return;
  901. }
  902. else {
  903. loaded_string_=p->second;
  904. if(loaded_string_.empty())
  905. return;
  906. std::istringstream ss(loaded_string_);
  907. ss.imbue(context.locale());
  908. ss>>value_;
  909. if(ss.fail() || !ss.eof())
  910. valid(false);
  911. else
  912. set(true);
  913. }
  914. }
  915. ///
  916. /// Validate the widget.
  917. ///
  918. virtual bool validate()
  919. {
  920. if(!valid())
  921. return false;
  922. if(!set()) {
  923. if(non_empty_) {
  924. valid(false);
  925. return false;
  926. }
  927. return true;
  928. }
  929. if(check_low_ && value_ <min_) {
  930. valid(false);
  931. return false;
  932. }
  933. if(check_high_ && value_ > max_) {
  934. valid(false);
  935. return false;
  936. }
  937. return true;
  938. }
  939. private:
  940. T min_,max_,value_;
  941. bool check_low_;
  942. bool check_high_;
  943. bool non_empty_;
  944. std::string loaded_string_;
  945. };
  946. ///
  947. /// \brief The password widget is a simple text widget with few, obvious differences.
  948. //
  949. class CPPCMS_API password: public text {
  950. public:
  951. password();
  952. ~password();
  953. ///
  954. /// Set the equality constraint to another password widget. This password should be
  955. /// equal to the one in \a p2. It is usefull when creating new passwords: if the passwords
  956. /// are not equal, the validation will fail.
  957. ///
  958. void check_equal(password &p2);
  959. virtual bool validate();
  960. private:
  961. struct _data;
  962. booster::hold_ptr<_data> d;
  963. password *password_to_check_;
  964. };
  965. ///
  966. /// \brief This class is extending a simple text widget by using additional regular expression validation.
  967. ///
  968. class CPPCMS_API regex_field : public text {
  969. public:
  970. regex_field();
  971. ///
  972. /// Create a widget using the regular expression \a e.
  973. ///
  974. regex_field(booster::regex const &e);
  975. ///
  976. /// Create a widget using the regular expression \a e.
  977. ///
  978. regex_field(std::string const &e);
  979. ///
  980. /// Set the regular expression.
  981. ///
  982. void regex(booster::regex const &e);
  983. ~regex_field();
  984. virtual bool validate();
  985. private:
  986. booster::regex expression_;
  987. struct _data;
  988. booster::hold_ptr<_data> d;
  989. };
  990. ///
  991. /// \brief This widget checks that the input is a valid email address.
  992. ///
  993. class CPPCMS_API email : public regex_field {
  994. public:
  995. email();
  996. ~email();
  997. private:
  998. struct _data;
  999. booster::hold_ptr<_data> d;
  1000. };
  1001. ///
  1002. /// \brief This class represent an HTML checkbox input element.
  1003. ///
  1004. class CPPCMS_API checkbox: public base_html_input {
  1005. public:
  1006. ///
  1007. /// The constructor that allows you to specify \c type HTML
  1008. /// attribute. It is passed to the constructor of the
  1009. /// \ref base_html_input class.
  1010. ///
  1011. checkbox(std::string const &type);
  1012. ///
  1013. /// Default constructor.
  1014. ///
  1015. checkbox();
  1016. virtual ~checkbox();
  1017. ///
  1018. /// Return true if the checkbox was checked (selected).
  1019. ///
  1020. bool value();
  1021. ///
  1022. /// Set the state as \a checked.
  1023. ///
  1024. void value(bool is_set);
  1025. ///
  1026. /// Get the unique identification string of the checkbox.
  1027. ///
  1028. std::string identification();
  1029. ///
  1030. /// Set the unique identification string of the checkbox. It is useful when you want to
  1031. /// have many options with the same name.
  1032. ///
  1033. void identification(std::string const &);
  1034. virtual void render_value(form_context &context);
  1035. virtual void load(http::context &context);
  1036. private:
  1037. struct _data;
  1038. booster::hold_ptr<_data> d;
  1039. std::string identification_;
  1040. bool value_;
  1041. };
  1042. ///
  1043. /// \brief This widget represents an HTML multiple select form element.
  1044. ///
  1045. class CPPCMS_API select_multiple : public base_widget {
  1046. public:
  1047. select_multiple();
  1048. ~select_multiple();
  1049. ///
  1050. /// Add to the multiple select a new option with the display name \a msg, and specify if it is initially
  1051. /// selected. The default is \a false.
  1052. ///
  1053. void add(std::string const &msg,bool selected=false);
  1054. ///
  1055. /// Add to the multiple select a new option with the display name \a msg, and specify if it is initially
  1056. /// selected (the default is \a false), providing a unique identification string to use as the element's \a id.
  1057. ///
  1058. void add(std::string const &msg,std::string const &id,bool selected=false);
  1059. ///
  1060. /// Add to the multiple select a new option with the localized display name \a msg, and specify if it is initially
  1061. /// selected. The default is \a false.
  1062. ///
  1063. void add(locale::message const &msg,bool selected=false);
  1064. ///
  1065. /// Add to the multiple select a new option with the localized display name \a msg, and specify if it is initially
  1066. /// selected (the default is \a false), providing a unique identification string to use as the element's \a id.
  1067. ///
  1068. void add(locale::message const &msg,std::string const &id,bool selected=false);
  1069. ///
  1070. /// Get the mapping of all the selected items according to the order they where added to the multiple select list.
  1071. ///
  1072. std::vector<bool> selected_map();
  1073. ///
  1074. /// Get all the selected items ids according to the order they where added to the list. If no
  1075. /// specific id was given, a string like "0", "1"... will be used.
  1076. ///
  1077. std::set<std::string> selected_ids();
  1078. ///
  1079. /// Get the minimum amount of options that can be chosen. The default is \a 0.
  1080. ///
  1081. unsigned at_least();
  1082. ///
  1083. /// Set the minimum amount of options that can be chosen. The default is \a 0.
  1084. ///
  1085. void at_least(unsigned v);
  1086. ///
  1087. /// Get the maximum amount of options that can be chosen. The default is unlimited.
  1088. ///
  1089. unsigned at_most();
  1090. ///
  1091. /// Set the maximum amount of options that can be chosen. The default is unlimited.
  1092. ///
  1093. void at_most(unsigned v);
  1094. ///
  1095. /// Same as at_least(1).
  1096. ///
  1097. void non_empty();
  1098. ///
  1099. /// Get the number of rows used to display the widget. The default is \a 0 -- undefined.
  1100. ///
  1101. unsigned rows();
  1102. ///
  1103. /// Set the number of rows used to display the widget. The default is \a 0 -- undefined.
  1104. ///
  1105. void rows(unsigned n);
  1106. virtual void render_input(form_context &context);
  1107. virtual bool validate();
  1108. virtual void load(http::context &context);
  1109. virtual void clear();
  1110. private:
  1111. struct _data;
  1112. booster::hold_ptr<_data> d;
  1113. struct element {
  1114. element();
  1115. element(std::string const &v,locale::message const &msg,bool sel);
  1116. element(std::string const &v,std::string const &msg,bool sel);
  1117. uint32_t selected : 1;
  1118. uint32_t need_translation : 1;
  1119. uint32_t original_select : 1;
  1120. CPPCMS_UNUSED_MEMBER uint32_t reserved : 29;
  1121. std::string id;
  1122. std::string str_option;
  1123. locale::message tr_option;
  1124. friend std::ostream &operator<<(std::ostream &out,element const &el);
  1125. };
  1126. std::vector<element> elements_;
  1127. unsigned low_;
  1128. unsigned high_;
  1129. unsigned rows_;
  1130. };
  1131. ///
  1132. /// \brief This is the base class for "select" like widgets which include dropdown lists
  1133. /// and radio button sets.
  1134. ///
  1135. class CPPCMS_API select_base : public base_widget {
  1136. public:
  1137. select_base();
  1138. virtual ~select_base();
  1139. ///
  1140. /// Add a new entry to the selection list.
  1141. ///
  1142. void add(std::string const &string);
  1143. ///
  1144. /// Add to the selection list a new entry with the unique identification string \a id.
  1145. ///
  1146. void add(std::string const &string,std::string const &id);
  1147. ///
  1148. /// Add a new localized entry to the selection list.
  1149. ///
  1150. void add(locale::message const &msg);
  1151. ///
  1152. /// Add to the selection list a new localized entry with the unique identification string \a id.
  1153. ///
  1154. void add(locale::message const &msg,std::string const &id);
  1155. ///
  1156. /// Return the number of the selected entry in the list. Entries are numbered starting from 0. -1 indicates that nothing
  1157. /// was selected.
  1158. ///
  1159. int selected();
  1160. ///
  1161. /// Return the identification string of the selected entry in the list. An empty string indicates that
  1162. /// nothing was selected.
  1163. ///
  1164. std::string selected_id();
  1165. ///
  1166. /// Select the entry numbered \a no.
  1167. ///
  1168. void selected(int no);
  1169. ///
  1170. /// Select the entry with the identification string \a id.
  1171. ///
  1172. void selected_id(std::string id);
  1173. ///
  1174. /// Require that one item in the list should be selected (for the validation).
  1175. ///
  1176. void non_empty();
  1177. virtual void render_input(form_context &context) = 0;
  1178. virtual bool validate();
  1179. virtual void load(http::context &context);
  1180. virtual void clear();
  1181. protected:
  1182. struct CPPCMS_API element {
  1183. element();
  1184. element(std::string const &v,locale::message const &msg);
  1185. element(std::string const &v,std::string const &msg);
  1186. element(element const &);
  1187. element const &operator=(element const &);
  1188. ~element();
  1189. uint32_t need_translation : 1;
  1190. CPPCMS_UNUSED_MEMBER uint32_t reserved : 31;
  1191. std::string id;
  1192. std::string str_option;
  1193. locale::message tr_option;
  1194. private:
  1195. struct _data;
  1196. booster::copy_ptr<_data> d;
  1197. };
  1198. std::vector<element> elements_;
  1199. private:
  1200. struct _data;
  1201. booster::hold_ptr<_data> d;
  1202. int selected_;
  1203. int default_selected_;
  1204. uint32_t non_empty_ : 1;
  1205. CPPCMS_UNUSED_MEMBER uint32_t reserverd : 32;
  1206. };
  1207. ///
  1208. /// \brief The widget that uses a drop-down list for selection.
  1209. ///
  1210. class CPPCMS_API select : public select_base {
  1211. public:
  1212. select();
  1213. virtual ~select();
  1214. virtual void render_input(form_context &context);
  1215. private:
  1216. struct _data;
  1217. booster::hold_ptr<_data> d;
  1218. };
  1219. ///
  1220. /// \brief The widget that uses a set of radio buttons..
  1221. ///
  1222. class CPPCMS_API radio : public select_base {
  1223. public:
  1224. radio();
  1225. virtual ~radio();
  1226. virtual void render_input(form_context &context);
  1227. ///
  1228. /// Return the rendering order
  1229. ///
  1230. bool vertical();
  1231. ///
  1232. /// Set rendering order of the list one behind other (default)
  1233. /// or in same line.
  1234. ///
  1235. /// Baiscally it defines whether the radio buttons should
  1236. /// appear in row (false) or in column (true).
  1237. ///
  1238. void vertical(bool);
  1239. private:
  1240. uint32_t vertical_ : 1;
  1241. CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 31;
  1242. struct _data;
  1243. booster::hold_ptr<_data> d;
  1244. };
  1245. ///
  1246. /// \brief This class represents a file upload form entry.
  1247. ///
  1248. /// If the file was not uploaded, set() will be false and
  1249. /// an attempt to access the member function value() will throw.
  1250. ///
  1251. class CPPCMS_API file : public base_html_input {
  1252. public:
  1253. ///
  1254. /// Ensure that a file is uploaded (for the validation).
  1255. ///
  1256. void non_empty();
  1257. ///
  1258. /// Set the minimum and maximum limits for the file size. Note: max == -1 indicates that there
  1259. /// is no maximum limit; min==0 indicates that there is no minimum limit.
  1260. ///
  1261. ///
  1262. void limits(int min,int max);
  1263. ///
  1264. /// Get the minimum and maximum size limits.
  1265. ///
  1266. std::pair<int,int> limits();
  1267. ///
  1268. /// Set the filename validation pattern. For example ".*\\.(jpg|jpeg|png)".
  1269. ///
  1270. /// Please, note that it is a good idea to check magic numbers as well
  1271. /// and not rely on file name only.
  1272. ///
  1273. /// See add_valid_magic() function
  1274. ///
  1275. void filename(booster::regex const &fn);
  1276. ///
  1277. /// Get the regular expression for the filename validation.
  1278. ///
  1279. booster::regex filename();
  1280. ///
  1281. /// Validate or not the filename's charset. The default is \a true.
  1282. ///
  1283. void validate_filename_charset(bool);
  1284. ///
  1285. /// Get the validation option for the filename's charset.
  1286. ///
  1287. bool validate_filename_charset();
  1288. ///
  1289. /// Get the uploaded file. This throws cppcms_error if set() == false, i.e. if no file
  1290. /// was uploaded.
  1291. ///
  1292. booster::shared_ptr<http::file> value();
  1293. ///
  1294. /// Set the required file mime type.
  1295. ///
  1296. void mime(std::string const &);
  1297. ///
  1298. /// Set the regular expression to validate the mime type.
  1299. ///
  1300. void mime(booster::regex const &expr);
  1301. ///
  1302. /// Add a string that represents a valid magic number that shoud exist on begging of file.
  1303. ///
  1304. /// By default no tests are performed.
  1305. ///
  1306. void add_valid_magic(std::string const &);
  1307. virtual void load(http::context &context);
  1308. virtual void render_value(form_context &context);
  1309. virtual bool validate();
  1310. file();
  1311. ~file();
  1312. private:
  1313. int size_min_;
  1314. int size_max_;
  1315. std::vector<std::string> magics_;
  1316. std::string mime_string_;
  1317. booster::regex mime_regex_;
  1318. booster::regex filename_regex_;
  1319. uint32_t check_charset_ : 1;
  1320. uint32_t check_non_empty_ : 1;
  1321. CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 30;
  1322. booster::shared_ptr<http::file> file_;
  1323. struct _data;
  1324. booster::hold_ptr<_data> d;
  1325. };
  1326. ///
  1327. /// \brief Submit button widget.
  1328. ///
  1329. class CPPCMS_API submit : public base_html_input {
  1330. public:
  1331. submit();
  1332. ~submit();
  1333. ///
  1334. /// Return true if this specific button was pressed.
  1335. ///
  1336. bool value();
  1337. ///
  1338. /// Set the text on the button.
  1339. ///
  1340. void value(std::string val);
  1341. ///
  1342. /// Set the text on the button.
  1343. ///
  1344. void value(locale::message const &msg);
  1345. virtual void render_value(form_context &context);
  1346. virtual void load(http::context &context);
  1347. private:
  1348. struct _data;
  1349. booster::hold_ptr<_data> d;
  1350. bool pressed_;
  1351. locale::message value_;
  1352. };
  1353. } // widgets
  1354. } //cppcms
  1355. #endif // CPPCMS_FORM_H