bool CPasswordCharPool::CheckPassword(const StringX &pwd, StringX &error) { /** * A password is "Good enough" if: * It is at least SufficientLength characters long * OR * It is at least MinLength characters long AND it has * at least one uppercase and one lowercase and one (digit or other). * * A future enhancement of this might be to calculate the Shannon Entropy * in combination with a minimum password length. * http://rosettacode.org/wiki/Entropy */ const size_t SufficientLength = 12; const size_t MinLength = 8; if (pwd.length() >= SufficientLength) { return true; } if (pwd.length() < MinLength) { LoadAString(error, IDSC_PASSWORDTOOSHORT); return false; } if (CheckPasswordClasses(pwd)) { return true; } else { LoadAString(error, IDSC_PASSWORDPOOR); return false; } }
void CItemField::Set(const StringX &value, Fish *bf) { const LPCTSTR plainstr = value.c_str(); Set(reinterpret_cast<const unsigned char *>(plainstr), value.length() * sizeof(*plainstr), bf); }
StringX CPasswordCharPool::MakePassword() const { // We don't care if the policy is inconsistent e.g. // number of lower case chars > 1 + make pronouceable // The individual routines (normal, hex, pronouceable) will // ignore what they don't need. // Saves an awful amount of bother with setting values to zero and // back as the user changes their minds! ASSERT(m_pwlen > 0); if (m_pronounceable) return MakePronounceable(); StringX password; bool hasalpha, hasdigit; do { hasalpha = !m_uselowercase && !m_useuppercase; // prevent infinite loop hasdigit = !m_usedigits; charT ch; password.assign(_T("")); for (uint i = 0; i < m_pwlen; i++) { ch = GetRandomChar(); password += ch; if (_istalpha(ch)) hasalpha = true; if (_istdigit(ch)) hasdigit = true; } if (m_pwlen <= 4) break; } while(!hasalpha || !hasdigit); ASSERT(password.length() == size_t(m_pwlen)); return password; };
// XXX taken from Windows PWSTreeCtrl.cpp // XXX move to core static StringX GetPathElem(StringX &sxPath) { // Get first path element and chop it off, i.e., if // path = "a.b.c.d" // will return "a" and path will be "b.c.d" // path = "a..b.c.d" // will return "a." and path will be "b.c.d" // (assuming GROUP_SEP is '.') StringX sxElement; size_t dotPos = sxPath.find_first_of(GROUP_SEP); size_t len=sxPath.length(); if (dotPos == StringX::npos){ sxElement = sxPath; sxPath = wxT(""); } else { while ((dotPos < len) && (sxPath[dotPos] == GROUP_SEP)) {// look for consecutive dots dotPos++; } if (dotPos < len) { sxElement = sxPath.substr(0, dotPos-1); sxPath = sxPath.substr(dotPos); } else { // trailing dots sxElement = sxPath; sxPath = wxT(""); } } return sxElement; }
size_t PWSfileV1V2::WriteCBC(unsigned char type, const StringX &data) { #ifndef UNICODE const unsigned char *datastr = (const unsigned char *)data.c_str(); return PWSfile::WriteCBC(type, datastr, data.length()); #else wchar_t *wcPtr = const_cast<wchar_t *>(data.c_str()); size_t wcLen = data.length() + 1; size_t mbLen = 3 * wcLen; unsigned char *acp = new unsigned char[mbLen]; size_t acpLen = pws_os::wcstombs(reinterpret_cast<char *>(acp), mbLen, wcPtr, wcLen, false); ASSERT(acpLen != 0); acpLen--; // remove unneeded null termination size_t retval = PWSfile::WriteCBC(type, acp, acpLen); trashMemory(acp, mbLen); delete[] acp; return retval; #endif }
pws_os::CUUID::CUUID(const StringX &s) : m_ua(NULL), m_canonic(false) { // s is a hex string as returned by cast to StringX ASSERT(s.length() == 32); unsigned char *uu = m_uuid; int x; for (int i = 0; i < 16; i++) { iStringXStream is(s.substr(i*2, 2)); is >> hex >> x; uu[i] = static_cast<unsigned char>(x); } }
pws_os::CUUID::CUUID(const StringX &s) : m_ua(NULL), m_canonic(false) { // s is a hex string as returned by cast to StringX ASSERT(s.length() == 32); uuid_array_t ua; unsigned int x(0); for (size_t i = 0; i < 16; i++) { iStringXStream is(s.substr(i * 2, 2)); is >> hex >> x; ua[i] = static_cast<unsigned char>(x); } array2UUUID(ua, m_uuid); }
bool CPasswordCharPool::CheckPassword(const StringX &pwd, StringX &error) { /** * A password is "Good enough" if: * It is at least SufficientLength characters long * OR * It is at least MinLength characters long AND it has * at least one uppercase and one lowercase and one (digit or other). * * A future enhancement of this might be to calculate the Shannon Entropy * in combination with a minimum password length. * http://rosettacode.org/wiki/Entropy */ const size_t SufficientLength = 12; const size_t MinLength = 8; const size_t length = pwd.length(); if (length >= SufficientLength) { return true; } if (length < MinLength) { LoadAString(error, IDSC_PASSWORDTOOSHORT); return false; } // check for at least one uppercase and lowercase and one (digit or other) bool has_uc = false, has_lc = false, has_digit = false, has_other = false; for (size_t i = 0; i < length; i++) { charT c = pwd[i]; if (_istlower(c)) has_lc = true; else if (_istupper(c)) has_uc = true; else if (_istdigit(c)) has_digit = true; else has_other = true; } if (has_uc && has_lc && (has_digit || has_other)) { return true; } else { LoadAString(error, IDSC_PASSWORDPOOR); return false; } }
bool CPasswordCharPool::CheckPasswordClasses(const StringX &pwd) { // check for at least one uppercase and lowercase and one (digit or other) bool has_uc = false, has_lc = false, has_digit = false, has_other = false; for (size_t i = 0; i < pwd.length(); i++) { charT c = pwd[i]; if (_istlower(c)) has_lc = true; else if (_istupper(c)) has_uc = true; else if (_istdigit(c)) has_digit = true; else has_other = true; } if (has_uc && has_lc && (has_digit || has_other)) { return true; } else { return false; } }
/** * Put text data to clipboard * @param[in] data data to store in clipboard * @param isSensitive if data sensitive, we remember its hash and will clear on ClearCBData() call * @return \c true, if we could open the clipboard and put the data */ bool PWSclipboard::SetData(const StringX &data) { wxMutexLocker clip(m_clipboardMutex); bool res = false; if (wxTheClipboard->Open()) { res = wxTheClipboard->SetData(new wxTextDataObject(data.c_str())); wxTheClipboard->Close(); } m_set = true; if (res) { // identify data in clipboard as ours, so as not to clear the wrong data later // of course, we don't want an extra copy of a password floating around // in memory, so we'll use the hash SHA256 ctx; const wchar_t *str = data.c_str(); ctx.Update(reinterpret_cast<const unsigned char *>(str), data.length()*sizeof(wchar_t)); ctx.Final(m_digest); } return res; }
bool CUTF8Conv::ToUTF8(const StringX &data, const unsigned char *&utf8, size_t &utf8Len) { // If we're not in Unicode, call MultiByteToWideChar to get from // current codepage to Unicode, and then WideCharToMultiByte to // get to UTF-8 encoding. if (data.empty()) { utf8Len = 0; return true; } wchar_t *wcPtr = const_cast<wchar_t *>(data.c_str()); size_t wcLen = data.length()+1; // first get needed utf8 buffer size size_t mbLen = pws_os::wcstombs(NULL, 0, wcPtr, wcLen); if (mbLen == 0) { // uh-oh ASSERT(0); m_utf8Len = 0; return false; } // Allocate buffer (if previous allocation was smaller) if (mbLen > m_utf8MaxLen) { if (m_utf8 != NULL) trashMemory(m_utf8, m_utf8MaxLen); delete[] m_utf8; m_utf8 = new unsigned char[mbLen]; m_utf8MaxLen = mbLen; } // Finally get result m_utf8Len = pws_os::wcstombs(reinterpret_cast<char *>(m_utf8), mbLen, wcPtr, wcLen); ASSERT(m_utf8Len != 0); m_utf8Len--; // remove unneeded null termination utf8 = m_utf8; utf8Len = m_utf8Len; return true; }
bool XFilterXMLProcessor::Process(const bool &bvalidation, const StringX &strXMLData, const stringT &strXMLFileName, const stringT &strXSDFileName) { USES_XMLCH_STR bool bErrorOccurred = false; stringT cs_validation; LoadAString(cs_validation, IDSC_XMLVALIDATION); stringT cs_import; LoadAString(cs_import, IDSC_XMLIMPORT); stringT strResultText(_T("")); m_bValidation = bvalidation; // Validate or Import XSecMemMgr sec_mm; // Initialize the XML4C2 system try { XMLPlatformUtils::Initialize(XMLUni::fgXercescDefaultLocale, 0, 0, &sec_mm); } catch (const XMLException& toCatch) { #ifdef UNICODE m_strXMLErrors = stringT(_X2ST(toCatch.getMessage())); #else char *szData = XMLString::transcode(toCatch.getMessage()); strResultText = stringT(szData); XMLString::release(&szData); #endif return false; } // Create a SAX2 parser object. SAX2XMLReader* pSAX2Parser = XMLReaderFactory::createXMLReader(&sec_mm); // Set non-default features pSAX2Parser->setFeature(XMLUni::fgSAX2CoreNameSpacePrefixes, true); pSAX2Parser->setFeature(XMLUni::fgSAX2CoreValidation, true); pSAX2Parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); pSAX2Parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false); pSAX2Parser->setFeature(XMLUni::fgXercesSkipDTDValidation, true); // Set properties pSAX2Parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, (void *)strXSDFileName.c_str()); pSAX2Parser->setProperty(XMLUni::fgXercesScannerName, (void *)XMLUni::fgSGXMLScanner); pSAX2Parser->setInputBufferSize(4096); // Create SAX handler object and install it on the pSAX2Parser, as the // document and error pSAX2Handler. XFilterSAX2Handlers * pSAX2Handler = new XFilterSAX2Handlers; pSAX2Parser->setContentHandler(pSAX2Handler); pSAX2Parser->setErrorHandler(pSAX2Handler); // Workaround/bypass until Xerces supports retrieving version from the // <xs:schema ...> statement! // Set 'dummy' schema version to arbitrary value > 1 pSAX2Handler->SetSchemaVersion(99); pSAX2Handler->SetVariables(m_pAsker, &m_MapFilters, m_FPool, m_bValidation); try { // Let's begin the parsing now if (!strXMLFileName.empty()) { pSAX2Parser->parse(_W2X(strXMLFileName.c_str())); } else { const char *szID = "database_filters"; #ifdef UNICODE const char *buffer = XMLString::transcode(_W2X(strXMLData.c_str())); #else const char *buffer = strXMLData.c_str(); #endif MemBufInputSource* memBufIS = new MemBufInputSource( (const XMLByte*)buffer, strXMLData.length(), szID, false); pSAX2Parser->parse(*memBufIS); delete memBufIS; #ifdef UNICODE XMLString::release((char **)&buffer); #endif } } catch (const OutOfMemoryException&) { LoadAString(strResultText, IDCS_XERCESOUTOFMEMORY); bErrorOccurred = true; } catch (const XMLException& e) { #ifdef UNICODE strResultText = stringT(_X2ST(e.getMessage())); #else char *szData = XMLString::transcode(e.getMessage()); strResultText = stringT(szData); XMLString::release(&szData); #endif bErrorOccurred = true; } catch (...) { LoadAString(strResultText, IDCS_XERCESEXCEPTION); bErrorOccurred = true; } if (pSAX2Handler->getIfErrors() || bErrorOccurred) { bErrorOccurred = true; strResultText = pSAX2Handler->getValidationResult(); Format(m_strXMLErrors, IDSC_XERCESPARSEERROR, m_bValidation ? cs_validation.c_str() : cs_import.c_str(), strResultText.c_str()); } else { m_strXMLErrors = strResultText; } // Delete the pSAX2Parser itself. Must be done prior to calling Terminate, below. delete pSAX2Parser; delete pSAX2Handler; USES_XMLCH_STR_END // And call the termination method XMLPlatformUtils::Terminate(); return !bErrorOccurred; }
/* SaveToDisk creates a new file of name "<tcAction>_Report.txt" e.g. "Merge_Report.txt" in the same directory as the current database or appends to this file if it already exists. */ bool CReport::SaveToDisk() { FILE *fd; stringT path(m_csDataBase); stringT drive, dir, file, ext; if (!pws_os::splitpath(path, drive, dir, file, ext)) { pws_os::IssueError(_T("StartReport: Finding path to database")); return false; } Format(m_cs_filename, IDSC_REPORTFILENAME, drive.c_str(), dir.c_str(), m_tcAction.c_str()); if ((fd = pws_os::FOpen(m_cs_filename, _T("a+b"))) == NULL) { pws_os::IssueError(_T("StartReport: Opening log file")); return false; } // **** MOST LIKELY ACTION **** // If file is new/emtpy AND we are UNICODE, write BOM, as some text editors insist! // **** LEAST LIKELY ACTIONS as it requires the user to use both U & NU versions **** // Text editors really don't like files with both UNICODE and ASCII characters, so - // If we are UNICODE and file is not, convert file to UNICODE before appending // If we are not UNICODE but file is, convert file to ASCII before appending bool bFileIsUnicode = isFileUnicode(m_cs_filename); #ifdef UNICODE const unsigned int iBOM = 0xFEFF; if (pws_os::fileLength(fd) == 0) { // File is empty - write BOM putwc(iBOM, fd); } else if (!bFileIsUnicode) { // Convert ASCII contents to UNICODE // Close original first fclose(fd); // Open again to read FILE *f_in = pws_os::FOpen(m_cs_filename, _S("rb")); // Open new file stringT cs_out = m_cs_filename + _S(".tmp"); FILE *f_out = pws_os::FOpen(cs_out, _S("wb")); // Write BOM putwc(iBOM, f_out); size_t nBytesRead; unsigned char inbuffer[4096]; wchar_t outwbuffer[4096]; // Now copy do { nBytesRead = fread(inbuffer, sizeof(inbuffer), 1, f_in); if (nBytesRead > 0) { size_t len = pws_os::mbstowcs(outwbuffer, 4096, reinterpret_cast<const char *>(inbuffer), nBytesRead); if (len != 0) fwrite(outwbuffer, sizeof(outwbuffer[0])*len, 1, f_out); } else break; } while(nBytesRead > 0); // Close files fclose(f_in); fclose(f_out); // Swap them pws_os::RenameFile(cs_out, m_cs_filename); // Re-open file if ((fd = pws_os::FOpen(m_cs_filename, _S("ab"))) == NULL) { pws_os::IssueError(_T("StartReport: Opening log file")); return false; } } #else if (bFileIsUnicode) { // Convert UNICODE contents to ASCII // Close original first fclose(fd); // Open again to read FILE *f_in = pws_os::FOpen(m_cs_filename, "rb"); // Open new file stringT cs_out = m_cs_filename + _T(".tmp"); FILE *f_out = pws_os::FOpen(cs_out, "wb"); UINT nBytesRead; WCHAR inwbuffer[4096]; unsigned char outbuffer[4096]; // Skip over BOM fseek(f_in, 2, SEEK_SET); // Now copy do { nBytesRead = fread(inwbuffer, sizeof(inwbuffer), 1, f_in); if (nBytesRead > 0) { size_t len = pws_os::wcstombs((char *)outbuffer, 4096, inwbuffer, nBytesRead); if (len != 0) fwrite(outbuffer, len, 1, f_out); } else break; } while(nBytesRead > 0); // Close files fclose(f_in); fclose(f_out); // Swap them pws_os::RenameFile(cs_out, m_cs_filename); // Re-open file if ((fd = pws_os::FOpen(m_cs_filename, _S("ab"))) == NULL) { pws_os::IssueError(_T("StartReport: Opening log file")); return false; } } #endif // Convert LF to CRLF StringX sxCRLF(L"\r\n"), sxLF(L"\n"); StringX sx = m_osxs.rdbuf()->str(); Replace(sx, sxCRLF, sxLF); Replace(sx, sxLF, sxCRLF); fwrite(reinterpret_cast<const void *>(sx.c_str()), sizeof(BYTE), sx.length() * sizeof(TCHAR), fd); fclose(fd); return true; }
//----------------------------------------------------------------- // Internal functions //----------------------------------------------------------------- static UINT ParseRunCommand(const StringX &sxInputString, std::vector<st_RunCommandTokens> &v_rctokens, bool &bDoAutoType, StringX &sxAutoType, stringT &serrmsg, StringX::size_type &st_column) { // tokenize into separate elements std::vector<st_RunCommandTokens>::iterator rc_iter; std::vector<size_t> v_pos; StringX::iterator str_Iter; st_RunCommandTokens st_rctoken; size_t st_num_quotes(0); UINT uierr(0); int var_index(0); const stringT alphanum = _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); if (sxInputString.empty()) { // String is empty! uierr = IDSC_EXS_INPUTEMPTY; goto exit; } for (StringX::size_type l = 0; l < sxInputString.length(); l++) { if (sxInputString[l] == _T('"')) st_num_quotes++; } if (st_num_quotes % 2 != 0) { st_column = sxInputString.find(_T('"')); // Unmatched quotes uierr = IDSC_EXS_UNMATCHEDQUOTES; goto exit; } // tokenize into separate elements using $ as the field separator for (StringX::size_type st_startpos = 0; st_startpos < sxInputString.size(); /* st_startpos advanced in body */) { StringX::size_type st_next = sxInputString.find(_T('$'), st_startpos); if (st_next == StringX::npos) st_next = sxInputString.size(); if (st_next > 0) { st_rctoken.sxname = sxInputString.substr(st_startpos, st_next - st_startpos); st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = st_startpos == 0 ? false : true; st_rctoken.has_brackets = false; v_rctokens.push_back(st_rctoken); v_pos.push_back(st_startpos); } st_startpos = st_next + 1; // too complex for for statement } // tokenization for loop // Check if escaped - ending character of previous token == '\' // Make sure this '\' is not escaped itself! for (size_t st_idx = v_rctokens.size() - 1; st_idx > 0 ; st_idx--) { st_RunCommandTokens &st_rctokens = v_rctokens[st_idx - 1]; StringX::size_type name_len = st_rctokens.sxname.length(); if (name_len == 0 || (name_len >= 2 && st_rctokens.sxname.substr(name_len - 2, 2).compare(_T("\\\\")) == 0)) continue; if (st_rctokens.sxname.substr(name_len - 1, 1).compare(_T("\\")) == 0) { st_rctokens.sxname = st_rctokens.sxname.substr(0, name_len - 1) + _T("$") + v_rctokens[st_idx].sxname; v_rctokens.erase(v_rctokens.begin() + st_idx); } } // Check if variable enclosed in curly brackets for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (v_rctokens[st_idx].sxname.length() == 0) continue; str_Iter = v_rctokens[st_idx].sxname.begin(); // Does it start with a curly bracket? if (*str_Iter == _T('{')) { v_rctokens[st_idx].has_brackets = true; StringX sxvar, sxnonvar, sxindex(_T("")); // Yes - Find end curly bracket StringX::size_type st_end_cb = v_rctokens[st_idx].sxname.find(_T('}')); if (st_end_cb == StringX::npos) { st_column = v_pos[st_idx] + v_rctokens[st_idx].sxname.length(); // Missing end curly bracket uierr = IDSC_EXS_MISSINGCURLYBKT; goto exit; } // Now see if there is an Index here StringX::size_type st_start_sb = v_rctokens[st_idx].sxname.find(_T('[')); if (st_start_sb != StringX::npos) { // Yes - find end square bracket if (st_start_sb > st_end_cb) { // Square backet after end of variable sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); v_rctokens[st_idx].sxname = sxvar; if (sxnonvar.length() > 0) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb); } continue; } StringX::size_type st_end_sb = v_rctokens[st_idx].sxname.find(_T(']'), st_start_sb); if (st_end_sb == StringX::npos) { st_column = v_pos[st_idx] + 1; // Missing end square bracket uierr = IDSC_EXS_MISSINGSQUAREBKT; goto exit; } // The end-curly backet must immediately follow the end-square bracket if (st_end_cb != st_end_sb + 1) { st_column = v_pos[st_idx] + st_end_sb + 1; // Characters between ']' and ')' uierr = IDSC_EXS_INVALIDBRACKETS; goto exit; } sxindex = v_rctokens[st_idx].sxname.substr(st_start_sb + 1, st_end_sb - st_start_sb - 1); v_rctokens[st_idx].sxindex = sxindex; // Now check index uierr = ProcessIndex(sxindex, var_index, st_column); if (uierr > 0) { st_column += v_pos[st_idx]; goto exit; } v_rctokens[st_idx].index = var_index; sxvar = v_rctokens[st_idx].sxname.substr(1, st_start_sb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); } else { // No square bracket // Split current token into 'variable' and 'non-variable' parts sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); } v_rctokens[st_idx].sxname = sxvar; if (sxnonvar.length() > 0) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb); } } } // Now use rules of variables to get the real variable for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (!v_rctokens[st_idx].is_variable) continue; if (v_rctokens[st_idx].sxname.length() == 0) { st_column = v_pos[st_idx]; // Variable name is empty uierr = IDSC_EXS_VARNAMEEMPTY; goto exit; } str_Iter = v_rctokens[st_idx].sxname.begin(); if (!isalpha(*str_Iter)) { st_column = v_pos[st_idx]; // First character of variable is not alphabetic uierr = IDSC_EXS_FIRSTNOTALPHA; goto exit; } StringX::size_type st_next = v_rctokens[st_idx].sxname.find_first_not_of(alphanum.c_str()); if (st_next != StringX::npos) { // Split current token into 'variable' and 'non-variable' parts StringX sxvar = v_rctokens[st_idx].sxname.substr(0, st_next); StringX sxnonvar = v_rctokens[st_idx].sxname.substr(st_next); v_rctokens[st_idx].sxname = sxvar; // Before saving non-variable part - check if it is an Index e.g. var[i] if (sxnonvar.c_str()[0] == _T('[')) { // Find ending square bracket StringX::size_type st_end_sb = sxnonvar.find(_T(']')); if (st_end_sb == StringX::npos) { st_column = v_pos[st_idx] + sxvar.length() + 2; // Missing end square bracket uierr = IDSC_EXS_MISSINGSQUAREBKT; goto exit; } StringX sxindex = sxnonvar.substr(1, st_end_sb - 1); v_rctokens[st_idx].sxindex = sxindex; // Now check index uierr = ProcessIndex(sxindex, var_index, st_column); if (uierr > 0) { st_column += v_pos[st_idx] + sxvar.length(); goto exit; } v_rctokens[st_idx].index = var_index; sxnonvar = sxnonvar.substr(st_end_sb + 1); } else { // Not a square bracket if (v_rctokens[st_idx].has_brackets) { st_column = v_pos[st_idx] + st_next + 1; // Variable must be alphanumeric uierr = IDSC_EXS_VARNAMEINVALID; goto exit; } } if (!sxnonvar.empty()) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_next); } } } // Special Autotype processing bDoAutoType = false; sxAutoType = _T(""); for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (!v_rctokens[st_idx].is_variable) continue; // Is it a autotype variable? if (v_rctokens[st_idx].sxname == _T("a") || v_rctokens[st_idx].sxname == _T("autotype")) { bDoAutoType = true; // Is the next token text and starts with '('? if (st_idx + 1 < v_rctokens.size() && !v_rctokens[st_idx + 1].is_variable && v_rctokens[st_idx + 1].sxname.c_str()[0] == _T('(')) { // Find ending round bracket StringX sx_autotype = v_rctokens[st_idx + 1].sxname; StringX::size_type st_end_rb = sx_autotype.find(_T(')')); if (st_end_rb == StringX::npos) { st_column = v_pos[st_idx + 1] + sx_autotype.length() + 2; // Missing end round bracket uierr = IDSC_EXS_MISSINGROUNDBKT; goto exit; } sxAutoType = sx_autotype.substr(1, st_end_rb - 1); v_rctokens[st_idx + 1].sxname = sx_autotype.substr(st_end_rb + 1); // Check if anything left in this text - none -> delete if (v_rctokens[st_idx + 1].sxname.length() == 0) v_rctokens.erase(v_rctokens.begin() + st_idx + 1); // Now delete Autotype variable v_rctokens.erase(v_rctokens.begin() + st_idx); break; } } } exit: if (uierr != 0) LoadAString(serrmsg, uierr); else serrmsg = _T(""); if (uierr > 0) { v_rctokens.clear(); } v_pos.clear(); return uierr; }
bool CUTF8Conv::ToUTF8(const StringX &data, const unsigned char *&utf8, size_t &utf8Len) { // If we're not in Unicode, call MultiByteToWideChar to get from // current codepage to Unicode, and then WideCharToMultiByte to // get to UTF-8 encoding. if (data.empty()) { utf8Len = 0; return true; } wchar_t *wcPtr; // to hide UNICODE differences size_t wcLen; // number of wide chars needed #ifndef UNICODE // first get needed wide char buffer size wcLen = pws_os::mbstowcs(NULL, 0, data.c_str(), size_t(-1), false); if (wcLen == 0) { // uh-oh ASSERT(0); m_utf8Len = 0; return false; } // Allocate buffer (if previous allocation was smaller) if (wcLen > m_wcMaxLen) { if (m_wc != NULL) trashMemory(m_wc, m_wcMaxLen * sizeof(m_wc[0])); delete[] m_wc; m_wc = new wchar_t[wcLen]; m_wcMaxLen = wcLen; } // next translate to buffer wcLen = pws_os::mbstowcs(m_wc, wcLen, data.c_str(), size_t(-1), false); ASSERT(wcLen != 0); wcPtr = m_wc; #else wcPtr = const_cast<wchar_t *>(data.c_str()); wcLen = data.length()+1; #endif // first get needed utf8 buffer size size_t mbLen = pws_os::wcstombs(NULL, 0, wcPtr, wcLen); if (mbLen == 0) { // uh-oh ASSERT(0); m_utf8Len = 0; return false; } // Allocate buffer (if previous allocation was smaller) if (mbLen > m_utf8MaxLen) { if (m_utf8 != NULL) trashMemory(m_utf8, m_utf8MaxLen); delete[] m_utf8; m_utf8 = new unsigned char[mbLen]; m_utf8MaxLen = mbLen; } // Finally get result m_utf8Len = pws_os::wcstombs(reinterpret_cast<char *>(m_utf8), mbLen, wcPtr, wcLen); ASSERT(m_utf8Len != 0); m_utf8Len--; // remove unneeded null termination utf8 = m_utf8; utf8Len = m_utf8Len; return true; }
int PWSfileV1V2::Open(const StringX &passkey) { int status = SUCCESS; ASSERT(m_curversion == V17 || m_curversion == V20); m_passkey = passkey; FOpen(); if (m_fd == NULL) return CANT_OPEN_FILE; LPCTSTR passstr = m_passkey.c_str(); size_t passLen = passkey.length(); unsigned char *pstr; #ifdef UNICODE size_t pstr_len = 3 * passLen; pstr = new unsigned char[pstr_len]; size_t len = pws_os::wcstombs(reinterpret_cast<char *>(pstr), 3 * passLen, passstr, passLen, false); ASSERT(len != 0); // hack around OS-dependent semantics - too widespread to fix systematically :-( pstr[len < pstr_len ? len : pstr_len - 1] = '\0'; passLen = strlen(reinterpret_cast<const char *>(pstr)); #else pstr = reinterpret_cast<unsigned char *>(passstr); #endif if (m_rw == Write) { // Following used to verify passkey against file's passkey unsigned char randstuff[StuffSize]; unsigned char randhash[20]; // HashSize PWSrand::GetInstance()->GetRandomData( randstuff, 8 ); randstuff[8] = randstuff[9] = TCHAR('\0'); GenRandhash(m_passkey, randstuff, randhash); SAFE_FWRITE(randstuff, 1, 8, m_fd); SAFE_FWRITE(randhash, 1, 20, m_fd); PWSrand::GetInstance()->GetRandomData(m_salt, SaltLength); SAFE_FWRITE(m_salt, 1, SaltLength, m_fd); PWSrand::GetInstance()->GetRandomData( m_ipthing, 8); SAFE_FWRITE(m_ipthing, 1, 8, m_fd); m_fish = BlowFish::MakeBlowFish(pstr, reinterpret_cast<int &>(passLen), m_salt, SaltLength); if (m_curversion == V20) { status = WriteV2Header(); } } else { // open for read status = CheckPasskey(m_filename, m_passkey, m_fd); if (status != SUCCESS) { #ifdef UNICODE trashMemory(pstr, pstr_len); delete[] pstr; #endif Close(); return status; } fread(m_salt, 1, SaltLength, m_fd); fread(m_ipthing, 1, 8, m_fd); m_fish = BlowFish::MakeBlowFish(pstr, reinterpret_cast<int &>(passLen), m_salt, SaltLength); if (m_curversion == V20) status = ReadV2Header(); } // read mode exit: if (status != SUCCESS) Close(); #ifdef UNICODE trashMemory(pstr, pstr_len); delete[] pstr; #endif return status; }
StringX CPasswordCharPool::MakePassword() const { // We don't care if the policy is inconsistent e.g. // number of lower case chars > 1 + make pronounceable // The individual routines (normal, hex, pronounceable) will // ignore what they don't need. // Saves an awful amount of bother with setting values to zero and // back as the user changes their minds! ASSERT(m_pwlen > 0); ASSERT(m_uselowercase || m_useuppercase || m_usedigits || m_usesymbols || m_usehexdigits || m_pronounceable); // pronounceable and hex passwords are handled separately: if (m_pronounceable) return MakePronounceable(); if (m_usehexdigits) return MakeHex(); vector<typeFreq_s> typeFreqs; if (m_uselowercase) typeFreqs.push_back(typeFreq_s(this, LOWERCASE, m_numlowercase)); if (m_useuppercase) typeFreqs.push_back(typeFreq_s(this, UPPERCASE, m_numuppercase)); if (m_usedigits) typeFreqs.push_back(typeFreq_s(this, DIGIT, m_numdigits)); if (m_usesymbols) typeFreqs.push_back(typeFreq_s(this, SYMBOL, m_numsymbols)); // Sort requested char type in decreasing order // of requested (at least) frequency: sort(typeFreqs.begin(), typeFreqs.end(), [](const typeFreq_s &a, const typeFreq_s &b) { return a.numchars > b.numchars; }); StringX temp; // First meet the 'at least' constraints for (auto iter = typeFreqs.begin(); iter != typeFreqs.end(); iter++) for (uint j = 0; j < iter->numchars; j++) { if (!iter->vchars.empty()) { temp.push_back(iter->vchars.back()); iter->vchars.pop_back(); if (temp.length() == m_pwlen) goto do_shuffle; // break out of two loops, goto needed } } // Now fill in the rest while (temp.length() != m_pwlen) { uint i = PWSrand::GetInstance()->RangeRand(typeFreqs.size()); if (!typeFreqs[i].vchars.empty()) { temp.push_back(typeFreqs[i].vchars.back()); typeFreqs[i].vchars.pop_back(); if (temp.length() == m_pwlen) goto do_shuffle; // break out of two loops, goto needed } } do_shuffle: // If 'at least' values were non-zero, we have some unwanted order, // se we mix things up a bit: RandomWrapper rnw; random_shuffle(temp.begin(), temp.end(), rnw); ASSERT(temp.length() == size_t(m_pwlen)); return temp; }