diff --git a/.gitignore b/.gitignore index 3205411..701b44a 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ __pycache__ /external/libssh-win-static/lib /external/mbedtls /external/sqlite +/external/libuv /client/tools/putty /client/tools/winscp @@ -69,3 +70,4 @@ __pycache__ # for not finished code /common/libex/test /client/tp_rdp +/server/tp_core/protocol/rdp diff --git a/common/libex/include/ex/ex_platform.h b/common/libex/include/ex/ex_platform.h index a30ff36..01bc685 100644 --- a/common/libex/include/ex/ex_platform.h +++ b/common/libex/include/ex/ex_platform.h @@ -1,118 +1,141 @@ -#ifndef __LIB_EX_PLATFORM_H__ -#define __LIB_EX_PLATFORM_H__ - -#if defined(_WIN32) || defined(WIN32) -# define EX_OS_WIN32 -#elif defined(__linux__) -# define EX_OS_LINUX -# define EX_OS_UNIX -#elif defined(__APPLE__) -# define EX_OS_MACOS -# define EX_OS_UNIX -#else -# error unsupported platform. -#endif - -// compiler -#ifdef EX_OS_WIN32 -# ifndef _MSC_VER -# error need VisualStudio on Windows. -# endif -# if _MSC_VER < 1900 // need VisualStudio 2015 and above. -# error need VisualStudio 2015 and above. -# endif -#endif - -#ifdef EX_OS_WIN32 -# if !defined(UNICODE) && !defined(_UNICODE) -# error "Does not support `Multi-Byte Character Set` on Windows." -# endif -# ifdef _DEBUG -# ifndef EX_DEBUG -# define EX_DEBUG -# endif -# endif -#endif - - -#ifdef EX_OS_WIN32 -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0500 // 0x0500 = Windows2000 -# endif -# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -# define _CRT_RAND_S // for rand_s(). -# include -# include -# include -# include -# define _CSTDIO_ -# define _CSTRING_ -# define _CWCHAR_ -# include -# include -# include -#else -# include -# include -# include -# include // free() -# include // va_start() -# include // readlink() -# include -# include -# include -# include -# include -#endif - - -/* -* On Windows PATH_MAX does not exist but MAX_PATH does. -* WinAPI MAX_PATH limit is only 256. MSVCR fuctions does not have this limit. -* Redefine PATH_MAX for Windows to support longer path names. -*/ -#if defined(EX_OS_WIN32) -# ifdef PATH_MAX -# undef PATH_MAX /* On Windows override PATH_MAX if defined. */ -# endif -# define PATH_MAX 1024 -#elif defined(EX_OS_LINUX) -# ifndef PATH_MAX -# define PATH_MAX 1024 -# endif -#elif defined(EX_OS_MACOS) -# define PATH_MAX 1024 /* Recommended value for OSX. */ -#endif - -// assert -#ifdef EX_DEBUG -# define ASSERT(exp) -# define CHECK(exp) do { if (!(exp)) abort(); } while (0) -//# define DEBUG_CHECKS (0) -#else -# include -# define ASSERT(exp) assert(exp) -# define CHECK(exp) assert(exp) -//# define DEBUG_CHECKS (1) -#endif - -#ifndef UNUSED -# if defined(_MSC_VER) -# define UNUSED(x) (void)(x) -# elif defined(__GUNC__) -# defined UNUSED(x) UNUSED_ ## x __attribute__((unused)) -# elif defined(__LCLINT__) -# define UNUSED(x) /*@unused@*/ x -# elif defined(__cplusplus) -# define UNUSED(x) -# else -# define UNUSED(x) (void)(x) -# endif -#endif - -#ifdef EX_OS_WIN32 -# pragma comment(lib, "shlwapi.lib") -#endif - - -#endif // __LIB_EX_PLATFORM_H__ +#ifndef __LIB_EX_PLATFORM_H__ +#define __LIB_EX_PLATFORM_H__ + +#if defined(_WIN32) || defined(WIN32) +# define EX_OS_WIN32 +#elif defined(__linux__) +# define EX_OS_LINUX +# define EX_OS_UNIX +#elif defined(__APPLE__) +# define EX_OS_MACOS +# define EX_OS_UNIX +#else +# error unsupported platform. +#endif + +// compiler +#ifdef EX_OS_WIN32 +# ifndef _MSC_VER +# error need VisualStudio on Windows. +# endif +# if _MSC_VER < 1900 // need VisualStudio 2015 and above. +# error need VisualStudio 2015 and above. +# endif +#endif + +#ifdef EX_OS_WIN32 +# if !defined(UNICODE) && !defined(_UNICODE) +# error "Does not support `Multi-Byte Character Set` on Windows." +# endif +# ifdef _DEBUG +# ifndef EX_DEBUG +# define EX_DEBUG +# endif +# endif +#endif + + +#ifdef EX_OS_WIN32 +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 // 0x0500 = Windows2000 +# endif +# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +# define _CRT_RAND_S // for rand_s(). +# include +# include +# include +# include +# define _CSTDIO_ +# define _CSTRING_ +# define _CWCHAR_ +# include +# include +# include +#else +# include +# include +# include +# include // free() +# include // va_start() +# include // readlink() +# include +# include +# include +# include +# include +#endif + + +/* +* On Windows PATH_MAX does not exist but MAX_PATH does. +* WinAPI MAX_PATH limit is only 256. MSVCR fuctions does not have this limit. +* Redefine PATH_MAX for Windows to support longer path names. +*/ +#if defined(EX_OS_WIN32) +# ifdef PATH_MAX +# undef PATH_MAX /* On Windows override PATH_MAX if defined. */ +# endif +# define PATH_MAX 1024 +#elif defined(EX_OS_LINUX) +# ifndef PATH_MAX +# define PATH_MAX 1024 +# endif +#elif defined(EX_OS_MACOS) +# define PATH_MAX 1024 /* Recommended value for OSX. */ +#endif + +// assert +#ifdef EX_DEBUG +# define ASSERT(exp) +# define CHECK(exp) do { if (!(exp)) abort(); } while (0) +//# define DEBUG_CHECKS (0) +#else +# include +# define ASSERT(exp) assert(exp) +# define CHECK(exp) assert(exp) +//# define DEBUG_CHECKS (1) +#endif + +#ifndef UNUSED +# if defined(_MSC_VER) +# define UNUSED(x) (void)(x) +# elif defined(__GUNC__) +# defined UNUSED(x) UNUSED_ ## x __attribute__((unused)) +# elif defined(__LCLINT__) +# define UNUSED(x) /*@unused@*/ x +# elif defined(__cplusplus) +# define UNUSED(x) +# else +# define UNUSED(x) (void)(x) +# endif +#endif + +/* check endian */ +#if !(defined(L_ENDIAN) || defined(B_ENDIAN)) +# if !defined(__BYTE_ORDER) && defined(__linux__) +# include +# endif + +# if defined(BYTE_ORDER) +# if BYTE_ORDER == BIG_ENDIAN +# define B_ENDIAN +# else +# define L_ENDIAN +# endif +# endif + +# if !(defined(L_ENDIAN) || defined(B_ENDIAN)) +# if defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__hppa__) +# define B_ENDIAN +# else +# define L_ENDIAN +# endif +# endif +#endif + +#ifdef EX_OS_WIN32 +# pragma comment(lib, "shlwapi.lib") +#endif + + +#endif // __LIB_EX_PLATFORM_H__ diff --git a/common/libex/include/ex/ex_str.h b/common/libex/include/ex/ex_str.h index d204581..2d95a48 100644 --- a/common/libex/include/ex/ex_str.h +++ b/common/libex/include/ex/ex_str.h @@ -1,83 +1,86 @@ -#ifndef __LIB_EX_STR_H__ -#define __LIB_EX_STR_H__ - -#include "ex_types.h" - -#define EX_CODEPAGE_ACP 0 -#define EX_CODEPAGE_UTF8 1 -#ifdef EX_OS_WIN32 -# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_ACP -#else -# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_UTF8 -#endif - -#define EX_RSC_BEGIN 0x01 -#define EX_RSC_END 0x02 -#define EX_RSC_ALL EX_RSC_BEGIN | EX_RSC_END - -//================================================= -// C Interface -//================================================= - -// copy a string from `source` to `target`. -// `size` is size of target buffer. -// if buffer is to small, NULL will return, but `size-1` characters have been copied. -char* ex_strcpy(char* target, size_t size, const char* source); -wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source); - - -// dupilicate a string. -// must use ex_free() to release the returned value. -char* ex_strdup(const char* src); -wchar_t* ex_wcsdup(const wchar_t* src); - -// convert between mutli-bytes and wide char string. -// must use ex_free() to release the returned value. -wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page); -char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page); - -// convert char** argv to wchar_t** argv. -// must use ex_free_argv() to release the returned value. -wchar_t** ex_make_wargv(int argc, char** argv); -void ex_free_wargv(int argc, wchar_t** argv); - -EX_BOOL ex_str_only_white_space(const wchar_t* src); -EX_BOOL ex_wcs_only_white_space(const char* src); - - -int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...); -int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...); - -//================================================= -// C++ Interface -//================================================= -#ifdef __cplusplus - -#include -#include - -typedef std::string ex_astr; -typedef std::wstring ex_wstr; - -typedef std::vector ex_astrs; -typedef std::vector ex_wstrs; - -bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); -bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); -bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); -bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); - -bool ex_only_white_space(const ex_astr& str_check); -bool ex_only_white_space(const ex_wstr& str_check); - -void ex_remove_white_space(ex_astr& str_fix, int ulFlag = EX_RSC_ALL); -void ex_remove_white_space(ex_wstr& str_fix, int ulFlag = EX_RSC_ALL); - -ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value); -ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value); - - -#endif - - -#endif // __LIB_EX_STR_H__ +#ifndef __LIB_EX_STR_H__ +#define __LIB_EX_STR_H__ + +#include "ex_types.h" + +#define EX_CODEPAGE_ACP 0 +#define EX_CODEPAGE_UTF8 1 +#ifdef EX_OS_WIN32 +# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_ACP +#else +# define EX_CODEPAGE_DEFAULT EX_CODEPAGE_UTF8 +#endif + +#define EX_RSC_BEGIN 0x01 +#define EX_RSC_END 0x02 +#define EX_RSC_ALL EX_RSC_BEGIN | EX_RSC_END + +//================================================= +// C Interface +//================================================= + +// copy a string from `source` to `target`. +// `size` is size of target buffer. +// if buffer is to small, NULL will return, but `size-1` characters have been copied. +char* ex_strcpy(char* target, size_t size, const char* source); +wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source); + + +// dupilicate a string. +// must use ex_free() to release the returned value. +char* ex_strdup(const char* src); +wchar_t* ex_wcsdup(const wchar_t* src); + +// convert between mutli-bytes and wide char string. +// must use ex_free() to release the returned value. +wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page); +char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page); + +// convert char** argv to wchar_t** argv. +// must use ex_free_argv() to release the returned value. +wchar_t** ex_make_wargv(int argc, char** argv); +void ex_free_wargv(int argc, wchar_t** argv); + +EX_BOOL ex_str_only_white_space(const wchar_t* src); +EX_BOOL ex_wcs_only_white_space(const char* src); + + +int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...); +int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...); + +//================================================= +// C++ Interface +//================================================= +#ifdef __cplusplus + +#include +#include + +typedef std::string ex_astr; +typedef std::wstring ex_wstr; + +typedef std::vector ex_astrs; +typedef std::vector ex_wstrs; +typedef std::vector ex_str_utf16le; + +bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); +bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page = EX_CODEPAGE_DEFAULT); +bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); +bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page = EX_CODEPAGE_DEFAULT); + +bool ex_only_white_space(const ex_astr& str_check); +bool ex_only_white_space(const ex_wstr& str_check); + +void ex_remove_white_space(ex_astr& str_fix, int ulFlag = EX_RSC_ALL); +void ex_remove_white_space(ex_wstr& str_fix, int ulFlag = EX_RSC_ALL); + +ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value); +ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value); + +// 将UTF8字符串转换为UTF16-LE字符串(输出结果包含\0结束符) +bool ex_utf8_to_utf16_le(const std::string& from, ex_str_utf16le& to); + +#endif + + +#endif // __LIB_EX_STR_H__ diff --git a/common/libex/include/ex/ex_types.h b/common/libex/include/ex/ex_types.h index 8993600..61fa4ca 100644 --- a/common/libex/include/ex/ex_types.h +++ b/common/libex/include/ex/ex_types.h @@ -1,44 +1,44 @@ -#ifndef __LIB_EX_TYPE_H__ -#define __LIB_EX_TYPE_H__ - -#include "ex_platform.h" - -#include - -typedef signed char ex_i8; -typedef signed short ex_i16; - -typedef unsigned char ex_u8; -typedef unsigned short ex_u16; -typedef unsigned int ex_u32; -typedef unsigned long ex_ulong; - -#if defined(EX_OS_WIN32) -typedef unsigned __int64 ex_u64; -typedef signed __int64 ex_i64; -typedef wchar_t ex_utf16; -#else -typedef unsigned long long ex_u64; -typedef signed long long ex_i64; -typedef ex_u16 ex_utf16; -#endif - -typedef int EX_BOOL; -#define EX_TRUE 1 -#define EX_FALSE 0 - - -typedef std::vector ex_bin; -typedef std::vector ex_chars; - -typedef ex_u32 ex_rv; - - -#if defined(EX_OS_WIN32) -# define EX_DYLIB_HANDLE HINSTANCE -#else -# define EX_DYLIB_HANDLE void* -#endif - - -#endif // __LIB_EX_TYPE_H__ +#ifndef __LIB_EX_TYPE_H__ +#define __LIB_EX_TYPE_H__ + +#include "ex_platform.h" + +#include + +typedef signed char ex_i8; +typedef signed short ex_i16; + +typedef unsigned char ex_u8; +typedef unsigned short ex_u16; +typedef unsigned int ex_u32; +typedef unsigned long ex_ulong; + +#if defined(EX_OS_WIN32) +typedef unsigned __int64 ex_u64; +typedef signed __int64 ex_i64; +typedef wchar_t ex_utf16; +#else +typedef unsigned long long ex_u64; +typedef signed long long ex_i64; +typedef ex_u16 ex_utf16; +#endif + +typedef int EX_BOOL; +#define EX_TRUE 1 +#define EX_FALSE 0 + + +typedef std::vector ex_bin; +typedef std::vector ex_chars; + +typedef ex_u32 ex_rv; + + +#if defined(EX_OS_WIN32) +# define EX_DYLIB_HANDLE HINSTANCE +#else +# define EX_DYLIB_HANDLE void* +#endif + + +#endif // __LIB_EX_TYPE_H__ diff --git a/common/libex/include/ex/ex_util.h b/common/libex/include/ex/ex_util.h index eaaf3d0..f98918a 100644 --- a/common/libex/include/ex/ex_util.h +++ b/common/libex/include/ex/ex_util.h @@ -1,44 +1,45 @@ -#ifndef __LIB_EX_UTIL_H__ -#define __LIB_EX_UTIL_H__ - -#include -#include - -#ifdef EX_OS_WIN32 -# include -//# include -//# include -// #include -#else -// #include -# include -# include -#endif - -EX_BOOL ex_initialize(const char* lc_ctype); - -void ex_free(void* buffer); - -// 在haystack(长度为haystacklen字节)中查找needle(长度为needlelen)的起始地址,返回NULL表示没有找到 -const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen); - -void ex_printf(const char* fmt, ...); -void ex_wprintf(const wchar_t* fmt, ...); - -ex_u64 ex_get_tick_count(void); -void ex_sleep_ms(int ms); - -EX_BOOL ex_localtime_now(int* t, struct tm* dt); - - -FILE* ex_fopen(const ex_wstr& filename, const wchar_t* mode); - - -EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path); -void ex_dlclose(EX_DYLIB_HANDLE dylib); - - -// inet... -int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); - -#endif // __LIB_EX_UTIL_H__ +#ifndef __LIB_EX_UTIL_H__ +#define __LIB_EX_UTIL_H__ + +#include +#include + +#ifdef EX_OS_WIN32 +# include +//# include +//# include +// #include +#else +// #include +# include +# include +#endif + +EX_BOOL ex_initialize(const char* lc_ctype); + +void ex_free(void* buffer); + +// 在haystack(长度为haystacklen字节)中查找needle(长度为needlelen)的起始地址,返回NULL表示没有找到 +const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen); +void ex_mem_reverse(ex_u8* p, size_t l); + +void ex_printf(const char* fmt, ...); +void ex_wprintf(const wchar_t* fmt, ...); + +ex_u64 ex_get_tick_count(void); +void ex_sleep_ms(int ms); + +EX_BOOL ex_localtime_now(int* t, struct tm* dt); + + +FILE* ex_fopen(const ex_wstr& filename, const wchar_t* mode); + + +EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path); +void ex_dlclose(EX_DYLIB_HANDLE dylib); + + +// inet... +int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); + +#endif // __LIB_EX_UTIL_H__ diff --git a/common/libex/src/ex_str.cpp b/common/libex/src/ex_str.cpp index 0189168..91073fa 100644 --- a/common/libex/src/ex_str.cpp +++ b/common/libex/src/ex_str.cpp @@ -1,380 +1,855 @@ -#include -#include -#include - -char* ex_strcpy(char* target, size_t size, const char* source) -{ - if (target == source) - return target; - -#ifdef EX_OS_WIN32 - if (SUCCEEDED(StringCchCopyA(target, size, source))) - return target; - else - return NULL; -#else - size_t len = strlen(source); - if (size > len) - { - return strcpy(target, source); - } - else - { - memmove(target, source, size - 1); - return NULL; - } -#endif -} - -wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source) -{ - if (target == source) - return target; - -#ifdef EX_OS_WIN32 - if (SUCCEEDED(StringCchCopyW(target, size, source))) - return target; - else - return NULL; -#else - size_t len = wcslen(source); - if (size > len) - { - return wcscpy(target, source); - } - else - { - memmove(target, source, (size - 1)*sizeof(wchar_t)); - return NULL; - } -#endif -} - -char* ex_strdup(const char* src) -{ - if (NULL == src) - return NULL; - size_t len = strlen(src) + 1; - char* ret = (char*)calloc(1, len); - memcpy(ret, src, len); - return ret; -} - -wchar_t* ex_wcsdup(const wchar_t* src) -{ - if (NULL == src) - return NULL; - size_t len = wcslen(src) + 1; - wchar_t* ret = (wchar_t*)calloc(sizeof(wchar_t), len); - memcpy(ret, src, sizeof(wchar_t)*len); - return ret; -} - -wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page) -{ - wchar_t* out_buffer = NULL; -#ifdef EX_OS_WIN32 - int wlen = 0; - UINT _cp = 0; - if (code_page == EX_CODEPAGE_ACP) - _cp = CP_ACP; - else if (code_page == EX_CODEPAGE_UTF8) - _cp = CP_UTF8; - - wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, NULL, 0); - if (0 == wlen) - return NULL; - - out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); - if (NULL == out_buffer) - return NULL; - - wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, out_buffer, wlen); - if (0 == wlen) - { - free(out_buffer); - return NULL; - } - -#else - size_t wlen = 0; - wlen = mbstowcs(NULL, in_buffer, 0); - if (wlen < 0) - return NULL; - - out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); - if (NULL == out_buffer) - return NULL; - - wlen = mbstowcs(out_buffer, in_buffer, wlen); - if (wlen < 0) - { - free(out_buffer); - return NULL; - } - -#endif - - return out_buffer; -} - - -char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page) -{ - char* out_buffer = NULL; - - if(NULL == in_buffer) - return NULL; - -#ifdef EX_OS_WIN32 - int len = 0; - UINT _cp = 0; - if (code_page == EX_CODEPAGE_ACP) - _cp = CP_ACP; - else if (code_page == EX_CODEPAGE_UTF8) - _cp = CP_UTF8; - - len = WideCharToMultiByte(_cp, 0, in_buffer, -1, NULL, 0, NULL, NULL); - if (0 == len) - return NULL; - - out_buffer = (char*)calloc(len + 1, sizeof(char)); - if (NULL == out_buffer) - return NULL; - - len = WideCharToMultiByte(_cp, 0, in_buffer, -1, out_buffer, len, NULL, NULL); - if (0 == len) - { - free(out_buffer); - return NULL; - } - -#else - size_t len = 0; - len = wcstombs(NULL, in_buffer, 0); - if (len < 0) - return NULL; - - out_buffer = (char*)calloc(len + 1, sizeof(char)); - if (NULL == out_buffer) - return NULL; - - len = wcstombs(out_buffer, in_buffer, len); - if (len < 0) - { - free(out_buffer); - return NULL; - } - -#endif - - return out_buffer; -} - -wchar_t** ex_make_wargv(int argc, char** argv) -{ - int i = 0; - wchar_t** ret = NULL; - - ret = (wchar_t**)calloc(argc + 1, sizeof(wchar_t*)); - if (!ret) - { - return NULL; - } - - for (i = 0; i < argc; ++i) - { - ret[i] = ex_str2wcs_alloc(argv[i], EX_CODEPAGE_DEFAULT); - if (NULL == ret[i]) - goto err; - } - - return ret; - -err: - ex_free_wargv(argc, ret); - return NULL; -} - -void ex_free_wargv(int argc, wchar_t** argv) -{ - int i = 0; - for (i = 0; i < argc; ++i) - free(argv[i]); - - free(argv); -} - -EX_BOOL ex_str_only_white_space(const wchar_t* src) -{ - if (ex_only_white_space(src)) - return EX_TRUE; - else - return EX_FALSE; -} - -EX_BOOL ex_wcs_only_white_space(const char* src) -{ - if (ex_only_white_space(src)) - return EX_TRUE; - else - return EX_FALSE; -} - -int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...) -{ - int ret = 0; - va_list valist; - va_start(valist, fmt); - //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); -#ifdef EX_OS_WIN32 - ret = vsnprintf(out_buf, buf_size, fmt, valist); -#else - ret = vsprintf(out_buf, fmt, valist); -#endif - va_end(valist); - return ret; -} - -int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...) -{ - int ret = 0; - va_list valist; - va_start(valist, fmt); - //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); -#ifdef EX_OS_WIN32 - //ret = vsnprintf(out_buf, buf_size, fmt, valist); - ret = _vsnwprintf_s(out_buf, buf_size, buf_size, fmt, valist); -#else - //ret = vsprintf(out_buf, fmt, valist); - ret = vswprintf(out_buf, buf_size, fmt, valist); -#endif - va_end(valist); - return ret; -} - - -#ifdef __cplusplus -bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - return ex_wstr2astr(in_str.c_str(), out_str, code_page); -} - -bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - char* astr = ex_wcs2str_alloc(in_str, code_page); - if (NULL == astr) - return false; - - out_str = astr; - ex_free(astr); - return true; -} - -bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - return ex_astr2wstr(in_str.c_str(), out_str, code_page); -} - -bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) -{ - wchar_t* wstr = ex_str2wcs_alloc(in_str, code_page); - if (NULL == wstr) - return false; - - out_str = wstr; - ex_free(wstr); - return true; -} - -bool ex_only_white_space(const ex_astr& str_check) -{ - ex_astr::size_type pos = 0; - ex_astr strFilter(" \t\r\n"); - pos = str_check.find_first_not_of(strFilter); - if (ex_astr::npos == pos) - return true; - else - return false; -} - -bool ex_only_white_space(const ex_wstr& str_check) -{ - ex_wstr::size_type pos = 0; - ex_wstr strFilter(L" \t\r\n"); - pos = str_check.find_first_not_of(strFilter); - if (ex_wstr::npos == pos) - return true; - else - return false; -} - -void ex_remove_white_space(ex_astr& str_fix, int ulFlag /*= EX_RSC_ALL*/) -{ - ex_astr::size_type pos = 0; - ex_astr strFilter(" \t\r\n"); - - if (ulFlag & EX_RSC_BEGIN) - { - pos = str_fix.find_first_not_of(strFilter); - if (ex_astr::npos != pos) - str_fix.erase(0, pos); - // FIXME - } - if (ulFlag & EX_RSC_END) - { - pos = str_fix.find_last_not_of(strFilter); - if (ex_astr::npos != pos) - str_fix.erase(pos + 1); - // FIXME - } -} - -void ex_remove_white_space(ex_wstr& str_fix, int ulFlag /*= EX_RSC_ALL*/) -{ - ex_wstr::size_type pos = 0; - ex_wstr strFilter(L" \t\r\n"); - - if (ulFlag & EX_RSC_BEGIN) - { - pos = str_fix.find_first_not_of(strFilter); - if (ex_wstr::npos != pos) - str_fix.erase(0, pos); - // FIXME - } - if (ulFlag & EX_RSC_END) - { - pos = str_fix.find_last_not_of(strFilter); - if (ex_wstr::npos != pos) - str_fix.erase(pos + 1); - // FIXME - } -} - -ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value) -{ - for (ex_astr::size_type pos(0); pos != ex_astr::npos; pos += new_value.length()) - { - if ((pos = str.find(old_value, pos)) != ex_astr::npos) - str.replace(pos, old_value.length(), new_value); - else - break; - } - - return str; -} - -ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value) -{ - for (ex_wstr::size_type pos(0); pos != ex_wstr::npos; pos += new_value.length()) - { - if ((pos = str.find(old_value, pos)) != ex_wstr::npos) - str.replace(pos, old_value.length(), new_value); - else - break; - } - - return str; -} - -#endif +#include +#include +#include + +char* ex_strcpy(char* target, size_t size, const char* source) +{ + if (target == source) + return target; + +#ifdef EX_OS_WIN32 + if (SUCCEEDED(StringCchCopyA(target, size, source))) + return target; + else + return NULL; +#else + size_t len = strlen(source); + if (size > len) + { + return strcpy(target, source); + } + else + { + memmove(target, source, size - 1); + return NULL; + } +#endif +} + +wchar_t* ex_wcscpy(wchar_t* target, size_t size, const wchar_t* source) +{ + if (target == source) + return target; + +#ifdef EX_OS_WIN32 + if (SUCCEEDED(StringCchCopyW(target, size, source))) + return target; + else + return NULL; +#else + size_t len = wcslen(source); + if (size > len) + { + return wcscpy(target, source); + } + else + { + memmove(target, source, (size - 1)*sizeof(wchar_t)); + return NULL; + } +#endif +} + +char* ex_strdup(const char* src) +{ + if (NULL == src) + return NULL; + size_t len = strlen(src) + 1; + char* ret = (char*)calloc(1, len); + memcpy(ret, src, len); + return ret; +} + +wchar_t* ex_wcsdup(const wchar_t* src) +{ + if (NULL == src) + return NULL; + size_t len = wcslen(src) + 1; + wchar_t* ret = (wchar_t*)calloc(sizeof(wchar_t), len); + memcpy(ret, src, sizeof(wchar_t)*len); + return ret; +} + +wchar_t* ex_str2wcs_alloc(const char* in_buffer, int code_page) +{ + wchar_t* out_buffer = NULL; +#ifdef EX_OS_WIN32 + int wlen = 0; + UINT _cp = 0; + if (code_page == EX_CODEPAGE_ACP) + _cp = CP_ACP; + else if (code_page == EX_CODEPAGE_UTF8) + _cp = CP_UTF8; + + wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, NULL, 0); + if (0 == wlen) + return NULL; + + out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); + if (NULL == out_buffer) + return NULL; + + wlen = MultiByteToWideChar(_cp, 0, in_buffer, -1, out_buffer, wlen); + if (0 == wlen) + { + free(out_buffer); + return NULL; + } + +#else + size_t wlen = 0; + wlen = mbstowcs(NULL, in_buffer, 0); + if (wlen < 0) + return NULL; + + out_buffer = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t)); + if (NULL == out_buffer) + return NULL; + + wlen = mbstowcs(out_buffer, in_buffer, wlen); + if (wlen < 0) + { + free(out_buffer); + return NULL; + } + +#endif + + return out_buffer; +} + + +char* ex_wcs2str_alloc(const wchar_t* in_buffer, int code_page) +{ + char* out_buffer = NULL; + + if(NULL == in_buffer) + return NULL; + +#ifdef EX_OS_WIN32 + int len = 0; + UINT _cp = 0; + if (code_page == EX_CODEPAGE_ACP) + _cp = CP_ACP; + else if (code_page == EX_CODEPAGE_UTF8) + _cp = CP_UTF8; + + len = WideCharToMultiByte(_cp, 0, in_buffer, -1, NULL, 0, NULL, NULL); + if (0 == len) + return NULL; + + out_buffer = (char*)calloc(len + 1, sizeof(char)); + if (NULL == out_buffer) + return NULL; + + len = WideCharToMultiByte(_cp, 0, in_buffer, -1, out_buffer, len, NULL, NULL); + if (0 == len) + { + free(out_buffer); + return NULL; + } + +#else + size_t len = 0; + len = wcstombs(NULL, in_buffer, 0); + if (len < 0) + return NULL; + + out_buffer = (char*)calloc(len + 1, sizeof(char)); + if (NULL == out_buffer) + return NULL; + + len = wcstombs(out_buffer, in_buffer, len); + if (len < 0) + { + free(out_buffer); + return NULL; + } + +#endif + + return out_buffer; +} + +wchar_t** ex_make_wargv(int argc, char** argv) +{ + int i = 0; + wchar_t** ret = NULL; + + ret = (wchar_t**)calloc(argc + 1, sizeof(wchar_t*)); + if (!ret) + { + return NULL; + } + + for (i = 0; i < argc; ++i) + { + ret[i] = ex_str2wcs_alloc(argv[i], EX_CODEPAGE_DEFAULT); + if (NULL == ret[i]) + goto err; + } + + return ret; + +err: + ex_free_wargv(argc, ret); + return NULL; +} + +void ex_free_wargv(int argc, wchar_t** argv) +{ + int i = 0; + for (i = 0; i < argc; ++i) + free(argv[i]); + + free(argv); +} + +EX_BOOL ex_str_only_white_space(const wchar_t* src) +{ + if (ex_only_white_space(src)) + return EX_TRUE; + else + return EX_FALSE; +} + +EX_BOOL ex_wcs_only_white_space(const char* src) +{ + if (ex_only_white_space(src)) + return EX_TRUE; + else + return EX_FALSE; +} + +int ex_strformat(char* out_buf, size_t buf_size, const char* fmt, ...) +{ + int ret = 0; + va_list valist; + va_start(valist, fmt); + //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); +#ifdef EX_OS_WIN32 + ret = vsnprintf(out_buf, buf_size, fmt, valist); +#else + ret = vsprintf(out_buf, fmt, valist); +#endif + va_end(valist); + return ret; +} + +int ex_wcsformat(wchar_t* out_buf, size_t buf_size, const wchar_t* fmt, ...) +{ + int ret = 0; + va_list valist; + va_start(valist, fmt); + //_ts_printf_a(level, EX_COLOR_BLACK, fmt, valist); +#ifdef EX_OS_WIN32 + //ret = vsnprintf(out_buf, buf_size, fmt, valist); + ret = _vsnwprintf_s(out_buf, buf_size, buf_size, fmt, valist); +#else + //ret = vsprintf(out_buf, fmt, valist); + ret = vswprintf(out_buf, buf_size, fmt, valist); +#endif + va_end(valist); + return ret; +} + + +#ifdef __cplusplus +bool ex_wstr2astr(const ex_wstr& in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + return ex_wstr2astr(in_str.c_str(), out_str, code_page); +} + +bool ex_wstr2astr(const wchar_t* in_str, ex_astr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + char* astr = ex_wcs2str_alloc(in_str, code_page); + if (NULL == astr) + return false; + + out_str = astr; + ex_free(astr); + return true; +} + +bool ex_astr2wstr(const ex_astr& in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + return ex_astr2wstr(in_str.c_str(), out_str, code_page); +} + +bool ex_astr2wstr(const char* in_str, ex_wstr& out_str, int code_page/* = EX_CODEPAGE_DEFAULT*/) +{ + wchar_t* wstr = ex_str2wcs_alloc(in_str, code_page); + if (NULL == wstr) + return false; + + out_str = wstr; + ex_free(wstr); + return true; +} + +bool ex_only_white_space(const ex_astr& str_check) +{ + ex_astr::size_type pos = 0; + ex_astr strFilter(" \t\r\n"); + pos = str_check.find_first_not_of(strFilter); + if (ex_astr::npos == pos) + return true; + else + return false; +} + +bool ex_only_white_space(const ex_wstr& str_check) +{ + ex_wstr::size_type pos = 0; + ex_wstr strFilter(L" \t\r\n"); + pos = str_check.find_first_not_of(strFilter); + if (ex_wstr::npos == pos) + return true; + else + return false; +} + +void ex_remove_white_space(ex_astr& str_fix, int ulFlag /*= EX_RSC_ALL*/) +{ + ex_astr::size_type pos = 0; + ex_astr strFilter(" \t\r\n"); + + if (ulFlag & EX_RSC_BEGIN) + { + pos = str_fix.find_first_not_of(strFilter); + if (ex_astr::npos != pos) + str_fix.erase(0, pos); + // FIXME + } + if (ulFlag & EX_RSC_END) + { + pos = str_fix.find_last_not_of(strFilter); + if (ex_astr::npos != pos) + str_fix.erase(pos + 1); + // FIXME + } +} + +void ex_remove_white_space(ex_wstr& str_fix, int ulFlag /*= EX_RSC_ALL*/) +{ + ex_wstr::size_type pos = 0; + ex_wstr strFilter(L" \t\r\n"); + + if (ulFlag & EX_RSC_BEGIN) + { + pos = str_fix.find_first_not_of(strFilter); + if (ex_wstr::npos != pos) + str_fix.erase(0, pos); + // FIXME + } + if (ulFlag & EX_RSC_END) + { + pos = str_fix.find_last_not_of(strFilter); + if (ex_wstr::npos != pos) + str_fix.erase(pos + 1); + // FIXME + } +} + +ex_astr& ex_replace_all(ex_astr& str, const ex_astr& old_value, const ex_astr& new_value) +{ + for (ex_astr::size_type pos(0); pos != ex_astr::npos; pos += new_value.length()) + { + if ((pos = str.find(old_value, pos)) != ex_astr::npos) + str.replace(pos, old_value.length(), new_value); + else + break; + } + + return str; +} + +ex_wstr& ex_replace_all(ex_wstr& str, const ex_wstr& old_value, const ex_wstr& new_value) +{ + for (ex_wstr::size_type pos(0); pos != ex_wstr::npos; pos += new_value.length()) + { + if ((pos = str.find(old_value, pos)) != ex_wstr::npos) + str.replace(pos, old_value.length(), new_value); + else + break; + } + + return str; +} + + + +#ifndef EX_OS_WIN32 + +// #define BYTE ts_u8 +// #define DWORD ts_u32 +// #define WCHAR ts_u16 +#define LPWSTR WCHAR* +#define BOOL int +#define TRUE 1 +#define FALSE 0 +#define UINT unsigned int +#define LPCSTR const char* +#define CP_UTF8 1 + +typedef enum +{ + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum +{ + strictConversion = 0, + lenientConversion +} ConversionFlags; + +static const char trailingBytesForUTF8[256] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +static const DWORD offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL +}; + +static const BYTE firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const DWORD halfBase = 0x0010000UL; +static const DWORD halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (DWORD)0xD800 +#define UNI_SUR_HIGH_END (DWORD)0xDBFF +#define UNI_SUR_LOW_START (DWORD)0xDC00 +#define UNI_SUR_LOW_END (DWORD)0xDFFF + +#define UNI_REPLACEMENT_CHAR (DWORD)0x0000FFFD +#define UNI_MAX_BMP (DWORD)0x0000FFFF +#define UNI_MAX_UTF16 (DWORD)0x0010FFFF +#define UNI_MAX_UTF32 (DWORD)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (DWORD)0x0010FFFF + + +static ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sourceEnd, BYTE** targetStart, BYTE* targetEnd, ConversionFlags flags) +{ + BYTE* target; + const WCHAR* source; + BOOL computeLength; + ConversionResult result; + computeLength = (!targetEnd) ? TRUE : FALSE; + source = *sourceStart; + target = *targetStart; + result = conversionOK; + + while (source < sourceEnd) + { + DWORD ch; + unsigned short bytesToWrite = 0; + const DWORD byteMask = 0xBF; + const DWORD byteMark = 0x80; + const WCHAR* oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) + { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) + { + DWORD ch2 = *source; + + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) + { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } + else if (flags == strictConversion) + { + /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + else + { + /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } + else if (flags == strictConversion) + { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) + { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + + /* Figure out how many bytes the result will require */ + if (ch < (DWORD)0x80) + { + bytesToWrite = 1; + } + else if (ch < (DWORD)0x800) + { + bytesToWrite = 2; + } + else if (ch < (DWORD)0x10000) + { + bytesToWrite = 3; + } + else if (ch < (DWORD)0x110000) + { + bytesToWrite = 4; + } + else + { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + + if ((target > targetEnd) && (!computeLength)) + { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + + if (!computeLength) + { + switch (bytesToWrite) + { + /* note: everything falls through. */ + case 4: + *--target = (BYTE)((ch | byteMark) & byteMask); + ch >>= 6; + + case 3: + *--target = (BYTE)((ch | byteMark) & byteMask); + ch >>= 6; + + case 2: + *--target = (BYTE)((ch | byteMark) & byteMask); + ch >>= 6; + + case 1: + *--target = (BYTE)(ch | firstByteMark[bytesToWrite]); + } + } + else + { + switch (bytesToWrite) + { + /* note: everything falls through. */ + case 4: + --target; + ch >>= 6; + + case 3: + --target; + ch >>= 6; + + case 2: + --target; + ch >>= 6; + + case 1: + --target; + } + } + + target += bytesToWrite; + } + + *sourceStart = source; + *targetStart = target; + return result; +} + + +static BOOL isLegalUTF8(const BYTE* source, int length) +{ + BYTE a; + const BYTE* srcptr = source + length; + + switch (length) + { + default: + return FALSE; + + /* Everything else falls through when "TRUE"... */ + case 4: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return FALSE; + + case 3: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return FALSE; + + case 2: + if ((a = (*--srcptr)) > 0xBF) return FALSE; + + switch (*source) + { + /* no fall-through in this inner switch */ + case 0xE0: + if (a < 0xA0) return FALSE; + + break; + + case 0xED: + if (a > 0x9F) return FALSE; + + break; + + case 0xF0: + if (a < 0x90) return FALSE; + + break; + + case 0xF4: + if (a > 0x8F) return FALSE; + + break; + + default: + if (a < 0x80) return FALSE; + } + + case 1: + if (*source >= 0x80 && *source < 0xC2) return FALSE; + } + + if (*source > 0xF4) + return FALSE; + + return TRUE; +} + +static ConversionResult _ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* sourceEnd, WCHAR** targetStart, WCHAR* targetEnd, ConversionFlags flags) +{ + WCHAR* target; + const BYTE* source; + BOOL computeLength; + ConversionResult result; + computeLength = (!targetEnd) ? TRUE : FALSE; + result = conversionOK; + source = *sourceStart; + target = *targetStart; + + while (source < sourceEnd) + { + DWORD ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + + if ((source + extraBytesToRead) >= sourceEnd) + { + result = sourceExhausted; + break; + } + + /* Do this check whether lenient or strict */ + if (!isLegalUTF8(source, extraBytesToRead + 1)) + { + result = sourceIllegal; + break; + } + + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) + { + case 5: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + + case 4: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + + case 3: + ch += *source++; + ch <<= 6; + + case 2: + ch += *source++; + ch <<= 6; + + case 1: + ch += *source++; + ch <<= 6; + + case 0: + ch += *source++; + } + + ch -= offsetsFromUTF8[extraBytesToRead]; + + if ((target >= targetEnd) && (!computeLength)) + { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + + if (ch <= UNI_MAX_BMP) + { + /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) + { + if (flags == strictConversion) + { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + else + { + if (!computeLength) + *target++ = UNI_REPLACEMENT_CHAR; + else + target++; + } + } + else + { + if (!computeLength) + *target++ = (WCHAR)ch; /* normal case */ + else + target++; + } + } + else if (ch > UNI_MAX_UTF16) + { + if (flags == strictConversion) + { + result = sourceIllegal; + source -= (extraBytesToRead + 1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } + else + { + if (!computeLength) + *target++ = UNI_REPLACEMENT_CHAR; + else + target++; + } + } + else + { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if ((target + 1 >= targetEnd) && (!computeLength)) + { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + + ch -= halfBase; + + if (!computeLength) + { + *target++ = (WCHAR)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (WCHAR)((ch & halfMask) + UNI_SUR_LOW_START); + } + else + { + target++; + target++; + } + } + } + + *sourceStart = source; + *targetStart = target; + return result; +} + +static int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar) +{ + int length; + LPWSTR targetStart; + const BYTE* sourceStart; + ConversionResult result; + + /* If cbMultiByte is 0, the function fails */ + + if (cbMultiByte == 0) + return 0; + + /* If cbMultiByte is -1, the string is null-terminated */ + + if (cbMultiByte == -1) + cbMultiByte = (int)strlen((char*)lpMultiByteStr) + 1; + + /* + * if cchWideChar is 0, the function returns the required buffer size + * in characters for lpWideCharStr and makes no use of the output parameter itself. + */ + + if (cchWideChar == 0) + { + sourceStart = (const BYTE*)lpMultiByteStr; + targetStart = (WCHAR*)NULL; + + result = _ConvertUTF8toUTF16(&sourceStart, &sourceStart[cbMultiByte], + &targetStart, NULL, strictConversion); + + length = (int)(targetStart - ((WCHAR*)NULL)); + cchWideChar = length; + } + else + { + sourceStart = (const BYTE*)lpMultiByteStr; + targetStart = lpWideCharStr; + + result = _ConvertUTF8toUTF16(&sourceStart, &sourceStart[cbMultiByte], + &targetStart, &targetStart[cchWideChar], strictConversion); + + length = (int)(targetStart - ((WCHAR*)lpWideCharStr)); + cchWideChar = length; + } + + return cchWideChar; +} + +#endif + + + +bool utf8_to_utf16_le(const std::string& from, ex_str_utf16le& to) +{ + int iSize = MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, NULL, 0); + if (iSize <= 0) + return false; + + //++iSize; + to.resize(iSize); + memset(&to[0], 0, sizeof(ex_utf16)); + + MultiByteToWideChar(CP_UTF8, 0, from.c_str(), -1, &to[0], iSize); + + return true; +} + +#endif diff --git a/common/libex/src/ex_util.cpp b/common/libex/src/ex_util.cpp index 81bd035..4c6c297 100644 --- a/common/libex/src/ex_util.cpp +++ b/common/libex/src/ex_util.cpp @@ -1,251 +1,264 @@ -#include -#include -#include -#include - -EX_BOOL ex_initialize(const char* lc_ctype) -{ -#ifdef EX_OS_UNIX - const char* _lc_default = "en_US.UTF-8"; - const char* _lc_ctype = NULL; - char* _loc = NULL; - if(NULL == lc_ctype) - _lc_ctype = _lc_default; - else - _lc_ctype = lc_ctype; - - _loc = setlocale(LC_CTYPE, _lc_ctype); - - if(NULL == _loc) - return EX_FALSE; -// if(0 != strcmp(_loc, _lc_ctype)) -// return EX_FALSE; - return EX_TRUE; - -#else - return EX_TRUE; -#endif -} - - -void ex_free(void* buffer) -{ - if (NULL == buffer) - return; - free(buffer); -} - -const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen) -{ - const ex_u8* cursor = NULL; - const ex_u8* last_possible_needle_location = haystack + haystacklen - needlelen; - - /** Easy answers */ - if (needlelen > haystacklen) return(NULL); - if (needle == NULL) return(NULL); - if (haystack == NULL) return(NULL); - if (needlelen == 0) return(NULL); - if (haystacklen == 0) return(NULL); - - for (cursor = haystack; cursor <= last_possible_needle_location; cursor++) - { - if (memcmp(needle, cursor, needlelen) == 0) - return cursor; - } - return(NULL); -} - -void ex_printf(const char* fmt, ...) -{ - if (NULL == fmt || 0 == strlen(fmt)) - return; - - va_list valist; - va_start(valist, fmt); - //_ts_printf_a(TS_COLOR_GRAY, TS_COLOR_BLACK, fmt, valist); - - char _tmp[4096] = { 0 }; -#ifdef EX_OS_WIN32 - vsnprintf_s(_tmp, 4096, 4095, fmt, valist); - printf_s("%s", _tmp); - fflush(stdout); -#else - vsnprintf(_tmp, 4095, fmt, valist); - printf("%s", _tmp); - fflush(stdout); -#endif - - va_end(valist); -} - -void ex_wprintf(const wchar_t* fmt, ...) -{ - if (NULL == fmt || 0 == wcslen(fmt)) - return; - - va_list valist; - va_start(valist, fmt); - - wchar_t _tmp[4096] = { 0 }; -#ifdef EX_OS_WIN32 - _vsnwprintf_s(_tmp, 4096, 4095, fmt, valist); - wprintf_s(L"%s", _tmp); - fflush(stdout); -#else - vswprintf(_tmp, 4095, fmt, valist); - - ex_astr _astr_tmp; - ex_wstr2astr(_tmp, _astr_tmp); - printf("%s", _astr_tmp.c_str()); - - fflush(stdout); -#endif - - va_end(valist); -} - -ex_u64 ex_get_tick_count(void) -{ -#ifdef EX_OS_WIN32 -# if (_WIN32_WINNT >= 0x0600) - return GetTickCount64(); -# else - LARGE_INTEGER TicksPerSecond = { 0 }; - LARGE_INTEGER Tick; - if (!TicksPerSecond.QuadPart) - QueryPerformanceFrequency(&TicksPerSecond); - QueryPerformanceCounter(&Tick); - ex_u64 Seconds = Tick.QuadPart / TicksPerSecond.QuadPart; - ex_u64 LeftPart = Tick.QuadPart - (TicksPerSecond.QuadPart*Seconds); - ex_u64 MillSeconds = LeftPart * 1000 / TicksPerSecond.QuadPart; - ex_u64 Ret = Seconds * 1000 + MillSeconds; - return Ret; -# endif -#else - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ((ex_u64)ts.tv_sec * 1000 + (ex_u64)ts.tv_nsec / 1000000); -#endif -} - -void ex_sleep_ms(int ms) -{ -#ifdef EX_OS_WIN32 - Sleep(ms); -#else - usleep(ms * 1000); -#endif -} - -EX_BOOL ex_localtime_now(int* t, struct tm* dt) -{ -// if (NULL == dt) -// return EX_FALSE; - - //struct tm *_tmp; - -#ifdef EX_OS_WIN32 - struct tm _tmp; - __time32_t timep; - _time32(&timep); - if (0 != _localtime32_s(&_tmp, &timep)) - return EX_FALSE; - if(NULL != dt) - memcpy(dt, &_tmp, sizeof(struct tm)); -#else - struct tm *_tmp; - time_t timep; - time(&timep); - _tmp = localtime(&timep); //get server's time - if (_tmp == NULL) - return NULL; - if(NULL != dt) - memcpy(dt, _tmp, sizeof(struct tm)); -#endif - - if (NULL != t) - *t = (int)timep; - - return EX_TRUE; -} - -FILE* ex_fopen(const ex_wstr& filename, const wchar_t* mode) -{ - FILE* f = NULL; -#ifdef EX_OS_WIN32 - errno_t err = 0; - err = _wfopen_s(&f, filename.c_str(), mode); - if (0 == err) - return f; - else - return NULL; -#else - ex_astr _fname; - ex_wstr2astr(filename, _fname); - ex_astr _mode; - ex_wstr2astr(mode, _mode); - f = fopen(_fname.c_str(), _mode.c_str()); - return f; -#endif -} - - -EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path) -{ - EX_DYLIB_HANDLE handle = NULL; - -#ifdef EX_OS_WIN32 - handle = LoadLibraryExW(dylib_path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - if (NULL == handle) - { - EXLOGE_WIN(L"LoadLibraryEx('%ls') failed.\n", dylib_path); - return NULL; - } -#else - ex_astr path; - if (!ex_wstr2astr(dylib_path, path, EX_CODEPAGE_UTF8)) - { - EXLOGE("convert dylib_path failed.\n"); - return NULL; - } - - handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL); - - if (NULL == handle) - { - EXLOGE("dlopen() failed: %s.\n", dlerror()); - return NULL; - } -#endif - - return handle; -} - -void ex_dlclose(EX_DYLIB_HANDLE dylib) -{ -#ifdef EX_OS_WIN32 - FreeLibrary(dylib); -#else - dlclose(dylib); -#endif -} - -static int _inet_ntop4(const unsigned char *src, char *dst, size_t size) { - static const char fmt[] = "%u.%u.%u.%u"; - char tmp[32]; - int l; - - l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); - if (l <= 0 || (size_t)l >= size) { - return -1; - } - ex_strcpy(dst, size, tmp); - dst[size - 1] = '\0'; - return 0; -} - -int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) -{ - return _inet_ntop4((const unsigned char*)&(src->sin_addr), dst, size); -} - +#include +#include +#include +#include + +EX_BOOL ex_initialize(const char* lc_ctype) +{ +#ifdef EX_OS_UNIX + const char* _lc_default = "en_US.UTF-8"; + const char* _lc_ctype = NULL; + char* _loc = NULL; + if(NULL == lc_ctype) + _lc_ctype = _lc_default; + else + _lc_ctype = lc_ctype; + + _loc = setlocale(LC_CTYPE, _lc_ctype); + + if(NULL == _loc) + return EX_FALSE; +// if(0 != strcmp(_loc, _lc_ctype)) +// return EX_FALSE; + return EX_TRUE; + +#else + return EX_TRUE; +#endif +} + + +void ex_free(void* buffer) +{ + if (NULL == buffer) + return; + free(buffer); +} + +const ex_u8* ex_memmem(const ex_u8* haystack, size_t haystacklen, const ex_u8* needle, size_t needlelen) +{ + const ex_u8* cursor = NULL; + const ex_u8* last_possible_needle_location = haystack + haystacklen - needlelen; + + /** Easy answers */ + if (needlelen > haystacklen) return(NULL); + if (needle == NULL) return(NULL); + if (haystack == NULL) return(NULL); + if (needlelen == 0) return(NULL); + if (haystacklen == 0) return(NULL); + + for (cursor = haystack; cursor <= last_possible_needle_location; cursor++) + { + if (memcmp(needle, cursor, needlelen) == 0) + return cursor; + } + return(NULL); +} + +void ex_mem_reverse(ex_u8* p, size_t l) +{ + ex_u8 temp = 0; + size_t i = 0, j = 0; + + for (i = 0, j = l - 1; i < j; i++, j--) + { + temp = p[i]; + p[i] = p[j]; + p[j] = temp; + } +} + +void ex_printf(const char* fmt, ...) +{ + if (NULL == fmt || 0 == strlen(fmt)) + return; + + va_list valist; + va_start(valist, fmt); + //_ts_printf_a(TS_COLOR_GRAY, TS_COLOR_BLACK, fmt, valist); + + char _tmp[4096] = { 0 }; +#ifdef EX_OS_WIN32 + vsnprintf_s(_tmp, 4096, 4095, fmt, valist); + printf_s("%s", _tmp); + fflush(stdout); +#else + vsnprintf(_tmp, 4095, fmt, valist); + printf("%s", _tmp); + fflush(stdout); +#endif + + va_end(valist); +} + +void ex_wprintf(const wchar_t* fmt, ...) +{ + if (NULL == fmt || 0 == wcslen(fmt)) + return; + + va_list valist; + va_start(valist, fmt); + + wchar_t _tmp[4096] = { 0 }; +#ifdef EX_OS_WIN32 + _vsnwprintf_s(_tmp, 4096, 4095, fmt, valist); + wprintf_s(L"%s", _tmp); + fflush(stdout); +#else + vswprintf(_tmp, 4095, fmt, valist); + + ex_astr _astr_tmp; + ex_wstr2astr(_tmp, _astr_tmp); + printf("%s", _astr_tmp.c_str()); + + fflush(stdout); +#endif + + va_end(valist); +} + +ex_u64 ex_get_tick_count(void) +{ +#ifdef EX_OS_WIN32 +# if (_WIN32_WINNT >= 0x0600) + return GetTickCount64(); +# else + LARGE_INTEGER TicksPerSecond = { 0 }; + LARGE_INTEGER Tick; + if (!TicksPerSecond.QuadPart) + QueryPerformanceFrequency(&TicksPerSecond); + QueryPerformanceCounter(&Tick); + ex_u64 Seconds = Tick.QuadPart / TicksPerSecond.QuadPart; + ex_u64 LeftPart = Tick.QuadPart - (TicksPerSecond.QuadPart*Seconds); + ex_u64 MillSeconds = LeftPart * 1000 / TicksPerSecond.QuadPart; + ex_u64 Ret = Seconds * 1000 + MillSeconds; + return Ret; +# endif +#else + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ((ex_u64)ts.tv_sec * 1000 + (ex_u64)ts.tv_nsec / 1000000); +#endif +} + +void ex_sleep_ms(int ms) +{ +#ifdef EX_OS_WIN32 + Sleep(ms); +#else + usleep(ms * 1000); +#endif +} + +EX_BOOL ex_localtime_now(int* t, struct tm* dt) +{ +// if (NULL == dt) +// return EX_FALSE; + + //struct tm *_tmp; + +#ifdef EX_OS_WIN32 + struct tm _tmp; + __time32_t timep; + _time32(&timep); + if (0 != _localtime32_s(&_tmp, &timep)) + return EX_FALSE; + if(NULL != dt) + memcpy(dt, &_tmp, sizeof(struct tm)); +#else + struct tm *_tmp; + time_t timep; + time(&timep); + _tmp = localtime(&timep); //get server's time + if (_tmp == NULL) + return NULL; + if(NULL != dt) + memcpy(dt, _tmp, sizeof(struct tm)); +#endif + + if (NULL != t) + *t = (int)timep; + + return EX_TRUE; +} + +FILE* ex_fopen(const ex_wstr& filename, const wchar_t* mode) +{ + FILE* f = NULL; +#ifdef EX_OS_WIN32 + errno_t err = 0; + err = _wfopen_s(&f, filename.c_str(), mode); + if (0 == err) + return f; + else + return NULL; +#else + ex_astr _fname; + ex_wstr2astr(filename, _fname); + ex_astr _mode; + ex_wstr2astr(mode, _mode); + f = fopen(_fname.c_str(), _mode.c_str()); + return f; +#endif +} + + +EX_DYLIB_HANDLE ex_dlopen(const wchar_t* dylib_path) +{ + EX_DYLIB_HANDLE handle = NULL; + +#ifdef EX_OS_WIN32 + handle = LoadLibraryExW(dylib_path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (NULL == handle) + { + EXLOGE_WIN(L"LoadLibraryEx('%ls') failed.\n", dylib_path); + return NULL; + } +#else + ex_astr path; + if (!ex_wstr2astr(dylib_path, path, EX_CODEPAGE_UTF8)) + { + EXLOGE("convert dylib_path failed.\n"); + return NULL; + } + + handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL); + + if (NULL == handle) + { + EXLOGE("dlopen() failed: %s.\n", dlerror()); + return NULL; + } +#endif + + return handle; +} + +void ex_dlclose(EX_DYLIB_HANDLE dylib) +{ +#ifdef EX_OS_WIN32 + FreeLibrary(dylib); +#else + dlclose(dylib); +#endif +} + +static int _inet_ntop4(const unsigned char *src, char *dst, size_t size) { + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[32]; + int l; + + l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); + if (l <= 0 || (size_t)l >= size) { + return -1; + } + ex_strcpy(dst, size, tmp); + dst[size - 1] = '\0'; + return 0; +} + +int ex_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) +{ + return _inet_ntop4((const unsigned char*)&(src->sin_addr), dst, size); +} + diff --git a/external/readme.md b/external/readme.md index 696f92a..7236dcc 100644 --- a/external/readme.md +++ b/external/readme.md @@ -31,5 +31,13 @@ teleport椤圭洰鐢ㄥ埌鐨勭涓夋柟搴 https://git.libssh.org/projects/libssh.git/snapshot libssh-0.7.4.zip Windows骞冲彴浣跨敤棰勫埗鐨刲ibssh-static宸ョ▼杩涜缂栬瘧銆 +- libuv + https://github.com/libuv/libuv + v1.11.0.zip + 娉ㄦ剰锛歵eleport椤圭洰浣跨敤婧愪唬鐮佺洿鎺ョ紪璇戯紝鍥犳瑙e帇缂╂簮浠g爜鍒版鍗冲彲銆 + + + + diff --git a/server/tp_core/common/ts_memstream.cpp b/server/tp_core/common/ts_memstream.cpp new file mode 100644 index 0000000..3b41e2b --- /dev/null +++ b/server/tp_core/common/ts_memstream.cpp @@ -0,0 +1,219 @@ +#include "ts_memstream.h" + +MemStream::MemStream(MemBuffer& mbuf) : m_mbuf(mbuf) +{ + m_offset = 0; +} + +MemStream::~MemStream() +{} + +void MemStream::reset(void) +{ + m_mbuf.empty(); + rewind(); +} + + +bool MemStream::seek(size_t offset) +{ + if (offset >= m_mbuf.size()) + return false; + + m_offset = offset; + return true; +} + +bool MemStream::skip(size_t n) +{ + if (m_offset + n >= m_mbuf.size()) + return false; + m_offset += n; + return true; +} + +bool MemStream::rewind(size_t n) +{ + if (m_offset < n) + return false; + + if (0 == n) + m_offset = 0; + else + m_offset -= n; + return true; +} + +ex_u8 MemStream::get_u8(void) +{ + ASSERT(m_offset + 1 <= m_mbuf.size()); + + ex_u8 v = (m_mbuf.data() + m_offset)[0]; + m_offset++; + return v; +} + +ex_u16 MemStream::get_u16_le(void) +{ + ASSERT(m_offset + 2 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u16 v = (ex_u16)(p[0] | (p[1] << 8)); +#else + ex_u16 v = ((ex_u16*)p)[0]; +#endif + m_offset += 2; + return v; +} + +ex_u16 MemStream::get_u16_be(void) +{ + ASSERT(m_offset + 2 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u16 v = ((ex_u16*)p)[0]; +#else + ex_u16 v = (ex_u16)((p[0] << 8) | p[1]); +#endif + m_offset += 2; + return v; +} + + +ex_u32 MemStream::get_u32_le(void) +{ + ASSERT(m_offset + 4 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u32 v = (ex_u32)(p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); +#else + ex_u32 v = ((ex_u32*)p)[0]; +#endif + m_offset += 4; + return v; +} + +ex_u32 MemStream::get_u32_be(void) +{ + ASSERT(m_offset + 4 <= m_mbuf.size()); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ex_u32 v = ((ex_u32*)p)[0]; +#else + ex_u32 v = (ex_u32)((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +#endif + m_offset += 4; + return v; +} + +ex_u8* MemStream::get_bin(size_t n) +{ + ASSERT(m_offset + 4 <= m_mbuf.size()); + ex_u8* p = m_mbuf.data() + m_offset; + m_offset += n; + return p; +} + + +void MemStream::put_zero(size_t n) +{ + m_mbuf.reserve(m_mbuf.size() + n); + memset(m_mbuf.data() + m_offset, 0, n); + m_offset += n; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u8(ex_u8 v) +{ + m_mbuf.reserve(m_mbuf.size() + 1); + + (m_mbuf.data() + m_offset)[0] = v; + m_offset++; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u16_le(ex_u16 v) +{ + m_mbuf.reserve(m_mbuf.size() + 2); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + p[0] = (ex_u8)v; + p[1] = (ex_u8)(v >> 8); +#else + ((ex_u16*)p)[0] = v; +#endif + m_offset += 2; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u16_be(ex_u16 v) +{ + m_mbuf.reserve(m_mbuf.size() + 2); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ((ex_u16*)p)[0] = v; +#else + ex_u8* _v = (ex_u8*)&v; + p[0] = _v[1]; + p[1] = _v[0]; +#endif + m_offset += 2; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u32_le(ex_u32 v) +{ + m_mbuf.reserve(m_mbuf.size() + 4); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + p[0] = (ex_u8)v; + p[1] = (ex_u8)(v >> 8); + p[2] = (ex_u8)(v >> 16); + p[3] = (ex_u8)(v >> 24); +#else + ((ex_u32*)p)[0] = v; +#endif + m_offset += 4; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_u32_be(ex_u32 v) +{ + m_mbuf.reserve(m_mbuf.size() + 4); + + ex_u8* p = m_mbuf.data() + m_offset; +#if defined(B_ENDIAN) + ((ex_u32*)p)[0] = v; +#else + ex_u8* _v = (ex_u8*)&v; + p[0] = _v[3]; + p[1] = _v[2]; + p[2] = _v[1]; + p[3] = _v[0]; +#endif + m_offset += 4; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + +void MemStream::put_bin(const ex_u8* p, size_t n) +{ + m_mbuf.reserve(m_mbuf.size() + n); + memcpy(m_mbuf.data() + m_offset, p, n); + m_offset += n; + if (m_mbuf.size() < m_offset) + m_mbuf.size(m_offset); +} + diff --git a/server/tp_core/common/ts_memstream.h b/server/tp_core/common/ts_memstream.h new file mode 100644 index 0000000..9ab425c --- /dev/null +++ b/server/tp_core/common/ts_memstream.h @@ -0,0 +1,45 @@ +#ifndef __TS_MEMSTREAM_H__ +#define __TS_MEMSTREAM_H__ + +#include "ts_membuf.h" + +class MemStream +{ +public: + MemStream(MemBuffer& mbuf); + ~MemStream(); + + void reset(void); // 清空缓冲区数据(但不释放内存),指针移动到头部 + + bool seek(size_t offset); // 移动指针到指定偏移,如果越界,则返回错误 + bool rewind(size_t n = 0); // 回退n字节,如果越界,返回错误,如果n为0,则回退到最开始处 + bool skip(size_t n); // 跳过n字节,如果越界,则返回错误 + + ex_u8* ptr(void) { return m_mbuf.data() + m_offset; } // 返回当前数据指针 + size_t offset(void) { return m_offset; } // 返回当前指针相对数据起始的偏移 + + size_t left(void) { return m_mbuf.size() - m_offset; } // 返回剩余数据的大小(从当前数据指针到缓冲区结尾) + + ex_u8 get_u8(void); + ex_u16 get_u16_le(void); + ex_u16 get_u16_be(void); + ex_u32 get_u32_le(void); + ex_u32 get_u32_be(void); + ex_u8* get_bin(size_t n); // 返回当前指向的数据的指针,内部偏移会向后移动n字节 + + void put_zero(size_t n); // 填充n字节的0 + void put_u8(ex_u8 v); + void put_u16_le(ex_u16 v); + void put_u16_be(ex_u16 v); + void put_u32_le(ex_u32 v); + void put_u32_be(ex_u32 v); + void put_bin(const ex_u8* p, size_t n); // 填充p指向的n字节数据 + + size_t size(void) { return m_mbuf.size(); } + +private: + MemBuffer& m_mbuf; + size_t m_offset; +}; + +#endif // __TS_MEMSTREAM_H__ diff --git a/server/tp_core/protocol/ssh/ssh_proxy.cpp b/server/tp_core/protocol/ssh/ssh_proxy.cpp index 04a248c..9b579cf 100644 --- a/server/tp_core/protocol/ssh/ssh_proxy.cpp +++ b/server/tp_core/protocol/ssh/ssh_proxy.cpp @@ -1,255 +1,255 @@ -#include "ssh_proxy.h" -#include "tpp_env.h" - -SshProxy g_ssh_proxy; - -SshProxy::SshProxy() : - ExThreadBase("ssh-proxy-thread"), - m_bind(NULL) -{ -} - -SshProxy::~SshProxy() -{ - if (NULL != m_bind) - ssh_bind_free(m_bind); - - ssh_finalize(); - - ts_sftp_sessions::iterator it = m_sftp_sessions.begin(); - for (; it != m_sftp_sessions.end(); ++it) - { - delete it->second; - } - m_sftp_sessions.clear(); -} - -bool SshProxy::init(void) -{ - m_host_ip = g_ssh_env.bind_ip; - m_host_port = g_ssh_env.bind_port; - - - m_bind = ssh_bind_new(); - if (NULL == m_bind) - { - EXLOGE("[ssh] can not create bind.\n"); - return false; - } - - if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDADDR, m_host_ip.c_str())) - { - EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDADDR.\n"); - return false; - } - if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDPORT, &m_host_port)) - { - EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDPORT.\n"); - return false; - } - - ex_wstr _key_file = g_ssh_env.etc_path; - ex_path_join(_key_file, false, L"tp_ssh_server.key", NULL); - ex_astr key_file; - ex_wstr2astr(_key_file, key_file); - - EXLOGV("[ssh] try to load ssh-server-key: %s\n", key_file.c_str()); - if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_RSAKEY, key_file.c_str())) - { - EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_RSAKEY.\n"); - return false; - } - - if (ssh_bind_listen(m_bind) < 0) - { - EXLOGE("[ssh] listening to socket: %s\n", ssh_get_error(m_bind)); - return false; - } - - return true; -} - -void SshProxy::_thread_loop(void) -{ - EXLOGV("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port); - _run(); - EXLOGV("[ssh] main-loop end.\n"); -} - -void SshProxy::_set_stop_flag(void) -{ - m_stop_flag = true; - - if (m_is_running) - { - // 用一个变通的方式来结束阻塞中的监听,就是连接一下它。 - ex_astr host_ip = m_host_ip; - if (host_ip == "0.0.0.0") - host_ip = "127.0.0.1"; - - ssh_session _session = ssh_new(); - ssh_options_set(_session, SSH_OPTIONS_HOST, host_ip.c_str()); - ssh_options_set(_session, SSH_OPTIONS_PORT, &m_host_port); - - int _timeout_us = 100000; - ssh_options_set(_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us); - ssh_connect(_session); - ssh_free(_session); - } - - m_thread_mgr.stop_all(); -} - -void SshProxy::_run(void) -{ - for (;;) - { - // 注意,ssh_new()出来的指针,如果遇到停止标志,本函数内部就释放了,否则这个指针交给了SshSession类实例管理,其析构时会释放。 - ssh_session sess_to_client = ssh_new(); - - struct sockaddr_storage sock_client; - char ip[32] = { 0 }; - int len = sizeof(ip); - - if (ssh_bind_accept(m_bind, sess_to_client) != SSH_OK) - { - EXLOGE("[ssh] accepting a connection failed: %s.\n", ssh_get_error(m_bind)); - continue; - } - EXLOGD("[ssh] ssh_bind_accept() returned...\n"); - - if (m_stop_flag) - { - ssh_free(sess_to_client); - break; - } - - SshSession* sess = new SshSession(this, sess_to_client); - -#ifdef EX_OS_WIN32 - getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, &len); -#else - getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, (unsigned int*)&len); -#endif - sockaddr_in* addrin = (sockaddr_in*)&sock_client; - - if (0 == ex_ip4_name(addrin, ip, sizeof(ip))) - { - sess->client_ip(ip); - sess->client_port(addrin->sin_port); - } - - - EXLOGV("[ssh] ------ NEW SSH CLIENT [%s:%d] ------\n", sess->client_ip(), sess->client_port()); - - - { - ExThreadSmartLock locker(m_lock); - m_sessions.insert(std::make_pair(sess, 0)); - } - - sess->start(); - } - - // 等待所有工作线程退出 - m_thread_mgr.stop_all(); -} - -void SshProxy::_dump_sftp_sessions(void) -{ - ts_sftp_sessions::iterator it = m_sftp_sessions.begin(); - for (; it != m_sftp_sessions.end(); ++it) - { - EXLOGD("ssh-proxy session: sid: %s\n", it->first.c_str()); - } -} - -void SshProxy::add_sftp_session_info(const ex_astr& sid, const ex_astr& host_ip, int host_port, const ex_astr& user_name, const ex_astr& user_auth, int auth_mode) -{ - ExThreadSmartLock locker(m_lock); - EXLOGD("[ssh] add sftp session-id: %s\n", sid.c_str()); - ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid); - if (it != m_sftp_sessions.end()) - { - EXLOGD("[ssh] sftp-session-id '%s' already exists.\n", sid.c_str()); - it->second->ref_count++; - return; - } - - TS_SFTP_SESSION_INFO* info = new TS_SFTP_SESSION_INFO; - info->host_ip = host_ip; - info->host_port = host_port; - info->user_name = user_name; - info->user_auth = user_auth; - info->auth_mode = auth_mode; - info->ref_count = 1; - - if (!m_sftp_sessions.insert(std::make_pair(sid, info)).second) - { - EXLOGE("[ssh] ssh-proxy can not insert a sftp-session-id.\n"); - } - - _dump_sftp_sessions(); -} - -bool SshProxy::get_sftp_session_info(const ex_astr& sid, TS_SFTP_SESSION_INFO& info) -{ - ExThreadSmartLock locker(m_lock); - EXLOGD("[ssh] try to get info by sftp session-id: %s\n", sid.c_str()); - - _dump_sftp_sessions(); - - ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid); - if (it == m_sftp_sessions.end()) - { - EXLOGD("sftp-session '%s' not exists.\n", sid.c_str()); - return false; - } - - info.host_ip = it->second->host_ip; - info.host_port = it->second->host_port; - info.user_name = it->second->user_name; - info.user_auth = it->second->user_auth; - info.auth_mode = it->second->auth_mode; - info.ref_count = it->second->ref_count; - - return true; -} - -void SshProxy::remove_sftp_sid(const ex_astr& sid) -{ - EXLOGD("[ssh] try to remove sftp session-id: %s\n", sid.c_str()); - - ExThreadSmartLock locker(m_lock); - ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid); - if (it == m_sftp_sessions.end()) - { - EXLOGE("[ssh] ssh-proxy when remove sftp sid, it not in charge.\n"); - return; - } - - it->second->ref_count--; - if (it->second->ref_count <= 0) - { - delete it->second; - m_sftp_sessions.erase(it); - EXLOGD("[ssh] sftp session-id '%s' removed.\n", sid.c_str()); - } -} - -void SshProxy::session_finished(SshSession* sess) -{ - ExThreadSmartLock locker(m_lock); - ts_ssh_sessions::iterator it = m_sessions.find(sess); - if (it != m_sessions.end()) - { - m_sessions.erase(it); - EXLOGV("[ssh] client %s:%d session removed.\n", sess->client_ip(), sess->client_port()); - } - else - { - EXLOGW("[ssh] when session %s:%d end, it not in charge.\n", sess->client_ip(), sess->client_port()); - } - - delete sess; -} +#include "ssh_proxy.h" +#include "tpp_env.h" + +SshProxy g_ssh_proxy; + +SshProxy::SshProxy() : + ExThreadBase("ssh-proxy-thread"), + m_bind(NULL) +{ +} + +SshProxy::~SshProxy() +{ + if (NULL != m_bind) + ssh_bind_free(m_bind); + + ssh_finalize(); + + ts_sftp_sessions::iterator it = m_sftp_sessions.begin(); + for (; it != m_sftp_sessions.end(); ++it) + { + delete it->second; + } + m_sftp_sessions.clear(); +} + +bool SshProxy::init(void) +{ + m_host_ip = g_ssh_env.bind_ip; + m_host_port = g_ssh_env.bind_port; + + + m_bind = ssh_bind_new(); + if (NULL == m_bind) + { + EXLOGE("[ssh] can not create bind.\n"); + return false; + } + + if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDADDR, m_host_ip.c_str())) + { + EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDADDR.\n"); + return false; + } + if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_BINDPORT, &m_host_port)) + { + EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_BINDPORT.\n"); + return false; + } + + ex_wstr _key_file = g_ssh_env.etc_path; + ex_path_join(_key_file, false, L"tp_ssh_server.key", NULL); + ex_astr key_file; + ex_wstr2astr(_key_file, key_file); + + EXLOGV("[ssh] try to load ssh-server-key: %s\n", key_file.c_str()); + if (SSH_OK != ssh_bind_options_set(m_bind, SSH_BIND_OPTIONS_RSAKEY, key_file.c_str())) + { + EXLOGE("[ssh] can not set bind option: SSH_BIND_OPTIONS_RSAKEY.\n"); + return false; + } + + if (ssh_bind_listen(m_bind) < 0) + { + EXLOGE("[ssh] listening to socket: %s\n", ssh_get_error(m_bind)); + return false; + } + + return true; +} + +void SshProxy::_thread_loop(void) +{ + EXLOGV("[ssh] TeleportServer-SSH ready on %s:%d\n", m_host_ip.c_str(), m_host_port); + _run(); + EXLOGV("[ssh] main-loop end.\n"); +} + +void SshProxy::_set_stop_flag(void) +{ + m_stop_flag = true; + + if (m_is_running) + { + // 用一个变通的方式来结束阻塞中的监听,就是连接一下它。 + ex_astr host_ip = m_host_ip; + if (host_ip == "0.0.0.0") + host_ip = "127.0.0.1"; + + ssh_session _session = ssh_new(); + ssh_options_set(_session, SSH_OPTIONS_HOST, host_ip.c_str()); + ssh_options_set(_session, SSH_OPTIONS_PORT, &m_host_port); + + int _timeout_us = 100000; + ssh_options_set(_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us); + ssh_connect(_session); + ssh_free(_session); + } + + m_thread_mgr.stop_all(); +} + +void SshProxy::_run(void) +{ + for (;;) + { + // 注意,ssh_new()出来的指针,如果遇到停止标志,本函数内部就释放了,否则这个指针交给了SshSession类实例管理,其析构时会释放。 + ssh_session sess_to_client = ssh_new(); + + struct sockaddr_storage sock_client; + char ip[32] = { 0 }; + int len = sizeof(ip); + + if (ssh_bind_accept(m_bind, sess_to_client) != SSH_OK) + { + EXLOGE("[ssh] accepting a connection failed: %s.\n", ssh_get_error(m_bind)); + continue; + } + EXLOGD("[ssh] ssh_bind_accept() returned...\n"); + + if (m_stop_flag) + { + ssh_free(sess_to_client); + break; + } + + SshSession* sess = new SshSession(this, sess_to_client); + +#ifdef EX_OS_WIN32 + getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, &len); +#else + getpeername(ssh_get_fd(sess_to_client), (struct sockaddr*)&sock_client, (unsigned int*)&len); +#endif + sockaddr_in* addrin = (sockaddr_in*)&sock_client; + + if (0 == ex_ip4_name(addrin, ip, sizeof(ip))) + { + sess->client_ip(ip); + sess->client_port(addrin->sin_port); + } + + + EXLOGV("[ssh] ------ NEW SSH CLIENT [%s:%d] ------\n", sess->client_ip(), sess->client_port()); + + + { + ExThreadSmartLock locker(m_lock); + m_sessions.insert(std::make_pair(sess, 0)); + } + + sess->start(); + } + + // 等待所有工作线程退出 + m_thread_mgr.stop_all(); +} + +void SshProxy::_dump_sftp_sessions(void) +{ + ts_sftp_sessions::iterator it = m_sftp_sessions.begin(); + for (; it != m_sftp_sessions.end(); ++it) + { + EXLOGD("ssh-proxy session: sid: %s\n", it->first.c_str()); + } +} + +void SshProxy::add_sftp_session_info(const ex_astr& sid, const ex_astr& host_ip, int host_port, const ex_astr& user_name, const ex_astr& user_auth, int auth_mode) +{ + ExThreadSmartLock locker(m_lock); + EXLOGD("[ssh] add sftp session-id: %s\n", sid.c_str()); + ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid); + if (it != m_sftp_sessions.end()) + { + EXLOGD("[ssh] sftp-session-id '%s' already exists.\n", sid.c_str()); + it->second->ref_count++; + return; + } + + TS_SFTP_SESSION_INFO* info = new TS_SFTP_SESSION_INFO; + info->host_ip = host_ip; + info->host_port = host_port; + info->user_name = user_name; + info->user_auth = user_auth; + info->auth_mode = auth_mode; + info->ref_count = 1; + + if (!m_sftp_sessions.insert(std::make_pair(sid, info)).second) + { + EXLOGE("[ssh] ssh-proxy can not insert a sftp-session-id.\n"); + } + + _dump_sftp_sessions(); +} + +bool SshProxy::get_sftp_session_info(const ex_astr& sid, TS_SFTP_SESSION_INFO& info) +{ + ExThreadSmartLock locker(m_lock); + EXLOGD("[ssh] try to get info by sftp session-id: %s\n", sid.c_str()); + + _dump_sftp_sessions(); + + ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid); + if (it == m_sftp_sessions.end()) + { + EXLOGD("sftp-session '%s' not exists.\n", sid.c_str()); + return false; + } + + info.host_ip = it->second->host_ip; + info.host_port = it->second->host_port; + info.user_name = it->second->user_name; + info.user_auth = it->second->user_auth; + info.auth_mode = it->second->auth_mode; + info.ref_count = it->second->ref_count; + + return true; +} + +void SshProxy::remove_sftp_sid(const ex_astr& sid) +{ + EXLOGD("[ssh] try to remove sftp session-id: %s\n", sid.c_str()); + + ExThreadSmartLock locker(m_lock); + ts_sftp_sessions::iterator it = m_sftp_sessions.find(sid); + if (it == m_sftp_sessions.end()) + { + EXLOGE("[ssh] ssh-proxy when remove sftp sid, it not in charge.\n"); + return; + } + + it->second->ref_count--; + if (it->second->ref_count <= 0) + { + delete it->second; + m_sftp_sessions.erase(it); + EXLOGD("[ssh] sftp session-id '%s' removed.\n", sid.c_str()); + } +} + +void SshProxy::session_finished(SshSession* sess) +{ + ExThreadSmartLock locker(m_lock); + ts_ssh_sessions::iterator it = m_sessions.find(sess); + if (it != m_sessions.end()) + { + m_sessions.erase(it); + EXLOGV("[ssh] client %s:%d session removed.\n", sess->client_ip(), sess->client_port()); + } + else + { + EXLOGW("[ssh] when session %s:%d end, it not in charge.\n", sess->client_ip(), sess->client_port()); + } + + delete sess; +} diff --git a/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj b/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj index 6e6f5cc..53f4c86 100644 --- a/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj +++ b/server/tp_core/protocol/ssh/tpssh.vs2015.vcxproj @@ -1,218 +1,157 @@ -锘 - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {FDA16D20-09B7-45AF-ADF1-DAF3EF2C0531} - Win32Proj - tpssh - 8.1 - tpssh - - - - DynamicLibrary - true - v140_xp - Unicode - - - DynamicLibrary - false - v140_xp - true - Unicode - - - DynamicLibrary - true - v140 - Unicode - - - DynamicLibrary - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - ..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\ - ..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ - - - true - - - false - ..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\ - ..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions) - ..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) - MultiThreadedDebug - - - Windows - true - ..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories) - - - - - - - Level3 - Disabled - _DEBUG;_WINDOWS;_USRDLL;TPSSH_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions) - ..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) - MultiThreaded - - - Windows - true - true - true - ..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - NDEBUG;_WINDOWS;_USRDLL;TPSSH_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - - - false - - - false - - - false - - - - - - - - - - - - - +锘 + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {FDA16D20-09B7-45AF-ADF1-DAF3EF2C0531} + Win32Proj + tpssh + 8.1 + tpssh + + + + DynamicLibrary + true + v140_xp + Unicode + + + DynamicLibrary + false + v140_xp + true + Unicode + + + + + + + + + + + + + + + true + ..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\ + ..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + false + ..\..\..\..\out\server\$(PlatformTarget)\$(Configuration)\ + ..\..\..\..\out\_tmp_\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions) + ..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) + MultiThreadedDebug + + + Windows + true + ..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;TPP_EXPORTS;LIBSSH_STATIC;%(PreprocessorDefinitions) + ..\..\..\..\common\libex\include;..\..\..\..\external\libssh-win-static\include;%(AdditionalIncludeDirectories) + MultiThreaded + + + Windows + true + true + true + ..\..\..\..\external\libssh-win-static\lib;..\..\..\..\external\openssl\out32;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + + + + + + + + + + + \ No newline at end of file