mirror of
https://github.com/MetaCubeX/subconverter.git
synced 2025-11-04 18:19:42 +08:00
Add support for exporting SIP002 subscription. Add support for exporting ShadowsocksR subscription. Add support for exporting ShadowsocksD subscription. Add support for exporting v2rayN ver.2 VMess subscription. Add support for exporting Quantumult VMess subscription. Add support for exporting Quantumult X subscription. TODO: Clean up duplicate codes.
812 lines
20 KiB
C++
812 lines
20 KiB
C++
#include <chrono>
|
|
#include <regex>
|
|
#include <fstream>
|
|
#include <thread>
|
|
#include <sstream>
|
|
#include <iosfwd>
|
|
//#include <filesystem>
|
|
#include <unistd.h>
|
|
|
|
#include <rapidjson/document.h>
|
|
#include <openssl/md5.h>
|
|
|
|
#include "misc.h"
|
|
|
|
#ifdef _WIN32
|
|
//#include <io.h>
|
|
#include <windows.h>
|
|
#include <winreg.h>
|
|
#else
|
|
#ifndef __hpux
|
|
#include <sys/select.h>
|
|
#endif /* __hpux */
|
|
#ifndef _access
|
|
#define _access access
|
|
#endif // _access
|
|
#include <sys/socket.h>
|
|
#endif // _WIN32
|
|
|
|
using namespace std::__cxx11;
|
|
|
|
void sleep(int interval)
|
|
{
|
|
/*
|
|
#ifdef _WIN32
|
|
Sleep(interval);
|
|
#else
|
|
// Portable sleep for platforms other than Windows.
|
|
struct timeval wait = { 0, interval * 1000 };
|
|
select(0, NULL, NULL, NULL, &wait);
|
|
#endif
|
|
*/
|
|
//upgrade to c++11 standard
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
|
|
}
|
|
|
|
std::string GBKToUTF8(std::string str_src)
|
|
{
|
|
#ifdef _WIN32
|
|
const char* strGBK = str_src.c_str();
|
|
int len = MultiByteToWideChar(CP_ACP, 0, strGBK, -1, NULL, 0);
|
|
wchar_t* wstr = new wchar_t[len + 1];
|
|
memset(wstr, 0, len + 1);
|
|
MultiByteToWideChar(CP_ACP, 0, strGBK, -1, wstr, len);
|
|
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
|
|
char* str = new char[len + 1];
|
|
memset(str, 0, len + 1);
|
|
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
|
|
std::string strTemp = str;
|
|
if(wstr)
|
|
delete[] wstr;
|
|
if(str)
|
|
delete[] str;
|
|
return strTemp;
|
|
#else
|
|
return str_src;
|
|
#endif // _WIN32
|
|
}
|
|
|
|
std::string UTF8ToGBK(std::string str_src)
|
|
{
|
|
#ifdef _WIN32
|
|
const char* strUTF8 = str_src.data();
|
|
int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, NULL, 0);
|
|
wchar_t* wszGBK = new wchar_t[len + 1];
|
|
memset(wszGBK, 0, len * 2 + 2);
|
|
MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, wszGBK, len);
|
|
len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
|
|
char* szGBK = new char[len + 1];
|
|
memset(szGBK, 0, len + 1);
|
|
WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
|
|
std::string strTemp(szGBK);
|
|
if (wszGBK)
|
|
delete[] wszGBK;
|
|
if (szGBK)
|
|
delete[] szGBK;
|
|
return strTemp;
|
|
#else
|
|
return str_src;
|
|
#endif
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
// std::string to wstring
|
|
void StringToWstring(std::wstring& szDst, std::string str)
|
|
{
|
|
std::string temp = str;
|
|
int len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)temp.c_str(), -1, NULL,0);
|
|
wchar_t* wszUtf8 = new wchar_t[len + 1];
|
|
memset(wszUtf8, 0, len * 2 + 2);
|
|
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)temp.c_str(), -1, (LPWSTR)wszUtf8, len);
|
|
szDst = wszUtf8;
|
|
std::wstring r = wszUtf8;
|
|
delete[] wszUtf8;
|
|
}
|
|
#endif // _WIN32
|
|
|
|
unsigned char ToHex(unsigned char x)
|
|
{
|
|
return x > 9 ? x + 55 : x + 48;
|
|
}
|
|
|
|
unsigned char FromHex(unsigned char x)
|
|
{
|
|
unsigned char y = '\0';
|
|
if (x >= 'A' && x <= 'Z')
|
|
y = x - 'A' + 10;
|
|
else if (x >= 'a' && x <= 'z')
|
|
y = x - 'a' + 10;
|
|
else if (x >= '0' && x <= '9')
|
|
y = x - '0';
|
|
else
|
|
assert(0);
|
|
return y;
|
|
}
|
|
|
|
std::string UrlEncode(const std::string& str)
|
|
{
|
|
std::string strTemp = "";
|
|
size_t length = str.length();
|
|
for (size_t i = 0; i < length; i++)
|
|
{
|
|
if (isalnum((unsigned char)str[i]) ||
|
|
(str[i] == '-') ||
|
|
(str[i] == '_') ||
|
|
(str[i] == '.') ||
|
|
(str[i] == '~'))
|
|
strTemp += str[i];
|
|
else if (str[i] == ' ')
|
|
strTemp += "+";
|
|
else
|
|
{
|
|
strTemp += '%';
|
|
strTemp += ToHex((unsigned char)str[i] >> 4);
|
|
strTemp += ToHex((unsigned char)str[i] % 16);
|
|
}
|
|
}
|
|
return strTemp;
|
|
}
|
|
|
|
std::string UrlDecode(const std::string& str)
|
|
{
|
|
std::string strTemp = "";
|
|
size_t length = str.length();
|
|
for (size_t i = 0; i < length; i++)
|
|
{
|
|
if (str[i] == '+')
|
|
strTemp += ' ';
|
|
else if (str[i] == '%')
|
|
{
|
|
if(i + 2 >= length)
|
|
return strTemp;
|
|
unsigned char high = FromHex((unsigned char)str[++i]);
|
|
unsigned char low = FromHex((unsigned char)str[++i]);
|
|
strTemp += high * 16 + low;
|
|
}
|
|
else
|
|
strTemp += str[i];
|
|
}
|
|
return strTemp;
|
|
}
|
|
|
|
static inline bool is_base64(unsigned char c)
|
|
{
|
|
return (isalnum(c) || (c == '+') || (c == '/'));
|
|
}
|
|
|
|
std::string base64_encode(std::string string_to_encode)
|
|
{
|
|
char const* bytes_to_encode = string_to_encode.data();
|
|
unsigned int in_len = string_to_encode.size();
|
|
|
|
std::string ret;
|
|
int i = 0;
|
|
int j = 0;
|
|
unsigned char char_array_3[3];
|
|
unsigned char char_array_4[4];
|
|
|
|
while (in_len--)
|
|
{
|
|
char_array_3[i++] = *(bytes_to_encode++);
|
|
if (i == 3)
|
|
{
|
|
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
|
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
|
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
|
char_array_4[3] = char_array_3[2] & 0x3f;
|
|
|
|
for(i = 0; (i <4) ; i++)
|
|
ret += base64_chars[char_array_4[i]];
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
if (i)
|
|
{
|
|
for(j = i; j < 3; j++)
|
|
char_array_3[j] = '\0';
|
|
|
|
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
|
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
|
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
|
char_array_4[3] = char_array_3[2] & 0x3f;
|
|
|
|
for (j = 0; (j < i + 1); j++)
|
|
ret += base64_chars[char_array_4[j]];
|
|
|
|
while((i++ < 3))
|
|
ret += '=';
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
std::string base64_decode(std::string encoded_string)
|
|
{
|
|
int in_len = encoded_string.size();
|
|
int i = 0;
|
|
int j = 0;
|
|
int in_ = 0;
|
|
unsigned char char_array_4[4], char_array_3[3];
|
|
std::string ret;
|
|
|
|
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_]))
|
|
{
|
|
char_array_4[i++] = encoded_string[in_];
|
|
in_++;
|
|
if (i ==4)
|
|
{
|
|
for (i = 0; i <4; i++)
|
|
char_array_4[i] = base64_chars.find(char_array_4[i]);
|
|
|
|
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
|
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
|
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
|
|
|
for (i = 0; (i < 3); i++)
|
|
ret += char_array_3[i];
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
if (i)
|
|
{
|
|
for (j = i; j <4; j++)
|
|
char_array_4[j] = 0;
|
|
|
|
for (j = 0; j <4; j++)
|
|
char_array_4[j] = base64_chars.find(char_array_4[j]);
|
|
|
|
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
|
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
|
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
|
|
|
for (j = 0; (j < i - 1); j++)
|
|
ret += char_array_3[j];
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
std::vector<std::string> split(const std::string &s, const std::string &seperator)
|
|
{
|
|
std::vector<std::string> result;
|
|
typedef std::string::size_type string_size;
|
|
string_size i = 0;
|
|
|
|
while(i != s.size())
|
|
{
|
|
int flag = 0;
|
|
while(i != s.size() && flag == 0)
|
|
{
|
|
flag = 1;
|
|
for(string_size x = 0; x < seperator.size(); ++x)
|
|
if(s[i] == seperator[x])
|
|
{
|
|
++i;
|
|
flag = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
flag = 0;
|
|
string_size j = i;
|
|
while(j != s.size() && flag == 0)
|
|
{
|
|
for(string_size x = 0; x < seperator.size(); ++x)
|
|
if(s[j] == seperator[x])
|
|
{
|
|
flag = 1;
|
|
break;
|
|
}
|
|
if(flag == 0)
|
|
++j;
|
|
}
|
|
if(i != j)
|
|
{
|
|
result.push_back(s.substr(i, j-i));
|
|
i = j;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::string getSystemProxy()
|
|
{
|
|
#ifdef _WIN32
|
|
HKEY key;
|
|
auto ret = RegOpenKeyEx(HKEY_CURRENT_USER, R"(Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings)", 0, KEY_ALL_ACCESS, &key);
|
|
if(ret != ERROR_SUCCESS)
|
|
{
|
|
//std::cout << "open failed: " << ret << std::endl;
|
|
return std::string();
|
|
}
|
|
|
|
DWORD values_count, max_value_name_len, max_value_len;
|
|
ret = RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&values_count, &max_value_name_len, &max_value_len, NULL, NULL);
|
|
if(ret != ERROR_SUCCESS)
|
|
{
|
|
//std::cout << "query failed" << std::endl;
|
|
return std::string();
|
|
}
|
|
|
|
std::vector<std::tuple<std::shared_ptr<char>, DWORD, std::shared_ptr<BYTE>>> values;
|
|
for(DWORD i = 0; i < values_count; i++)
|
|
{
|
|
std::shared_ptr<char> value_name(new char[max_value_name_len + 1],
|
|
std::default_delete<char[]>());
|
|
DWORD value_name_len = max_value_name_len + 1;
|
|
DWORD value_type, value_len;
|
|
RegEnumValue(key, i, value_name.get(), &value_name_len, NULL, &value_type, NULL, &value_len);
|
|
std::shared_ptr<BYTE> value(new BYTE[value_len],
|
|
std::default_delete<BYTE[]>());
|
|
value_name_len = max_value_name_len + 1;
|
|
RegEnumValue(key, i, value_name.get(), &value_name_len, NULL, &value_type, value.get(), &value_len);
|
|
values.push_back(std::make_tuple(value_name, value_type, value));
|
|
}
|
|
|
|
DWORD ProxyEnable = 0;
|
|
for (auto x : values)
|
|
{
|
|
if (strcmp(std::get<0>(x).get(), "ProxyEnable") == 0)
|
|
{
|
|
ProxyEnable = *(DWORD*)(std::get<2>(x).get());
|
|
}
|
|
}
|
|
|
|
if (ProxyEnable)
|
|
{
|
|
for (auto x : values)
|
|
{
|
|
if (strcmp(std::get<0>(x).get(), "ProxyServer") == 0)
|
|
{
|
|
//std::cout << "ProxyServer: " << (char*)(std::get<2>(x).get()) << std::endl;
|
|
return std::string((char*)(std::get<2>(x).get()));
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
else {
|
|
//std::cout << "Proxy not Enabled" << std::endl;
|
|
}
|
|
*/
|
|
//return 0;
|
|
return std::string();
|
|
#else
|
|
char* proxy = getenv("ALL_PROXY");
|
|
if(proxy != NULL)
|
|
return std::string(proxy);
|
|
else
|
|
return std::string();
|
|
#endif // _WIN32
|
|
}
|
|
|
|
std::string trim(const std::string& str)
|
|
{
|
|
std::string::size_type pos = str.find_first_not_of(' ');
|
|
if (pos == std::string::npos)
|
|
{
|
|
return str;
|
|
}
|
|
std::string::size_type pos2 = str.find_last_not_of(' ');
|
|
if (pos2 != std::string::npos)
|
|
{
|
|
return str.substr(pos, pos2 - pos + 1);
|
|
}
|
|
return str.substr(pos);
|
|
}
|
|
|
|
std::string getUrlArg(std::string url, std::string request)
|
|
{
|
|
std::smatch result;
|
|
if (regex_search(url.cbegin(), url.cend(), result, std::regex(request + "=(.*?)&")))
|
|
{
|
|
return result[1];
|
|
}
|
|
else if (regex_search(url.cbegin(), url.cend(), result, std::regex(request + "=(.*)")))
|
|
{
|
|
return result[1];
|
|
}
|
|
else
|
|
{
|
|
return std::string();
|
|
}
|
|
}
|
|
|
|
std::string replace_all_distinct(std::string str, std::string old_value, std::string new_value)
|
|
{
|
|
for(std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length())
|
|
{
|
|
if((pos = str.find(old_value, pos)) != std::string::npos)
|
|
str.replace(pos, old_value.length(), new_value);
|
|
else
|
|
break;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
bool regFind(std::string src, std::string target)
|
|
{
|
|
std::regex reg(target);
|
|
return regex_search(src, reg);
|
|
}
|
|
|
|
std::string regReplace(std::string src, std::string match, std::string rep)
|
|
{
|
|
std::string result = "";
|
|
std::regex reg(match);
|
|
regex_replace(back_inserter(result), src.begin(), src.end(), reg, rep);
|
|
return result;
|
|
}
|
|
|
|
bool regMatch(std::string src, std::string match)
|
|
{
|
|
std::regex reg(match);
|
|
return regex_match(src, reg);
|
|
}
|
|
|
|
std::string speedCalc(double speed)
|
|
{
|
|
if(speed == 0.0)
|
|
return std::string("0.00B");
|
|
char str[10];
|
|
std::string retstr;
|
|
if(speed >= 1073741824.0)
|
|
sprintf(str, "%.2fGB", speed / 1073741824.0);
|
|
else if(speed >= 1048576.0)
|
|
sprintf(str, "%.2fMB", speed / 1048576.0);
|
|
else if(speed >= 1024.0)
|
|
sprintf(str, "%.2fKB", speed / 1024.0);
|
|
else
|
|
sprintf(str, "%.2fB", speed);
|
|
retstr = str;
|
|
return retstr;
|
|
}
|
|
|
|
std::string urlsafe_base64_reverse(std::string encoded_string)
|
|
{
|
|
return replace_all_distinct(replace_all_distinct(encoded_string, "-", "+"), "_", "/");
|
|
}
|
|
|
|
std::string urlsafe_base64_decode(std::string encoded_string)
|
|
{
|
|
return base64_decode(urlsafe_base64_reverse(encoded_string));
|
|
}
|
|
|
|
std::string urlsafe_base64_encode(std::string string_to_encode)
|
|
{
|
|
return replace_all_distinct(replace_all_distinct(base64_encode(string_to_encode), "+", "-"), "/", "_");
|
|
}
|
|
|
|
std::string getMD5(std::string data)
|
|
{
|
|
MD5_CTX ctx;
|
|
std::string result;
|
|
unsigned int i = 0;
|
|
unsigned char digest[16] = {};
|
|
|
|
MD5_Init(&ctx);
|
|
MD5_Update(&ctx, data.data(), data.size());
|
|
MD5_Final((unsigned char *)&digest, &ctx);
|
|
|
|
char tmp[3] = {};
|
|
for(i = 0; i < 16; i++)
|
|
{
|
|
snprintf(tmp, 3, "%02x", digest[i]);
|
|
result += tmp;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
std::string fileGet(std::string path, bool binary)
|
|
{
|
|
std::ifstream infile;
|
|
std::stringstream strstrm;
|
|
std::ios::openmode mode = binary ? std::ios::binary : std::ios::in;
|
|
|
|
infile.open(path, mode);
|
|
if(infile)
|
|
{
|
|
strstrm<<infile.rdbuf();
|
|
infile.close();
|
|
return strstrm.str();
|
|
}
|
|
return std::string();
|
|
}
|
|
|
|
bool fileExist(std::string path)
|
|
{
|
|
//using c++17 standard, but may cause problem on clang
|
|
//return std::filesystem::exists(path);
|
|
return _access(path.data(), 4) != -1;
|
|
}
|
|
|
|
bool fileCopy(std::string source, std::string dest)
|
|
{
|
|
std::ifstream infile;
|
|
std::ofstream outfile;
|
|
infile.open(source, std::ios::binary);
|
|
if(!infile)
|
|
return false;
|
|
outfile.open(dest, std::ios::binary);
|
|
if(!outfile)
|
|
return false;
|
|
try
|
|
{
|
|
outfile<<infile.rdbuf();
|
|
}
|
|
catch (std::exception &e)
|
|
{
|
|
return false;
|
|
}
|
|
infile.close();
|
|
outfile.close();
|
|
return true;
|
|
}
|
|
|
|
std::string fileToBase64(std::string filepath)
|
|
{
|
|
return base64_encode(fileGet(filepath));
|
|
}
|
|
|
|
std::string fileGetMD5(std::string filepath)
|
|
{
|
|
return getMD5(fileGet(filepath));
|
|
}
|
|
|
|
int fileWrite(std::string path, std::string content, bool overwrite)
|
|
{
|
|
std::fstream outfile;
|
|
std::ios::openmode mode = overwrite ? std::ios::out : std::ios::app;
|
|
outfile.open(path, mode);
|
|
outfile << content << std::endl;
|
|
outfile.close();
|
|
return 0;
|
|
}
|
|
|
|
bool isIPv4(std::string address)
|
|
{
|
|
return regMatch(address, "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
|
|
}
|
|
|
|
bool isIPv6(std::string address)
|
|
{
|
|
std::vector<std::string> regLists = {"^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$", "^((?:[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((?:([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$", "^(::(?:[0-9A-Fa-f]{1,4})(?::[0-9A-Fa-f]{1,4}){5})|((?:[0-9A-Fa-f]{1,4})(?::[0-9A-Fa-f]{1,4}){5}::)$"};
|
|
for(unsigned int i = 0; i < regLists.size(); i++)
|
|
{
|
|
if(regMatch(address, regLists[i]))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::string rand_str(const int len)
|
|
{
|
|
std::string retData;
|
|
srand(time(NULL));
|
|
int cnt = 0;
|
|
while(cnt < len)
|
|
{
|
|
switch((rand() % 3))
|
|
{
|
|
case 1:
|
|
retData += ('A' + rand() % 26);
|
|
break;
|
|
case 2:
|
|
retData += ('a' + rand() % 26);
|
|
break;
|
|
default:
|
|
retData += ('0' + rand() % 10);
|
|
break;
|
|
}
|
|
cnt++;
|
|
}
|
|
return retData;
|
|
}
|
|
|
|
void urlParse(std::string url, std::string &host, std::string &path, int &port, bool &isTLS)
|
|
{
|
|
std::vector<std::string> args;
|
|
|
|
if(regMatch(url, "^https://(.*)"))
|
|
isTLS = true;
|
|
url = regReplace(url, "^(http|https)://", "");
|
|
if(url.find("/") == url.npos)
|
|
{
|
|
host = url;
|
|
path = "/";
|
|
}
|
|
else
|
|
{
|
|
host = url.substr(0, url.find("/"));
|
|
path = url.substr(url.find("/"));
|
|
}
|
|
if(regFind(host, "\\[(.*)\\]")) //IPv6
|
|
{
|
|
args = split(regReplace(host, "\\[(.*)\\](.*)", "$1,$2"), ",");
|
|
if(args.size() == 2) //with port
|
|
port = stoi(args[1].substr(1));
|
|
host = args[0];
|
|
}
|
|
else if(strFind(host, ":"))
|
|
{
|
|
port = stoi(host.substr(host.rfind(":") + 1));
|
|
host = host.substr(0, host.rfind(":"));
|
|
}
|
|
if(port == 0)
|
|
{
|
|
if(isTLS)
|
|
port = 443;
|
|
else
|
|
port = 80;
|
|
}
|
|
}
|
|
|
|
bool is_str_utf8(std::string data)
|
|
{
|
|
const char *str = data.c_str();
|
|
unsigned int nBytes = 0;
|
|
unsigned char chr = *str;
|
|
bool bAllAscii = true;
|
|
for (unsigned int i = 0; str[i] != '\0'; ++i)
|
|
{
|
|
chr = *(str + i);
|
|
if (nBytes == 0 && (chr & 0x80) != 0)
|
|
{
|
|
bAllAscii = false;
|
|
}
|
|
if (nBytes == 0)
|
|
{
|
|
if (chr >= 0x80)
|
|
{
|
|
if (chr >= 0xFC && chr <= 0xFD)
|
|
{
|
|
nBytes = 6;
|
|
}
|
|
else if (chr >= 0xF8)
|
|
{
|
|
nBytes = 5;
|
|
}
|
|
else if (chr >= 0xF0)
|
|
{
|
|
nBytes = 4;
|
|
}
|
|
else if (chr >= 0xE0)
|
|
{
|
|
nBytes = 3;
|
|
}
|
|
else if (chr >= 0xC0)
|
|
{
|
|
nBytes = 2;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
nBytes--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((chr & 0xC0) != 0x80)
|
|
{
|
|
return false;
|
|
}
|
|
nBytes--;
|
|
}
|
|
}
|
|
if (nBytes != 0)
|
|
{
|
|
return false;
|
|
}
|
|
if (bAllAscii)
|
|
{
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void removeUTF8BOM(std::string &data)
|
|
{
|
|
int BOM[3] = {0xef, 0xbb, 0xbf};
|
|
if(data.compare(0, 3, (char*)BOM) == 0)
|
|
data = data.substr(3);
|
|
}
|
|
|
|
int shortAssemble(unsigned short num_a, unsigned short num_b)
|
|
{
|
|
return (int)num_b << 16 | num_a;
|
|
}
|
|
|
|
void shortDisassemble(int source, unsigned short &num_a, unsigned short &num_b)
|
|
{
|
|
num_a = (unsigned short)source;
|
|
num_b = (unsigned short)(source >> 16);
|
|
}
|
|
|
|
std::string to_string(YAML::Node &node)
|
|
{
|
|
std::stringstream ss;
|
|
ss << node;
|
|
return ss.str();
|
|
}
|
|
|
|
std::string getFormData(std::string &raw_data)
|
|
{
|
|
std::stringstream strstrm;
|
|
std::string line;
|
|
|
|
std::string boundary;
|
|
std::string disp; /* content disposition string */
|
|
std::string type; /* content type string */
|
|
std::string file; /* actual file content */
|
|
|
|
|
|
int i = 0;
|
|
|
|
strstrm<<raw_data;
|
|
|
|
while (std::getline(strstrm, line))
|
|
{
|
|
if(i == 0)
|
|
{
|
|
// Get boundary
|
|
boundary = line.substr(0, line.length() - 1);
|
|
}
|
|
else if(line.find("Content-Disposition") == 0)
|
|
{
|
|
disp = line;
|
|
}
|
|
else if(line.find("Content-Type") == 0)
|
|
{
|
|
type = line;
|
|
}
|
|
else if(line.find(boundary) == 0)
|
|
{
|
|
// The end
|
|
type = line;
|
|
break;
|
|
}
|
|
else if(line.length() == 1)
|
|
{
|
|
// Time to get raw data
|
|
|
|
char c;
|
|
int bl = boundary.length();
|
|
bool endfile = false;
|
|
char buffer[256];
|
|
while(!endfile)
|
|
{
|
|
int j = 0;
|
|
int k;
|
|
while(j < 256 && strstrm.get(c) && !endfile)
|
|
{
|
|
buffer[j] = c;
|
|
k = 0;
|
|
// Verify if we are at the end
|
|
while(boundary[bl - 1 - k] == buffer[j - k])
|
|
{
|
|
if(k >= bl - 1)
|
|
{
|
|
// We are at the end of the file
|
|
endfile = true;
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
j++;
|
|
}
|
|
file.append(buffer, j);
|
|
j = 0;
|
|
};
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
return file;
|
|
}
|