mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-14 21:09:05 +08:00
462 lines
13 KiB
C++
462 lines
13 KiB
C++
// sktoolslib - common files for SK tools
|
|
|
|
// Copyright (C) 2012-2017, 2019-2020 - Stefan Kueng
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software Foundation,
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "StringUtils.h"
|
|
#include "OnOutOfScope.h"
|
|
|
|
#include <Wincrypt.h>
|
|
|
|
#pragma comment(lib, "Crypt32.lib")
|
|
|
|
int strwildcmp(const char* wild, const char* str)
|
|
{
|
|
const char* cp = nullptr;
|
|
const char* mp = nullptr;
|
|
while ((*str) && (*wild != '*'))
|
|
{
|
|
if ((*wild != *str) && (*wild != '?'))
|
|
{
|
|
return 0;
|
|
}
|
|
wild++;
|
|
str++;
|
|
}
|
|
while (*str)
|
|
{
|
|
if (*wild == '*')
|
|
{
|
|
if (!*++wild)
|
|
{
|
|
return 1;
|
|
}
|
|
mp = wild;
|
|
cp = str + 1;
|
|
}
|
|
else if ((*wild == *str) || (*wild == '?'))
|
|
{
|
|
wild++;
|
|
str++;
|
|
}
|
|
else
|
|
{
|
|
wild = mp;
|
|
str = cp++;
|
|
}
|
|
}
|
|
|
|
while (*wild == '*')
|
|
{
|
|
wild++;
|
|
}
|
|
return !*wild;
|
|
}
|
|
|
|
int wcswildcmp(const wchar_t* wild, const wchar_t* str)
|
|
{
|
|
const wchar_t* cp = nullptr;
|
|
const wchar_t* mp = nullptr;
|
|
while ((*str) && (*wild != L'*'))
|
|
{
|
|
if ((*wild != *str) && (*wild != L'?'))
|
|
{
|
|
return 0;
|
|
}
|
|
wild++;
|
|
str++;
|
|
}
|
|
while (*str)
|
|
{
|
|
if (*wild == L'*')
|
|
{
|
|
if (!*++wild)
|
|
{
|
|
return 1;
|
|
}
|
|
mp = wild;
|
|
cp = str + 1;
|
|
}
|
|
else if ((*wild == *str) || (*wild == L'?'))
|
|
{
|
|
wild++;
|
|
str++;
|
|
}
|
|
else
|
|
{
|
|
wild = mp;
|
|
str = cp++;
|
|
}
|
|
}
|
|
|
|
while (*wild == L'*')
|
|
{
|
|
wild++;
|
|
}
|
|
return !*wild;
|
|
}
|
|
|
|
int wcswildicmp(const wchar_t* wild, const wchar_t* str)
|
|
{
|
|
const wchar_t* cp = nullptr;
|
|
const wchar_t* mp = nullptr;
|
|
while ((*str) && (*wild != L'*'))
|
|
{
|
|
if ((*wild != L'?') && (::towlower(*wild) != ::towlower(*str)))
|
|
{
|
|
return 0;
|
|
}
|
|
wild++;
|
|
str++;
|
|
}
|
|
while (*str)
|
|
{
|
|
if (*wild == L'*')
|
|
{
|
|
if (!*++wild)
|
|
{
|
|
return 1;
|
|
}
|
|
mp = wild;
|
|
cp = str + 1;
|
|
}
|
|
else if ((*wild == L'?') || (::towlower(*wild) == ::towlower(*str)))
|
|
{
|
|
wild++;
|
|
str++;
|
|
}
|
|
else
|
|
{
|
|
wild = mp;
|
|
str = cp++;
|
|
}
|
|
}
|
|
|
|
while (*wild == L'*')
|
|
{
|
|
wild++;
|
|
}
|
|
return !*wild;
|
|
}
|
|
|
|
static constexpr BYTE HexLookup[513] = {
|
|
"000102030405060708090a0b0c0d0e0f"
|
|
"101112131415161718191a1b1c1d1e1f"
|
|
"202122232425262728292a2b2c2d2e2f"
|
|
"303132333435363738393a3b3c3d3e3f"
|
|
"404142434445464748494a4b4c4d4e4f"
|
|
"505152535455565758595a5b5c5d5e5f"
|
|
"606162636465666768696a6b6c6d6e6f"
|
|
"707172737475767778797a7b7c7d7e7f"
|
|
"808182838485868788898a8b8c8d8e8f"
|
|
"909192939495969798999a9b9c9d9e9f"
|
|
"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
|
|
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
|
|
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
|
|
"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
|
|
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
|
|
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"};
|
|
static constexpr BYTE DecLookup[] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // gap before first hex digit
|
|
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, 2, 3, 4, 5, 6, 7, 8, 9, // 0123456789
|
|
0, 0, 0, 0, 0, 0, 0, // :;<=>?@ (gap)
|
|
10, 11, 12, 13, 14, 15, // ABCDEF
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // GHIJKLMNOPQRS (gap)
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // TUVWXYZ[/]^_` (gap)
|
|
10, 11, 12, 13, 14, 15 // abcdef
|
|
};
|
|
|
|
std::string CStringUtils::ToHexString(BYTE* pSrc, int nSrcLen)
|
|
{
|
|
WORD* pwHex = (WORD*)HexLookup;
|
|
auto dest = std::make_unique<char[]>((nSrcLen * 2) + 1);
|
|
WORD* pwDest = (WORD*)dest.get();
|
|
for (int j = 0; j < nSrcLen; j++)
|
|
{
|
|
*pwDest = pwHex[*pSrc];
|
|
pwDest++;
|
|
pSrc++;
|
|
}
|
|
*((BYTE*)pwDest) = 0; // terminate the string
|
|
return std::string(dest.get());
|
|
}
|
|
|
|
bool CStringUtils::FromHexString(const std::string& src, BYTE* pDest)
|
|
{
|
|
if (src.size() % 2)
|
|
return false;
|
|
for (auto it = src.cbegin(); it != src.cend(); ++it)
|
|
{
|
|
if ((*it < '0') || (*it > 'f'))
|
|
return false;
|
|
int d = DecLookup[*it] << 4;
|
|
++it;
|
|
d |= DecLookup[*it];
|
|
*pDest++ = (BYTE)d;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::wstring CStringUtils::ToHexWString(BYTE* pSrc, int nSrcLen)
|
|
{
|
|
std::string s = ToHexString(pSrc, nSrcLen);
|
|
return std::wstring(s.begin(), s.end());
|
|
}
|
|
|
|
std::unique_ptr<char[]> CStringUtils::Decrypt(const char* text)
|
|
{
|
|
DWORD dwLen = 0;
|
|
if (CryptStringToBinaryA(text, (DWORD)strlen(text), CRYPT_STRING_HEX, nullptr, &dwLen, nullptr, nullptr) == FALSE)
|
|
return nullptr;
|
|
|
|
auto strIn = std::make_unique<BYTE[]>(dwLen + 1);
|
|
if (CryptStringToBinaryA(text, (DWORD)strlen(text), CRYPT_STRING_HEX, strIn.get(), &dwLen, nullptr, nullptr) == FALSE)
|
|
return nullptr;
|
|
|
|
DATA_BLOB blobin;
|
|
blobin.cbData = dwLen;
|
|
blobin.pbData = strIn.get();
|
|
LPWSTR descr = nullptr;
|
|
DATA_BLOB blobout = {0};
|
|
if (CryptUnprotectData(&blobin, &descr, nullptr, nullptr, nullptr, CRYPTPROTECT_UI_FORBIDDEN, &blobout) == FALSE)
|
|
return nullptr;
|
|
SecureZeroMemory(blobin.pbData, blobin.cbData);
|
|
|
|
auto result = std::make_unique<char[]>(blobout.cbData + 1);
|
|
strncpy_s(result.get(), blobout.cbData + 1, (const char*)blobout.pbData, blobout.cbData);
|
|
SecureZeroMemory(blobout.pbData, blobout.cbData);
|
|
LocalFree(blobout.pbData);
|
|
LocalFree(descr);
|
|
return result;
|
|
}
|
|
|
|
std::unique_ptr<wchar_t[]> CStringUtils::Decrypt(const wchar_t* text)
|
|
{
|
|
DWORD dwLen = 0;
|
|
if (CryptStringToBinaryW(text, (DWORD)wcslen(text), CRYPT_STRING_HEX, nullptr, &dwLen, nullptr, nullptr) == FALSE)
|
|
return nullptr;
|
|
|
|
auto strIn = std::make_unique<BYTE[]>(dwLen + 1);
|
|
if (CryptStringToBinaryW(text, (DWORD)wcslen(text), CRYPT_STRING_HEX, strIn.get(), &dwLen, nullptr, nullptr) == FALSE)
|
|
return nullptr;
|
|
|
|
DATA_BLOB blobin;
|
|
blobin.cbData = dwLen;
|
|
blobin.pbData = strIn.get();
|
|
LPWSTR descr = nullptr;
|
|
DATA_BLOB blobout = {0};
|
|
if (CryptUnprotectData(&blobin, &descr, nullptr, nullptr, nullptr, CRYPTPROTECT_UI_FORBIDDEN, &blobout) == FALSE)
|
|
return nullptr;
|
|
SecureZeroMemory(blobin.pbData, blobin.cbData);
|
|
|
|
auto result = std::make_unique<wchar_t[]>((blobout.cbData) / sizeof(wchar_t) + 1);
|
|
wcsncpy_s(result.get(), (blobout.cbData) / sizeof(wchar_t) + 1, (const wchar_t*)blobout.pbData, blobout.cbData / sizeof(wchar_t));
|
|
SecureZeroMemory(blobout.pbData, blobout.cbData);
|
|
LocalFree(blobout.pbData);
|
|
LocalFree(descr);
|
|
return result;
|
|
}
|
|
|
|
std::string CStringUtils::Encrypt(const char* text)
|
|
{
|
|
DATA_BLOB blobin = {0};
|
|
DATA_BLOB blobout = {0};
|
|
std::string result;
|
|
|
|
blobin.cbData = (DWORD)strlen(text);
|
|
blobin.pbData = (BYTE*)(LPCSTR)text;
|
|
if (CryptProtectData(&blobin, L"TSVNAuth", nullptr, nullptr, nullptr, CRYPTPROTECT_UI_FORBIDDEN, &blobout) == FALSE)
|
|
return result;
|
|
DWORD dwLen = 0;
|
|
if (CryptBinaryToStringA(blobout.pbData, blobout.cbData, CRYPT_STRING_HEX | CRYPT_STRING_NOCRLF, nullptr, &dwLen) == FALSE)
|
|
return result;
|
|
auto strOut = std::make_unique<char[]>(dwLen + 1);
|
|
if (CryptBinaryToStringA(blobout.pbData, blobout.cbData, CRYPT_STRING_HEX | CRYPT_STRING_NOCRLF, strOut.get(), &dwLen) == FALSE)
|
|
return result;
|
|
LocalFree(blobout.pbData);
|
|
|
|
result = strOut.get();
|
|
|
|
return result;
|
|
}
|
|
|
|
std::wstring CStringUtils::Encrypt(const wchar_t* text)
|
|
{
|
|
DATA_BLOB blobin = {0};
|
|
DATA_BLOB blobout = {0};
|
|
std::wstring result;
|
|
|
|
blobin.cbData = (DWORD)wcslen(text) * sizeof(wchar_t);
|
|
blobin.pbData = (BYTE*)(LPCWSTR)text;
|
|
if (CryptProtectData(&blobin, L"TSVNAuth", nullptr, nullptr, nullptr, CRYPTPROTECT_UI_FORBIDDEN, &blobout) == FALSE)
|
|
return result;
|
|
DWORD dwLen = 0;
|
|
if (CryptBinaryToStringW(blobout.pbData, blobout.cbData, CRYPT_STRING_HEX | CRYPT_STRING_NOCRLF, nullptr, &dwLen) == FALSE)
|
|
return result;
|
|
auto strOut = std::make_unique<wchar_t[]>(dwLen + 1);
|
|
if (CryptBinaryToStringW(blobout.pbData, blobout.cbData, CRYPT_STRING_HEX | CRYPT_STRING_NOCRLF, strOut.get(), &dwLen) == FALSE)
|
|
return result;
|
|
LocalFree(blobout.pbData);
|
|
|
|
result = strOut.get();
|
|
|
|
return result;
|
|
}
|
|
|
|
std::wstring CStringUtils::Format(const wchar_t* frmt, ...)
|
|
{
|
|
std::wstring buffer;
|
|
if (frmt != nullptr)
|
|
{
|
|
va_list marker;
|
|
|
|
va_start(marker, frmt);
|
|
|
|
// Get formatted string length adding one for the NUL
|
|
auto len = _vscwprintf(frmt, marker);
|
|
if (len > 0)
|
|
{
|
|
buffer.resize(len + 1);
|
|
_vsnwprintf_s(&buffer[0], buffer.size(), len, frmt, marker);
|
|
buffer.resize(len);
|
|
}
|
|
|
|
va_end(marker);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
std::string CStringUtils::Format(const char* frmt, ...)
|
|
{
|
|
std::string buffer;
|
|
if (frmt != nullptr)
|
|
{
|
|
va_list marker;
|
|
|
|
va_start(marker, frmt);
|
|
|
|
// Get formatted string length adding one for the NUL
|
|
auto len = _vscprintf(frmt, marker);
|
|
if (len > 0)
|
|
{
|
|
buffer.resize(len + 1);
|
|
_vsnprintf_s(&buffer[0], buffer.size(), len, frmt, marker);
|
|
buffer.resize(len);
|
|
}
|
|
|
|
va_end(marker);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
bool WriteAsciiStringToClipboard(const wchar_t* sClipdata, HWND hOwningWnd)
|
|
{
|
|
if (OpenClipboard(hOwningWnd))
|
|
{
|
|
OnOutOfScope(
|
|
CloseClipboard(););
|
|
EmptyClipboard();
|
|
size_t sLen = wcslen(sClipdata);
|
|
HGLOBAL hClipboardData = GlobalAlloc(GMEM_DDESHARE, (sLen + 1) * sizeof(wchar_t));
|
|
if (hClipboardData)
|
|
{
|
|
wchar_t* pchData = (wchar_t*)GlobalLock(hClipboardData);
|
|
if (pchData)
|
|
{
|
|
wcscpy_s(pchData, sLen + 1, sClipdata);
|
|
if (GlobalUnlock(hClipboardData))
|
|
{
|
|
if (SetClipboardData(CF_UNICODETEXT, hClipboardData) == nullptr)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void SearchReplace(std::wstring& str, const std::wstring& toreplace, const std::wstring& replacewith)
|
|
{
|
|
std::wstring result;
|
|
std::wstring::size_type pos = 0;
|
|
for (;;)
|
|
{
|
|
std::wstring::size_type next = str.find(toreplace, pos);
|
|
result.append(str, pos, next - pos);
|
|
if (next != std::wstring::npos)
|
|
{
|
|
result.append(replacewith);
|
|
pos = next + toreplace.size();
|
|
}
|
|
else
|
|
{
|
|
break; // exit loop
|
|
}
|
|
}
|
|
str = std::move(result);
|
|
}
|
|
|
|
void SearchReplace(std::string& str, const std::string& toreplace, const std::string& replacewith)
|
|
{
|
|
std::string result;
|
|
std::string::size_type pos = 0;
|
|
for (;;)
|
|
{
|
|
std::string::size_type next = str.find(toreplace, pos);
|
|
result.append(str, pos, next - pos);
|
|
if (next != std::string::npos)
|
|
{
|
|
result.append(replacewith);
|
|
pos = next + toreplace.size();
|
|
}
|
|
else
|
|
{
|
|
break; // exit loop
|
|
}
|
|
}
|
|
str = std::move(result);
|
|
}
|
|
|
|
void SearchRemoveAll(std::string& str, const std::string& toremove)
|
|
{
|
|
std::string::size_type pos = 0;
|
|
for (;;)
|
|
{
|
|
auto nextpos = str.find(toremove, pos);
|
|
if (nextpos == std::string::npos)
|
|
break;
|
|
str.erase(nextpos, toremove.length());
|
|
pos = nextpos;
|
|
}
|
|
}
|
|
|
|
void SearchRemoveAll(std::wstring& str, const std::wstring& toremove)
|
|
{
|
|
std::wstring::size_type pos = 0;
|
|
for (;;)
|
|
{
|
|
auto nextpos = str.find(toremove, pos);
|
|
if (nextpos == std::wstring::npos)
|
|
break;
|
|
str.erase(nextpos, toremove.length());
|
|
pos = nextpos;
|
|
}
|
|
}
|