Browse Source

Inital support of forms added

master
Artyom Beilis 15 years ago
parent
commit
ab48046e27
17 changed files with 986 additions and 229 deletions
  1. +2
    -1
      Makefile.am
  2. +19
    -0
      base_view.h
  3. +5
    -3
      config.js
  4. +10
    -9
      encoding.cpp
  5. +3
    -3
      encoding.h
  6. +36
    -19
      encoding_validators.h
  7. +293
    -57
      form.cpp
  8. +502
    -72
      form.h
  9. +57
    -0
      hello_world.cpp
  10. +7
    -7
      http_context.cpp
  11. +1
    -0
      http_context.h
  12. +6
    -3
      http_response.cpp
  13. +4
    -47
      light.conf
  14. +21
    -2
      locale_charset.cpp
  15. +7
    -5
      locale_charset.h
  16. +0
    -0
      rpc_json.h
  17. +13
    -1
      utf_iterator.h

+ 2
- 1
Makefile.am View File

@@ -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


+ 19
- 0
base_view.h View File

@@ -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 {


+ 5
- 3
config.js View File

@@ -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",


+ 10
- 9
encoding.cpp View File

@@ -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 {};


+ 3
- 3
encoding.h View File

@@ -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:


+ 36
- 19
encoding_validators.h View File

@@ -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;


+ 293
- 57
form.cpp View File

@@ -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<<"&nbsp;";
@@ -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<<"&nbsp;";
@@ -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



+ 502
- 72
form.h View File

@@ -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



+ 57
- 0
hello_world.cpp View File

@@ -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");


+ 7
- 7
http_context.cpp View File

@@ -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()


+ 1
- 0
http_context.h View File

@@ -11,6 +11,7 @@
namespace cppcms {

class service;
class application;
namespace json { class value; }
namespace locale { class environment; }
namespace impl { namespace cgi { class connection; } }


+ 6
- 3
http_response.cpp View File

@@ -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()
{


+ 4
- 47
light.conf View File

@@ -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"
)))
)))


+ 21
- 2
locale_charset.cpp View File

@@ -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
{


+ 7
- 5
locale_charset.h View File

@@ -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;


json_object.h → rpc_json.h View File


+ 13
- 1
utf_iterator.h View File

@@ -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;


Loading…
Cancel
Save