form.h
//
// Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
// See accompanying file COPYING.TXT file for licensing details.
//
#ifndef CPPCMS_FORM_H
#define CPPCMS_FORM_H
#include <cppcms/defs.h>
#include <booster/noncopyable.h>
#include <string>
#include <set>
#include <map>
#include <list>
#include <vector>
#include <stack>
#include <ostream>
#include <sstream>
#include <cppcms/http_context.h>
#include <cppcms/http_request.h>
#include <cppcms/http_response.h>
#include <booster/copy_ptr.h>
#include <booster/perl_regex.h>
#include <booster/shared_ptr.h>
#include <cppcms/cppcms_error.h>
#include <cppcms/util.h>
#include <cppcms/localization.h>
namespace cppcms {
namespace http {
class file;
}
namespace widgets {
class base_widget;
}
struct form_flags {
typedef enum {
as_html = 0,
as_xhtml= 1,
} html_type;
typedef enum {
as_p = 0 ,
as_table= 1 ,
as_ul = 2 ,
as_dl = 3 ,
as_space= 4
} html_list_type;
typedef enum {
first_part = 0,
second_part = 1
} widget_part_type;
};
class CPPCMS_API form_context : public form_flags
{
public:
form_context();
form_context(form_context const &other);
form_context const &operator = (form_context const &other);
form_context( std::ostream &output,
html_type ht = form_flags::as_html,
html_list_type hlt=form_flags::as_p);
~form_context();
void html(html_type t);
void html_list(html_list_type t);
void widget_part(widget_part_type t);
void out(std::ostream &out);
html_type html() const;
html_list_type html_list() const;
widget_part_type widget_part() const;
std::ostream &out() const;
private:
uint32_t html_type_;
uint32_t html_list_type_;
uint32_t widget_part_type_;
std::ostream *output_;
uint32_t reserved_1;
uint32_t reserved_2;
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API base_form : public form_flags {
public:
virtual void render(form_context &context) = 0;
virtual void load(http::context &context) = 0;
virtual bool validate() = 0;
virtual void clear() = 0;
virtual void parent(base_form *subform) = 0;
virtual base_form *parent() = 0;
base_form();
virtual ~base_form();
};
class CPPCMS_API form : public booster::noncopyable,
public base_form
{
public:
form();
virtual ~form();
virtual void render(form_context &context);
virtual void load(http::context &cont);
virtual bool validate();
virtual void clear();
void add(form &subform);
void attach(form *subform);
void add(widgets::base_widget &widget);
void attach(widgets::base_widget *widget);
CPPCMS_DEPRECATED inline form &operator + (form &f)
{
add(f);
return *this;
}
CPPCMS_DEPRECATED inline form &operator + (widgets::base_widget &f)
{
add(f);
return *this;
}
virtual void parent(base_form *subform);
virtual form *parent();
class CPPCMS_API iterator : public std::iterator<std::input_iterator_tag,widgets::base_widget>
{
public:
iterator();
iterator(form &);
~iterator();
iterator(iterator const &other);
iterator const &operator = (iterator const &other);
widgets::base_widget *operator->() const
{
return get();
}
widgets::base_widget &operator*() const
{
return *get();
}
bool operator==(iterator const &other) const
{
return equal(other);
}
bool operator!=(iterator const &other) const
{
return !equal(other);
}
iterator operator++(int /*unused*/)
{
iterator tmp(*this);
next();
return tmp;
}
iterator &operator++()
{
next();
return *this;
}
private:
friend class form;
bool equal(iterator const &other) const;
void zero();
void next();
widgets::base_widget *get() const;
std::stack<unsigned> return_positions_;
form *current_;
unsigned offset_;
struct _data;
booster::copy_ptr<_data> d;
};
iterator begin();
iterator end();
private:
friend class iterator;
struct _data;
// Widget and ownership - true means I own it.
typedef std::pair<base_form *,bool> widget_type;
std::vector<widget_type> elements_;
form *parent_;
booster::hold_ptr<_data> d;
};
namespace widgets {
class CPPCMS_API base_widget :
public base_form,
public booster::noncopyable
{
public:
base_widget();
virtual ~base_widget();
bool set();
bool valid();
std::string id();
std::string name();
locale::message message();
bool has_message();
locale::message error_message();
bool has_error_message();
locale::message help();
bool has_help();
bool disabled();
void disabled(bool);
std::string attributes_string();
void set(bool);
void valid(bool);
void id(std::string);
void name(std::string);
void message(std::string);
void message(locale::message const &);
void error_message(std::string);
void error_message(locale::message const &);
void help(std::string);
void help(locale::message const &msg);
void attributes_string(std::string v);
virtual void render(form_context &context);
virtual void render_input(form_context &context) = 0;
virtual void clear();
virtual bool validate();
virtual void render_attributes(form_context &context);
virtual void parent(base_form *subform);
virtual form *parent();
void pre_load(http::context &);
protected:
void auto_generate(form_context *context = 0);
private:
void generate(int position,form_context *context = 0);
std::string id_;
std::string name_;
locale::message message_;
locale::message error_message_;
locale::message help_;
std::string attr_;
form *parent_;
uint32_t is_valid_ : 1;
uint32_t is_set_ : 1;
uint32_t is_disabled_ : 1;
uint32_t is_generation_done_ : 1;
uint32_t has_message_ : 1;
uint32_t has_error_ : 1;
uint32_t has_help_ : 1;
uint32_t reserverd_ : 25;
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API base_text : virtual public base_widget {
public:
base_text();
virtual ~base_text();
std::string value();
void value(std::string v);
void non_empty();
void limits(int min,int max);
std::pair<int,int> limits();
void validate_charset(bool );
bool validate_charset();
virtual bool validate();
virtual void load(http::context &);
private:
std::string value_;
int low_;
int high_;
bool validate_charset_;
size_t code_points_;
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API base_html_input : virtual public base_widget {
public:
base_html_input(std::string const &type);
virtual ~base_html_input();
virtual void render_input(form_context &context);
protected:
virtual void render_value(form_context &context) = 0;
private:
struct _data;
booster::hold_ptr<_data> d;
std::string type_;
};
class CPPCMS_API text : public base_html_input, public base_text
{
public:
text();
text(std::string const &type);
~text();
void size(int n);
int size();
virtual void render_attributes(form_context &context);
virtual void render_value(form_context &context);
private:
int size_;
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API hidden : public text
{
public:
hidden();
~hidden();
virtual void render(form_context &context);
private:
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API textarea : public base_text
{
public:
textarea();
~textarea();
int rows();
int cols();
void rows(int n);
void cols(int n);
virtual void render_input(form_context &context);
private:
int rows_,cols_;
struct _data;
booster::hold_ptr<_data> d;
};
template<typename T>
class numeric: public base_html_input {
public:
numeric() :
base_html_input("text"),
check_low_(false),
check_high_(false),
non_empty_(false)
{
}
void non_empty()
{
non_empty_=true;
}
T value()
{
if(!set())
throw cppcms_error("Value not loaded");
return value_;
}
void value(T v)
{
set(true);
value_=v;
}
void low(T a)
{
min_=a;
check_low_=true;
non_empty();
}
void high(T b)
{
max_=b;
check_high_=true;
non_empty();
}
void range(T a,T b)
{
low(a);
high(b);
}
virtual void render_value(form_context &context)
{
if(set())
context.out()<<"value=\""<<value_<<"\" ";
else
context.out()<<"value=\""<<util::escape(loaded_string_)<<"\" ";
}
virtual void clear()
{
base_html_input::clear();
loaded_string_.clear();
}
virtual void load(http::context &context)
{
pre_load(context);
loaded_string_.clear();
set(false);
valid(true);
http::request::form_type::const_iterator p;
http::request::form_type const &request=context.request().post_or_get();
p=request.find(name());
if(p==request.end()) {
return;
}
else {
loaded_string_=p->second;
if(loaded_string_.empty())
return;
std::istringstream ss(loaded_string_);
ss.imbue(context.locale());
ss>>value_;
if(ss.fail() || !ss.eof())
valid(false);
else
set(true);
}
}
virtual bool validate()
{
if(!valid())
return false;
if(!set()) {
if(non_empty_) {
valid(false);
return false;
}
return true;
}
if(check_low_ && value_ <min_) {
valid(false);
return false;
}
if(check_high_ && value_ > max_) {
valid(false);
return false;
}
return true;
}
private:
T min_,max_,value_;
bool check_low_;
bool check_high_;
bool non_empty_;
std::string loaded_string_;
};
//
class CPPCMS_API password: public text {
public:
password();
~password();
void check_equal(password &p2);
virtual bool validate();
private:
struct _data;
booster::hold_ptr<_data> d;
password *password_to_check_;
};
class CPPCMS_API regex_field : public text {
public:
regex_field();
regex_field(booster::regex const &e);
regex_field(std::string const &e);
void regex(booster::regex const &e);
~regex_field();
virtual bool validate();
private:
booster::regex expression_;
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API email : public regex_field {
public:
email();
~email();
private:
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API checkbox: public base_html_input {
public:
checkbox(std::string const &type);
checkbox();
virtual ~checkbox();
bool value();
void value(bool is_set);
std::string identification();
void identification(std::string const &);
virtual void render_value(form_context &context);
virtual void load(http::context &context);
private:
struct _data;
booster::hold_ptr<_data> d;
std::string identification_;
bool value_;
};
class CPPCMS_API select_multiple : public base_widget {
public:
select_multiple();
~select_multiple();
void add(std::string const &msg,bool selected=false);
void add(std::string const &msg,std::string const &id,bool selected=false);
void add(locale::message const &msg,bool selected=false);
void add(locale::message const &msg,std::string const &id,bool selected=false);
std::vector<bool> selected_map();
std::set<std::string> selected_ids();
unsigned at_least();
void at_least(unsigned v);
unsigned at_most();
void at_most(unsigned v);
void non_empty();
unsigned rows();
void rows(unsigned n);
virtual void render_input(form_context &context);
virtual bool validate();
virtual void load(http::context &context);
virtual void clear();
private:
struct _data;
booster::hold_ptr<_data> d;
struct element {
element();
element(std::string const &v,locale::message const &msg,bool sel);
element(std::string const &v,std::string const &msg,bool sel);
uint32_t selected : 1;
uint32_t need_translation : 1;
uint32_t original_select : 1;
uint32_t reserved : 29;
std::string id;
std::string str_option;
locale::message tr_option;
friend std::ostream &operator<<(std::ostream &out,element const &el);
};
std::vector<element> elements_;
unsigned low_;
unsigned high_;
unsigned rows_;
};
class CPPCMS_API select_base : public base_widget {
public:
select_base();
virtual ~select_base();
void add(std::string const &string);
void add(std::string const &string,std::string const &id);
void add(locale::message const &msg);
void add(locale::message const &msg,std::string const &id);
int selected();
std::string selected_id();
void selected(int no);
void selected_id(std::string id);
void non_empty();
virtual void render_input(form_context &context) = 0;
virtual bool validate();
virtual void load(http::context &context);
virtual void clear();
protected:
struct CPPCMS_API element {
element();
element(std::string const &v,locale::message const &msg);
element(std::string const &v,std::string const &msg);
element(element const &);
element const &operator=(element const &);
~element();
uint32_t need_translation : 1;
uint32_t reserved : 31;
std::string id;
std::string str_option;
locale::message tr_option;
private:
struct _data;
booster::copy_ptr<_data> d;
};
std::vector<element> elements_;
private:
struct _data;
booster::hold_ptr<_data> d;
int selected_;
int default_selected_;
uint32_t non_empty_ : 1;
uint32_t reserverd : 32;
};
class CPPCMS_API select : public select_base {
public:
select();
virtual ~select();
virtual void render_input(form_context &context);
private:
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API radio : public select_base {
public:
radio();
virtual ~radio();
virtual void render_input(form_context &context);
bool vertical();
void vertical(bool);
private:
uint32_t vertical_ : 1;
uint32_t reserved_ : 31;
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API file : public base_html_input {
public:
void non_empty();
void limits(int min,int max);
std::pair<int,int> limits();
void filename(booster::regex const &fn);
booster::regex filename();
void validate_filename_charset(bool);
bool validate_filename_charset();
booster::shared_ptr<http::file> value();
void mime(std::string const &);
void mime(booster::regex const &expr);
void add_valid_magic(std::string const &);
virtual void load(http::context &context);
virtual void render_value(form_context &context);
virtual bool validate();
file();
~file();
private:
int size_min_;
int size_max_;
std::vector<std::string> magics_;
std::string mime_string_;
booster::regex mime_regex_;
booster::regex filename_regex_;
uint32_t check_charset_ : 1;
uint32_t check_non_empty_ : 1;
uint32_t reserved_ : 30;
booster::shared_ptr<http::file> file_;
struct _data;
booster::hold_ptr<_data> d;
};
class CPPCMS_API submit : public base_html_input {
public:
submit();
~submit();
bool value();
void value(std::string val);
void value(locale::message const &msg);
virtual void render_value(form_context &context);
virtual void load(http::context &context);
private:
struct _data;
booster::hold_ptr<_data> d;
bool pressed_;
locale::message value_;
};
} // widgets
} //cppcms
#endif // CPPCMS_FORM_H
cppcms::form_context::out
void out(std::ostream &out)
booster::regex
This is a simple wrapper of PCRE library.
Definition: perl_regex.h:35
cppcms::widgets::numeric::range
void range(T a, T b)
Definition: form.h:1009
cppcms::form::iterator::operator==
bool operator==(iterator const &other) const
Definition: form.h:367
cppcms::widgets::submit
Submit button widget.
Definition: form.h:1574
cppcms::widgets::select_base
This is the base class for "select" like widgets which include dropdown lists and radio button sets...
Definition: form.h:1332
cppcms::widgets::base_text
This widget is used as base for text input fields.
Definition: form.h:707
booster::hold_ptr< _data >
cppcms::form::iterator::operator!=
bool operator!=(iterator const &other) const
Definition: form.h:375
cppcms::form_context
This class represents the context required to generate the widgets' HTML.
Definition: form.h:77
cppcms::form_flags::as_dl
Render each widget using definitions list.
Definition: form.h:61
cppcms::form_flags::as_html
render form/widget as ordinary HTML
Definition: form.h:50
cppcms::base_form
This class is the base class for any form or form widget used in CppCMS.
Definition: form.h:169
cppcms::form_flags::as_xhtml
render form/widget as XHTML
Definition: form.h:51
cppcms::form::iterator::operator++
iterator & operator++()
Definition: form.h:397
cppcms::util::escape
std::string CPPCMS_API escape(std::string const &s)
cppcms::widgets::base_widget::name
std::string name()
cppcms::widgets::base_widget::clear
virtual void clear()
cppcms::widgets::numeric
Widget for number input. It is a template class that assumes that T is a number.
Definition: form.h:942
cppcms::widgets::numeric::value
void value(T v)
Definition: form.h:980
cppcms::cppcms_error
Exception thrown by CppCMS framework.
Definition: cppcms_error.h:22
cppcms::widgets::numeric::low
void low(T a)
Definition: form.h:989
cppcms::form_flags::as_table
Render each widget using table.
Definition: form.h:59
cppcms::widgets::file
This class represents a file upload form entry.
Definition: form.h:1475
cppcms::widgets::text
This class represents an HTML form input element of type text.
Definition: form.h:830
cppcms::form_flags::html_list_type
html_list_type
Definition: form.h:57
cppcms::http::context::locale
std::locale locale()
cppcms::widgets::base_html_input::base_html_input
base_html_input(std::string const &type)
booster::copy_ptr< _data >
cppcms::widgets::base_widget::valid
bool valid()
cppcms::widgets::numeric::non_empty
void non_empty()
Definition: form.h:955
cppcms::form::iterator
Input iterator used to iterate over all the widgets in a form.
Definition: form.h:320
cppcms::widgets::base_html_input
This class represents a basic widget that generates HTML form elements the widgets that use the <inpu...
Definition: form.h:797
cppcms::widgets::numeric::high
void high(T b)
Definition: form.h:999
cppcms::widgets::numeric::render_value
virtual void render_value(form_context &context)
Definition: form.h:1018
cppcms::http::request::post_or_get
form_type const & post_or_get()
cppcms::http::context
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
cppcms::form_flags::widget_part_type
widget_part_type
Definition: form.h:68
cppcms::widgets::numeric::validate
virtual bool validate()
Definition: form.h:1068
cppcms::widgets::select_multiple
This widget represents an HTML multiple select form element.
Definition: form.h:1222
cppcms::widgets::hidden
This widget represents a hidden input form element. It is used to provide information invisible to th...
Definition: form.h:876
cppcms::widgets::select
The widget that uses a drop-down list for selection.
Definition: form.h:1427
booster::shared_ptr
Definition: log.h:25
cppcms::form_flags::second_part
Render part 2: complete part 1.
Definition: form.h:70
cppcms::form::iterator::operator++
iterator operator++(int)
Definition: form.h:386
cppcms::form
The form is a container used to collect other widgets and forms into a single unit.
Definition: form.h:216
cppcms::widgets::checkbox
This class represent an HTML checkbox input element.
Definition: form.h:1173
cppcms::widgets::numeric::clear
virtual void clear()
Definition: form.h:1026
cppcms::form_flags::first_part
Render part 1: HTML attributes can be inserted after it.
Definition: form.h:69
cppcms::widgets::select_base::element
Definition: form.h:1390
cppcms::widgets::email
This widget checks that the input is a valid email address.
Definition: form.h:1159
cppcms::widgets::regex_field
This class is extending a simple text widget by using additional regular expression validation...
Definition: form.h:1127
cppcms::form_flags::as_ul
Render each widget using unordered list.
Definition: form.h:60
cppcms::widgets::base_widget::pre_load
void pre_load(http::context &)
cppcms::http::context::request
http::request & request()
cppcms::widgets::textarea
This text widget behaves similarly to the text widget but uses the textarea HTML tag rather than the ...
Definition: form.h:897
cppcms::widgets::radio
The widget that uses a set of radio buttons..
Definition: form.h:1441
cppcms::form_flags
This struct holds various flags to control the HTML generation.
Definition: form.h:45
booster::locale::message
basic_message< char > message
Definition: message.h:494
cppcms::widgets::numeric::load
virtual void load(http::context &context)
Definition: form.h:1035
cppcms::form_flags::as_p
Render each widget using paragraphs.
Definition: form.h:58
cppcms::widgets::password
The password widget is a simple text widget with few, obvious differences.
Definition: form.h:1103
cppcms::form::iterator::operator*
widgets::base_widget & operator*() const
Definition: form.h:359
booster::locale::basic_message
This class represents a message that can be converted to a specific locale message.
Definition: message.h:171
booster::locale::operator+
date_time_period_set operator+(date_time_period_set const &a, date_time_period_set const &b)
Definition: date_time.h:446
cppcms::form_flags::as_space
Render each widget using simple blank space separators.
Definition: form.h:62
cppcms::operator<<
archive & operator<<(archive &a, Archivable const &object)
Definition: serialization_classes.h:176
cppcms::form::iterator::operator->
widgets::base_widget * operator->() const
Definition: form.h:351
cppcms::widgets::numeric::value
T value()
Definition: form.h:970
cppcms::widgets::base_widget
this class is the base class of all renderable widgets which can be used with CppCMS form system...
Definition: form.h:457
cppcms::widgets::base_widget::set
bool set()
cppcms::form_flags::html_type
html_type
Definition: form.h:49
booster::noncopyable
This class makes impossible to copy any class derived from this one.
Definition: noncopyable.h:15
cppcms::http::request::form_type
std::multimap< std::string, std::string > form_type
Definition: http_request.h:235