CppCMS
form.h
1 //
3 // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
4 //
5 // See accompanying file COPYING.TXT file for licensing details.
6 //
8 #ifndef CPPCMS_FORM_H
9 #define CPPCMS_FORM_H
10 
11 #include <cppcms/defs.h>
12 #include <booster/noncopyable.h>
13 
14 #include <string>
15 #include <set>
16 #include <map>
17 #include <list>
18 #include <vector>
19 #include <stack>
20 #include <ostream>
21 #include <sstream>
22 #include <cppcms/http_context.h>
23 #include <cppcms/http_request.h>
24 #include <cppcms/http_response.h>
25 #include <booster/copy_ptr.h>
26 #include <booster/perl_regex.h>
27 #include <booster/shared_ptr.h>
28 #include <cppcms/cppcms_error.h>
29 #include <cppcms/util.h>
30 #include <cppcms/localization.h>
31 
32 namespace cppcms {
33 
34  namespace http {
35  class file;
36  }
37 
38  namespace widgets {
39  class base_widget;
40  }
41 
45  struct form_flags {
49  typedef enum {
50  as_html = 0,
51  as_xhtml= 1,
52  } html_type;
53 
57  typedef enum {
58  as_p = 0 ,
59  as_table= 1 ,
60  as_ul = 2 ,
61  as_dl = 3 ,
64 
68  typedef enum {
69  first_part = 0,
72  };
73 
77  class CPPCMS_API form_context : public form_flags
78  {
79  public:
83  form_context();
84 
88  form_context(form_context const &other);
89 
93  form_context const &operator = (form_context const &other);
94 
102  form_context( std::ostream &output,
105 
109  ~form_context();
110 
114  void html(html_type t);
115 
119  void html_list(html_list_type t);
120 
124  void widget_part(widget_part_type t);
125 
129  void out(std::ostream &out);
130 
134  html_type html() const;
135 
139  html_list_type html_list() const;
140 
144  widget_part_type widget_part() const;
145 
149  std::ostream &out() const;
150 
151  private:
152  uint32_t html_type_;
153  uint32_t html_list_type_;
154  uint32_t widget_part_type_;
155  std::ostream *output_;
156  uint32_t reserved_1;
157  uint32_t reserved_2;
158  struct _data;
160 
161  };
162 
163 
169  class CPPCMS_API base_form : public form_flags {
170  public:
176  virtual void render(form_context &context) = 0;
177 
183  virtual void load(http::context &context) = 0;
184 
189  virtual bool validate() = 0;
190 
194  virtual void clear() = 0;
195 
199  virtual void parent(base_form *subform) = 0;
200 
204  virtual base_form *parent() = 0;
205 
206  base_form();
207  virtual ~base_form();
208  };
209 
216  class CPPCMS_API form : public booster::noncopyable,
217  public base_form
218  {
219  public:
220  form();
221  virtual ~form();
222 
227  virtual void render(form_context &context);
228 
232  virtual void load(http::context &cont);
233 
238  virtual bool validate();
239 
243  virtual void clear();
244 
249  void add(form &subform);
250 
256  void attach(form *subform);
257 
262  void add(widgets::base_widget &widget);
263 
269  void attach(widgets::base_widget *widget);
270 
276  CPPCMS_DEPRECATED inline form &operator + (form &f)
277  {
278  add(f);
279  return *this;
280  }
281 
287  CPPCMS_DEPRECATED inline form &operator + (widgets::base_widget &f)
288  {
289  add(f);
290  return *this;
291  }
292 
297  virtual void parent(base_form *subform);
298 
303  virtual form *parent();
304 
320  class CPPCMS_API iterator : public std::iterator<std::input_iterator_tag,widgets::base_widget>
321  {
322  public:
326  iterator();
327 
331  iterator(form &);
332 
336  ~iterator();
337 
341  iterator(iterator const &other);
342 
346  iterator const &operator = (iterator const &other);
347 
352  {
353  return get();
354  }
355 
360  {
361  return *get();
362  }
363 
367  bool operator==(iterator const &other) const
368  {
369  return equal(other);
370  }
371 
375  bool operator!=(iterator const &other) const
376  {
377  return !equal(other);
378  }
379 
386  iterator operator++(int /*unused*/)
387  {
388  iterator tmp(*this);
389  next();
390  return tmp;
391  }
392 
398  {
399  next();
400  return *this;
401  }
402 
403  private:
404 
405  friend class form;
406 
407  bool equal(iterator const &other) const;
408  void zero();
409  void next();
410  widgets::base_widget *get() const;
411 
412  std::stack<unsigned> return_positions_;
413  form *current_;
414  unsigned offset_;
415  struct _data;
417 
418  };
419 
423  iterator begin();
424 
428  iterator end();
429 
430 
431  private:
432  friend class iterator;
433 
434  struct _data;
435  // Widget and ownership - true means I own it.
436  typedef std::pair<base_form *,bool> widget_type;
437  std::vector<widget_type> elements_;
438  form *parent_;
440  };
441 
442 
443 
447  namespace widgets {
448 
456 
457  class CPPCMS_API base_widget :
458  public base_form,
459  public booster::noncopyable
460  {
461  public:
465  base_widget();
466 
467  virtual ~base_widget();
468 
478  bool set();
479 
483  bool valid();
484 
488  std::string id();
489 
493  std::string name();
494 
499 
503  bool has_message();
504 
509  locale::message error_message();
510 
514  bool has_error_message();
515 
519  locale::message help();
520 
524  bool has_help();
525 
529  bool disabled();
530 
534  void disabled(bool);
535 
539  std::string attributes_string();
540 
546  void set(bool);
547 
554  void valid(bool);
555 
559  void id(std::string);
560 
566  void name(std::string);
567 
574  void message(std::string);
575 
582  void message(locale::message const &);
583 
589  void error_message(std::string);
590 
596  void error_message(locale::message const &);
597 
601  void help(std::string);
602 
606  void help(locale::message const &msg);
607 
618  void attributes_string(std::string v);
619 
620 
625  virtual void render(form_context &context);
626 
631  virtual void render_input(form_context &context) = 0;
632 
636  virtual void clear();
637 
641  virtual bool validate();
642 
646  virtual void render_attributes(form_context &context);
647 
652  virtual void parent(base_form *subform);
653 
658  virtual form *parent();
659 
665  void pre_load(http::context &);
666 
667  protected:
672  void auto_generate(form_context *context = 0);
673 
674  private:
675  void generate(int position,form_context *context = 0);
676 
677  std::string id_;
678  std::string name_;
679  locale::message message_;
680  locale::message error_message_;
681  locale::message help_;
682  std::string attr_;
683  form *parent_;
684 
685  uint32_t is_valid_ : 1;
686  uint32_t is_set_ : 1;
687  uint32_t is_disabled_ : 1;
688  uint32_t is_generation_done_ : 1;
689  uint32_t has_message_ : 1;
690  uint32_t has_error_ : 1;
691  uint32_t has_help_ : 1;
692  uint32_t reserverd_ : 25;
693 
694  struct _data;
696  };
697 
707  class CPPCMS_API base_text : virtual public base_widget {
708  public:
709 
710  base_text();
711  virtual ~base_text();
712 
716  std::string value();
717 
721  void value(std::string v);
722 
727  void non_empty();
728 
737  void limits(int min,int max);
738 
742  std::pair<int,int> limits();
743 
752  void validate_charset(bool );
753 
757  bool validate_charset();
758 
770  virtual bool validate();
771 
776  virtual void load(http::context &);
777 
778  private:
779  std::string value_;
780  int low_;
781  int high_;
782  bool validate_charset_;
783  size_t code_points_;
784  struct _data;
786  };
787 
796 
797  class CPPCMS_API base_html_input : virtual public base_widget {
798  public:
803  base_html_input(std::string const &type);
804 
808  virtual ~base_html_input();
809 
813  virtual void render_input(form_context &context);
814 
815  protected:
819  virtual void render_value(form_context &context) = 0;
820 
821  private:
822  struct _data;
824  std::string type_;
825  };
826 
830  class CPPCMS_API text : public base_html_input, public base_text
831  {
832  public:
836  text();
837 
842  text(std::string const &type);
843 
844  ~text();
845 
849  void size(int n);
850 
854  int size();
855 
856 
857  virtual void render_attributes(form_context &context);
858  virtual void render_value(form_context &context);
859 
860  private:
861  int size_;
862  struct _data;
864  };
865 
876  class CPPCMS_API hidden : public text
877  {
878  public:
879  hidden();
880  ~hidden();
886  virtual void render(form_context &context);
887  private:
888  struct _data;
890  };
891 
892 
897  class CPPCMS_API textarea : public base_text
898  {
899  public:
900  textarea();
901  ~textarea();
902 
906  int rows();
907 
911  int cols();
912 
916  void rows(int n);
917 
921  void cols(int n);
922 
923  virtual void render_input(form_context &context);
924 
925  private:
926  int rows_,cols_;
927 
928  struct _data;
930  };
931 
941  template<typename T>
942  class numeric: public base_html_input {
943  public:
944  numeric() :
945  base_html_input("text"),
946  check_low_(false),
947  check_high_(false),
948  non_empty_(false)
949  {
950  }
951 
955  void non_empty()
956  {
957  non_empty_=true;
958  }
959 
960 
970  T value()
971  {
972  if(!set())
973  throw cppcms_error("Value not loaded");
974  return value_;
975  }
976 
980  void value(T v)
981  {
982  set(true);
983  value_=v;
984  }
985 
989  void low(T a)
990  {
991  min_=a;
992  check_low_=true;
993  non_empty();
994  }
995 
999  void high(T b)
1000  {
1001  max_=b;
1002  check_high_=true;
1003  non_empty();
1004  }
1005 
1009  void range(T a,T b)
1010  {
1011  low(a);
1012  high(b);
1013  }
1014 
1018  virtual void render_value(form_context &context)
1019  {
1020  if(set())
1021  context.out()<<"value=\""<<value_<<"\" ";
1022  else
1023  context.out()<<"value=\""<<util::escape(loaded_string_)<<"\" ";
1024  }
1025 
1026  virtual void clear()
1027  {
1029  loaded_string_.clear();
1030  }
1031 
1035  virtual void load(http::context &context)
1036  {
1037  pre_load(context);
1038 
1039  loaded_string_.clear();
1040 
1041  set(false);
1042  valid(true);
1043 
1044  http::request::form_type::const_iterator p;
1045  http::request::form_type const &request=context.request().post_or_get();
1046  p=request.find(name());
1047  if(p==request.end()) {
1048  return;
1049  }
1050  else {
1051  loaded_string_=p->second;
1052  if(loaded_string_.empty())
1053  return;
1054 
1055  std::istringstream ss(loaded_string_);
1056  ss.imbue(context.locale());
1057  ss>>value_;
1058  if(ss.fail() || !ss.eof())
1059  valid(false);
1060  else
1061  set(true);
1062  }
1063  }
1064 
1068  virtual bool validate()
1069  {
1070  if(!valid())
1071  return false;
1072  if(!set()) {
1073  if(non_empty_) {
1074  valid(false);
1075  return false;
1076  }
1077  return true;
1078  }
1079  if(check_low_ && value_ <min_) {
1080  valid(false);
1081  return false;
1082  }
1083  if(check_high_ && value_ > max_) {
1084  valid(false);
1085  return false;
1086  }
1087  return true;
1088  }
1089 
1090  private:
1091 
1092  T min_,max_,value_;
1093 
1094  bool check_low_;
1095  bool check_high_;
1096  bool non_empty_;
1097  std::string loaded_string_;
1098  };
1099 
1102  //
1103  class CPPCMS_API password: public text {
1104  public:
1105  password();
1106 
1107  ~password();
1108 
1114  void check_equal(password &p2);
1115  virtual bool validate();
1116 
1117  private:
1118  struct _data;
1120  password *password_to_check_;
1121  };
1122 
1123 
1127  class CPPCMS_API regex_field : public text {
1128  public:
1129  regex_field();
1133  regex_field(booster::regex const &e);
1134 
1138  regex_field(std::string const &e);
1139 
1140 
1144  void regex(booster::regex const &e);
1145 
1146  ~regex_field();
1147 
1148  virtual bool validate();
1149 
1150  private:
1151  booster::regex expression_;
1152  struct _data;
1154  };
1155 
1159  class CPPCMS_API email : public regex_field {
1160  public:
1161 
1162  email();
1163  ~email();
1164 
1165  private:
1166  struct _data;
1168  };
1169 
1173  class CPPCMS_API checkbox: public base_html_input {
1174  public:
1180  checkbox(std::string const &type);
1181 
1185  checkbox();
1186  virtual ~checkbox();
1187 
1191  bool value();
1192 
1196  void value(bool is_set);
1197 
1201  std::string identification();
1202 
1207  void identification(std::string const &);
1208 
1209  virtual void render_value(form_context &context);
1210  virtual void load(http::context &context);
1211 
1212  private:
1213  struct _data;
1215  std::string identification_;
1216  bool value_;
1217  };
1218 
1222  class CPPCMS_API select_multiple : public base_widget {
1223  public:
1224  select_multiple();
1225  ~select_multiple();
1226 
1231  void add(std::string const &msg,bool selected=false);
1232 
1237  void add(std::string const &msg,std::string const &id,bool selected=false);
1238 
1243  void add(locale::message const &msg,bool selected=false);
1244 
1249  void add(locale::message const &msg,std::string const &id,bool selected=false);
1250 
1254  std::vector<bool> selected_map();
1255 
1260  std::set<std::string> selected_ids();
1261 
1265  unsigned at_least();
1266 
1270  void at_least(unsigned v);
1271 
1275  unsigned at_most();
1276 
1280  void at_most(unsigned v);
1281 
1285  void non_empty();
1286 
1290  unsigned rows();
1291 
1295  void rows(unsigned n);
1296 
1297  virtual void render_input(form_context &context);
1298  virtual bool validate();
1299  virtual void load(http::context &context);
1300  virtual void clear();
1301 
1302  private:
1303  struct _data;
1305 
1306  struct element {
1307  element();
1308  element(std::string const &v,locale::message const &msg,bool sel);
1309  element(std::string const &v,std::string const &msg,bool sel);
1310  uint32_t selected : 1;
1311  uint32_t need_translation : 1;
1312  uint32_t original_select : 1;
1313  uint32_t reserved : 29;
1314  std::string id;
1315  std::string str_option;
1316  locale::message tr_option;
1317  friend std::ostream &operator<<(std::ostream &out,element const &el);
1318  };
1319 
1320  std::vector<element> elements_;
1321 
1322  unsigned low_;
1323  unsigned high_;
1324  unsigned rows_;
1325 
1326  };
1327 
1332  class CPPCMS_API select_base : public base_widget {
1333  public:
1334  select_base();
1335  virtual ~select_base();
1336 
1340  void add(std::string const &string);
1341 
1345  void add(std::string const &string,std::string const &id);
1346 
1350  void add(locale::message const &msg);
1351 
1355  void add(locale::message const &msg,std::string const &id);
1356 
1361  int selected();
1362 
1367  std::string selected_id();
1368 
1372  void selected(int no);
1373 
1377  void selected_id(std::string id);
1378 
1382  void non_empty();
1383 
1384  virtual void render_input(form_context &context) = 0;
1385  virtual bool validate();
1386  virtual void load(http::context &context);
1387  virtual void clear();
1388 
1389  protected:
1390  struct CPPCMS_API element {
1391 
1392  element();
1393  element(std::string const &v,locale::message const &msg);
1394  element(std::string const &v,std::string const &msg);
1395  element(element const &);
1396  element const &operator=(element const &);
1397  ~element();
1398 
1399  uint32_t need_translation : 1;
1400  uint32_t reserved : 31;
1401  std::string id;
1402  std::string str_option;
1403  locale::message tr_option;
1404 
1405  private:
1406  struct _data;
1408 
1409  };
1410 
1411  std::vector<element> elements_;
1412 
1413  private:
1414  struct _data;
1416 
1417  int selected_;
1418  int default_selected_;
1419 
1420  uint32_t non_empty_ : 1;
1421  uint32_t reserverd : 32;
1422  };
1423 
1427  class CPPCMS_API select : public select_base {
1428  public:
1429  select();
1430  virtual ~select();
1431  virtual void render_input(form_context &context);
1432 
1433  private:
1434  struct _data;
1436  };
1437 
1441  class CPPCMS_API radio : public select_base {
1442  public:
1443  radio();
1444  virtual ~radio();
1445  virtual void render_input(form_context &context);
1446 
1450  bool vertical();
1451 
1459  void vertical(bool);
1460 
1461  private:
1462  uint32_t vertical_ : 1;
1463  uint32_t reserved_ : 31;
1464 
1465  struct _data;
1467  };
1468 
1475  class CPPCMS_API file : public base_html_input {
1476  public:
1480  void non_empty();
1481 
1487  void limits(int min,int max);
1488 
1492  std::pair<int,int> limits();
1493 
1502  void filename(booster::regex const &fn);
1503 
1507  booster::regex filename();
1508 
1512  void validate_filename_charset(bool);
1513 
1517  bool validate_filename_charset();
1518 
1524 
1528  void mime(std::string const &);
1529 
1533  void mime(booster::regex const &expr);
1534 
1540  void add_valid_magic(std::string const &);
1541 
1542  virtual void load(http::context &context);
1543  virtual void render_value(form_context &context);
1544  virtual bool validate();
1545 
1546  file();
1547  ~file();
1548 
1549  private:
1550 
1551  int size_min_;
1552  int size_max_;
1553 
1554  std::vector<std::string> magics_;
1555 
1556  std::string mime_string_;
1557  booster::regex mime_regex_;
1558  booster::regex filename_regex_;
1559 
1560  uint32_t check_charset_ : 1;
1561  uint32_t check_non_empty_ : 1;
1562  uint32_t reserved_ : 30;
1563 
1565 
1566  struct _data;
1568  };
1569 
1570 
1574  class CPPCMS_API submit : public base_html_input {
1575  public:
1576  submit();
1577  ~submit();
1578 
1582  bool value();
1583 
1587  void value(std::string val);
1588 
1592  void value(locale::message const &msg);
1593 
1594  virtual void render_value(form_context &context);
1595  virtual void load(http::context &context);
1596 
1597  private:
1598  struct _data;
1600  bool pressed_;
1601  locale::message value_;
1602  };
1603 
1604 
1605 
1606 
1607  } // widgets
1608 
1609 
1610 } //cppcms
1611 
1612 #endif // CPPCMS_FORM_H
void out(std::ostream &out)
This is a simple wrapper of PCRE library.
Definition: perl_regex.h:35
void range(T a, T b)
Definition: form.h:1009
bool operator==(iterator const &other) const
Definition: form.h:367
Submit button widget.
Definition: form.h:1574
This is the base class for "select" like widgets which include dropdown lists and radio button sets...
Definition: form.h:1332
This widget is used as base for text input fields.
Definition: form.h:707
bool operator!=(iterator const &other) const
Definition: form.h:375
This class represents the context required to generate the widgets' HTML.
Definition: form.h:77
Render each widget using definitions list.
Definition: form.h:61
render form/widget as ordinary HTML
Definition: form.h:50
This class is the base class for any form or form widget used in CppCMS.
Definition: form.h:169
render form/widget as XHTML
Definition: form.h:51
iterator & operator++()
Definition: form.h:397
std::string CPPCMS_API escape(std::string const &s)
Widget for number input. It is a template class that assumes that T is a number.
Definition: form.h:942
void value(T v)
Definition: form.h:980
Exception thrown by CppCMS framework.
Definition: cppcms_error.h:22
void low(T a)
Definition: form.h:989
Render each widget using table.
Definition: form.h:59
This class represents a file upload form entry.
Definition: form.h:1475
This class represents an HTML form input element of type text.
Definition: form.h:830
html_list_type
Definition: form.h:57
std::locale locale()
base_html_input(std::string const &type)
void non_empty()
Definition: form.h:955
Input iterator used to iterate over all the widgets in a form.
Definition: form.h:320
This class represents a basic widget that generates HTML form elements the widgets that use the <inpu...
Definition: form.h:797
void high(T b)
Definition: form.h:999
virtual void render_value(form_context &context)
Definition: form.h:1018
form_type const & post_or_get()
context is a central class that holds all specific connection related information. It encapsulates CGI request and response, cache, session and locale information
Definition: http_context.h:45
widget_part_type
Definition: form.h:68
virtual bool validate()
Definition: form.h:1068
This widget represents an HTML multiple select form element.
Definition: form.h:1222
This widget represents a hidden input form element. It is used to provide information invisible to th...
Definition: form.h:876
The widget that uses a drop-down list for selection.
Definition: form.h:1427
Definition: log.h:25
Render part 2: complete part 1.
Definition: form.h:70
iterator operator++(int)
Definition: form.h:386
The form is a container used to collect other widgets and forms into a single unit.
Definition: form.h:216
This class represent an HTML checkbox input element.
Definition: form.h:1173
virtual void clear()
Definition: form.h:1026
Render part 1: HTML attributes can be inserted after it.
Definition: form.h:69
This widget checks that the input is a valid email address.
Definition: form.h:1159
This class is extending a simple text widget by using additional regular expression validation...
Definition: form.h:1127
Render each widget using unordered list.
Definition: form.h:60
void pre_load(http::context &)
http::request & request()
This text widget behaves similarly to the text widget but uses the textarea HTML tag rather than the ...
Definition: form.h:897
The widget that uses a set of radio buttons..
Definition: form.h:1441
This struct holds various flags to control the HTML generation.
Definition: form.h:45
basic_message< char > message
Definition: message.h:494
virtual void load(http::context &context)
Definition: form.h:1035
Render each widget using paragraphs.
Definition: form.h:58
The password widget is a simple text widget with few, obvious differences.
Definition: form.h:1103
widgets::base_widget & operator*() const
Definition: form.h:359
This class represents a message that can be converted to a specific locale message.
Definition: message.h:171
date_time_period_set operator+(date_time_period_set const &a, date_time_period_set const &b)
Definition: date_time.h:446
Render each widget using simple blank space separators.
Definition: form.h:62
archive & operator<<(archive &a, Archivable const &object)
Definition: serialization_classes.h:176
widgets::base_widget * operator->() const
Definition: form.h:351
T value()
Definition: form.h:970
this class is the base class of all renderable widgets which can be used with CppCMS form system...
Definition: form.h:457
html_type
Definition: form.h:49
This class makes impossible to copy any class derived from this one.
Definition: noncopyable.h:15
std::multimap< std::string, std::string > form_type
Definition: http_request.h:235