@@ -50,7 +50,8 @@ libcppcms_la_SOURCES = \ | |||
aio_timer.cpp \ | |||
json.cpp \ | |||
encoding.cpp \ | |||
locale_charset.cpp | |||
locale_charset.cpp \ | |||
form.cpp | |||
cppcms_config_find_param_SOURCES=cppcms_config_find_param.cpp json.cpp | |||
@@ -87,6 +87,25 @@ private: | |||
template<> | |||
void CPPCMS_API base_view::escape(std::ostream &,std::string const &s); | |||
#ifdef HAVE_STD_WSTRING | |||
template<> | |||
void CPPCMS_API base_view::escape(std::ostream &,std::wstring const &s); | |||
#endif | |||
#ifdef HAVE_CPP0X_UXSTRING | |||
template<> | |||
void CPPCMS_API base_view::escape(std::ostream &,std::u16string const &s); | |||
template<> | |||
void CPPCMS_API base_view::escape(std::ostream &,std::u32string const &s); | |||
#endif | |||
#ifdef HAVE_ICU | |||
template<> | |||
void CPPCMS_API base_view::escape(std::ostream &,icu::UnicodeString const &s); | |||
#endif | |||
void CPPCMS_API operator<<(std::ostream &,std::tm const &t); | |||
namespace details { | |||
@@ -7,7 +7,7 @@ | |||
"procs" : 0, | |||
"worker_threads": 5, | |||
"api" : "http", | |||
"port" : 8001, | |||
"port" : 8080, | |||
// "ip" : "0.0.0.0" | |||
"ip" : "127.0.0.1" | |||
// "socket" : "/tmp/scgi.socket" | |||
@@ -30,11 +30,13 @@ | |||
// "buffer" : 4096 | |||
}, | |||
"locale" : { | |||
"locales" : [ "he_IL.UTF-8", "en_US.UTF-8" ], // list of supported languages | |||
"locales" : [ "he_IL.UTF-8", "en_US.UTF-8", "he_IL.ISO-8859-8" ], // list of supported languages | |||
//"default" : "he_IL.ISO-8859-8", // default language (default first one) | |||
"default" : "he_IL.UTF-8", // default language (default first one) | |||
"gettext_domains" : [ "app", "test" ], // list of supported domains | |||
"default_gettext_domain" : "test", // default domain (default first one) | |||
"gettext_path" : "./transtext/locale" // path to locale directory | |||
"gettext_path" : "./transtext/locale", // path to locale directory | |||
"disable_charset_in_content_type" : false // Disable | |||
}, | |||
"session" : { | |||
"expire" : "browser", | |||
@@ -71,10 +71,11 @@ namespace cppcms { namespace encoding { | |||
if(descriptor_!=(iconv_t)(-1)) | |||
iconv_close(descriptor_); | |||
} | |||
bool check_symbols(uint32_t const *begin,uint32_t const *end) | |||
bool check_symbols(uint32_t const *begin,uint32_t const *end,size_t &count) | |||
{ | |||
while(begin!=end) { | |||
uint32_t c=*begin++; | |||
count++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
if(c<0x20 || (0x7F<=c && c<=0x9F)) | |||
@@ -83,7 +84,7 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
bool valid(char const *begin,char const *end) | |||
bool valid(char const *begin,char const *end,size_t &count) | |||
{ | |||
iconv(descriptor_,0,0,0,0); // reset | |||
uint32_t buffer[64]; | |||
@@ -95,12 +96,12 @@ namespace cppcms { namespace encoding { | |||
size_t res=do_iconv(::iconv,descriptor_,&begin,&input,(char**)&output,&outsize); | |||
if(res==(size_t)(-1) && errno==E2BIG) { | |||
if(!check_symbols(buffer,output)) | |||
if(!check_symbols(buffer,output,count)) | |||
return false; | |||
continue; | |||
} | |||
if(res!=(size_t)(-1) && input==0) | |||
return check_symbols(buffer,output); | |||
return check_symbols(buffer,output,count); | |||
return false; | |||
} | |||
return true; | |||
@@ -144,15 +145,15 @@ namespace cppcms { namespace encoding { | |||
delete iconv_; | |||
} | |||
bool validator::valid(std::string const &s) | |||
bool validator::valid(std::string const &s,size_t &count) | |||
{ | |||
return valid(s.data(),s.data()+s.size()); | |||
return valid(s.data(),s.data()+s.size(),count); | |||
} | |||
bool validator::valid(char const *begin,char const *end) | |||
bool validator::valid(char const *begin,char const *end,size_t &count) | |||
{ | |||
if(tester_) | |||
return tester_(begin,end); | |||
return iconv_->valid(begin,end); | |||
return tester_(begin,end,count); | |||
return iconv_->valid(begin,end,count); | |||
} | |||
struct validators_set::data {}; | |||
@@ -17,7 +17,7 @@ int cppcms_validator_test_function(); | |||
namespace cppcms { | |||
namespace encoding { | |||
typedef bool (*encoding_tester_type)(char const *begin,char const *end); | |||
typedef bool (*encoding_tester_type)(char const *begin,char const *end,size_t &count); | |||
class iconv_validator; | |||
@@ -30,8 +30,8 @@ namespace cppcms { | |||
validator const &operator=(validator const &other); | |||
bool valid(char const *begin,char const *end); | |||
bool valid(std::string const &str); | |||
bool valid(char const *begin,char const *end,size_t &count); | |||
bool valid(std::string const &str,size_t &count); | |||
~validator(); | |||
private: | |||
@@ -6,15 +6,16 @@ | |||
namespace cppcms { namespace encoding { | |||
template<typename Iterator> | |||
bool utf8_valid(Iterator p,Iterator e) | |||
bool utf8_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
return utf8::validate(p,e,true); | |||
return utf8::validate(p,e,count,true); | |||
} | |||
template<typename Iterator> | |||
bool ascii_valid(Iterator p,Iterator e) | |||
bool ascii_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -24,9 +25,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool iso_8859_1_2_4_5_9_10_13_14_15_16_valid(Iterator p,Iterator e) | |||
bool iso_8859_1_2_4_5_9_10_13_14_15_16_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -36,9 +38,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool iso_8859_3_valid(Iterator p,Iterator e) | |||
bool iso_8859_3_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -58,9 +61,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool iso_8859_6_valid(Iterator p,Iterator e) | |||
bool iso_8859_6_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -81,9 +85,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool iso_8859_7_valid(Iterator p,Iterator e) | |||
bool iso_8859_7_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -100,9 +105,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool iso_8859_8_valid(Iterator p,Iterator e) | |||
bool iso_8859_8_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -122,9 +128,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool iso_8859_11_valid(Iterator p,Iterator e) | |||
bool iso_8859_11_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -146,9 +153,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool windows_1250_valid(Iterator p,Iterator e) | |||
bool windows_1250_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -166,9 +174,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool windows_1251_valid(Iterator p,Iterator e) | |||
bool windows_1251_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -178,9 +187,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool windows_1252_valid(Iterator p,Iterator e) | |||
bool windows_1252_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -198,9 +208,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool windows_1253_valid(Iterator p,Iterator e) | |||
bool windows_1253_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -231,9 +242,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool windows_1254_valid(Iterator p,Iterator e) | |||
bool windows_1254_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -254,9 +266,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool windows_1255_valid(Iterator p,Iterator e) | |||
bool windows_1255_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -296,9 +309,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool windows_1256_valid(Iterator p,Iterator e) | |||
bool windows_1256_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -308,9 +322,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool windows_1257_valid(Iterator p,Iterator e) | |||
bool windows_1257_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -336,9 +351,10 @@ namespace cppcms { namespace encoding { | |||
} | |||
template<typename Iterator> | |||
bool windows_1258_valid(Iterator p,Iterator e) | |||
bool windows_1258_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -360,9 +376,10 @@ namespace cppcms { namespace encoding { | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool koi8_valid(Iterator p,Iterator e) | |||
bool koi8_valid(Iterator p,Iterator e,size_t &count) | |||
{ | |||
while(p!=e) { | |||
count++; | |||
unsigned c=(unsigned char)*p++; | |||
if(c==0x09 || c==0xA || c==0xD) | |||
continue; | |||
@@ -1,10 +1,10 @@ | |||
#define CPPCMS_SOURCE | |||
#include "form.h" | |||
#include "util.h" | |||
#include <boost/format.hpp> | |||
#include <iostream> | |||
#include "cppcms_error.h" | |||
#include <stack> | |||
#include <boost/format.hpp> | |||
#include "locale_charset.h" | |||
#include "locale_environment.h" | |||
namespace cppcms { | |||
@@ -50,8 +50,7 @@ bool form::validate() | |||
{ | |||
bool result=true; | |||
for(unsigned int i=0;i<elements_.size();i++) { | |||
if(!elements_[i].first->validate()) | |||
result=false; | |||
result = elements_[i].first->validate() & result; | |||
} | |||
return result; | |||
} | |||
@@ -63,14 +62,23 @@ void form::clear() | |||
} | |||
} | |||
void form::add(base_form &subform) | |||
void form::add(widgets::base_widget &form) | |||
{ | |||
elements_.push_back(widget_type(&form,false)); | |||
} | |||
void form::add(form &subform) | |||
{ | |||
elements_.push_back(widget_type(&subform,false)); | |||
} | |||
void form::attach(form *subform) | |||
{ | |||
elements_.push_back(std::make_pair(&subform,false)); | |||
elements_.push_back(widget_type(subform,true)); | |||
} | |||
void form::attach(base_form *subform) | |||
void form::attach(widgets::base_widget *subform) | |||
{ | |||
elements_.push_back(std::make_pair(subform,true)); | |||
elements_.push_back(widget_type(subform,true)); | |||
} | |||
struct form::iterator::data { | |||
@@ -97,9 +105,9 @@ form::iterator const &form::iterator::operator=(form::iterator const &other) | |||
return *this; | |||
} | |||
bool form::iterator::equal(form::iterator const &other) | |||
bool form::iterator::equal(form::iterator const &other) const | |||
{ | |||
return d->stack == other.d->stack && d->pos=other.d->pos; | |||
return (d->stack == other.d->stack) && (d->pos == other.d->pos); | |||
} | |||
void form::iterator::next() | |||
@@ -113,7 +121,7 @@ void form::iterator::next() | |||
form *top=d->stack.top().first; | |||
d->pos++; | |||
if((size_t)pos >= top->elements_.size() ) { | |||
if((size_t)d->pos >= top->elements_.size() ) { | |||
d->pos=d->stack.top().second; | |||
d->stack.pop(); | |||
continue; | |||
@@ -124,14 +132,14 @@ void form::iterator::next() | |||
form &f=dynamic_cast<form &>(*top->elements_[d->pos].first); | |||
d->stack.push_back(std::make_pair(&f,d->pos)); | |||
d->stack.push(std::make_pair(&f,d->pos)); | |||
d->pos=-1; | |||
} | |||
} | |||
form::iterator::pointer_type form::iterator::get() const | |||
widgets::base_widget *form::iterator::get() const | |||
{ | |||
return static_cast<base_widget *>(d->stack.top().first)->elements_[d->pos].first | |||
return static_cast<widgets::base_widget *>(d->stack.top().first->elements_[d->pos].first); | |||
} | |||
form::iterator form::begin() | |||
@@ -174,13 +182,17 @@ base_widget::base_widget(std::string name) : | |||
base_widget::base_widget(std::string name,std::string msg) : | |||
name_(name), | |||
msg_(msg), | |||
message_(msg), | |||
is_valid_(1), | |||
is_set_(0), | |||
is_disabled_(0) | |||
{ | |||
} | |||
base_widget::~base_widget() | |||
{ | |||
} | |||
bool base_widget::set() | |||
{ | |||
return is_set_; | |||
@@ -244,6 +256,16 @@ void base_widget::attributes_string(std::string v) | |||
attr_=v; | |||
} | |||
bool base_widget::disabled() | |||
{ | |||
return is_disabled_; | |||
} | |||
void base_widget::disabled(bool v) | |||
{ | |||
is_disabled_=v; | |||
} | |||
std::string base_widget::attributes_string() | |||
{ | |||
return attr_; | |||
@@ -261,10 +283,10 @@ void base_widget::render(std::ostream &output,unsigned int flags) | |||
case as_table: output<<"<tr><th>"; break; | |||
case as_ul: output<<"<li>"; break; | |||
case as_dl: output<<"<dt>"; break; | |||
default; | |||
default: ; | |||
} | |||
if(!id().empty() && !msg().empty()) { | |||
output<<"<label for=\"" << id() << "\">" << util::escape(msg()) <<":</label> "; | |||
if(!id().empty() && !message().empty()) { | |||
output<<"<label for=\"" << id() << "\">" << util::escape(message()) <<":</label> "; | |||
} | |||
else { | |||
output<<" "; | |||
@@ -272,11 +294,11 @@ void base_widget::render(std::ostream &output,unsigned int flags) | |||
switch(how) { | |||
case as_table: output<<"</th><td>"; break; | |||
case as_dl: output<<"</dt><dd>"; break; | |||
default; | |||
default: ; | |||
} | |||
if(!valid() && !no_error) { | |||
output<<"<span class=\"cppcms_form_error\">"<<util::escape(err)<<"</span> " | |||
output<<"<span class=\"cppcms_form_error\">"<<util::escape(err)<<"</span> "; | |||
} | |||
else { | |||
output<<" "; | |||
@@ -288,21 +310,21 @@ void base_widget::render(std::ostream &output,unsigned int flags) | |||
output<<"</span>"; | |||
if(!help().empty()) { | |||
output<<"<span class=\"cppcms_form_help\">"<<util::escape(help)<<"</span>"; | |||
output<<"<span class=\"cppcms_form_help\">"<<util::escape(help())<<"</span>"; | |||
} | |||
switch(how) { | |||
case as_p: output<<"</p>"; break; | |||
case as_table: output<<"</td><tr>"; break; | |||
case as_ul: output<<"</li>"; break; | |||
case as_dl: output<<"</dd>"; break; | |||
case as_p: output<<"</p>\n"; break; | |||
case as_table: output<<"</td><tr>\n"; break; | |||
case as_ul: output<<"</li>\n"; break; | |||
case as_dl: output<<"</dd>\n"; break; | |||
case as_space: | |||
if(flags & as_xhtml) | |||
output<<"<br />"; | |||
output<<"<br />\n"; | |||
else | |||
output<<"<br>"; | |||
output<<"<br>\n"; | |||
break; | |||
default; | |||
default: ; | |||
} | |||
} | |||
@@ -318,56 +340,71 @@ bool base_widget::validate() | |||
} | |||
//////////////////////////////// | |||
// widgets::text | |||
// widgets::base_text | |||
//////////////////////////////// | |||
struct text::data {} | |||
struct base_text::data {}; | |||
text::text() : low_(0),high_(-1),validate_charset_(true) | |||
base_text::base_text() : low_(0),high_(-1),validate_charset_(true) | |||
{ | |||
} | |||
text::text(std::string name) : base_widget(name), low_(0),high_(-1),validate_charset_(true) | |||
base_text::base_text(std::string name) : base_widget(name), low_(0),high_(-1),validate_charset_(true) | |||
{ | |||
} | |||
text::text(std::string name,std::string msg) : base_widget(name,msg), low_(0),high_(-1),validate_charset_(true) | |||
base_text::base_text(std::string name,std::string msg) : base_widget(name,msg), low_(0),high_(-1),validate_charset_(true) | |||
{ | |||
} | |||
text::~text() | |||
base_text::~base_text() | |||
{ | |||
} | |||
std::string text::value() | |||
std::string base_text::value() | |||
{ | |||
if(!set()) | |||
throw cppcms_error("Value was not loaded"); | |||
return value_; | |||
} | |||
void text::value(std::string v) | |||
void base_text::value(std::string v) | |||
{ | |||
set(true); | |||
value_=v; | |||
} | |||
std::string text::value(std::locale const &v) | |||
std::string base_text::value(std::locale const &v) | |||
{ | |||
return std::use_facet<locale::charset>(v).to_utf8(value_); | |||
} | |||
void base_text::value(std::string v,std::locale const &l) | |||
{ | |||
value(std::use_facet<locale::charset>(l).from_utf8(v)); | |||
} | |||
#ifdef HAVE_STD_WSTRING | |||
std::string text::value_wstring(std::locale const &v) | |||
std::string base_text::value_wstring() | |||
{ | |||
return locale::charset().to_wstring(value_); | |||
} | |||
void base_text::value(std::wstring v) | |||
{ | |||
value(locale::charset().from_wstring(v)); | |||
} | |||
std::string base_text::value_wstring(std::locale const &v) | |||
{ | |||
return std::use_facet<locale::charset>(v).to_wstring(value_); | |||
} | |||
void text::value(std::wstring v,std::locale const &l) | |||
void base_text::value(std::wstring v,std::locale const &l) | |||
{ | |||
value(std::use_facet<locale::charset>(l).from_wstring(v)); | |||
} | |||
@@ -376,23 +413,45 @@ void text::value(std::wstring v,std::locale const &l) | |||
#ifdef HAVE_CPP0X_UXSTRING | |||
std::u16string text::value_u16string(std::locale const &v) | |||
std::u16string base_text::value_u16string() | |||
{ | |||
return locale::charset().to_u16string(value_); | |||
} | |||
void base_text::value(std::u16string v) | |||
{ | |||
value(locale::charset().from_u16string(v)); | |||
} | |||
std::u32string base_text::value_u32string() | |||
{ | |||
return locale::charset().to_u32string(value_); | |||
} | |||
void base_text::value(std::u32string v) | |||
{ | |||
value(locale::charset().from_u32string(v)); | |||
} | |||
std::u16string base_text::value_u16string(std::locale const &v) | |||
{ | |||
return std::use_facet<locale::charset>(v).to_u16string(value_); | |||
} | |||
void text::value(std::u16string v,std::locale const &l) | |||
void base_text::value(std::u16string v,std::locale const &l) | |||
{ | |||
value(std::use_facet<locale::charset>(l).from_u16string(v)); | |||
} | |||
std::u32string text::value_u32string(std::locale const &v) | |||
std::u32string base_text::value_u32string(std::locale const &v) | |||
{ | |||
return std::use_facet<locale::charset>(v).to_u32string(value_); | |||
} | |||
void text::value(std::u32string v,std::locale const &l) | |||
void base_text::value(std::u32string v,std::locale const &l) | |||
{ | |||
value(std::use_facet<locale::charset>(l).from_u32string(v)); | |||
} | |||
@@ -400,36 +459,56 @@ void text::value(std::u32string v,std::locale const &l) | |||
#endif | |||
#ifdef HAVE_ICU | |||
icu::UnicodeString text::value_icu_string(std::locale const &v) | |||
icu::UnicodeString base_text::value_icu_string() | |||
{ | |||
return locale::charset().to_icu_string(value_); | |||
} | |||
void base_text::value(icu::UnicodeString const &v) | |||
{ | |||
value(locale::charset().from_icu_string(v)); | |||
} | |||
icu::UnicodeString base_text::value_icu_string(std::locale const &v) | |||
{ | |||
return std::use_facet<locale::charset>(v).to_icu_string(value_); | |||
} | |||
void text::value(icu::UnicodeString const &v,std::locale const &l) | |||
void base_text::value(icu::UnicodeString const &v,std::locale const &l) | |||
{ | |||
value(std::use_facet<locale::charset>(l).from_icu_string(v)); | |||
} | |||
#endif | |||
void text::non_empty() | |||
void base_text::non_empty() | |||
{ | |||
limits(1,-1); | |||
} | |||
void text::limits(int min,int max) | |||
void base_text::limits(int min,int max) | |||
{ | |||
low_=min; | |||
high_=max; | |||
} | |||
void text::disable_charset_validation() | |||
std::pair<int,int> base_text::limits() | |||
{ | |||
return std::make_pair(low_,high_); | |||
} | |||
void base_text::validate_charset(bool v) | |||
{ | |||
validate_charset_=v; | |||
} | |||
bool base_text::validate_charset() | |||
{ | |||
validate_charset_=false; | |||
return validate_charset_; | |||
} | |||
void text::load(http::context &context) | |||
void base_text::load(http::context &context) | |||
{ | |||
value_.clear(); | |||
code_points_ = 0; | |||
set(false); | |||
valid(true); | |||
if(name().empty()) { | |||
@@ -443,27 +522,184 @@ void text::load(http::context &context) | |||
value_=p->second; | |||
set(true); | |||
if(validate_charset_) { | |||
code_points_ = 0; | |||
locale::charset const &charset=std::use_facet<locale::charset>(context.locale().get()); | |||
if(!charset.validate(value)) | |||
if(!charset.validate(value_,code_points_)) | |||
valid(false); | |||
} | |||
else { | |||
code_points_=value_.size(); | |||
} | |||
} | |||
bool text::validate() | |||
bool base_text::validate() | |||
{ | |||
if(!valid()) | |||
return false; | |||
if(!set() && low_=0 && high_==-1) { | |||
if(!set() && low_==0 && high_==-1) { | |||
valid(true); | |||
return true; | |||
} | |||
if(value_.size() < low_ || (high_ >=0 && value_.size() > size_t(high_))) { | |||
if(code_points_ < size_t(low_) || (high_ >=0 && code_points_ > size_t(high_))) { | |||
valid(false); | |||
return false; | |||
} | |||
return true; | |||
} | |||
////////////////////////////////////////////// | |||
/// widgets::text | |||
///////////////////////////////////////////// | |||
struct text::data {}; | |||
text::text() : size_(-1),type_("text") {} | |||
text::~text() {} | |||
text::text(std::string n) : base_text(n) , size_(-1),type_("text") {} | |||
text::text(std::string n,std::string m) : base_text(n,m),size_(-1),type_("text") {} | |||
void text::type(std::string t) | |||
{ | |||
type_=t; | |||
} | |||
void text::render_input_start(std::ostream &output,unsigned flags) | |||
{ | |||
output<<"<input type=\""<<type_<<"\" "; | |||
std::string v; | |||
v=id(); | |||
if(!v.empty()) output << "id=\"" << v << "\" "; | |||
v=name(); | |||
if(!v.empty()) output << "name=\"" << v << "\" "; | |||
if(disabled()) { | |||
if(flags & as_xhtml) | |||
output << "disabled=\"disabled\" "; | |||
else | |||
output << "disabled "; | |||
} | |||
if(size_ >= 0) | |||
output << boost::format("size=\"%1%\" ",std::locale::classic()) % size_; | |||
std::pair<int,int> lm=limits(); | |||
if(lm.second >= 0 && validate_charset()) { | |||
output << boost::format("maxlength=\"%1%\" ",std::locale::classic()) % lm.second; | |||
} | |||
if(set()) { | |||
output << "value=\""<<util::escape(value())<<"\""; | |||
} | |||
} | |||
void text::render_input_end(std::ostream &output,unsigned flags) | |||
{ | |||
if(flags & as_xhtml) | |||
output<<" />"; | |||
else | |||
output<<" >"; | |||
} | |||
////////////////////////////////////////////// | |||
/// widgets::textarea | |||
///////////////////////////////////////////// | |||
struct textarea::data {}; | |||
textarea::textarea() : rows_(-1), cols_(-1) {} | |||
textarea::~textarea() {} | |||
textarea::textarea(std::string n) : base_text(n), rows_(-1), cols_(-1) {} | |||
textarea::textarea(std::string n,std::string m) : base_text(n,m), rows_(-1), cols_(-1) {} | |||
int textarea::rows() { return rows_; } | |||
int textarea::cols() { return cols_; } | |||
void textarea::rows(int n) { rows_ = n; } | |||
void textarea::cols(int n) { cols_ = n; } | |||
void textarea::render_input_start(std::ostream &output,unsigned flags) | |||
{ | |||
output<<"<textarea "; | |||
std::string v; | |||
v=id(); | |||
if(!v.empty()) output << "id=\"" << v << "\" "; | |||
v=name(); | |||
if(!v.empty()) output << "name=\"" << v << "\" "; | |||
if(disabled()) { | |||
if(flags & as_xhtml) | |||
output << "disabled=\"disabled\" "; | |||
else | |||
output << "disabled "; | |||
} | |||
if(rows_ >= 0) { | |||
output<<boost::format("rows=\"%1%\"",std::locale::classic()) % rows_; | |||
} | |||
if(cols_ >= 0) { | |||
output<<boost::format("cols=\"%1%\"",std::locale::classic()) % cols_; | |||
} | |||
} | |||
void textarea::render_input_end(std::ostream &output,unsigned flags) | |||
{ | |||
if(set()) { | |||
output << ">"<<util::escape(value())<<"</textarea>"; | |||
} | |||
else { | |||
output << "></textarea>"; | |||
} | |||
} | |||
//////////////////////// | |||
/// Password widget /// | |||
//////////////////////// | |||
struct password::data {}; | |||
password::password() : password_to_check_(0) | |||
{ | |||
type("password"); | |||
} | |||
password::password(std::string name) : text(name), password_to_check_(0) | |||
{ | |||
type("password"); | |||
} | |||
password::password(std::string name,std::string msg) : text(name,msg), password_to_check_(0) | |||
{ | |||
type("password"); | |||
} | |||
password::~password() | |||
{ | |||
} | |||
void password::check_equal(password &p2) | |||
{ | |||
password_to_check_ = &p2; | |||
} | |||
bool password::validate() | |||
{ | |||
if(!text::validate()) { | |||
value(""); | |||
return false; | |||
} | |||
if(password_to_check_) { | |||
if(!password_to_check_->set() || password_to_check_->value()!=value()) { | |||
valid(false); | |||
value(""); | |||
password_to_check_->value(""); | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
} // widgets | |||
@@ -12,6 +12,14 @@ | |||
#include <ostream> | |||
#include <sstream> | |||
#include "http_context.h" | |||
#include "http_request.h" | |||
#include "http_response.h" | |||
#include "copy_ptr.h" | |||
#include "cppcms_error.h" | |||
#include "util.h" | |||
#include "regex.h" | |||
namespace cppcms { | |||
namespace widgets { | |||
@@ -153,7 +161,7 @@ namespace cppcms { | |||
/// | |||
inline form &operator + (form &f) | |||
{ | |||
add(&f); | |||
add(f); | |||
return *this; | |||
} | |||
@@ -162,7 +170,7 @@ namespace cppcms { | |||
/// | |||
inline form &operator + (widgets::base_widget &f) | |||
{ | |||
add(&f); | |||
add(f); | |||
return *this; | |||
} | |||
/// | |||
@@ -180,7 +188,7 @@ namespace cppcms { | |||
/// \endcode | |||
/// | |||
class iterator : public std::iterator<std::input_iterator_tag,base_from> | |||
class CPPCMS_API iterator : public std::iterator<std::input_iterator_tag,widgets::base_widget> | |||
{ | |||
public: | |||
iterator(); | |||
@@ -188,11 +196,11 @@ namespace cppcms { | |||
iterator(iterator const &other); | |||
iterator const &operator = (iterator const &other); | |||
pointer_type operator->() const | |||
widgets::base_widget *operator->() const | |||
{ | |||
return get(); | |||
} | |||
reference operator*() const | |||
widgets::base_widget &operator*() const | |||
{ | |||
return *get(); | |||
} | |||
@@ -225,8 +233,9 @@ namespace cppcms { | |||
bool equal(iterator const &other) const; | |||
void next(); | |||
pointer_type get() const; | |||
widgets::base_widget *get() const; | |||
struct data; | |||
util::copy_ptr<data> d; | |||
}; | |||
@@ -335,6 +344,12 @@ namespace cppcms { | |||
bool disabled(); | |||
/// | |||
/// Set/Unset disabled html attribute | |||
/// | |||
void disabled(bool); | |||
/// | |||
/// Get the general user defined attributes string that can be added to widget | |||
/// | |||
std::string attributes_string(); | |||
@@ -367,7 +382,7 @@ namespace cppcms { | |||
/// data. | |||
/// | |||
void name(std::string) | |||
void name(std::string); | |||
/// | |||
/// Set short description for the widget. Generally it is good idea to | |||
@@ -410,7 +425,7 @@ namespace cppcms { | |||
virtual void render(std::ostream &output,unsigned int flags); | |||
/// | |||
/// This is pure-virtual member function that should be implemented by each widget | |||
/// This is a virtual member function that should be implemented by each widget | |||
/// | |||
/// It executes actual rendering of the input HTML form up to the position where | |||
/// user can insert its own data in HTML templates | |||
@@ -452,8 +467,8 @@ namespace cppcms { | |||
private: | |||
std::string id_; | |||
std::string name_; | |||
std::string msg_; | |||
std::string error_msg_; | |||
std::string message_; | |||
std::string error_message_; | |||
std::string help_; | |||
std::string attr_; | |||
@@ -466,79 +481,435 @@ namespace cppcms { | |||
util::hold_ptr<data> d; | |||
}; | |||
/// | |||
/// \brief this is the widget that is used as base for text input field representation | |||
/// | |||
/// This widget is used as base class for other widgets that are used for | |||
/// text input like: text, textarea, etc. | |||
/// | |||
/// This widget does much more then reading simple filed data from the POST | |||
/// or GET form, it performs charset validation and if required conversion | |||
/// to and from Unicode charset to locale charset. | |||
/// | |||
class text : public base_widget { | |||
class CPPCMS_API base_text : public base_widget { | |||
public: | |||
text(); | |||
text(std::string name); | |||
text(std::string name,std::string msg); | |||
~text(); | |||
/// | |||
/// Create an empty widget | |||
/// | |||
base_text(); | |||
/// | |||
/// Create a widget with http attribute name - \a name | |||
/// | |||
base_text(std::string name); | |||
/// | |||
/// Create a widget with http attribute name - \a name | |||
/// and short description \a msg. | |||
/// | |||
base_text(std::string name,std::string msg); | |||
~base_text(); | |||
/// | |||
/// Get the string that contains input value of the widget | |||
/// the string is returned in locale specific representation. | |||
/// i.e. if the locale is ru_RU.ISO8859-5 (8 bit encoding) | |||
/// then the string is encoded in ISO-8859-5 encoding. | |||
/// If the locale is ru_RU.UTF-8 that the string is encoded | |||
/// in UTF-8. | |||
/// | |||
std::string value(); | |||
std::string value(std::locale const &); | |||
/// | |||
/// Get the string that contains input value of the widget | |||
/// converting the string from the locale \a loc to | |||
/// UTF-8 Unicode encoding. If the locale uses UTF-8 | |||
/// natively it is just copied without conversion. | |||
/// | |||
std::string value(std::locale const &loc); | |||
/// | |||
/// Set the widget content before rendering, the value \a v | |||
/// is assumed to be encoding according to current locale. | |||
/// It should be encoded appropriately. | |||
/// | |||
/// For example. If the locale is ru_RU.ISO8859-5, then \a v | |||
/// should be encoded as ISO-8859-5 if it is ru_RU.UTF-8 | |||
/// then it should be encoded as UTF-8 string. | |||
/// | |||
void value(std::string v); | |||
void value(std::string v,std::locale const &); | |||
/// | |||
/// Set the widget content before rendering, to value \a v, | |||
/// where string \a v is encoded in UTF-8 Unicode encoding, | |||
/// and it is converted to locale specific encoding defined | |||
/// by locale \a loc. | |||
/// | |||
/// If the locale uses UTF-8 encoding natively then the string | |||
/// is just copied. | |||
/// | |||
void value(std::string v,std::locale const &loc); | |||
#ifdef HAVE_STD_WSTRING | |||
std::wstring value_wstring(std::locale const &); | |||
void value(std::wstring v,std::locale const &); | |||
/// | |||
/// Get the value of the widget represented as wide character string. | |||
/// | |||
/// Please note, std::wstring may represent UTF-16 variable length | |||
/// encoded string (mostly on Win32) or fixed length encoded UTF-32 string | |||
/// (mostly UNIX platforms) according to sizeof(wchar_t). So if you develop | |||
/// cross platform applications, never assume that one wchar_t represents | |||
/// one code point. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
std::wstring value_wstring(); | |||
/// | |||
/// Set the content of widget converting wide character string to UTF-8 string. | |||
/// | |||
/// Please note, std::wstring may represent UTF-16 variable length | |||
/// encoded string (mostly on Win32) or fixed length encoded UTF-32 string | |||
/// (mostly UNIX platforms) according to sizeof(wchar_t). So if you develop | |||
/// cross platform applications, never assume that one wchar_t represents | |||
/// one code point. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
void value(std::wstring v); | |||
/// | |||
/// Get the value of the widget represented as wide character | |||
/// string converting it from the locale's \a loc encoding. | |||
/// | |||
/// Please note, std::wstring may represent UTF-16 variable length | |||
/// encoded string (mostly on Win32) or fixed length encoded UTF-32 string | |||
/// (mostly UNIX platforms) according to sizeof(wchar_t). So if you develop | |||
/// cross platform applications, never assume that one wchar_t represents | |||
/// one code point. | |||
/// | |||
std::wstring value_wstring(std::locale const &loc); | |||
/// | |||
/// Set the content of widget converting wide character string to the locale's \a loc | |||
/// encoding. | |||
/// | |||
/// Please note, std::wstring may represent UTF-16 variable length | |||
/// encoded string (mostly on Win32) or fixed length encoded UTF-32 string | |||
/// (mostly UNIX platforms) according to sizeof(wchar_t). So if you develop | |||
/// cross platform applications, never assume that one wchar_t represents | |||
/// one code point. | |||
/// | |||
void value(std::wstring v,std::locale const &loc); | |||
#endif | |||
#ifdef HAVE_CPP0X_UXSTRING | |||
/// | |||
/// Get the value of the widget represented as UTF-16 encoded | |||
/// string converting it from the locale's \a loc encoding. | |||
/// | |||
std::u16string value_u16string(std::locale const &); | |||
/// | |||
/// Get the value of the widget represented as UTF-32 encoded | |||
/// string converting it from the locale's \a loc encoding. | |||
/// | |||
std::u32string value_u32string(std::locale const &); | |||
/// | |||
/// Set the content of widget converting UTF-16 encoded string to the locale's \a loc | |||
/// encoding. | |||
/// | |||
void value(std::u16string v,std::locale const &); | |||
/// | |||
/// Set the content of widget converting UTF-32 encoded string to the locale's \a loc | |||
/// encoding. | |||
/// | |||
void value(std::u32string v,std::locale const &); | |||
/// | |||
/// Get the value of the widget represented as utf16 encoded string. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
std::u16string value_u16string(); | |||
/// | |||
/// Get the value of the widget represented as utf32 encoded string. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
std::u32string value_u32string(); | |||
/// | |||
/// Set the content of widget converting utf-16 encoded string to UTF-8 string. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
void value(std::u16string v); | |||
/// | |||
/// Set the content of widget converting utf-32 encoded string to UTF-8 string. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
void value(std::u32string v); | |||
#endif | |||
#ifdef HAVE_ICU | |||
/// | |||
/// Get the value of the widget represented ICU UnicodeString. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
icu::UnicodeString value_icu_string(); | |||
/// | |||
/// Set the content of widget ICU UnicodeString string to UTF-8 string. | |||
/// | |||
/// Important Note: it assumes that the current locale character encoding is UTF-8. | |||
/// Never use it if you support non UTF-8 encodings. | |||
/// | |||
void value(icu::UnicodeString const &v); | |||
/// | |||
/// Get the value of the widget represented as ICU UnicodeString | |||
/// converting it from the locale's \a loc encoding. | |||
/// | |||
icu::UnicodeString value_icu_string(std::locale const &); | |||
/// | |||
/// Set the content of widget converting ICU UnocodeString to the locale's \a loc | |||
/// encoding. | |||
/// | |||
void value(icu::UnicodeString const &v,std::locale const &); | |||
#endif | |||
/// | |||
/// Acknowledge the validator that this text widget should contain some text. | |||
/// similar to limits(1,-1) | |||
/// | |||
void non_empty(); | |||
/// | |||
/// Set minimum and maximum limits for text size. Note max == -1 indicates that there | |||
/// is no maximal limit, min==0 indicates that there is no minimal limit. | |||
/// | |||
/// Note: these numbers represent the length in Unicode code points (even if the encoding | |||
/// is not Unicode). If character set validation is disabled, then these number represent | |||
/// the number of octets in the string. | |||
/// | |||
void limits(int min,int max); | |||
void disable_charset_validation(); | |||
/// | |||
/// Get minimal and maximal size limits, | |||
/// | |||
std::pair<int,int> limits(); | |||
/// | |||
/// Acknowledge the validator if it should not check the validity of the charset. | |||
/// Default -- enabled | |||
/// | |||
/// Generally you should not use this option unless you want to load some raw data as | |||
/// form input, or the character set is different from the defined in locale. | |||
/// | |||
void validate_charset(bool ); | |||
/// | |||
/// Returns true if charset validation is enabled. | |||
/// | |||
bool validate_charset(); | |||
virtual void render_input_start(std::ostream &output,unsigned flags) = 0; | |||
virtual void render_input_end(std::ostream &output,unsigned flags) = 0; | |||
/// | |||
/// Validate the widget content according to rules and charset encoding. | |||
/// | |||
/// Notes: | |||
/// | |||
/// - The charset validation is very efficient for variable length UTF-8 encoding, | |||
/// and most popular fixed length ISO-8859-*, windows-125* and koi8* encodings, for other | |||
/// encodings iconv conversion is used for actual validation. | |||
/// - Special characters (that not allowed in HTML) are assumed as forbidden, even they are | |||
/// valid code points (like NUL = 0 or DEL=127). | |||
/// | |||
virtual bool validate(); | |||
/// | |||
/// Load the widget for http::context. It used the locale given in the context for | |||
/// validation of text. | |||
/// | |||
virtual void load(http::context &); | |||
private: | |||
std::string value_; | |||
unsigned low_; | |||
int low_; | |||
int high_; | |||
bool validate_charset_; | |||
size_t code_points_; | |||
struct data; | |||
util::hold_ptr<data> d; | |||
}; | |||
/// | |||
/// \brief This class represents html input of type text | |||
/// | |||
class CPPCMS_API text : public base_text | |||
{ | |||
public: | |||
/// | |||
/// Create an empty text widget | |||
/// | |||
text(); | |||
/// | |||
/// Create a text widget with http attribute name - \a name | |||
/// | |||
text(std::string name); | |||
/// | |||
/// Create a text widget with http attribute name - \a name | |||
/// and short description \a msg. | |||
/// | |||
text(std::string name,std::string msg); | |||
/// | |||
/// Set html attribute size of the widget | |||
/// | |||
void size(int n); | |||
/// | |||
/// Get html attribute size of the widget, -1 undefined | |||
/// | |||
int size(); | |||
~text(); | |||
virtual void render_input_start(std::ostream &output,unsigned flags); | |||
virtual void render_input_end(std::ostream &output,unsigned flags); | |||
protected: | |||
void type(std::string str); | |||
private: | |||
int size_; | |||
std::string type_; | |||
struct data; | |||
util::hold_ptr<data> d; | |||
}; | |||
class CPPCMS_API textarea : public base_text | |||
{ | |||
public: | |||
/// | |||
/// Create an empty text widget | |||
/// | |||
textarea(); | |||
/// | |||
/// Create a text widget with http attribute name - \a name | |||
/// | |||
textarea(std::string name); | |||
/// | |||
/// Create a text widget with http attribute name - \a name | |||
/// and short description \a msg. | |||
/// | |||
textarea(std::string name,std::string msg); | |||
~textarea(); | |||
/// | |||
/// Get number of rows in textarea -- default -1 -- undefined | |||
/// | |||
int rows(); | |||
/// | |||
/// Get number of columns in textarea -- default -1 -- undefined | |||
/// | |||
int cols(); | |||
/// | |||
/// Set number of rows in textarea | |||
/// | |||
void rows(int n); | |||
/// | |||
/// Set number of columns in textarea | |||
/// | |||
void cols(int n); | |||
virtual void render_input_start(std::ostream &output,unsigned flags); | |||
virtual void render_input_end(std::ostream &output,unsigned flags); | |||
private: | |||
int rows_,cols_; | |||
struct data; | |||
util::hold_ptr<data> d; | |||
}; | |||
/// | |||
/// \brief Widget for number input. It is template class that assumes that T is number | |||
/// | |||
template<typename T> | |||
class number: public text { | |||
class number: public base_widget { | |||
public: | |||
number(string name="",string msg="") : | |||
text(name,msg), | |||
value_(0), | |||
check_low_(false), | |||
check_high_(false), | |||
non_empty_(false) | |||
number() | |||
{ | |||
init(); | |||
} | |||
/// | |||
/// Construct widget with html attribute name \a name | |||
/// | |||
number(std::string name) : base_widget(name) | |||
{ | |||
init(); | |||
} | |||
/// | |||
/// Construct widget with html attribute name \a name and description \a msg | |||
/// | |||
number(std::string name,std::string msg) : base_widget(name,msg) | |||
{ | |||
init(); | |||
} | |||
/// | |||
/// Defines that this widget should have some value | |||
/// | |||
void non_empty() | |||
{ | |||
non_empty_=true; | |||
} | |||
/// | |||
/// Get loaded widget value | |||
/// | |||
T value() | |||
{ | |||
if(!set()) | |||
@@ -546,55 +917,98 @@ namespace cppcms { | |||
return value_; | |||
} | |||
/// | |||
/// Set widget value | |||
/// | |||
void value(T v) | |||
{ | |||
set(true); | |||
value_=v; | |||
} | |||
/// | |||
/// Set minimal input number value | |||
/// | |||
void low(T a) | |||
{ | |||
min_=a; | |||
check_low_=true; | |||
set_nonempty(); | |||
non_empty(); | |||
} | |||
/// | |||
/// Set maximal input number value | |||
/// | |||
void high(T b) | |||
{ | |||
max_=b; | |||
check_high_=true; | |||
set_nonempty(); | |||
non_empty(); | |||
} | |||
/// | |||
/// Same as low(a); high(b); | |||
/// | |||
void range(T a,T b) | |||
{ | |||
set_low(a); | |||
set_high(b); | |||
low(a); | |||
high(b); | |||
} | |||
void render_input_start(std::ostream &output,unsigned flags) | |||
/// | |||
/// Render first part of widget | |||
/// | |||
virtual void render_input_start(std::ostream &output,unsigned flags) | |||
{ | |||
output<<"<input "; | |||
} | |||
void render_input_end(std::ostream &output,unsigned flags) | |||
/// | |||
/// Render second part of widget | |||
/// | |||
virtual void render_input_end(std::ostream &output,unsigned flags) | |||
{ | |||
render_element(output,id(),"id"); | |||
render_element(output,name(),"name"); | |||
std::string v=id(); | |||
if(!v.empty()) | |||
output<<"id=\""<<v<<"\" "; | |||
v=name(); | |||
if(!v.empty()) | |||
output<<"name=\""<<v<<"\" "; | |||
output<<" type=\"text\" "; | |||
if(set()) | |||
output<<"value="<<value_<<"\" "; | |||
output<<"value=\""<<value_<<"\" "; | |||
else | |||
render_element(output,loaded_string_,"value"); | |||
output<<"value=\""<<util::escape(loaded_string_)<<"\" "; | |||
if(disabled()) { | |||
if(flags & as_xhtml) | |||
output<<"disabled=\"disabled\" "; | |||
else | |||
output<<"disabled "; | |||
} | |||
if(flags & as_xhtml) | |||
outout<<"/>"; | |||
output<<"/>"; | |||
else | |||
output<<">"; | |||
} | |||
void load(http::context &context) | |||
virtual void clear() | |||
{ | |||
base_widget::clear(); | |||
loaded_string_.clear(); | |||
} | |||
/// | |||
/// Load widget data | |||
/// | |||
virtual void load(http::context &context) | |||
{ | |||
loaded_string_.clear(); | |||
@@ -617,10 +1031,15 @@ namespace cppcms { | |||
ss>>value_; | |||
if(ss.fail() || !ss.eof()) | |||
valid(false); | |||
else | |||
set(true); | |||
} | |||
} | |||
bool validate() | |||
/// | |||
/// Validate widget | |||
/// | |||
virtual bool validate() | |||
{ | |||
if(!valid()) | |||
return false; | |||
@@ -636,19 +1055,16 @@ namespace cppcms { | |||
return false; | |||
} | |||
if(check_high_ && value_ > max_) { | |||
valud(false); | |||
valid(false); | |||
return false; | |||
} | |||
return true; | |||
} | |||
private: | |||
void render_element(std::ostream &out,std::string const &v,char const *field) | |||
void init() | |||
{ | |||
if(v.empty()) | |||
return; | |||
out<<" "<<field<<"=\""<<util::escape(v)<<"\" "; | |||
check_low_=check_high_=non_empty_=false; | |||
} | |||
T min_,max_,value_; | |||
@@ -659,39 +1075,53 @@ namespace cppcms { | |||
std::string loaded_string_; | |||
}; | |||
class password: public text { | |||
password *other; | |||
/// | |||
/// \brief The password widget is a simple text widget with some different | |||
// | |||
class CPPCMS_API password: public text { | |||
public: | |||
password(string name="",string msg="") : text(name,msg),other(0) {} ; | |||
void set_equal(password &p2) { other=&p2; } ; | |||
password(); | |||
password(std::string name); | |||
password(std::string name,std::string msg); | |||
~password(); | |||
void check_equal(password &p2); | |||
virtual bool validate(); | |||
virtual string render_input(int how); | |||
}; | |||
class textarea: public text { | |||
public: | |||
int rows,cols; | |||
textarea(string name="",string msg="") : text(name,msg) { rows=cols=-1; }; | |||
virtual string render_input(int how); | |||
private: | |||
struct data; | |||
util::hold_ptr<data> d; | |||
password *password_to_check_; | |||
}; | |||
class regex_field : public text { | |||
util::regex const *exp; | |||
class CPPCMS_API regex_field : public text { | |||
public: | |||
regex_field() : exp(0) {} | |||
regex_field(util::regex const &e,string name="",string msg="") : text(name,msg),exp(&e) {} | |||
regex_field(util::regex const &e); | |||
regex_field(util::regex const &e,std::string name); | |||
regex_field(util::regex const &e,std::string name,std::string msg); | |||
~regex_field(); | |||
virtual bool validate(); | |||
private: | |||
util::regex const *expression_; | |||
struct data; | |||
util::hold_ptr<data> d; | |||
}; | |||
class email : public regex_field { | |||
class CPPCMS_API email : public regex_field { | |||
public: | |||
email(string name="",string msg=""); | |||
email(); | |||
~email(); | |||
email(std::string name); | |||
email(std::string name,std::string msg); | |||
private: | |||
static util::regex const email_expression_; | |||
struct data; | |||
util::hold_ptr<data> d; | |||
}; | |||
/* | |||
class checkbox: public base_widget { | |||
public: | |||
string input_value; | |||
@@ -785,7 +1215,7 @@ namespace cppcms { | |||
submit(string name="",string button="",string msg="") : base_widget(name,msg), value(button),pressed(false) {}; | |||
virtual string render_input(int); | |||
virtual void load(cgicc::Cgicc const &cgi); | |||
}; | |||
}; */ | |||
} // widgets | |||
@@ -10,6 +10,7 @@ | |||
#include "format.h" | |||
#include "aio_timer.h" | |||
#include "intrusive_ptr.h" | |||
#include "form.h" | |||
#include <sstream> | |||
#include <stdexcept> | |||
#include <stdlib.h> | |||
@@ -157,6 +158,32 @@ private: | |||
cppcms::aio::timer timer_; | |||
}; | |||
class my_form : public cppcms::form | |||
{ | |||
public: | |||
cppcms::widgets::text name; | |||
cppcms::widgets::number<double> age; | |||
cppcms::widgets::password p1; | |||
cppcms::widgets::password p2; | |||
cppcms::widgets::textarea description; | |||
my_form() : | |||
name("name","Your Name"), | |||
age("age","Your Age"), | |||
p1("p1","Password"), | |||
p2("p2","Confirm"), | |||
description("descr","Describe") | |||
{ | |||
name.limits(2,30); | |||
age.range(0,120); | |||
p1.check_equal(p2); | |||
p1.non_empty(); | |||
*this + name + age + p1 + p2 + description; | |||
} | |||
}; | |||
class hello : public cppcms::application { | |||
public: | |||
hello(cppcms::service &srv) : | |||
@@ -167,6 +194,7 @@ public: | |||
dispatcher().assign("^/post$",&hello::pform,this); | |||
dispatcher().assign("^/err$",&hello::err,this); | |||
dispatcher().assign("^/forward$",&hello::forward,this); | |||
dispatcher().assign("^/form$",&hello::form,this); | |||
dispatcher().assign(".*",&hello::hello_world,this); | |||
std::cout<<"hello()"<<std::endl; | |||
} | |||
@@ -175,6 +203,35 @@ public: | |||
std::cout<<"~hello()"<<std::endl; | |||
} | |||
void form() | |||
{ | |||
my_form f; | |||
bool ok=false; | |||
if(request().request_method()=="POST") { | |||
f.load(context()); | |||
if(f.validate()) { | |||
ok=true; | |||
} | |||
} | |||
response().out()<< | |||
"<html><body>\n"; | |||
if(ok) { | |||
response().out() << f.name.value() <<" " <<f.age.value(); | |||
f.clear(); | |||
} | |||
response().out()<< | |||
"<form action='" << | |||
request().script_name() + request().path_info() | |||
<< "' method='post'>\n" | |||
"<table>\n"; | |||
f.render(response().out(),cppcms::form::as_table); | |||
response().out()<<"</table><input type='submit' value='Send' ></form>\n"; | |||
response().out()<<"</form></body></html>"<<std::endl; | |||
} | |||
void forward() | |||
{ | |||
//response().set_redirect_header("http://127.0.0.1:8080/hello"); | |||
@@ -19,13 +19,12 @@ namespace cppcms { | |||
namespace http { | |||
struct context::data { | |||
http::request request; | |||
http::response response; | |||
cppcms::locale::environment locale; | |||
http::request request; | |||
std::auto_ptr<http::response> response; | |||
data(context &cntx) : | |||
request(cntx.connection()), | |||
response(cntx), | |||
locale(cntx.connection().service()) | |||
locale(cntx.connection().service()), | |||
request(cntx.connection()) | |||
{ | |||
} | |||
}; | |||
@@ -33,7 +32,8 @@ namespace http { | |||
context::context(intrusive_ptr<impl::cgi::connection> conn) : | |||
conn_(conn) | |||
{ | |||
d.reset(new data(*this)); | |||
d.reset(new data(*this)); | |||
d->response.reset(new http::response(*this)); | |||
} | |||
@@ -165,7 +165,7 @@ http::request &context::request() | |||
http::response &context::response() | |||
{ | |||
return d->response; | |||
return *d->response; | |||
} | |||
json::value const &context::settings() | |||
@@ -11,6 +11,7 @@ | |||
namespace cppcms { | |||
class service; | |||
class application; | |||
namespace json { class value; } | |||
namespace locale { class environment; } | |||
namespace impl { namespace cgi { class connection; } } | |||
@@ -10,6 +10,7 @@ | |||
#include "service.h" | |||
#include "config.h" | |||
#include "locale_environment.h" | |||
#include "locale_info.h" | |||
#include "util.h" | |||
#include <iostream> | |||
@@ -89,11 +90,13 @@ response::~response() | |||
void response::set_content_header(std::string const &content_type) | |||
{ | |||
std::string charset=context_.settings().get("l10n.charset",""); | |||
if(charset.empty()) | |||
if(context_.settings().get("locale.disable_charset_in_content_type",false)) { | |||
set_header("Content-Type",content_type); | |||
else | |||
} | |||
else { | |||
std::string charset=std::use_facet<locale::info>(context_.locale().get()).encoding(); | |||
set_header("Content-Type",content_type+"; charset="+charset); | |||
} | |||
} | |||
void response::set_html_header() | |||
{ | |||
@@ -1,70 +1,27 @@ | |||
server.modules = ("mod_fastcgi" , "mod_scgi") | |||
server.modules = ("mod_fastcgi") | |||
server.document-root = "./" | |||
# mimetype mapping | |||
mimetype.assign = ( | |||
".pdf" => "application/pdf", | |||
".sig" => "application/pgp-signature", | |||
".spl" => "application/futuresplash", | |||
".class" => "application/octet-stream", | |||
".ps" => "application/postscript", | |||
".torrent" => "application/x-bittorrent", | |||
".dvi" => "application/x-dvi", | |||
".gz" => "application/x-gzip", | |||
".pac" => "application/x-ns-proxy-autoconfig", | |||
".swf" => "application/x-shockwave-flash", | |||
".tar.gz" => "application/x-tgz", | |||
".tgz" => "application/x-tgz", | |||
".tar" => "application/x-tar", | |||
".zip" => "application/zip", | |||
".mp3" => "audio/mpeg", | |||
".m3u" => "audio/x-mpegurl", | |||
".wma" => "audio/x-ms-wma", | |||
".wax" => "audio/x-ms-wax", | |||
".ogg" => "application/ogg", | |||
".wav" => "audio/x-wav", | |||
".gif" => "image/gif", | |||
".jpg" => "image/jpeg", | |||
".jpeg" => "image/jpeg", | |||
".png" => "image/png", | |||
".xbm" => "image/x-xbitmap", | |||
".xpm" => "image/x-xpixmap", | |||
".xwd" => "image/x-xwindowdump", | |||
".css" => "text/css", | |||
".html" => "text/html", | |||
".htm" => "text/html", | |||
".js" => "text/javascript", | |||
".asc" => "text/plain", | |||
".c" => "text/plain", | |||
".cpp" => "text/plain", | |||
".log" => "text/plain", | |||
".conf" => "text/plain", | |||
".text" => "text/plain", | |||
".txt" => "text/plain", | |||
".dtd" => "text/xml", | |||
".xml" => "text/xml", | |||
".mpeg" => "video/mpeg", | |||
".mpg" => "video/mpeg", | |||
".mov" => "video/quicktime", | |||
".qt" => "video/quicktime", | |||
".avi" => "video/x-msvideo", | |||
".asf" => "video/x-ms-asf", | |||
".asx" => "video/x-ms-asf", | |||
".wmv" => "video/x-ms-wmv", | |||
".bz2" => "application/x-bzip", | |||
".tbz" => "application/x-bzip-compressed-tar", | |||
".tar.bz2" => "application/x-bzip-compressed-tar", | |||
# default mime type | |||
"" => "application/octet-stream", | |||
) | |||
) | |||
server.port = 8080 | |||
server.bind = "0.0.0.0" | |||
scgi.server = ( "/hello" => ( "localhost" => ( | |||
fastcgi.server = ( "/hello" => (( | |||
"check-local" => "disable", | |||
"host" => "127.0.0.1", | |||
"port" => 8001 | |||
# "socket" => "/tmp/scgi.socket" | |||
))) | |||
))) | |||
@@ -11,6 +11,23 @@ struct charset::data {}; | |||
std::locale::id charset::id; | |||
charset::charset(std::size_t refs) : | |||
std::locale::facet(refs), | |||
is_utf8_(true), | |||
validators_(0) | |||
{ | |||
} | |||
charset::charset(std::string charset,std::size_t refs) : | |||
std::locale::facet(refs), | |||
name_(charset), | |||
validators_(0) | |||
{ | |||
is_utf8_ = charset=="utf8" || charset=="UTF8" || charset=="utf-8" || charset=="UTF-8"; | |||
} | |||
charset::charset(std::string charset,intrusive_ptr<encoding::validators_set> p,std::size_t refs) : | |||
std::locale::facet(refs), | |||
name_(charset), | |||
@@ -24,10 +41,12 @@ charset::~charset() | |||
} | |||
bool charset::do_validate(char const *begin,char const *end) const | |||
bool charset::do_validate(char const *begin,char const *end,size_t &count) const | |||
{ | |||
if(!validators_) | |||
return true; | |||
encoding::validator v=(*validators_)[name_]; | |||
return v.valid(begin,end); | |||
return v.valid(begin,end,count); | |||
} | |||
std::string charset::do_to_utf8(std::string const &v) const | |||
{ | |||
@@ -18,16 +18,18 @@ namespace locale { | |||
class CPPCMS_API charset : public std::locale::facet { | |||
public: | |||
static std::locale::id id; | |||
charset(std::size_t refs=0); | |||
charset(std::string charset,std::size_t refs=0); | |||
charset(std::string charset,intrusive_ptr<encoding::validators_set> p,std::size_t refs=0); | |||
~charset(); | |||
bool validate(char const *begin,char const *end) const | |||
bool validate(char const *begin,char const *end,size_t &count) const | |||
{ | |||
return do_validate(begin,end); | |||
return do_validate(begin,end,count); | |||
} | |||
bool validate(std::string const &s) const | |||
bool validate(std::string const &s,size_t &count) const | |||
{ | |||
return do_validate(s.data(),s.data()+s.size()); | |||
return do_validate(s.data(),s.data()+s.size(),count); | |||
} | |||
std::string to_utf8(std::string const &v) const | |||
@@ -104,7 +106,7 @@ namespace locale { | |||
private: | |||
virtual bool do_validate(char const *begin,char const *end) const; | |||
virtual bool do_validate(char const *begin,char const *end,size_t &count) const; | |||
virtual std::string do_to_utf8(std::string const &v) const; | |||
virtual std::string do_from_utf8(std::string const &v) const; | |||
@@ -1,6 +1,7 @@ | |||
#ifndef CPPCMS_UTF_ITERATOR_H | |||
#define CPPCMS_UTF_ITERATOR_H | |||
#include <stdint.h> | |||
#include <string.h> | |||
namespace cppcms { | |||
@@ -117,9 +118,20 @@ namespace utf8 { | |||
template<typename Iterator> | |||
bool validate(Iterator p,Iterator e,size_t &count,bool html=false) | |||
{ | |||
while(p!=e) { | |||
if(next(p,e,html)==utf::illegal) | |||
return false; | |||
count++; | |||
} | |||
return true; | |||
} | |||
template<typename Iterator> | |||
bool validate(Iterator p,Iterator e,bool html=false) | |||
{ | |||
while(p!=e) | |||
while(p!=e) | |||
if(next(p,e,html)==utf::illegal) | |||
return false; | |||
return true; | |||