@@ -138,6 +138,10 @@ if(CMAKE_COMPILER_IS_GNUCXX) | |||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | |||
set(CXX_FLAGS "-Wall -Wextra") | |||
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") | |||
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -rdynamic") | |||
endif() | |||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") | |||
set(CXX_FLAGS "-Wall") | |||
elseif(MSVC) | |||
@@ -288,6 +292,17 @@ endif() | |||
check_function_exists(canonicalize_file_name CPPCMS_HAVE_CANONICALIZE_FILE_NAME) | |||
check_function_exists(pthread_mutexattr_setpshared CPPCMS_HAS_THREAD_PSHARED_LIBC) | |||
if(NOT CPPCMS_HAS_THREAD_PSHARED_LIBC AND LIB_PTHREAD) | |||
check_library_exists(${LIB_PTHREAD} pthread_mutexattr_setpshared "" CPPCMS_HAS_THREAD_PSHARED_PTHREAD) | |||
endif() | |||
if(CPPCMS_HAS_THREAD_PSHARED_LIBC OR CPPCMS_HAS_THREAD_PSHARED_PTHREAD) | |||
set(CPPCMS_HAS_THREAD_PSHARED ON) | |||
else() | |||
set(CPPCMS_HAS_THREAD_PSHARED OFF) | |||
endif() | |||
add_definitions(-DCPPCMS_BOOST_ALL_NO_LIB) | |||
@@ -899,7 +899,7 @@ class csrf_block: | |||
class include_block: | |||
basic_pattern = 'include' | |||
basic_name = 'include' | |||
pattern=r'^<%\s*include\s+([a-zA_Z]\w*(::\w+)?)\s*\(\s*(.*)\)' \ | |||
pattern=r'^<%\s*include\s+([a-zA-Z]\w*(::\w+)?)\s*\(\s*(.*)\)' \ | |||
+ r'(?:\s+' \ | |||
+ r'(from\s+(?P<from>\w+)' \ | |||
+ '|' \ | |||
@@ -61,7 +61,11 @@ else() | |||
endif() | |||
option(USE_WINDOWS6_API "Use Windows 6 API (Vista, 7)" OFF) | |||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR APPLE) | |||
check_function_exists(newlocale BOOSTER_HAS_XLOCALE) | |||
if( "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" | |||
OR APPLE | |||
OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD" AND BOOSTER_HAS_XLOCALE) ) | |||
option(DISABLE_POSIX_LOCALE "Disable POSIX locale backend" OFF) | |||
else() | |||
option(DISABLE_POSIX_LOCALE "Disable POSIX locale backend" ON) | |||
@@ -631,7 +635,7 @@ macro(add_booster_param_test MODULE TEST PARAMETER) | |||
target_link_libraries(${TEST_NAME} ${BOOSTER_LIB}) | |||
set_target_properties(${TEST_NAME} PROPERTIES COMPILE_DEFINITIONS "${EXE_COM_DEFS}") | |||
add_test(${TEST_NAME} ${TEST_NAME} ${PARAMETER}) | |||
set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT 10) | |||
set_tests_properties(${TEST_NAME} PROPERTIES TIMEOUT 20) | |||
endmacro() | |||
macro(add_booster_test MODULE TEST) | |||
@@ -27,7 +27,6 @@ namespace boundary { | |||
int compare_text(LeftIterator l_begin,LeftIterator l_end,RightIterator r_begin,RightIterator r_end) | |||
{ | |||
typedef LeftIterator left_iterator; | |||
typedef RightIterator right_iterator; | |||
typedef typename std::iterator_traits<left_iterator>::value_type char_type; | |||
typedef std::char_traits<char_type> traits; | |||
while(l_begin!=l_end && r_begin!=r_end) { | |||
@@ -79,8 +79,14 @@ public: | |||
res = conv(0,0,&out_ptr,&out_left); | |||
int err = errno; | |||
size_t output_count = (out_ptr - out_start) / sizeof(OutChar); | |||
if(res!=0 && res!=(size_t)(-1)) { | |||
if(how_ == stop) { | |||
throw conversion_error(); | |||
} | |||
} | |||
sresult.append(&result[0],output_count); | |||
@@ -166,7 +172,6 @@ public: | |||
}; | |||
template<typename CharType> | |||
class iconv_to_utf : public iconverter_base, public converter_to_utf<CharType> | |||
{ | |||
@@ -188,7 +193,6 @@ public: | |||
} // impl | |||
} // conv | |||
} // locale | |||
@@ -31,7 +31,11 @@ index_type map_direct(boundary_type t,icu::BreakIterator *it,int reserve) | |||
{ | |||
index_type indx; | |||
indx.reserve(reserve); | |||
#if U_ICU_VERSION_MAJOR_NUM >= 52 | |||
icu::BreakIterator *rbbi=it; | |||
#else | |||
icu::RuleBasedBreakIterator *rbbi=dynamic_cast<icu::RuleBasedBreakIterator *>(it); | |||
#endif | |||
indx.push_back(break_info()); | |||
it->first(); | |||
@@ -263,7 +263,7 @@ namespace locale { | |||
return cache->date_time_format_[1][1]; | |||
return strftime_to_icu_full( | |||
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull,icu::DateFormat::kFull,locale), | |||
"YYYY-MM-dd HH:mm:ss" | |||
"yyyy-MM-dd HH:mm:ss" | |||
); | |||
} | |||
// not supported by ICU ;( | |||
@@ -272,7 +272,7 @@ namespace locale { | |||
case 'd': // Day of Month [01,31] | |||
return "dd"; | |||
case 'D': // %m/%d/%y | |||
return "MM/dd/YY"; | |||
return "MM/dd/yy"; | |||
case 'e': // Day of Month [1,31] | |||
return "d"; | |||
case 'h': // == b | |||
@@ -312,7 +312,7 @@ namespace locale { | |||
return cache->date_format_[1]; | |||
return strftime_to_icu_full( | |||
icu::DateFormat::createDateInstance(icu::DateFormat::kMedium,locale), | |||
"YYYY-MM-dd" | |||
"yyyy-MM-dd" | |||
); | |||
} | |||
case 'X': // Time | |||
@@ -325,9 +325,9 @@ namespace locale { | |||
); | |||
} | |||
case 'y': // Year [00-99] | |||
return "YY"; | |||
return "yy"; | |||
case 'Y': // Year 1998 | |||
return "YYYY"; | |||
return "yyyy"; | |||
case 'Z': // timezone | |||
return "vvvv"; | |||
case '%': // % | |||
@@ -385,7 +385,7 @@ struct basic_numpunct { | |||
} | |||
basic_numpunct(locale_t lc) | |||
{ | |||
#ifdef __APPLE__ | |||
#if defined(__APPLE__) || defined(__FreeBSD__) | |||
lconv *cv = localeconv_l(lc); | |||
grouping = cv->grouping; | |||
thousands_sep = cv->thousands_sep; | |||
@@ -12,6 +12,13 @@ | |||
namespace booster { | |||
namespace locale { | |||
#if defined(__ICONV_F_HIDE_INVALID) && defined(__FreeBSD__) | |||
inline size_t call_iconv(iconv_t d,char **in,size_t *insize,char **out,size_t *outsize) | |||
{ | |||
char const **rin = const_cast<char const **>(in); | |||
return __iconv(d,rin,insize,out,outsize,__ICONV_F_HIDE_INVALID,0); | |||
} | |||
#else | |||
extern "C" { | |||
typedef size_t (*gnu_iconv_ptr_type)(iconv_t d,char const **in,size_t *insize,char **out,size_t *outsize); | |||
typedef size_t (*posix_iconv_ptr_type)(iconv_t d,char **in,size_t *insize,char **out,size_t *outsize); | |||
@@ -29,6 +36,7 @@ namespace booster { | |||
{ | |||
return do_iconv( iconv, d, in,insize,out,outsize); | |||
} | |||
#endif | |||
} // locale | |||
} // boost | |||
@@ -14,14 +14,14 @@ int main() | |||
} | |||
#else | |||
//#define BOOST_LOCALE_ERROR_LIMIT 1000000 | |||
//#define BOOST_LOCALE_ERROR_LIMIT 0 | |||
#define BOOSTER_LOCALE_ERROR_LIMIT 100000 | |||
#include <booster/locale/boundary.h> | |||
#include <booster/locale/generator.h> | |||
#include "test_locale.h" | |||
#include "test_locale_tools.h" | |||
#include <list> | |||
#include <unicode/uversion.h> | |||
// Debugging code | |||
@@ -394,13 +394,19 @@ void test_boundaries(std::string *all,int *first,int *second,lb::boundary_type t | |||
void word_boundary() | |||
{ | |||
booster::locale::generator g; | |||
std::string all1[]={"10"," ","Hello"," ","Windows7"," ","平仮名","ひらがな","ヒラガナ",""}; | |||
//std::string all1[]={"10"," ","Hello"," ","Windows7"," ","平仮名","ひらがな","ヒラガナ",""}; | |||
//std::string all1[]={"10"," ","Hello"," ","Windows7"," ","平仮名","ひん","アヒル",""}; | |||
std::string all1[]={"10"," ","Hello"," ","Windows7"," ","平仮名","アヒル",""}; | |||
int none1[]={ 0, 1, 0, 1, 0, 1, 0, 0, 0}; | |||
int num1[]={ 1, 0, 0, 0, 1, 0, 0 , 0 , 0}; | |||
int word1[]={ 0, 0, 1, 0, 1, 0, 0 , 0 , 0}; | |||
#if U_ICU_VERSION_MAJOR_NUM >= 50 | |||
int kana1[]={ 0, 0, 0, 0, 0, 0, 0, 0 , 0}; | |||
int ideo1[]={ 0, 0, 0, 0, 0, 0, 1, 1 , 1}; | |||
#else | |||
int kana1[]={ 0, 0, 0, 0, 0, 0, 0, 1 , 1}; | |||
int ideo1[]={ 0, 0, 0, 0, 0, 0, 1, 0 , 0}; | |||
#endif | |||
int zero[25]={0}; | |||
@@ -288,8 +288,12 @@ int main() | |||
std::cout << "Testing Shift-JIS using POSIX/iconv" << std::endl; | |||
cvt = booster::locale::impl_posix::create_iconv_converter("Shift-JIS"); | |||
TEST(cvt.get()); | |||
test_shiftjis(cvt); | |||
if(cvt.get()) { | |||
test_shiftjis(cvt); | |||
} | |||
else { | |||
std::cout<< "- Shift-JIS is not supported!" << std::endl; | |||
} | |||
#endif | |||
} | |||
@@ -41,7 +41,19 @@ using namespace booster::locale; | |||
#ifdef TEST_DEBUG | |||
#undef BOOSTER_HAS_CHAR16_T | |||
#undef BOOSTER_HAS_CHAR32_T | |||
#define TESTEQ(x,y) do { std::cerr << "["<<x << "]!=\n[" << y <<"]"<< std::endl; TEST((x)==(y)); } while(0) | |||
template<typename T> | |||
void print_diff(T const &,T const &,int) | |||
{ | |||
} | |||
template<> | |||
void print_diff(std::string const &l,std::string const &r,int line) | |||
{ | |||
if(l!=r) { | |||
std::cerr << "----[" << l <<"]!=\n----["<<r<<"] in " << line << std::endl; | |||
} | |||
} | |||
#define TESTEQ(x,y) do { print_diff((x),(y),__LINE__); TEST((x)==(y)); } while(0) | |||
#else | |||
#define TESTEQ(x,y) TEST((x)==(y)) | |||
#endif | |||
@@ -54,6 +66,40 @@ do{ \ | |||
TESTEQ(ss.str(),to_correct_string<CharType>(expected,loc)); \ | |||
}while(0) | |||
#ifndef _LIBCPP_VERSION | |||
static bool parsing_fails() | |||
{ | |||
return true; | |||
} | |||
#else | |||
static bool parsing_fails() | |||
{ | |||
static bool checked=false; | |||
static bool fails; | |||
if(!checked) { | |||
try { | |||
std::istringstream ss("x"); | |||
ss.exceptions(std::ios_base::failbit); | |||
int x; | |||
ss>>x; | |||
fails =false; | |||
} | |||
catch(std::ios_base::failure const &) { | |||
fails=true; | |||
} | |||
catch(...) { | |||
fails=false; | |||
} | |||
checked=true; | |||
if(!fails) { | |||
std::cerr << "!!! Warning: libc++ library does not throw an exception on failbit !!!" << std::endl; | |||
} | |||
} | |||
return fails; | |||
} | |||
#endif | |||
#define TEST_NOPAR(manip,actual,type) \ | |||
do{ \ | |||
type v; \ | |||
@@ -66,7 +112,7 @@ do{ \ | |||
ss >> manip >> v ; \ | |||
TEST(ss.fail()); \ | |||
} \ | |||
{ \ | |||
if(parsing_fails()){ \ | |||
std::basic_istringstream<CharType> ss; \ | |||
ss.imbue(loc); \ | |||
ss.str(act); \ | |||
@@ -288,25 +334,40 @@ void test_manip(std::string e_charset="UTF-8") | |||
TEST_FP2(as::time, as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM",time_t,a_time+a_timesec); | |||
TEST_FP3(as::time,as::time_short ,as::time_zone("GMT+01:00"),a_datetime,"4:33 PM",time_t,a_time); | |||
TEST_FP3(as::time,as::time_medium,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM",time_t,a_time+a_timesec); | |||
TEST_FP3(as::time,as::time_long ,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM GMT+01:00",time_t,a_time+a_timesec); | |||
#if U_ICU_VERSION_MAJOR_NUM >= 52 | |||
#define GMT_P100 "GMT+1" | |||
#else | |||
#define GMT_P100 "GMT+01:00" | |||
#endif | |||
#if U_ICU_VERSION_MAJOR_NUM >= 50 | |||
#define PERIOD "," | |||
#define ICUAT " at" | |||
#else | |||
#define PERIOD "" | |||
#define ICUAT "" | |||
#endif | |||
TEST_FP3(as::time,as::time_long ,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM " GMT_P100,time_t,a_time+a_timesec); | |||
#if BOOSTER_ICU_VER == 308 && defined(__CYGWIN__) | |||
// Known faliture ICU issue | |||
#else | |||
TEST_FP3(as::time,as::time_full ,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM GMT+01:00",time_t,a_time+a_timesec); | |||
#endif | |||
TEST_FP2(as::datetime, as::gmt,a_datetime,"Feb 5, 1970 3:33:13 PM",time_t,a_datetime); | |||
TEST_FP4(as::datetime,as::date_short ,as::time_short ,as::gmt,a_datetime,"2/5/70 3:33 PM",time_t,a_date+a_time); | |||
TEST_FP4(as::datetime,as::date_medium,as::time_medium,as::gmt,a_datetime,"Feb 5, 1970 3:33:13 PM",time_t,a_datetime); | |||
TEST_FP2(as::datetime, as::gmt,a_datetime,"Feb 5, 1970" PERIOD " 3:33:13 PM",time_t,a_datetime); | |||
TEST_FP4(as::datetime,as::date_short ,as::time_short ,as::gmt,a_datetime,"2/5/70" PERIOD " 3:33 PM",time_t,a_date+a_time); | |||
TEST_FP4(as::datetime,as::date_medium,as::time_medium,as::gmt,a_datetime,"Feb 5, 1970" PERIOD " 3:33:13 PM",time_t,a_datetime); | |||
#if BOOSTER_ICU_VER >= 408 | |||
TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970 3:33:13 PM GMT",time_t,a_datetime); | |||
TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970" ICUAT " 3:33:13 PM GMT",time_t,a_datetime); | |||
#if BOOSTER_ICU_EXACT_VER != 40800 | |||
// know bug #8675 | |||
TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970 3:33:13 PM GMT",time_t,a_datetime); | |||
TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970" ICUAT " 3:33:13 PM GMT",time_t,a_datetime); | |||
#endif | |||
#else | |||
TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970 3:33:13 PM GMT+00:00",time_t,a_datetime); | |||
TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970 3:33:13 PM GMT+00:00",time_t,a_datetime); | |||
TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970" PERIOD " 3:33:13 PM GMT+00:00",time_t,a_datetime); | |||
TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970" PERIOD " 3:33:13 PM GMT+00:00",time_t,a_datetime); | |||
#endif | |||
time_t now=time(0); | |||
@@ -330,7 +391,7 @@ void test_manip(std::string e_charset="UTF-8") | |||
std::string result[]= { | |||
"Thu","Thursday","Feb","February", // aAbB | |||
#if BOOSTER_ICU_VER >= 408 | |||
"Thursday, February 5, 1970 3:33:13 PM GMT", // c | |||
"Thursday, February 5, 1970" ICUAT " 3:33:13 PM GMT", // c | |||
#else | |||
"Thursday, February 5, 1970 3:33:13 PM GMT+00:00", // c | |||
#endif | |||
@@ -433,7 +494,7 @@ void test_format(std::string charset="UTF-8") | |||
time_t a_timesec = 13; | |||
time_t a_datetime = a_date + a_time + a_timesec; | |||
FORMAT("{1,date,gmt};{1,time,gmt};{1,datetime,gmt};{1,dt,gmt}",a_datetime, | |||
"Feb 5, 1970;3:33:13 PM;Feb 5, 1970 3:33:13 PM;Feb 5, 1970 3:33:13 PM"); | |||
"Feb 5, 1970;3:33:13 PM;Feb 5, 1970" PERIOD " 3:33:13 PM;Feb 5, 1970" PERIOD " 3:33:13 PM"); | |||
#if BOOSTER_ICU_VER >= 408 | |||
FORMAT("{1,time=short,gmt};{1,time=medium,gmt};{1,time=long,gmt};{1,date=full,gmt}",a_datetime, | |||
"3:33 PM;3:33:13 PM;3:33:13 PM GMT;Thursday, February 5, 1970"); | |||
@@ -451,6 +512,13 @@ void test_format(std::string charset="UTF-8") | |||
FORMAT("{1,gmt,ftime='%H'''}",a_datetime,"15'"); | |||
FORMAT("{1,gmt,ftime='''%H'}",a_datetime,"'15"); | |||
FORMAT("{1,gmt,ftime='%H o''clock'}",a_datetime,"15 o'clock"); | |||
// Test not a year of the week | |||
a_datetime=1388491200; // 2013-12-31 12:00 - check we don't use week of year | |||
FORMAT("{1,gmt,ftime='%Y'}",a_datetime,"2013"); | |||
FORMAT("{1,gmt,ftime='%y'}",a_datetime,"13"); | |||
FORMAT("{1,gmt,ftime='%D'}",a_datetime,"12/31/13"); | |||
} | |||
@@ -74,7 +74,7 @@ void test_char() | |||
std::string name; | |||
#ifndef __APPLE__ | |||
#if !defined(__APPLE__) && !defined(__FreeBSD__) | |||
std::string names[] = { "en_US.UTF-8", "en_US.ISO8859-1" }; | |||
for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) { | |||
if(have_locale(names[i])) { | |||
@@ -89,7 +89,7 @@ void test_char() | |||
} | |||
} | |||
#else | |||
std::cout << "- Collation is broken in Mac OS X's C standard library, skipping" << std::endl; | |||
std::cout << "- Collation is broken on this OS C standard library, skipping" << std::endl; | |||
#endif | |||
} | |||
@@ -59,7 +59,7 @@ void test_char() | |||
std::cout << "Testing " << name << std::endl; | |||
std::locale l=gen(name); | |||
test_one<CharType>(l,"Hello World","hello world","HELLO WORLD"); | |||
#ifdef __APPLE__ | |||
#if defined(__APPLE__) || defined(__FreeBSD__) | |||
if(sizeof(CharType)!=1) | |||
#endif | |||
test_one<CharType>(l,"Façade","façade","FAÇADE"); | |||
@@ -54,9 +54,6 @@ template<typename CharType,typename RefCharType> | |||
void test_by_char(std::locale const &l,locale_t lreal) | |||
{ | |||
typedef std::basic_stringstream<CharType> ss_type; | |||
typedef std::basic_stringstream<RefCharType> ss_ref_type; | |||
typedef std::basic_string<RefCharType> string_type; | |||
typedef std::basic_string<RefCharType> string_ref_type; | |||
using namespace booster::locale; | |||
@@ -74,6 +74,9 @@ void test_char() | |||
std::string name; | |||
#if defined(_LIBCPP_VERSION) && (defined(__APPLE__) || defined(__FreeBSD__)) | |||
std::cout << "- Collation is broken on this OS's standard C++ library, skipping" << std::endl; | |||
#else | |||
std::string names[] = { "en_US.UTF-8", "en_US.ISO8859-1" }; | |||
for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) { | |||
name = get_std_name(names[i]); | |||
@@ -87,6 +90,7 @@ void test_char() | |||
std::cout << "- " << names[i] << " not supported, skipping" << std::endl; | |||
} | |||
} | |||
#endif | |||
} | |||
@@ -60,8 +60,6 @@ void test_by_char(std::locale const &l,std::locale const &lreal) | |||
{ | |||
typedef std::basic_stringstream<CharType> ss_type; | |||
typedef std::basic_stringstream<RefCharType> ss_ref_type; | |||
typedef std::basic_string<RefCharType> string_type; | |||
typedef std::basic_string<RefCharType> string_ref_type; | |||
using namespace booster::locale; | |||
@@ -194,13 +194,15 @@ namespace booster { | |||
extern "C" void *booster_thread_func(void *p) | |||
{ | |||
// Do not add reference count as it was added upon sucesseful thread creation | |||
intrusive_ptr<win_thread_data> d(reinterpret_cast<win_thread_data *>(p),false); | |||
try { | |||
d->run(); | |||
} | |||
catch(...) { | |||
} | |||
{ | |||
// Do not add reference count as it was added upon sucesseful thread creation | |||
intrusive_ptr<win_thread_data> d(reinterpret_cast<win_thread_data *>(p),false); | |||
try { | |||
d->run(); | |||
} | |||
catch(...) { | |||
} | |||
} | |||
_endthreadex(0); | |||
return 0; | |||
@@ -44,6 +44,31 @@ bool tls_ok = true; | |||
booster::mutex dtor_called_mutex; | |||
int dtor_called = 0; | |||
struct counted_functor { | |||
counted_functor() { add(1); } | |||
counted_functor(counted_functor const &) { add(1); } | |||
counted_functor const &operator=(counted_functor const &) { return *this; } | |||
~counted_functor() { add(-1); } | |||
void operator()() const | |||
{ | |||
booster::ptime::millisleep(200); | |||
} | |||
static void add(int v) | |||
{ | |||
booster::unique_lock<booster::mutex> g(lock); | |||
objects+= v; | |||
} | |||
static booster::mutex lock; | |||
static int objects; | |||
}; | |||
booster::mutex counted_functor::lock; | |||
int counted_functor::objects; | |||
struct tls_object { | |||
int counter; | |||
tls_object() : counter(0) {} | |||
@@ -180,6 +205,30 @@ int main() | |||
t.join(); | |||
TEST(called_); | |||
} | |||
{ | |||
std::cout << "Functor destruction" << std::endl; | |||
TEST(counted_functor::objects==0); | |||
{ | |||
counted_functor f; | |||
booster::thread t(f); | |||
TEST(counted_functor::objects>=2); | |||
t.join(); | |||
TEST(counted_functor::objects==1); | |||
} | |||
TEST(counted_functor::objects==0); | |||
{ | |||
{ | |||
counted_functor f; | |||
booster::thread t(f); | |||
TEST(counted_functor::objects>=2); | |||
t.detach(); | |||
} | |||
TEST(counted_functor::objects>=1); | |||
booster::ptime::millisleep(400); | |||
TEST(counted_functor::objects==0); | |||
} | |||
} | |||
std::cout << "Test recursive mutex" << std::endl; | |||
{ | |||
booster::recursive_mutex m; | |||
@@ -109,6 +109,7 @@ | |||
#cmakedefine CPPCMS_NO_PREFOK_CACHE | |||
#cmakedefine CPPCMS_NO_GZIP | |||
#cmakedefine CPPCMS_SQLITE_LINK_STATIC | |||
#cmakedefine CPPCMS_HAS_THREAD_PSHARED | |||
#endif |
@@ -248,7 +248,7 @@ namespace cppcms { | |||
/// | |||
bool operator!=(string_key const &other) const | |||
{ | |||
return !(*this!=other); | |||
return !(*this==other); | |||
} | |||
/// | |||
@@ -94,7 +94,7 @@ namespace cppcms { | |||
p.reset(new View(stream,dynamic_cast<Content &>(*c))); | |||
} | |||
catch(std::bad_cast const &) { | |||
throw cppcms_error("cppcms::views::generator: an attempt to use content if invalid type"); | |||
throw cppcms_error("cppcms::views::generator: an attempt to use content of invalid type"); | |||
} | |||
return p; | |||
} | |||
@@ -14,6 +14,7 @@ | |||
#include <booster/intrusive_ptr.h> | |||
#include <cppcms/cstdint.h> | |||
#include <cppcms/base_cache_fwd.h> | |||
#include <time.h> | |||
namespace cppcms { | |||
namespace impl { | |||
@@ -32,6 +32,7 @@ public: | |||
virtual std::string encrypt(std::string const &plain); | |||
virtual bool decrypt(std::string const &cipher,std::string &plain); | |||
static bool equal(void const *a,void const *b,size_t n); | |||
private: | |||
crypto::key key_; | |||
std::string hash_; | |||
@@ -138,31 +138,42 @@ namespace cppcms { | |||
} | |||
break; | |||
case expecting_separator_boundary: | |||
if(*buffer == boundary_[position_]) | |||
position_++; | |||
else if(position_ > 0) { | |||
file_->write_data().write(boundary_.c_str(),position_); | |||
position_ = 0; | |||
if(*buffer == boundary_[0]) | |||
position_=1; | |||
if(!file_->write_data()) | |||
return no_room_left; | |||
} | |||
if(position_ == 0) { | |||
file_->write_data() << *buffer; | |||
if(!file_->write_data()) | |||
return no_room_left; | |||
} | |||
else if(position_ == boundary_.size()) { | |||
state_ = expecting_one_crlf_or_eof; | |||
position_ = 0; | |||
file_->data().seekg(0); | |||
files_.push_back(file_); | |||
file_.reset(new http::file()); | |||
file_->set_temporary_directory(temp_dir_); | |||
if(memory_limit_ != -1) { | |||
file_->set_memory_limit(memory_limit_); | |||
} | |||
{ | |||
std::streambuf *out=file_->write_data().rdbuf(); | |||
char const *this_boundary = boundary_.c_str(); | |||
size_t boundary_size = boundary_.size(); | |||
while(size > 0) { | |||
char c=*buffer; | |||
if(c == this_boundary[position_]) | |||
position_++; | |||
else if(position_ > 0) { | |||
std::streamsize expected = position_; | |||
std::streamsize s=out->sputn(this_boundary,position_); | |||
position_ = 0; | |||
if(c == boundary_[0]) | |||
position_=1; | |||
if(s!=expected) | |||
return no_room_left; | |||
} | |||
if(position_ == 0) { | |||
if(out->sputc(c)==EOF) | |||
return no_room_left; | |||
} | |||
else if(position_ == boundary_size) { | |||
state_ = expecting_one_crlf_or_eof; | |||
position_ = 0; | |||
file_->data().seekg(0); | |||
files_.push_back(file_); | |||
file_.reset(new http::file()); | |||
file_->set_temporary_directory(temp_dir_); | |||
if(memory_limit_ != -1) { | |||
file_->set_memory_limit(memory_limit_); | |||
} | |||
break; | |||
} | |||
buffer++; | |||
size--; | |||
} // end while | |||
} | |||
break; | |||
} | |||
@@ -49,6 +49,7 @@ namespace impl { | |||
pthread_mutex_init(m,0); | |||
} | |||
else { | |||
#ifdef CPPCMS_HAS_THREAD_PSHARED | |||
pthread_mutexattr_t attr; | |||
pthread_mutexattr_init(&attr); | |||
try { | |||
@@ -64,6 +65,9 @@ namespace impl { | |||
pthread_mutexattr_destroy(&attr); | |||
throw; | |||
} | |||
#else | |||
throw cppcms_error("Process shared mutex is not supported"); | |||
#endif | |||
} | |||
} | |||
@@ -78,6 +82,7 @@ namespace impl { | |||
pthread_rwlock_init(m,0); | |||
} | |||
else { | |||
#ifdef CPPCMS_HAS_THREAD_PSHARED | |||
pthread_rwlockattr_t attr; | |||
pthread_rwlockattr_init(&attr); | |||
try { | |||
@@ -93,6 +98,9 @@ namespace impl { | |||
pthread_rwlockattr_destroy(&attr); | |||
throw; | |||
} | |||
#else | |||
throw cppcms_error("Process shared mutex is not supported"); | |||
#endif | |||
} | |||
} | |||
@@ -102,7 +110,7 @@ namespace impl { | |||
} | |||
#ifdef CPPCMS_HAS_THREAD_PSHARED | |||
inline bool test_pthread_mutex_pshared_impl() | |||
{ | |||
void *memory=mmap_anonymous(sizeof(pthread_mutex_t)); | |||
@@ -124,6 +132,13 @@ namespace impl { | |||
static bool has = test_pthread_mutex_pshared_impl(); | |||
return has; | |||
} | |||
#else | |||
inline bool test_pthread_mutex_pshared() | |||
{ | |||
return false; | |||
} | |||
#endif | |||
class mutex : public booster::noncopyable { | |||
@@ -15,7 +15,7 @@ | |||
#include <sstream> | |||
#include <cppcms/cppcms_error.h> | |||
#include "aes_encryptor.h" | |||
#include "hmac_encryptor.h" | |||
#include <cppcms/base64.h> | |||
#include <cppcms/crypto.h> | |||
#include <string.h> | |||
@@ -169,7 +169,7 @@ bool aes_cipher::decrypt(std::string const &cipher,std::string &plain) | |||
std::vector<char> verify(digest_size,0); | |||
signature.readout(&verify[0]); | |||
if(memcmp(&verify[0],cipher.c_str() + real_size,digest_size)!=0) { | |||
if(!hmac_cipher::equal(&verify[0],cipher.c_str() + real_size,digest_size)) { | |||
memset(&verify[0],0,digest_size); | |||
return false; | |||
} | |||
@@ -7,9 +7,21 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#define CPPCMS_SOURCE | |||
#include <cppcms/config.h> | |||
#include <set> | |||
#ifndef CPPCMS_BOOST_DETAIL_NO_CONTAINER_FWD | |||
#define CPPCMS_BOOST_DETAIL_NO_CONTAINER_FWD | |||
#endif | |||
#ifndef CPPCMS_BOOST_NO_0X_HDR_INITIALIZER_LIST | |||
#define CPPCMS_BOOST_NO_0X_HDR_INITIALIZER_LIST | |||
#endif | |||
#ifndef CPPCMS_NO_CACHE | |||
#include "cache_storage.h" | |||
#include <booster/thread.h> | |||
#include <iostream> | |||
@@ -25,6 +37,7 @@ | |||
#endif | |||
#include <map> | |||
#include <string> | |||
#include <list> | |||
#include <limits> | |||
#include <memory> | |||
@@ -739,11 +739,11 @@ void textarea::render_input(form_context &context) | |||
render_attributes(context); | |||
if(rows_ >= 0) { | |||
output<<"rows=\""<< cint(rows_) << "\""; | |||
output<<"rows=\""<< cint(rows_) << "\" "; | |||
} | |||
if(cols_ >= 0) { | |||
output<<"cols=\"" <<cint(cols_) << "\""; | |||
output<<"cols=\"" <<cint(cols_) << "\" "; | |||
} | |||
} | |||
else { | |||
@@ -56,6 +56,18 @@ std::string hmac_cipher::encrypt(std::string const &plain) | |||
return std::string(&data[0],cipher_size); | |||
} | |||
bool hmac_cipher::equal(void const *a,void const *b,size_t n) | |||
{ | |||
char const *left = static_cast<char const *>(a); | |||
char const *right = static_cast<char const *>(b); | |||
size_t diff = 0; | |||
for(size_t i=0;i<n;i++) { | |||
if(left[i]!=right[i]) | |||
diff++; | |||
} | |||
return diff==0; | |||
} | |||
bool hmac_cipher::decrypt(std::string const &cipher,std::string &plain) | |||
{ | |||
crypto::hmac md(hash_,key_); | |||
@@ -68,7 +80,7 @@ bool hmac_cipher::decrypt(std::string const &cipher,std::string &plain) | |||
md.append(cipher.c_str(),message_size); | |||
std::vector<char> mac(digest_size,0); | |||
md.readout(&mac[0]); | |||
bool ok = memcmp(&mac[0],cipher.c_str() + message_size,digest_size) == 0; | |||
bool ok = equal(&mac[0],cipher.c_str() + message_size,digest_size); | |||
memset(&mac[0],0,digest_size); | |||
if(ok) { | |||
plain = cipher.substr(0,message_size); | |||
@@ -12,7 +12,6 @@ | |||
#include <booster/nowide/cstdio.h> | |||
#include <booster/nowide/fstream.h> | |||
#include <stdlib.h> | |||
#include <vector> | |||
#include "tohex.h" | |||
@@ -77,11 +76,7 @@ std::ostream &file::write_data() | |||
void file::copy_stream(std::istream &in,std::ostream &out) | |||
{ | |||
std::vector<char> v(1024,0); | |||
while(!in.eof()) { | |||
in.read(&v.front(),1024); | |||
out.write(&v.front(),in.gcount()); | |||
} | |||
out << in.rdbuf(); | |||
} | |||
void file::save_to(std::string const &filename) | |||
@@ -1019,7 +1019,7 @@ namespace json { | |||
bool parse_number() | |||
{ | |||
is_ >> real; | |||
return is_; | |||
return !is_.fail();; | |||
} | |||
}; | |||
@@ -86,7 +86,7 @@ int main(int argc,char **argv) | |||
cbc = next; | |||
else if(arg=="--hmac-file") | |||
hmac_file = next; | |||
else if(arg=="--hmac-cbc") | |||
else if(arg=="--cbc-file") | |||
cbc_file = next; | |||
else if(arg=="--output") | |||
output = next; | |||
@@ -6,6 +6,9 @@ | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#define CPPCMS_SOURCE | |||
#ifndef CPPCMS_BOOST_NO_0X_HDR_INITIALIZER_LIST | |||
#define CPPCMS_BOOST_NO_0X_HDR_INITIALIZER_LIST | |||
#endif | |||
#include "session_memory_storage.h" | |||
#include <cppcms/config.h> | |||
#include "hash_map.h" | |||
@@ -10,6 +10,7 @@ | |||
#include "http_protocol.h" | |||
#include <stdio.h> | |||
#include <iterator> | |||
#include <ostream> | |||
#include "md5.h" | |||
#include "tohex.h" | |||
@@ -55,6 +55,19 @@ std::string format(json::value const &v) | |||
int main() | |||
{ | |||
try { | |||
{ | |||
cppcms::string_key a("a"),aa("a"); | |||
cppcms::string_key b("b"); | |||
TEST(a==aa); | |||
TEST(a!=b); | |||
TEST(a<b); | |||
TEST(a<=b); | |||
TEST(a<=a); | |||
TEST(b>a); | |||
TEST(b>=b); | |||
TEST(b>=a); | |||
} | |||
json::value v; | |||
json::value const &vc=v; | |||
TEST(v.type()==json::is_undefined); | |||