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 ,
62  as_space= 4
64 
68  typedef enum {
69  first_part = 0,
70  second_part = 1
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  CPPCMS_UNUSED_MEMBER uint32_t reserved_1;
157  CPPCMS_UNUSED_MEMBER 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 
536 
541  bool readonly();
542 
547  void readonly(bool);
548 
552  std::string attributes_string();
553 
559  void set(bool);
560 
567  void valid(bool);
568 
572  void id(std::string);
573 
579  void name(std::string);
580 
587  void message(std::string);
588 
595  void message(locale::message const &);
596 
602  void error_message(std::string);
603 
609  void error_message(locale::message const &);
610 
614  void help(std::string);
615 
619  void help(locale::message const &msg);
620 
631  void attributes_string(std::string v);
632 
633 
638  virtual void render(form_context &context);
639 
644  virtual void render_input(form_context &context) = 0;
645 
649  virtual void clear();
650 
654  virtual bool validate();
655 
659  virtual void render_attributes(form_context &context);
660 
665  virtual void parent(base_form *subform);
666 
671  virtual form *parent();
672 
678  void pre_load(http::context &);
679 
680  protected:
685  void auto_generate(form_context *context = 0);
686 
687  private:
688  void generate(int position,form_context *context = 0);
689 
690  std::string id_;
691  std::string name_;
692  locale::message message_;
693  locale::message error_message_;
694  locale::message help_;
695  std::string attr_;
696  form *parent_;
697 
698  uint32_t is_valid_ : 1;
699  uint32_t is_set_ : 1;
700  uint32_t is_disabled_ : 1;
701  uint32_t is_readonly_ : 1;
702  uint32_t is_generation_done_ : 1;
703  uint32_t has_message_ : 1;
704  uint32_t has_error_ : 1;
705  uint32_t has_help_ : 1;
706  CPPCMS_UNUSED_MEMBER uint32_t reserverd_ : 24;
707 
708  struct _data;
710  };
711 
721  class CPPCMS_API base_text : virtual public base_widget {
722  public:
723 
724  base_text();
725  virtual ~base_text();
726 
730  std::string value();
731 
735  void value(std::string v);
736 
741  void non_empty();
742 
751  void limits(int min,int max);
752 
756  std::pair<int,int> limits();
757 
766  void validate_charset(bool );
767 
771  bool validate_charset();
772 
784  virtual bool validate();
785 
790  virtual void load(http::context &);
791 
792  private:
793  std::string value_;
794  int low_;
795  int high_;
796  bool validate_charset_;
797  size_t code_points_;
798  struct _data;
800  };
801 
810 
811  class CPPCMS_API base_html_input : virtual public base_widget {
812  public:
817  base_html_input(std::string const &type);
818 
822  virtual ~base_html_input();
823 
827  virtual void render_input(form_context &context);
828 
829  protected:
833  virtual void render_value(form_context &context) = 0;
834 
835  private:
836  struct _data;
838  std::string type_;
839  };
840 
844  class CPPCMS_API text : public base_html_input, public base_text
845  {
846  public:
850  text();
851 
856  text(std::string const &type);
857 
858  ~text();
859 
863  void size(int n);
864 
868  int size();
869 
870 
871  virtual void render_attributes(form_context &context);
872  virtual void render_value(form_context &context);
873 
874  private:
875  int size_;
876  struct _data;
878  };
879 
890  class CPPCMS_API hidden : public text
891  {
892  public:
893  hidden();
894  ~hidden();
900  virtual void render(form_context &context);
901  private:
902  struct _data;
904  };
905 
906 
911  class CPPCMS_API textarea : public base_text
912  {
913  public:
914  textarea();
915  ~textarea();
916 
920  int rows();
921 
925  int cols();
926 
930  void rows(int n);
931 
935  void cols(int n);
936 
937  virtual void render_input(form_context &context);
938 
939  private:
940  int rows_,cols_;
941 
942  struct _data;
944  };
945 
955  template<typename T>
956  class numeric: public base_html_input {
957  public:
958  numeric() :
959  base_html_input("text"),
960  check_low_(false),
961  check_high_(false),
962  non_empty_(false)
963  {
964  }
965 
969  void non_empty()
970  {
971  non_empty_=true;
972  }
973 
974 
984  T value()
985  {
986  if(!set())
987  throw cppcms_error("Value not loaded");
988  return value_;
989  }
990 
994  void value(T v)
995  {
996  set(true);
997  value_=v;
998  }
999 
1003  void low(T a)
1004  {
1005  min_=a;
1006  check_low_=true;
1007  non_empty();
1008  }
1009 
1013  void high(T b)
1014  {
1015  max_=b;
1016  check_high_=true;
1017  non_empty();
1018  }
1019 
1023  void range(T a,T b)
1024  {
1025  low(a);
1026  high(b);
1027  }
1028 
1032  virtual void render_value(form_context &context)
1033  {
1034  if(set())
1035  context.out()<<"value=\""<<value_<<"\" ";
1036  else
1037  context.out()<<"value=\""<<util::escape(loaded_string_)<<"\" ";
1038  }
1039 
1040  virtual void clear()
1041  {
1042  base_html_input::clear();
1043  loaded_string_.clear();
1044  }
1045 
1049  virtual void load(http::context &context)
1050  {
1051  pre_load(context);
1052 
1053  loaded_string_.clear();
1054 
1055  set(false);
1056  valid(true);
1057 
1058  http::request::form_type::const_iterator p;
1059  http::request::form_type const &request=context.request().post_or_get();
1060  p=request.find(name());
1061  if(p==request.end()) {
1062  return;
1063  }
1064  else {
1065  loaded_string_=p->second;
1066  if(loaded_string_.empty())
1067  return;
1068 
1069  std::istringstream ss(loaded_string_);
1070  ss.imbue(context.locale());
1071  ss>>value_;
1072  if(ss.fail() || !ss.eof())
1073  valid(false);
1074  else
1075  set(true);
1076  }
1077  }
1078 
1082  virtual bool validate()
1083  {
1084  if(!valid())
1085  return false;
1086  if(!set()) {
1087  if(non_empty_) {
1088  valid(false);
1089  return false;
1090  }
1091  return true;
1092  }
1093  if(check_low_ && value_ <min_) {
1094  valid(false);
1095  return false;
1096  }
1097  if(check_high_ && value_ > max_) {
1098  valid(false);
1099  return false;
1100  }
1101  return true;
1102  }
1103 
1104  private:
1105 
1106  T min_,max_,value_;
1107 
1108  bool check_low_;
1109  bool check_high_;
1110  bool non_empty_;
1111  std::string loaded_string_;
1112  };
1113 
1116  //
1117  class CPPCMS_API password: public text {
1118  public:
1119  password();
1120 
1121  ~password();
1122 
1128  void check_equal(password &p2);
1129  virtual bool validate();
1130 
1131  private:
1132  struct _data;
1134  password *password_to_check_;
1135  };
1136 
1137 
1141  class CPPCMS_API regex_field : public text {
1142  public:
1143  regex_field();
1147  regex_field(booster::regex const &e);
1148 
1152  regex_field(std::string const &e);
1153 
1154 
1158  void regex(booster::regex const &e);
1159 
1160  ~regex_field();
1161 
1162  virtual bool validate();
1163 
1164  private:
1165  booster::regex expression_;
1166  struct _data;
1168  };
1169 
1173  class CPPCMS_API email : public regex_field {
1174  public:
1175 
1176  email();
1177  ~email();
1178 
1179  private:
1180  struct _data;
1182  };
1183 
1187  class CPPCMS_API checkbox: public base_html_input {
1188  public:
1194  checkbox(std::string const &type);
1195 
1199  checkbox();
1200  virtual ~checkbox();
1201 
1205  bool value();
1206 
1210  void value(bool is_set);
1211 
1215  std::string identification();
1216 
1221  void identification(std::string const &);
1222 
1223  virtual void render_value(form_context &context);
1224  virtual void load(http::context &context);
1225 
1226  private:
1227  struct _data;
1229  std::string identification_;
1230  bool value_;
1231  };
1232 
1236  class CPPCMS_API select_multiple : public base_widget {
1237  public:
1238  select_multiple();
1239  ~select_multiple();
1240 
1245  void add(std::string const &msg,bool selected=false);
1246 
1251  void add(std::string const &msg,std::string const &id,bool selected=false);
1252 
1257  void add(locale::message const &msg,bool selected=false);
1258 
1263  void add(locale::message const &msg,std::string const &id,bool selected=false);
1264 
1268  std::vector<bool> selected_map();
1269 
1274  std::set<std::string> selected_ids();
1275 
1279  unsigned at_least();
1280 
1284  void at_least(unsigned v);
1285 
1289  unsigned at_most();
1290 
1294  void at_most(unsigned v);
1295 
1299  void non_empty();
1300 
1304  unsigned rows();
1305 
1309  void rows(unsigned n);
1310 
1311  virtual void render_input(form_context &context);
1312  virtual bool validate();
1313  virtual void load(http::context &context);
1314  virtual void clear();
1315 
1316  private:
1317  struct _data;
1319 
1320  struct element {
1321  element();
1322  element(std::string const &v,locale::message const &msg,bool sel);
1323  element(std::string const &v,std::string const &msg,bool sel);
1324  uint32_t selected : 1;
1325  uint32_t need_translation : 1;
1326  uint32_t original_select : 1;
1327  CPPCMS_UNUSED_MEMBER uint32_t reserved : 29;
1328  std::string id;
1329  std::string str_option;
1330  locale::message tr_option;
1331  friend std::ostream &operator<<(std::ostream &out,element const &el);
1332  };
1333 
1334  std::vector<element> elements_;
1335 
1336  unsigned low_;
1337  unsigned high_;
1338  unsigned rows_;
1339 
1340  };
1341 
1346  class CPPCMS_API select_base : public base_widget {
1347  public:
1348  select_base();
1349  virtual ~select_base();
1350 
1354  void add(std::string const &string);
1355 
1359  void add(std::string const &string,std::string const &id);
1360 
1364  void add(locale::message const &msg);
1365 
1369  void add(locale::message const &msg,std::string const &id);
1370 
1375  int selected();
1376 
1381  std::string selected_id();
1382 
1386  void selected(int no);
1387 
1391  void selected_id(std::string id);
1392 
1396  void non_empty();
1397 
1398  virtual void render_input(form_context &context) = 0;
1399  virtual bool validate();
1400  virtual void load(http::context &context);
1401  virtual void clear();
1402 
1403  protected:
1404  struct CPPCMS_API element {
1405 
1406  element();
1407  element(std::string const &v,locale::message const &msg);
1408  element(std::string const &v,std::string const &msg);
1409  element(element const &);
1410  element const &operator=(element const &);
1411  ~element();
1412 
1413  uint32_t need_translation : 1;
1414  CPPCMS_UNUSED_MEMBER uint32_t reserved : 31;
1415  std::string id;
1416  std::string str_option;
1417  locale::message tr_option;
1418 
1419  private:
1420  struct _data;
1422 
1423  };
1424 
1425  std::vector<element> elements_;
1426 
1427  private:
1428  struct _data;
1430 
1431  int selected_;
1432  int default_selected_;
1433 
1434  uint32_t non_empty_ : 1;
1435  CPPCMS_UNUSED_MEMBER uint32_t reserverd : 32;
1436  };
1437 
1441  class CPPCMS_API select : public select_base {
1442  public:
1443  select();
1444  virtual ~select();
1445  virtual void render_input(form_context &context);
1446 
1447  private:
1448  struct _data;
1450  };
1451 
1455  class CPPCMS_API radio : public select_base {
1456  public:
1457  radio();
1458  virtual ~radio();
1459  virtual void render_input(form_context &context);
1460 
1464  bool vertical();
1465 
1473  void vertical(bool);
1474 
1475  private:
1476  uint32_t vertical_ : 1;
1477  CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 31;
1478 
1479  struct _data;
1481  };
1482 
1489  class CPPCMS_API file : public base_html_input {
1490  public:
1494  void non_empty();
1495 
1501  void limits(int min,int max);
1502 
1506  std::pair<int,int> limits();
1507 
1516  void filename(booster::regex const &fn);
1517 
1521  booster::regex filename();
1522 
1526  void validate_filename_charset(bool);
1527 
1531  bool validate_filename_charset();
1532 
1538 
1542  void mime(std::string const &);
1543 
1547  void mime(booster::regex const &expr);
1548 
1554  void add_valid_magic(std::string const &);
1555 
1556  virtual void load(http::context &context);
1557  virtual void render_value(form_context &context);
1558  virtual bool validate();
1559 
1560  file();
1561  ~file();
1562 
1563  private:
1564 
1565  int size_min_;
1566  int size_max_;
1567 
1568  std::vector<std::string> magics_;
1569 
1570  std::string mime_string_;
1571  booster::regex mime_regex_;
1572  booster::regex filename_regex_;
1573 
1574  uint32_t check_charset_ : 1;
1575  uint32_t check_non_empty_ : 1;
1576  CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 30;
1577 
1579 
1580  struct _data;
1582  };
1583 
1584 
1588  class CPPCMS_API submit : public base_html_input {
1589  public:
1590  submit();
1591  ~submit();
1592 
1596  bool value();
1597 
1601  void value(std::string val);
1602 
1606  void value(locale::message const &msg);
1607 
1608  virtual void render_value(form_context &context);
1609  virtual void load(http::context &context);
1610 
1611  private:
1612  struct _data;
1614  bool pressed_;
1615  locale::message value_;
1616  };
1617 
1618 
1619 
1620 
1621  } // widgets
1622 
1623 
1624 } //cppcms
1625 
1626 #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:1023
bool operator==(iterator const &other) const
Definition: form.h:367
Submit button widget.
Definition: form.h:1588
This is the base class for "select" like widgets which include dropdown lists and radio button sets...
Definition: form.h:1346
This widget is used as base for text input fields.
Definition: form.h:721
bool operator!=(iterator const &other) const
Definition: form.h:375
This class represents the context required to generate the widgets&#39; HTML.
Definition: form.h:77
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
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:956
void value(T v)
Definition: form.h:994
Exception thrown by CppCMS framework.
Definition: cppcms_error.h:22
void low(T a)
Definition: form.h:1003
This class represents a file upload form entry.
Definition: form.h:1489
This class represents an HTML form input element of type text.
Definition: form.h:844
html_list_type
Definition: form.h:57
std::locale locale()
This is the namespace where all CppCMS functionality is placed.
Definition: application.h:19
void non_empty()
Definition: form.h:969
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:811
void high(T b)
Definition: form.h:1013
virtual void render_value(form_context &context)
Definition: form.h:1032
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:47
widget_part_type
Definition: form.h:68
virtual bool validate()
Definition: form.h:1082
This widget represents an HTML multiple select form element.
Definition: form.h:1236
This widget represents a hidden input form element. It is used to provide information invisible to th...
Definition: form.h:890
The widget that uses a drop-down list for selection.
Definition: form.h:1441
Definition: log.h:25
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:1187
virtual void clear()
Definition: form.h:1040
This widget checks that the input is a valid email address.
Definition: form.h:1173
This class is extending a simple text widget by using additional regular expression validation...
Definition: form.h:1141
http::request & request()
This text widget behaves similarly to the text widget but uses the textarea HTML tag rather than the ...
Definition: form.h:911
The widget that uses a set of radio buttons..
Definition: form.h:1455
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:1049
Render each widget using paragraphs.
Definition: form.h:58
The password widget is a simple text widget with few, obvious differences.
Definition: form.h:1117
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
widgets::base_widget * operator->() const
Definition: form.h:351
T value()
Definition: form.h:984
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:238