00001
00002
00003
00004
00005
00006
00008 #ifndef CPPCMS_FORM_H
00009 #define CPPCMS_FORM_H
00010
00011 #include <cppcms/defs.h>
00012 #include <booster/noncopyable.h>
00013
00014 #include <string>
00015 #include <set>
00016 #include <map>
00017 #include <list>
00018 #include <vector>
00019 #include <stack>
00020 #include <ostream>
00021 #include <sstream>
00022 #include <cppcms/http_context.h>
00023 #include <cppcms/http_request.h>
00024 #include <cppcms/http_response.h>
00025 #include <booster/copy_ptr.h>
00026 #include <booster/perl_regex.h>
00027 #include <booster/shared_ptr.h>
00028 #include <cppcms/cppcms_error.h>
00029 #include <cppcms/util.h>
00030 #include <cppcms/localization.h>
00031
00032 namespace cppcms {
00033
00034 namespace http {
00035 class file;
00036 }
00037
00038 namespace widgets {
00039 class base_widget;
00040 }
00041
00045 struct form_flags {
00049 typedef enum {
00050 as_html = 0,
00051 as_xhtml= 1,
00052 } html_type;
00053
00057 typedef enum {
00058 as_p = 0 ,
00059 as_table= 1 ,
00060 as_ul = 2 ,
00061 as_dl = 3 ,
00062 as_space= 4
00063 } html_list_type;
00064
00068 typedef enum {
00069 first_part = 0,
00070 second_part = 1
00071 } widget_part_type;
00072 };
00073
00077 class CPPCMS_API form_context : public form_flags
00078 {
00079 public:
00083 form_context();
00084
00088 form_context(form_context const &other);
00089
00093 form_context const &operator = (form_context const &other);
00094
00102 form_context( std::ostream &output,
00103 html_type ht = form_flags::as_html,
00104 html_list_type hlt=form_flags::as_p);
00105
00109 ~form_context();
00110
00114 void html(html_type t);
00115
00119 void html_list(html_list_type t);
00120
00124 void widget_part(widget_part_type t);
00125
00129 void out(std::ostream &out);
00130
00134 html_type html() const;
00135
00139 html_list_type html_list() const;
00140
00144 widget_part_type widget_part() const;
00145
00149 std::ostream &out() const;
00150
00151 private:
00152 uint32_t html_type_;
00153 uint32_t html_list_type_;
00154 uint32_t widget_part_type_;
00155 std::ostream *output_;
00156 uint32_t reserved_1;
00157 uint32_t reserved_2;
00158 struct _data;
00159 booster::hold_ptr<_data> d;
00160
00161 };
00162
00163
00169 class CPPCMS_API base_form : public form_flags {
00170 public:
00176 virtual void render(form_context &context) = 0;
00177
00183 virtual void load(http::context &context) = 0;
00184
00189 virtual bool validate() = 0;
00190
00194 virtual void clear() = 0;
00195
00199 virtual void parent(base_form *subform) = 0;
00200
00204 virtual base_form *parent() = 0;
00205
00206 base_form();
00207 virtual ~base_form();
00208 };
00209
00216 class CPPCMS_API form : public booster::noncopyable,
00217 public base_form
00218 {
00219 public:
00220 form();
00221 virtual ~form();
00222
00227 virtual void render(form_context &context);
00228
00232 virtual void load(http::context &cont);
00233
00238 virtual bool validate();
00239
00243 virtual void clear();
00244
00249 void add(form &subform);
00250
00256 void attach(form *subform);
00257
00262 void add(widgets::base_widget &widget);
00263
00269 void attach(widgets::base_widget *widget);
00270
00276 CPPCMS_DEPRECATED inline form &operator + (form &f)
00277 {
00278 add(f);
00279 return *this;
00280 }
00281
00287 CPPCMS_DEPRECATED inline form &operator + (widgets::base_widget &f)
00288 {
00289 add(f);
00290 return *this;
00291 }
00292
00297 virtual void parent(base_form *subform);
00298
00303 virtual form *parent();
00304
00320 class CPPCMS_API iterator : public std::iterator<std::input_iterator_tag,widgets::base_widget>
00321 {
00322 public:
00326 iterator();
00327
00331 iterator(form &);
00332
00336 ~iterator();
00337
00341 iterator(iterator const &other);
00342
00346 iterator const &operator = (iterator const &other);
00347
00351 widgets::base_widget *operator->() const
00352 {
00353 return get();
00354 }
00355
00359 widgets::base_widget &operator*() const
00360 {
00361 return *get();
00362 }
00363
00367 bool operator==(iterator const &other) const
00368 {
00369 return equal(other);
00370 }
00371
00375 bool operator!=(iterator const &other) const
00376 {
00377 return !equal(other);
00378 }
00379
00386 iterator operator++(int )
00387 {
00388 iterator tmp(*this);
00389 next();
00390 return tmp;
00391 }
00392
00397 iterator &operator++()
00398 {
00399 next();
00400 return *this;
00401 }
00402
00403 private:
00404
00405 friend class form;
00406
00407 bool equal(iterator const &other) const;
00408 void zero();
00409 void next();
00410 widgets::base_widget *get() const;
00411
00412 std::stack<unsigned> return_positions_;
00413 form *current_;
00414 unsigned offset_;
00415 struct _data;
00416 booster::copy_ptr<_data> d;
00417
00418 };
00419
00423 iterator begin();
00424
00428 iterator end();
00429
00430
00431 private:
00432 friend class iterator;
00433
00434 struct _data;
00435
00436 typedef std::pair<base_form *,bool> widget_type;
00437 std::vector<widget_type> elements_;
00438 form *parent_;
00439 booster::hold_ptr<_data> d;
00440 };
00441
00442
00443
00447 namespace widgets {
00448
00456
00457 class CPPCMS_API base_widget :
00458 public base_form,
00459 public booster::noncopyable
00460 {
00461 public:
00465 base_widget();
00466
00467 virtual ~base_widget();
00468
00478 bool set();
00479
00483 bool valid();
00484
00488 std::string id();
00489
00493 std::string name();
00494
00498 locale::message message();
00499
00503 bool has_message();
00504
00509 locale::message error_message();
00510
00514 bool has_error_message();
00515
00519 locale::message help();
00520
00524 bool has_help();
00525
00529 bool disabled();
00530
00534 void disabled(bool);
00535
00539 std::string attributes_string();
00540
00546 void set(bool);
00547
00554 void valid(bool);
00555
00559 void id(std::string);
00560
00566 void name(std::string);
00567
00574 void message(std::string);
00575
00582 void message(locale::message const &);
00583
00589 void error_message(std::string);
00590
00596 void error_message(locale::message const &);
00597
00601 void help(std::string);
00602
00606 void help(locale::message const &msg);
00607
00618 void attributes_string(std::string v);
00619
00620
00625 virtual void render(form_context &context);
00626
00631 virtual void render_input(form_context &context) = 0;
00632
00636 virtual void clear();
00637
00641 virtual bool validate();
00642
00646 virtual void render_attributes(form_context &context);
00647
00652 virtual void parent(base_form *subform);
00653
00658 virtual form *parent();
00659
00665 void pre_load(http::context &);
00666
00667 protected:
00672 void auto_generate(form_context *context = 0);
00673
00674 private:
00675 void generate(int position,form_context *context = 0);
00676
00677 std::string id_;
00678 std::string name_;
00679 locale::message message_;
00680 locale::message error_message_;
00681 locale::message help_;
00682 std::string attr_;
00683 form *parent_;
00684
00685 uint32_t is_valid_ : 1;
00686 uint32_t is_set_ : 1;
00687 uint32_t is_disabled_ : 1;
00688 uint32_t is_generation_done_ : 1;
00689 uint32_t has_message_ : 1;
00690 uint32_t has_error_ : 1;
00691 uint32_t has_help_ : 1;
00692 uint32_t reserverd_ : 25;
00693
00694 struct _data;
00695 booster::hold_ptr<_data> d;
00696 };
00697
00707 class CPPCMS_API base_text : virtual public base_widget {
00708 public:
00709
00710 base_text();
00711 virtual ~base_text();
00712
00716 std::string value();
00717
00721 void value(std::string v);
00722
00727 void non_empty();
00728
00737 void limits(int min,int max);
00738
00742 std::pair<int,int> limits();
00743
00752 void validate_charset(bool );
00753
00757 bool validate_charset();
00758
00770 virtual bool validate();
00771
00776 virtual void load(http::context &);
00777
00778 private:
00779 std::string value_;
00780 int low_;
00781 int high_;
00782 bool validate_charset_;
00783 size_t code_points_;
00784 struct _data;
00785 booster::hold_ptr<_data> d;
00786 };
00787
00796
00797 class CPPCMS_API base_html_input : virtual public base_widget {
00798 public:
00803 base_html_input(std::string const &type);
00804
00808 virtual ~base_html_input();
00809
00813 virtual void render_input(form_context &context);
00814
00815 protected:
00819 virtual void render_value(form_context &context) = 0;
00820
00821 private:
00822 struct _data;
00823 booster::hold_ptr<_data> d;
00824 std::string type_;
00825 };
00826
00830 class CPPCMS_API text : public base_html_input, public base_text
00831 {
00832 public:
00836 text();
00837
00842 text(std::string const &type);
00843
00844 ~text();
00845
00849 void size(int n);
00850
00854 int size();
00855
00856
00857 virtual void render_attributes(form_context &context);
00858 virtual void render_value(form_context &context);
00859
00860 private:
00861 int size_;
00862 struct _data;
00863 booster::hold_ptr<_data> d;
00864 };
00865
00876 class CPPCMS_API hidden : public text
00877 {
00878 public:
00879 hidden();
00880 ~hidden();
00886 virtual void render(form_context &context);
00887 private:
00888 struct _data;
00889 booster::hold_ptr<_data> d;
00890 };
00891
00892
00897 class CPPCMS_API textarea : public base_text
00898 {
00899 public:
00900 textarea();
00901 ~textarea();
00902
00906 int rows();
00907
00911 int cols();
00912
00916 void rows(int n);
00917
00921 void cols(int n);
00922
00923 virtual void render_input(form_context &context);
00924
00925 private:
00926 int rows_,cols_;
00927
00928 struct _data;
00929 booster::hold_ptr<_data> d;
00930 };
00931
00941 template<typename T>
00942 class numeric: public base_html_input {
00943 public:
00944 numeric() :
00945 base_html_input("text"),
00946 check_low_(false),
00947 check_high_(false),
00948 non_empty_(false)
00949 {
00950 }
00951
00955 void non_empty()
00956 {
00957 non_empty_=true;
00958 }
00959
00960
00970 T value()
00971 {
00972 if(!set())
00973 throw cppcms_error("Value not loaded");
00974 return value_;
00975 }
00976
00980 void value(T v)
00981 {
00982 set(true);
00983 value_=v;
00984 }
00985
00989 void low(T a)
00990 {
00991 min_=a;
00992 check_low_=true;
00993 non_empty();
00994 }
00995
00999 void high(T b)
01000 {
01001 max_=b;
01002 check_high_=true;
01003 non_empty();
01004 }
01005
01009 void range(T a,T b)
01010 {
01011 low(a);
01012 high(b);
01013 }
01014
01018 virtual void render_value(form_context &context)
01019 {
01020 if(set())
01021 context.out()<<"value=\""<<value_<<"\" ";
01022 else
01023 context.out()<<"value=\""<<util::escape(loaded_string_)<<"\" ";
01024 }
01025
01026 virtual void clear()
01027 {
01028 base_html_input::clear();
01029 loaded_string_.clear();
01030 }
01031
01035 virtual void load(http::context &context)
01036 {
01037 pre_load(context);
01038
01039 loaded_string_.clear();
01040
01041 set(false);
01042 valid(true);
01043
01044 http::request::form_type::const_iterator p;
01045 http::request::form_type const &request=context.request().post_or_get();
01046 p=request.find(name());
01047 if(p==request.end()) {
01048 return;
01049 }
01050 else {
01051 loaded_string_=p->second;
01052 if(loaded_string_.empty())
01053 return;
01054
01055 std::istringstream ss(loaded_string_);
01056 ss.imbue(context.locale());
01057 ss>>value_;
01058 if(ss.fail() || !ss.eof())
01059 valid(false);
01060 else
01061 set(true);
01062 }
01063 }
01064
01068 virtual bool validate()
01069 {
01070 if(!valid())
01071 return false;
01072 if(!set()) {
01073 if(non_empty_) {
01074 valid(false);
01075 return false;
01076 }
01077 return true;
01078 }
01079 if(check_low_ && value_ <min_) {
01080 valid(false);
01081 return false;
01082 }
01083 if(check_high_ && value_ > max_) {
01084 valid(false);
01085 return false;
01086 }
01087 return true;
01088 }
01089
01090 private:
01091
01092 T min_,max_,value_;
01093
01094 bool check_low_;
01095 bool check_high_;
01096 bool non_empty_;
01097 std::string loaded_string_;
01098 };
01099
01102
01103 class CPPCMS_API password: public text {
01104 public:
01105 password();
01106
01107 ~password();
01108
01114 void check_equal(password &p2);
01115 virtual bool validate();
01116
01117 private:
01118 struct _data;
01119 booster::hold_ptr<_data> d;
01120 password *password_to_check_;
01121 };
01122
01123
01127 class CPPCMS_API regex_field : public text {
01128 public:
01129 regex_field();
01133 regex_field(booster::regex const &e);
01134
01138 regex_field(std::string const &e);
01139
01140
01144 void regex(booster::regex const &e);
01145
01146 ~regex_field();
01147
01148 virtual bool validate();
01149
01150 private:
01151 booster::regex expression_;
01152 struct _data;
01153 booster::hold_ptr<_data> d;
01154 };
01155
01159 class CPPCMS_API email : public regex_field {
01160 public:
01161
01162 email();
01163 ~email();
01164
01165 private:
01166 struct _data;
01167 booster::hold_ptr<_data> d;
01168 };
01169
01173 class CPPCMS_API checkbox: public base_html_input {
01174 public:
01180 checkbox(std::string const &type);
01181
01185 checkbox();
01186 virtual ~checkbox();
01187
01191 bool value();
01192
01196 void value(bool is_set);
01197
01201 std::string identification();
01202
01207 void identification(std::string const &);
01208
01209 virtual void render_value(form_context &context);
01210 virtual void load(http::context &context);
01211
01212 private:
01213 struct _data;
01214 booster::hold_ptr<_data> d;
01215 std::string identification_;
01216 bool value_;
01217 };
01218
01222 class CPPCMS_API select_multiple : public base_widget {
01223 public:
01224 select_multiple();
01225 ~select_multiple();
01226
01231 void add(std::string const &msg,bool selected=false);
01232
01237 void add(std::string const &msg,std::string const &id,bool selected=false);
01238
01243 void add(locale::message const &msg,bool selected=false);
01244
01249 void add(locale::message const &msg,std::string const &id,bool selected=false);
01250
01254 std::vector<bool> selected_map();
01255
01260 std::set<std::string> selected_ids();
01261
01265 unsigned at_least();
01266
01270 void at_least(unsigned v);
01271
01275 unsigned at_most();
01276
01280 void at_most(unsigned v);
01281
01285 void non_empty();
01286
01290 unsigned rows();
01291
01295 void rows(unsigned n);
01296
01297 virtual void render_input(form_context &context);
01298 virtual bool validate();
01299 virtual void load(http::context &context);
01300 virtual void clear();
01301
01302 private:
01303 struct _data;
01304 booster::hold_ptr<_data> d;
01305
01306 struct element {
01307 element();
01308 element(std::string const &v,locale::message const &msg,bool sel);
01309 element(std::string const &v,std::string const &msg,bool sel);
01310 uint32_t selected : 1;
01311 uint32_t need_translation : 1;
01312 uint32_t original_select : 1;
01313 uint32_t reserved : 29;
01314 std::string id;
01315 std::string str_option;
01316 locale::message tr_option;
01317 friend std::ostream &operator<<(std::ostream &out,element const &el);
01318 };
01319
01320 std::vector<element> elements_;
01321
01322 unsigned low_;
01323 unsigned high_;
01324 unsigned rows_;
01325
01326 };
01327
01332 class CPPCMS_API select_base : public base_widget {
01333 public:
01334 select_base();
01335 virtual ~select_base();
01336
01340 void add(std::string const &string);
01341
01345 void add(std::string const &string,std::string const &id);
01346
01350 void add(locale::message const &msg);
01351
01355 void add(locale::message const &msg,std::string const &id);
01356
01361 int selected();
01362
01367 std::string selected_id();
01368
01372 void selected(int no);
01373
01377 void selected_id(std::string id);
01378
01382 void non_empty();
01383
01384 virtual void render_input(form_context &context) = 0;
01385 virtual bool validate();
01386 virtual void load(http::context &context);
01387 virtual void clear();
01388
01389 protected:
01390 struct CPPCMS_API element {
01391
01392 element();
01393 element(std::string const &v,locale::message const &msg);
01394 element(std::string const &v,std::string const &msg);
01395 element(element const &);
01396 element const &operator=(element const &);
01397 ~element();
01398
01399 uint32_t need_translation : 1;
01400 uint32_t reserved : 31;
01401 std::string id;
01402 std::string str_option;
01403 locale::message tr_option;
01404
01405 private:
01406 struct _data;
01407 booster::copy_ptr<_data> d;
01408
01409 };
01410
01411 std::vector<element> elements_;
01412
01413 private:
01414 struct _data;
01415 booster::hold_ptr<_data> d;
01416
01417 int selected_;
01418 int default_selected_;
01419
01420 uint32_t non_empty_ : 1;
01421 uint32_t reserverd : 32;
01422 };
01423
01427 class CPPCMS_API select : public select_base {
01428 public:
01429 select();
01430 virtual ~select();
01431 virtual void render_input(form_context &context);
01432
01433 private:
01434 struct _data;
01435 booster::hold_ptr<_data> d;
01436 };
01437
01441 class CPPCMS_API radio : public select_base {
01442 public:
01443 radio();
01444 virtual ~radio();
01445 virtual void render_input(form_context &context);
01446
01450 bool vertical();
01451
01459 void vertical(bool);
01460
01461 private:
01462 uint32_t vertical_ : 1;
01463 uint32_t reserved_ : 31;
01464
01465 struct _data;
01466 booster::hold_ptr<_data> d;
01467 };
01468
01475 class CPPCMS_API file : public base_html_input {
01476 public:
01480 void non_empty();
01481
01487 void limits(int min,int max);
01488
01492 std::pair<int,int> limits();
01493
01502 void filename(booster::regex const &fn);
01503
01507 booster::regex filename();
01508
01512 void validate_filename_charset(bool);
01513
01517 bool validate_filename_charset();
01518
01523 booster::shared_ptr<http::file> value();
01524
01528 void mime(std::string const &);
01529
01533 void mime(booster::regex const &expr);
01534
01540 void add_valid_magic(std::string const &);
01541
01542 virtual void load(http::context &context);
01543 virtual void render_value(form_context &context);
01544 virtual bool validate();
01545
01546 file();
01547 ~file();
01548
01549 private:
01550
01551 int size_min_;
01552 int size_max_;
01553
01554 std::vector<std::string> magics_;
01555
01556 std::string mime_string_;
01557 booster::regex mime_regex_;
01558 booster::regex filename_regex_;
01559
01560 uint32_t check_charset_ : 1;
01561 uint32_t check_non_empty_ : 1;
01562 uint32_t reserved_ : 30;
01563
01564 booster::shared_ptr<http::file> file_;
01565
01566 struct _data;
01567 booster::hold_ptr<_data> d;
01568 };
01569
01570
01574 class CPPCMS_API submit : public base_html_input {
01575 public:
01576 submit();
01577 ~submit();
01578
01582 bool value();
01583
01587 void value(std::string val);
01588
01592 void value(locale::message const &msg);
01593
01594 virtual void render_value(form_context &context);
01595 virtual void load(http::context &context);
01596
01597 private:
01598 struct _data;
01599 booster::hold_ptr<_data> d;
01600 bool pressed_;
01601 locale::message value_;
01602 };
01603
01604
01605
01606
01607 }
01608
01609
01610 }
01611
01612 #endif // CPPCMS_FORM_H