strutil.cpp
来自「一款密码保险箱源码」· C++ 代码 · 共 578 行
CPP
578 行
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2007 Dominik Reichl <dominik.reichl@t-online.de>
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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "StdAfx.h"
#include "StrUtil.h"
#include "AppUtil.h"
#include "MemUtil.h"
// Securely erase a CString object
void EraseCString(CString *pString)
{
ASSERT(pString != NULL); if(pString == NULL) return;
const int nBufLen = pString->GetLength();
if(nBufLen <= 0) return; // Nothing to clear
LPTSTR lpt = pString->GetBuffer(0);
for(int j = 0; j < nBufLen; ++j)
lpt[j] = (TCHAR)0;
pString->ReleaseBuffer();
}
void EraseWCharVector(std::vector<WCHAR>& vBuffer)
{
for(DWORD i = 0; i < vBuffer.size(); ++i)
vBuffer[i] = 0;
vBuffer.clear();
}
void EraseTCharVector(std::vector<TCHAR>& vBuffer)
{
for(DWORD i = 0; i < vBuffer.size(); ++i)
vBuffer[i] = 0;
vBuffer.clear();
}
void FixURL(CString *pstrURL)
{
CString strTemp;
BOOL bPre = FALSE;
ASSERT(pstrURL != NULL);
// Load string and make lower
strTemp = *pstrURL;
strTemp.MakeLower();
// If the string begins with one of the following prefixes it is an URL
if(strTemp.Left(5) == _T("http:")) bPre = TRUE;
else if(strTemp.Left(6) == _T("https:")) bPre = TRUE;
else if(strTemp.Left(4) == _T("cmd:")) bPre = TRUE;
else if(strTemp.Left(4) == _T("ftp:")) bPre = TRUE;
else if(strTemp.Left(5) == _T("file:")) bPre = TRUE;
else if(strTemp.Left(7) == _T("gopher:")) bPre = TRUE;
else if(strTemp.Left(7) == _T("mailto:")) bPre = TRUE;
else if(strTemp.Left(5) == _T("news:")) bPre = TRUE;
else if(strTemp.Left(5) == _T("nntp:")) bPre = TRUE;
else if(strTemp.Left(9) == _T("prospero:")) bPre = TRUE;
else if(strTemp.Left(7) == _T("telnet:")) bPre = TRUE;
else if(strTemp.Left(5) == _T("wais:")) bPre = TRUE;
else if(strTemp.Left(4) == _T("irc:")) bPre = TRUE;
else
{
int nIndex = strTemp.Find(_T("://"));
int nNoIndex = strTemp.FindOneOf(_T("/@;: \t\\"));
if((nIndex != -1) && ((nNoIndex == -1) || (nNoIndex >= nIndex))) bPre = TRUE;
}
if(bPre == FALSE) // The string isn't a valid URL, so assume it's a HTTP
{
strTemp = _T("http:");
if(pstrURL->Left(1) != _T("/")) strTemp += _T("//");
strTemp += *pstrURL;
*pstrURL = strTemp;
}
}
void _PwTimeToString(PW_TIME t, CString *pstrDest)
{
CString strFormatted;
_PwTimeToStringEx(t, strFormatted, FALSE);
*pstrDest = strFormatted;
}
void _PwTimeToStringEx(const PW_TIME& t, CString& strDest, BOOL bUseLocalFormat)
{
strDest.Empty();
BOOL bUseIso = FALSE;
if(bUseLocalFormat == TRUE)
{
SYSTEMTIME st;
st.wYear = t.shYear;
st.wMonth = t.btMonth;
st.wDay = t.btDay;
st.wDayOfWeek = 0;
st.wHour = t.btHour;
st.wMinute = t.btMinute;
st.wSecond = t.btSecond;
TCHAR tszBuf[32];
tszBuf[0] = 0; tszBuf[1] = 0;
if(GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL,
tszBuf, 31) == 0)
{
bUseIso = TRUE; ASSERT(FALSE);
}
else strDest += tszBuf;
strDest += _T(" ");
tszBuf[0] = 0; tszBuf[1] = 0;
if(GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, tszBuf, 31) == 0)
{
bUseIso = TRUE; ASSERT(FALSE);
}
else strDest += tszBuf;
}
else bUseIso = TRUE;
if(bUseIso == TRUE)
{
strDest.Format(_T("%04u-%02u-%02u %02u:%02u:%02u"), t.shYear,
t.btMonth, t.btDay, t.btHour, t.btMinute, t.btSecond);
}
}
void _PwTimeToXmlTime(PW_TIME t, CString *pstrDest)
{
ASSERT(pstrDest != NULL);
pstrDest->Empty();
pstrDest->Format(_T("%04u-%02u-%02uT%02u:%02u:%02u"), t.shYear, t.btMonth,
t.btDay, t.btHour, t.btMinute, t.btSecond);
}
void _UuidToString(const BYTE *pUuid, CString *pstrDest)
{
CString strTemp;
ASSERT(pstrDest != NULL);
pstrDest->Empty();
for(int i = 0; i < 16; i++)
{
strTemp.Format(_T("%02x"), pUuid[i]);
*pstrDest += strTemp;
}
}
C_FN_SHARE void _StringToUuid(const TCHAR *ptszSource, BYTE *pUuid)
{
ASSERT((ptszSource != NULL) && (pUuid != NULL));
if((ptszSource == NULL) || (pUuid == NULL)) return;
// Check against invalid UUID
ASSERT(_tcslen(ptszSource) == 32);
if(_tcslen(ptszSource) != 32) return;
TCHAR ch;
BYTE bt;
DWORD i;
for(i = 0; i < 16; i++)
{
ch = ptszSource[i << 1];
if((ch >= _T('0')) && (ch <= _T('9')))
bt = (BYTE)(ch - _T('0'));
else
bt = (BYTE)(ch - _T('a') + 0x0A);
ASSERT(bt < 0x10);
bt <<= 4;
ch = ptszSource[(i << 1) + 1];
if((ch >= _T('0')) && (ch <= _T('9')))
bt |= (BYTE)(ch - _T('0'));
else
bt |= (BYTE)(ch - _T('a') + 0x0A);
pUuid[i] = bt;
}
}
void ParseURL(CString *pString, PW_ENTRY *pEntry, BOOL bMakeSimString, BOOL bCmdQuotes)
{
CString str, strTemp;
int nPos;
ASSERT(pString != NULL); if(pString == NULL) return;
ASSERT_ENTRY(pEntry); if(pEntry == NULL) return;
str = *pString;
while(1)
{
nPos = str.Find(_T("%TITLE%"));
if(nPos == -1) nPos = str.Find(_T("{TITLE}"));
if(nPos == -1) break;
if(bMakeSimString == FALSE)
{
strTemp = pEntry->pszTitle;
if(bCmdQuotes == TRUE) strTemp.Replace(_T("\""), _T("\"\"\""));
str = str.Left(nPos) + strTemp + str.Right(str.GetLength() - nPos - 7);
}
else
str = str.Left(nPos) + TagSimString(pEntry->pszTitle) + str.Right(str.GetLength() - nPos - 7);
}
while(1)
{
nPos = str.Find(_T("%USERNAME%"));
if(nPos == -1) nPos = str.Find(_T("{USERNAME}"));
if(nPos == -1) break;
if(bMakeSimString == FALSE)
{
strTemp = pEntry->pszUserName;
if(bCmdQuotes == TRUE) strTemp.Replace(_T("\""), _T("\"\"\""));
str = str.Left(nPos) + strTemp + str.Right(str.GetLength() - nPos - 10);
}
else
str = str.Left(nPos) + TagSimString(pEntry->pszUserName) + str.Right(str.GetLength() - nPos - 10);
}
while(1)
{
nPos = str.Find(_T("%URL%"));
if(nPos == -1) nPos = str.Find(_T("{URL}"));
if(nPos == -1) break;
if(bMakeSimString == FALSE)
{
strTemp = pEntry->pszURL;
if(bCmdQuotes == TRUE) strTemp.Replace(_T("\""), _T("\"\"\""));
str = str.Left(nPos) + strTemp + str.Right(str.GetLength() - nPos - 5);
}
else
str = str.Left(nPos) + TagSimString(pEntry->pszURL) + str.Right(str.GetLength() - nPos - 5);
}
while(1)
{
nPos = str.Find(_T("%PASSWORD%"));
if(nPos == -1) nPos = str.Find(_T("{PASSWORD}"));
if(nPos == -1) break;
if(bMakeSimString == FALSE)
{
strTemp = pEntry->pszPassword;
if(bCmdQuotes == TRUE) strTemp.Replace(_T("\""), _T("\"\"\""));
str = str.Left(nPos) + strTemp + str.Right(str.GetLength() - nPos - 10);
}
else
str = str.Left(nPos) + TagSimString(pEntry->pszPassword) + str.Right(str.GetLength() - nPos - 10);
}
while(1)
{
nPos = str.Find(_T("%NOTES%"));
if(nPos == -1) nPos = str.Find(_T("{NOTES}"));
if(nPos == -1) break;
if(bMakeSimString == FALSE)
{
strTemp = pEntry->pszAdditional;
strTemp = CsRemoveMeta(&strTemp);
if(bCmdQuotes == TRUE) strTemp.Replace(_T("\""), _T("\"\"\""));
str = str.Left(nPos) + strTemp + str.Right(str.GetLength() - nPos - 7);
EraseCString(&strTemp);
}
else
{
strTemp = pEntry->pszAdditional;
strTemp = CsRemoveMeta(&strTemp);
str = str.Left(nPos) + TagSimString((LPCTSTR)strTemp) + str.Right(str.GetLength() - nPos - 7);
EraseCString(&strTemp);
}
}
while(1)
{
nPos = str.Find(_T("%APPDIR%"));
if(nPos == -1) nPos = str.Find(_T("{APPDIR}"));
if(nPos == -1) break;
TCHAR tszBufP[512];
GetApplicationDirectory(tszBufP, 512 - 1, TRUE, FALSE);
if(bMakeSimString == FALSE)
str = str.Left(nPos) + tszBufP + str.Right(str.GetLength() - nPos - 8);
else
str = str.Left(nPos) + TagSimString(tszBufP) + str.Right(str.GetLength() - nPos - 8);
}
if(bMakeSimString == TRUE)
{
CString strSourceCopy = str;
unsigned char uch;
int i;
EraseCString(&str);
for(nPos = 0; nPos < strSourceCopy.GetLength(); nPos++)
{
uch = (unsigned char)strSourceCopy.GetAt(nPos);
if(uch > 0x7E)
{
str += _T("(%{NUMPAD0}");
strTemp.Format(_T("%u"), uch);
ASSERT(strTemp.GetLength() == 3);
for(i = 0; i < strTemp.GetLength(); i++)
{
str += _T("{NUMPAD");
str += strTemp.GetAt(i);
str += _T("}");
}
str += _T(")");
}
else str += (TCHAR)uch;
}
EraseCString(&strTemp);
}
str.Replace(_T("{CLEARFIELD}"), _T("{DELAY 150}{HOME}(+{END}){DEL}{DELAY 150}"));
*pString = str;
EraseCString(&str);
}
CString CsRemoveMeta(CString *psString)
{
CString str = _T(""), strLower;
int nPos, nCount;
LPCTSTR lpRemove = NULL;
int i;
ASSERT(psString != NULL); if(psString == NULL) return str;
str = *psString;
strLower = str; strLower.MakeLower();
for(i = 0; i < 2; i++)
{
if(i == 0) lpRemove = _T("auto-type:");
else if(i == 1) lpRemove = _T("auto-type-window:");
nPos = strLower.Find(lpRemove, 0);
if(nPos != -1)
{
if(nPos != 0)
if(strLower.GetAt(nPos - 1) == _T('\n')) nPos -= 1;
if(nPos != 0)
if(strLower.GetAt(nPos - 1) == _T('\r')) nPos -= 1;
nCount = strLower.Find(_T('\n'), (int)(nPos + _tcslen(lpRemove) - 1));
if(nCount == -1) nCount = strLower.GetLength() - nPos;
else nCount -= nPos - 1;
strLower.Delete(nPos, nCount);
str.Delete(nPos, nCount);
}
}
return str;
}
CString CsFileOnly(const CString *psFilePath)
{
CString str;
int i, j, k;
ASSERT(psFilePath != NULL); if(psFilePath == NULL) return CString("");
i = psFilePath->ReverseFind(_T('\\'));
j = psFilePath->ReverseFind(_T('/'));
k = (i > j) ? i : j;
if(k <= -1) str = *psFilePath;
else str = psFilePath->Right(psFilePath->GetLength() - k - 1);
return str;
}
#define LOCAL_NUMXMLCONV 7
#pragma warning(push)
#pragma warning(disable: 4996) // _tcscpy deprecated
TCHAR *MakeSafeXmlString(const TCHAR *ptString)
{
size_t i, j;
size_t dwStringLen, dwNeededChars = 0, dwOutPos = 0;
TCHAR tch;
BOOL bFound;
TCHAR *pFinal;
TCHAR aChar[LOCAL_NUMXMLCONV] = {
_T('<'), _T('>'), _T('&'), _T('\"'), _T('\''),
_T('\r'), _T('\n')
};
TCHAR *pTrans[LOCAL_NUMXMLCONV] = {
_T("<"), _T(">"), _T("&"), _T("""), _T("'"),
_T("
"), _T("
")
};
ASSERT(ptString != NULL); if(ptString == NULL) return NULL;
dwStringLen = _tcslen(ptString);
for(i = 0; i < dwStringLen; i++)
{
tch = ptString[i];
bFound = FALSE;
for(j = 0; j < LOCAL_NUMXMLCONV; j++)
{
if(tch == aChar[j])
{
dwNeededChars += _tcslen(pTrans[j]);
bFound = TRUE;
}
}
if(bFound == FALSE) dwNeededChars++;
}
pFinal = new TCHAR[dwNeededChars + 4];
ASSERT(pFinal != NULL); if(pFinal == NULL) return NULL;
for(i = 0; i < dwStringLen; i++)
{
tch = ptString[i];
bFound = FALSE;
for(j = 0; j < LOCAL_NUMXMLCONV; j++)
{
if(tch == aChar[j])
{
_tcscpy(&pFinal[dwOutPos], pTrans[j]);
dwOutPos += _tcslen(pTrans[j]);
bFound = TRUE;
}
}
if(bFound == FALSE)
{
pFinal[dwOutPos] = tch;
dwOutPos++;
}
}
ASSERT(dwOutPos == dwNeededChars);
pFinal[dwOutPos] = 0; pFinal[dwOutPos + 1] = 0;
ASSERT(_tcslen(pFinal) == dwNeededChars);
return pFinal;
}
char *szcpy(char *szDestination, const char *szSource)
{
ASSERT(szDestination != NULL); if(szDestination == NULL) return NULL;
ASSERT(szSource != NULL); if(szSource == NULL) { szDestination[0] = 0; return szDestination; }
return strcpy(szDestination, szSource);
}
#pragma warning(pop) // _tcscpy / strcpy deprecated
DWORD szlen(const char *pszString)
{
ASSERT(pszString != NULL); if(pszString == NULL) return 0;
return static_cast<DWORD>(strlen(pszString));
}
// Extracts a substring from the lpstr string
// Example: to extract the auto-type command, pass "auto-type:" in lpStart
CString ExtractParameterFromString(LPCTSTR lpstr, LPCTSTR lpStart,
DWORD dwInstance)
{
TCHAR *lp;
TCHAR tch;
CString str = _T("");
int nPos = -1, nSearchFrom = 0;
ASSERT(lpstr != NULL); if(lpstr == NULL) return str; // _T("")
CString strSource = lpstr;
strSource.MakeLower();
lp = (TCHAR *)lpstr;
// nPos = strSource.Find(lpStart, 0);
while(dwInstance != DWORD_MAX)
{
nPos = strSource.Find(lpStart, nSearchFrom);
if(nPos != -1) nSearchFrom = nPos + 1;
else return str; // _T("")
dwInstance--;
}
if(nPos != -1)
{
lp += _tcslen(lpStart);
lp += nPos;
while(1)
{
tch = *lp;
if(tch == '\0') break;
else if(tch == '\n') break;
else if(tch == '\r') { }
else str += tch;
lp++;
}
}
str.TrimLeft(); str.TrimRight();
return str;
}
CString TagSimString(LPCTSTR lpString)
{
int i;
CString str = _T("");
TCHAR tch;
ASSERT(lpString != NULL); if(lpString == NULL) return str;
for(i = 0; i < (int)_tcslen(lpString); i++)
{
tch = lpString[i];
switch(tch)
{
case _T('+'): str += _T("{PLUS}"); break;
case _T('@'): str += _T("{AT}"); break;
// case _T('~'): str += _T("{TILDE}"); break;
case _T('~'): str += _T("(%{NUMPAD0}{NUMPAD1}{NUMPAD2}{NUMPAD6})"); break;
case _T('^'): str += _T("(%{NUMPAD0}{NUMPAD9}{NUMPAD4})"); break;
case _T('\''): str += _T("(%{NUMPAD0}{NUMPAD3}{NUMPAD9})"); break;
case _T('"'): str += _T("(%{NUMPAD0}{NUMPAD3}{NUMPAD4})"); break;
case _T('
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?