StringX PWSAuxParse::GetAutoTypeString(const CItemData &ci, const PWScore &core, std::vector<size_t> &vactionverboffsets) { // Set up all the data (a shortcut entry will change all of them!) StringX sxgroup = ci.GetGroup(); StringX sxtitle = ci.GetTitle(); StringX sxuser = ci.GetUser(); StringX sxpwd = ci.GetPassword(); StringX sxnotes = ci.GetNotes(); StringX sxurl = ci.GetURL(); StringX sxemail = ci.GetEmail(); StringX sxautotype = ci.GetAutoType(); if (ci.IsAlias()) { const CItemData *pbci = core.GetBaseEntry(&ci); if (pbci != NULL) { sxpwd = pbci->GetPassword(); } else { // Problem - alias entry without a base! ASSERT(0); } } else if (ci.IsShortcut()) { const CItemData *pbci = core.GetBaseEntry(&ci); if (pbci != NULL) { sxgroup = pbci->GetGroup(); sxtitle = pbci->GetTitle(); sxuser = pbci->GetUser(); sxpwd = pbci->GetPassword(); sxnotes = pbci->GetNotes(); sxurl = pbci->GetURL(); sxemail = pbci->GetEmail(); sxautotype = pbci->GetAutoType(); } else { // Problem - shortcut entry without a base! ASSERT(0); } } // ci.IsShortcut() // If empty, try the database default if (sxautotype.empty()) { sxautotype = PWSprefs::GetInstance()-> GetPref(PWSprefs::DefaultAutotypeString); // If still empty, take this default if (sxautotype.empty()) { // checking for user and password for default settings if (!sxpwd.empty()){ if (!sxuser.empty()) sxautotype = DEFAULT_AUTOTYPE; else sxautotype = _T("\\p\\n"); } } } return PWSAuxParse::GetAutoTypeString(sxautotype, sxgroup, sxtitle, sxuser, sxpwd, sxnotes, sxurl, sxemail, vactionverboffsets); }
void PWSTreeCtrl::FinishRenamingGroup(wxTreeEvent& evt, wxTreeItemId groupItem, const wxString& oldPath) { wxCHECK_RET(ItemIsGroup(groupItem), wxT("Cannot handle renaming of non-group items")); if (evt.IsEditCancelled()) return; // We DON'T need to handle these two as they can only occur while moving items // not removing groups as they become empty // renaming of groups that have only other groups as children MultiCommands* pmcmd = MultiCommands::Create(&m_core); if (!pmcmd) return; // For some reason, Command objects can't handle const references StringX sxOldPath = tostringx(oldPath); StringX sxNewPath = tostringx(GetItemGroup(groupItem)); // This takes care of modifying all the actual items pmcmd->Add(RenameGroupCommand::Create(&m_core, sxOldPath, sxNewPath)); // But we have to do the empty groups ourselves because EG_RENAME is not recursive typedef std::vector<StringX> EmptyGroupsArray; const EmptyGroupsArray& emptyGroups = m_core.GetEmptyGroups(); StringX sxOldPathWithDot = sxOldPath + _T('.'); for( EmptyGroupsArray::const_iterator itr = emptyGroups.begin(); itr != emptyGroups.end(); ++itr) { if (*itr == sxOldPath || itr->find(sxOldPathWithDot) == 0) { StringX sxOld = *itr; StringX sxNew = sxNewPath + itr->substr(sxOldPath.size()); pmcmd->Add(DBEmptyGroupsCommand::Create(&m_core, sxOld, sxNew)); } } if (pmcmd->GetSize()) m_core.Execute(pmcmd); // The old treeItem is gone, since it was renamed. We need to find the new one to select it wxTreeItemId newItem = Find(towxstring(sxNewPath), GetRootItem()); if (newItem.IsOk()) wxTreeCtrl::SelectItem(newItem); }
PWSfile::VERSION PWSfile::ReadVersion(const StringX &filename) { if (pws_os::FileExists(filename.c_str())) { VERSION v; if (PWSfileV3::IsV3x(filename, v)) return v; else return V20; } else return UNKNOWN_VERSION; }
///////////////////////////////////////////////////////////////// // Context diff //////// inline wchar_t context_tag(CItem::FieldType ft, const CItemData::FieldBits &fields, const CItemData &item, const CItemData &otherItem) { // The two items were compared & found to be differing on this field // only show this tag for fields there were compared if (fields.test(ft)) return '!'; const StringX val{item.GetFieldValue(ft)}; // This field was not compared, it could be different. Print it only if // it is the same in both items if (val == otherItem.GetFieldValue(ft)) return L' '; if (val.empty()) return L'+'; // Don't print it return L'-'; }
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 }
/** * 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; }
// Return whether first '«g» «t» «u»' is greater than the second '«g» «t» «u»' // used in std::sort below. // Need this as '»' is not in the correct lexical order for blank fields in entry bool MergeSyncGTUCompare(const StringX &elem1, const StringX &elem2) { StringX g1, t1, u1, g2, t2, u2, tmp1, tmp2; StringX::size_type i1 = elem1.find(L'\xbb'); g1 = (i1 == StringX::npos) ? elem1 : elem1.substr(0, i1 - 1); StringX::size_type i2 = elem2.find(L'\xbb'); g2 = (i2 == StringX::npos) ? elem2 : elem2.substr(0, i2 - 1); if (g1 != g2) return g1.compare(g2) < 0; tmp1 = elem1.substr(g1.length() + 3); tmp2 = elem2.substr(g2.length() + 3); i1 = tmp1.find(L'\xbb'); t1 = (i1 == StringX::npos) ? tmp1 : tmp1.substr(0, i1 - 1); i2 = tmp2.find(L'\xbb'); t2 = (i2 == StringX::npos) ? tmp2 : tmp2.substr(0, i2 - 1); if (t1 != t2) return t1.compare(t2) < 0; tmp1 = tmp1.substr(t1.length() + 3); tmp2 = tmp2.substr(t2.length() + 3); i1 = tmp1.find(L'\xbb'); u1 = (i1 == StringX::npos) ? tmp1 : tmp1.substr(0, i1 - 1); i2 = tmp2.find(L'\xbb'); u2 = (i2 == StringX::npos) ? tmp2 : tmp2.substr(0, i2 - 1); return u1.compare(u2) < 0; }
bool PWSRun::issuecmd(const StringX &sxFile, const StringX &sxParameters, const bool &bAutotype) const { SHELLEXECUTEINFO si; ZeroMemory(&si, sizeof(SHELLEXECUTEINFO)); si.cbSize = sizeof(SHELLEXECUTEINFO); si.nShow = SW_SHOWNORMAL; si.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_DOENVSUBST; si.lpFile = sxFile.c_str(); if (!sxParameters.empty()) { si.lpParameters = sxParameters.c_str(); } BOOL bAT_init(FALSE); if (bAutotype && isValid()) { if (pImpl->pInit != NULL && pImpl->pUnInit != NULL && pImpl->hCBWnd != NULL) { // OK - try and make it tell us! Won't if another instance of // PWS is doing this at exactly the same time - silly user! bAT_init = pImpl->pInit(pImpl->hCBWnd); pws_os::Trace(_T("PWSRun::issuecmd - AT_HK_Initialise: %s\n"), bAT_init == TRUE ? _T("OK") : _T("FAILED")); } } BOOL shellExecStatus = ::ShellExecuteEx(&si); if (shellExecStatus != TRUE) { // ShellExecute writes its own message on failure! if (bAT_init) { bAT_init = pImpl->pUnInit(pImpl->hCBWnd); pws_os::Trace(_T("PWSRun::issuecmd - AT_HK_UnInitialise: %s\n"), bAT_init == TRUE ? _T("OK") : _T("FAILED")); } return false; } return true; }
wxTreeItemId PWSTreeCtrl::AddGroup(const StringX &group) { wxTreeItemId ti = GetRootItem(); if (!ti.IsOk()) ti=AddRoot(wxString()); // Add a group at the end of path wxTreeItemId si; if (!group.empty()) { StringX path = group; StringX s; do { s = GetPathElem(path); if (!ExistsInTree(ti, s, si)) { ti = AppendItem(ti, s.c_str()); wxTreeCtrl::SetItemImage(ti, NODE_II); } else ti = si; } while (!path.empty()); } return ti; }
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; }
void CManagePSWDPols::OnGeneratePassword() { PWPolicy st_pp; CString cs_policyname(L""); if (m_iSelectedItem == 0) { // Use Default Password policy st_pp = m_st_default_pp; } else { // Named Password Policy cs_policyname = m_PolicyNames.GetItemText(m_iSelectedItem, 0); PSWDPolicyMapIter iter = m_MapPSWDPLC.find(StringX((LPCWSTR)cs_policyname)); if (iter == m_MapPSWDPLC.end()) return; st_pp = iter->second; } StringX passwd; GetMainDlg()->MakeRandomPassword(passwd, st_pp); m_password = passwd.c_str(); m_ex_password.SetWindowText(m_password); m_ex_password.Invalidate(); }
PWSfile::VERSION PWSfile::ReadVersion(const StringX &filename, const StringX &passkey) { if (pws_os::FileExists(filename.c_str())) { VERSION v; if (PWSfileV3::IsV3x(filename, v)) return v; else if (PWSfileV4::IsV4x(filename, passkey, v)) return v; else if (PWSfileV1V2::CheckPasskey(filename, passkey) == SUCCESS) return V20; else return UNKNOWN_VERSION; } else return UNKNOWN_VERSION; }
HTREEITEM CCWTreeCtrl::AddGroup(const CString &group) { // Add a group at the end of path HTREEITEM ti = TVI_ROOT; HTREEITEM si; if (!group.IsEmpty()) { StringX sxPath = group; StringX sxTemp, sxPath2Root(L""); do { sxTemp = GetFirstPathElem(sxPath); if (sxPath2Root.empty()) sxPath2Root = sxTemp; else sxPath2Root += GROUP_SEP2 + sxTemp; if (!ExistsInTree(ti, sxTemp, si)) { ti = InsertItem(sxTemp.c_str(), ti, TVI_SORT); SetItemImage(ti, CCWTreeCtrl::GROUP, CCWTreeCtrl::GROUP); } else ti = si; } while (!sxPath.empty()); } return ti; }
bool PWSTreeCtrl::ExistsInTree(wxTreeItemId node, const StringX &s, wxTreeItemId &si) const { // returns true iff s is a direct descendant of node wxTreeItemIdValue cookie; wxTreeItemId ti = GetFirstChild(node, cookie); while (ti) { const wxString itemText = GetItemText(ti); if (itemText == s.c_str()) { si = ti; return true; } ti = GetNextSibling(ti); } return false; }
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; } }
int PWSFilters::WriteFilterXMLFile(const StringX &filename, const PWSfile::HeaderRecord hdr, const StringX ¤tfile) { FILE *xmlfile = pws_os::FOpen(filename.c_str(), _T("wt")); if (xmlfile == NULL) return PWScore::CANT_OPEN_FILE; coStringXStream oss; int irc = WriteFilterXMLFile(oss, hdr, currentfile, true); // Write it out to the file, clear string stream, close file fwrite(oss.str().c_str(), 1, oss.str().length(), xmlfile); oss.str(""); fclose(xmlfile); return irc; }
inline wostream& print_field_value(wostream &os, wchar_t tag, const CItemData &item, CItemData::FieldType ft) { StringX fieldValue; switch (ft) { case CItemData::DCA: case CItemData::SHIFTDCA: { int16 dca = -1; if (item.GetDCA(dca) != -1) { LoadAString(fieldValue, dca2str(dca)); } break; } case CItemData::PWHIST: { const StringX pwh_str = item.GetPWHistory(); if (!pwh_str.empty()) { StringXStream value_stream; size_t ignored; PWHistList pwhl; const bool save_pwhistory = CreatePWHistoryList(pwh_str, ignored, ignored, pwhl, PWSUtil::TMC_LOCALE); value_stream << L"Save: " << (save_pwhistory? L"Yes" : L"No"); if ( !pwhl.empty() ) value_stream << endl; for( const auto &pwh: pwhl) value_stream << pwh.changedate << L": " << pwh.password << endl; fieldValue = value_stream.str(); } break; } case CItemData::POLICY: { PWPolicy policy; item.GetPWPolicy(policy); fieldValue = policy.GetDisplayString(); break; } default: fieldValue = item.GetFieldValue(ft); break; } const StringX sep1{L' '}, sep2{L": "}; StringXStream tmpStream; tmpStream << tag << L' ' << item.FieldName(ft) << L": " << fieldValue; const auto offset = 1 /*tag*/ + sep1.size() + sep2.size() + item.FieldName(ft).size(); lines_vec lines{ stream2vec(tmpStream)}; if ( lines.size() > 1) { std::for_each( lines.begin()+1, lines.end(), [offset](StringX &line) { line.insert(0, offset, L' '); }); } for( const auto &line: lines ) os << line << endl; return os; }
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; } }
int PWSfile::CheckPasskey(const StringX &filename, const StringX &passkey, VERSION &version) { if (passkey.empty()) return WRONG_PASSWORD; int status; version = UNKNOWN_VERSION; status = PWSfileV3::CheckPasskey(filename, passkey); if (status == SUCCESS) version = V30; if (status == NOT_PWS3_FILE) { status = PWSfileV1V2::CheckPasskey(filename, passkey); if (status == SUCCESS) version = V20; // or V17? } return status; }
static void ExtractURL(StringX ¬esStr, StringX &outurl) { StringX instr(notesStr); // Extract first instance of (http|https|ftp)://[^ \t\r\n]+ StringX::size_type left = instr.find(_T("http://")); if (left == StringX::npos) left = instr.find(_T("https://")); if (left == StringX::npos) left = instr.find(_T("ftp://")); if (left == StringX::npos) { outurl = _T(""); } else { StringX url(instr); instr = notesStr.substr(0, left); url = url.substr(left); // throw out everything left of URL StringX::size_type right = url.find_first_of(_T(" \t\r\n")); if (right != StringX::npos) { instr += url.substr(right); url = url.substr(0, right); } outurl = url; notesStr = instr; } }
bool CRUEList::GetAllMenuItemStrings(vector<RUEntryData> &ListofAllMenuStrings) const { RUEntryData ruentrydata; bool retval = false; RUEListConstIter iter; for (iter = m_RUEList.begin(); iter != m_RUEList.end(); iter++) { ItemListConstIter pw_listpos = m_core.Find(*iter); if (pw_listpos == m_core.GetEntryEndIter()) { ruentrydata.string = L""; ruentrydata.image = -1; ruentrydata.pci = NULL; } else { const CItemData &ci = m_core.GetEntry(pw_listpos); StringX group = ci.GetGroup(); StringX title = ci.GetTitle(); StringX user = ci.GetUser(); if (group.empty()) group = L" "; if (title.empty()) title = L" "; if (user.empty()) user = L" "; // Looks similar to <g><t><u> ruentrydata.string = L"\xab" + group + L"\xbb " + L"\xab" + title + L"\xbb " + L"\xab" + user + L"\xbb"; ruentrydata.image = app.GetMainDlg()->GetEntryImage(ci); ruentrydata.pci = (CItemData *)&ci; } ListofAllMenuStrings.push_back(ruentrydata); retval = true; } return retval; }
void CAddEdit_Basic::OnGeneratePassword() { UpdateData(TRUE); if (QuerySiblings(PP_UPDATE_PWPOLICY, 0L) != 0L) { return; } INT_PTR rc(CChangeAliasPswd::CHANGEALIAS); if (M_original_entrytype() == CItemData::ET_ALIAS) { CChangeAliasPswd dlgchngepswd; CSecString cs_base = M_base(); cs_base.Replace(L"[", L"\xab"); cs_base.Replace(L":", L"\xbb \xab"); cs_base.Replace(L"]", L"\xbb"); dlgchngepswd.m_BaseEntry = (CString)cs_base; rc = dlgchngepswd.DoModal(); switch (rc) { case IDCANCEL: return; case CChangeAliasPswd::CHANGEBASE: // Change Base break; case CChangeAliasPswd::CHANGEALIAS: // Change Alias break; default: ASSERT(0); } } StringX passwd; if (M_ipolicy() == NAMED_POLICY) { PWPolicy st_pp; GetMainDlg()->GetPolicyFromName(M_policyname(), st_pp); GetMainDlg()->MakeRandomPassword(passwd, st_pp); } else { // XXX temp - to be cleaned up PWPolicy policy(M_pwp()); policy.symbols = LPCWSTR(M_symbols()); GetMainDlg()->MakeRandomPassword(passwd, policy); } if (rc == CChangeAliasPswd::CHANGEBASE) { // Change Base ItemListIter iter = GetMainDlg()->Find(M_base_uuid()); ASSERT(iter != M_pcore()->GetEntryEndIter()); CItemData *pci = &iter->second; Command *pcmd = UpdatePasswordCommand::Create(M_pcore(), *pci, passwd); GetMainDlg()->Execute(pcmd); } else { M_realpassword() = m_password = passwd.c_str(); if (m_isPWHidden) { m_password2 = m_password; } m_ae_psh->SetChanged(true); UpdateData(FALSE); } QuerySiblings(PP_UPDATE_PWPOLICY, 0L); }
UINT CAddEdit_Basic::ExternalEditorThread(LPVOID me) // static method! { CAddEdit_Basic *self = (CAddEdit_Basic *)me; wchar_t szExecName[MAX_PATH + 1]; wchar_t lpPathBuffer[4096]; DWORD dwBufSize(4096); StringX sxEditor = PWSprefs::GetInstance()->GetPref(PWSprefs::AltNotesEditor); if (sxEditor.empty()) { // Find out the users default editor for "txt" files DWORD dwSize(MAX_PATH); HRESULT stat = ::AssocQueryString(0, ASSOCSTR_EXECUTABLE, L".txt", L"Open", szExecName, &dwSize); if (int(stat) != S_OK) { #ifdef _DEBUG CGeneralMsgBox gmb; gmb.AfxMessageBox(L"oops"); #endif // Send error return (WPARAM != 0) self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0); return 16; } sxEditor = szExecName; } DWORD dwResult = ExpandEnvironmentStrings(sxEditor.c_str(), szExecName, MAX_PATH + 1); if (dwResult == 0 || dwResult > (MAX_PATH + 1)) { CGeneralMsgBox gmb; CString cs_msg, cs_title(MAKEINTRESOURCE(IDS_EDITEXTERNALLY)); cs_msg.Format(IDS_CANT_FIND_EXT_EDITOR, sxEditor.c_str()); gmb.MessageBox(cs_msg, cs_title, MB_OK | MB_ICONEXCLAMATION); // Send error return (WPARAM != 0) self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0); return 0; } sxEditor = szExecName; if (!pws_os::FileExists(sxEditor.c_str())) { CGeneralMsgBox gmb; CString cs_msg, cs_title(MAKEINTRESOURCE(IDS_EDITEXTERNALLY)); cs_msg.Format(IDS_CANT_FIND_EXT_EDITOR, sxEditor.c_str()); gmb.MessageBox(cs_msg, cs_title, MB_OK | MB_ICONEXCLAMATION); // Send error return (WPARAM != 0) self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0); return 0; } // Now we know the editor exists - go copy the data for it! // Get the temp path GetTempPath(dwBufSize, // length of the buffer lpPathBuffer); // buffer for path // Create a temporary file. GetTempFileName(lpPathBuffer, // directory for temp files L"NTE", // temp file name prefix 0, // create unique name self->m_szTempName); // buffer for name FILE *fd; if ((fd = pws_os::FOpen(self->m_szTempName, _T("w+b"))) == NULL) { return 0; } // Write BOM const unsigned int iBOM = 0xFEFF; putwc(iBOM, fd); // Write out text fwrite(reinterpret_cast<const void *>((LPCWSTR)self->M_realnotes()), sizeof(BYTE), self->M_realnotes().GetLength() * sizeof(TCHAR), fd); // Close file before invoking editor fclose(fd); // Create an Edit process STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); DWORD dwCreationFlags(0); dwCreationFlags = CREATE_UNICODE_ENVIRONMENT; CString cs_CommandLine; // Make the command line = "<program>" "file" cs_CommandLine.Format(L"\"%s\" \"%s\"", sxEditor.c_str(), self->m_szTempName); int ilen = cs_CommandLine.GetLength(); LPWSTR pszCommandLine = cs_CommandLine.GetBuffer(ilen); if (!CreateProcess(NULL, pszCommandLine, NULL, NULL, FALSE, dwCreationFlags, NULL, lpPathBuffer, &si, &pi)) { pws_os::IssueError(L"External Editor CreateProcess", false); CGeneralMsgBox gmb; gmb.AfxMessageBox(IDS_CANT_FIND_EXT_EDITOR, MB_OK | MB_ICONEXCLAMATION); // Delete temporary file _wremove(self->m_szTempName); SecureZeroMemory(self->m_szTempName, sizeof(self->m_szTempName)); // Send error return (WPARAM != 0) self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0); return 0; } pws_os::Trace(L"%d\n", sizeof(self->m_szTempName)); WaitForInputIdle(pi.hProcess, INFINITE); // Wait until child process exits. WaitForSingleObject(pi.hProcess, INFINITE); // Close process and thread handles. CloseHandle(pi.hProcess); CloseHandle(pi.hThread); cs_CommandLine.ReleaseBuffer(); self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 0, 0); return 0; }
BOOL COptionsShortcuts::OnInitDialog() { COptions_PropertyPage::OnInitDialog(); m_AppHotKeyCtrl.m_pParent = this; m_AppHotKeyCtrl.SetHotKey(LOWORD(m_AppHotKeyValue),HIWORD(m_AppHotKeyValue)); if (m_bAppHotKeyEnabled == FALSE) m_AppHotKeyCtrl.EnableWindow(FALSE); // Program shortcuts m_ShortcutLC.Init(this); // Override default HeaderCtrl ID of 0 CHeaderCtrl *pLCHdrCtrl = m_ShortcutLC.GetHeaderCtrl(); pLCHdrCtrl->SetDlgCtrlID(IDC_LIST_HEADER); DWORD dwExtendedStyle = m_ShortcutLC.GetExtendedStyle() | LVS_EX_GRIDLINES; m_ShortcutLC.SetExtendedStyle(dwExtendedStyle); CString cs_colname; cs_colname.LoadString(IDS_COL_SHORTCUT); m_ShortcutLC.InsertColumn(0, cs_colname); // SHCT_SHORTCUTKEYS cs_colname.LoadString(IDS_COL_MENUITEM); m_ShortcutLC.InsertColumn(1, cs_colname); // SHCT_MENUITEMTEXT MapMenuShortcutsIter MenuMapiter, MenuMapiter_parent; CString str; int iItem(0); for (MenuMapiter = m_MapMenuShortcuts.begin(); MenuMapiter != m_MapMenuShortcuts.end(); MenuMapiter++) { // We don't allow change of certain menu items // Just don't put in the list that the user sees. if (MenuMapiter->second.uiParentID == 0) continue; if (std::find(m_ExcludedMenuItems.begin(), m_ExcludedMenuItems.end(), MenuMapiter->first) != m_ExcludedMenuItems.end()) continue; str = CMenuShortcut::FormatShortcut(MenuMapiter); MenuMapiter_parent = m_MapMenuShortcuts.find(MenuMapiter->second.uiParentID); ASSERT(MenuMapiter_parent != m_MapMenuShortcuts.end()); CString sMenuItemtext = (CString(MenuMapiter_parent->second.name.c_str()) + CString(L" \xbb ") + CString(MenuMapiter->second.name.c_str())); // Remove the ampersand from the menu item the user sees here sMenuItemtext.Remove(L'&'); iItem = m_ShortcutLC.InsertItem(iItem, str); // SHCT_SHORTCUTKEYS m_ShortcutLC.SetItemText(iItem, 1, sMenuItemtext); // SHCT_MENUITEMTEXT DWORD dwData = MAKELONG(MenuMapiter->first, MenuMapiter->second.iMenuPosition); m_ShortcutLC.SetItemData(iItem, dwData); } // foreach m_MapMenuShortcuts // Now sort via Menu item position m_ShortcutLC.SortItems(CompareFunc, NULL); m_ShortcutLC.SetColumnWidth(0, m_iColWidth); // SHCT_SHORTCUTKEYS m_ShortcutLC.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER); // SHCT_MENUITEMTEXT m_ShortcutLC.ModifyStyle(LVS_OWNERDRAWFIXED, 0, 0); // Entry shortcuts // Override default HeaderCtrl ID of 0 CHeaderCtrl *pEntryLCHdrCtrl = m_EntryShortcutLC.GetHeaderCtrl(); pEntryLCHdrCtrl->SetDlgCtrlID(IDC_ENTLIST_HEADER); dwExtendedStyle = m_EntryShortcutLC.GetExtendedStyle() | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT; m_EntryShortcutLC.SetExtendedStyle(dwExtendedStyle); cs_colname.LoadString(IDS_COL_SHORTCUT); m_EntryShortcutLC.InsertColumn(0, cs_colname); // SHORTCUT cs_colname.LoadString(IDS_GROUP); m_EntryShortcutLC.InsertColumn(1, cs_colname); // GROUP cs_colname.LoadString(IDS_TITLE); m_EntryShortcutLC.InsertColumn(2, cs_colname); // TITLE cs_colname.LoadString(IDS_USERNAME); m_EntryShortcutLC.InsertColumn(3, cs_colname); // USER iItem = 0; KBShortcutMapConstIter kbiter; m_KBShortcutMap = GetMainDlg()->GetAllKBShortcuts(); for (kbiter = m_KBShortcutMap.begin(); kbiter != m_KBShortcutMap.end(); kbiter++) { int32 iKBShortcut = kbiter->first; WORD wVirtualKeyCode = iKBShortcut & 0xff; WORD wPWSModifiers = iKBShortcut >> 16; // Translate from PWS modifers to HotKey WORD wHKModifiers = ConvertModifersPWS2MFC(wPWSModifiers); str = CMenuShortcut::FormatShortcut(wHKModifiers, wVirtualKeyCode); ItemListIter iter = app.GetCore()->Find(kbiter->second); const StringX sxGroup = iter->second.GetGroup(); const StringX sxTitle = iter->second.GetTitle(); const StringX sxUser = iter->second.GetUser(); iItem = m_EntryShortcutLC.InsertItem(iItem, str); // SHCT_SHORTCUTKEYS ASSERT(iItem != -1); m_EntryShortcutLC.SetItemText(iItem, 1, sxGroup.c_str()); // Group m_EntryShortcutLC.SetItemText(iItem, 2, sxTitle.c_str()); // Title m_EntryShortcutLC.SetItemText(iItem, 3, sxUser.c_str()); // User m_EntryShortcutLC.SetItemData(iItem, iKBShortcut); } // foreach mapKBShortcutMap // Now sort via keyboard shortcut m_EntryShortcutLC.SortItems(CKBSHCompareFunc, (LPARAM)this); m_EntryShortcutLC.SetColumnWidth(0, m_iColWidth); // SHCT_SHORTCUTKEYS m_EntryShortcutLC.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER); // GROUP m_EntryShortcutLC.SetColumnWidth(2, LVSCW_AUTOSIZE_USEHEADER); // TITLE m_EntryShortcutLC.SetColumnWidth(3, LVSCW_AUTOSIZE_USEHEADER); // USER InitToolTip(); AddTool(IDC_ENTSHORTCUTLIST, IDS_KBS_TOOLTIP1); ActivateToolTip(); m_stc_warning.ShowWindow(SW_HIDE); m_stc_warning.SetColour(RGB(255, 0, 0)); return TRUE; }
int CAddEdit_Additional::CheckKeyboardShortcut() { if (m_AEMD.uicaller == IDS_VIEWENTRY) return 0; int32 iKBShortcut; m_stc_warning.ShowWindow(SW_HIDE); WORD wVirtualKeyCode, wHKModifiers, wPWSModifiers; m_KBShortcutCtrl.GetHotKey(wVirtualKeyCode, wHKModifiers); // Translate from CHotKeyCtrl to PWS modifiers wPWSModifiers = ConvertModifersMFC2PWS(wHKModifiers); iKBShortcut = (wPWSModifiers << 16) + wVirtualKeyCode ; if (m_iOldHotKey != iKBShortcut) m_bWarnUserKBShortcut = false; if (iKBShortcut != 0) { CString cs_errmsg, cs_msg; // Luckily for valid alphanumeric characters, Windows Virtual Key Code // is the same as the ASCII character - no need for any conversion static const wchar_t *wcValidKeys = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (wcschr(wcValidKeys, wVirtualKeyCode) == NULL) { // Not alphanumeric cs_msg.LoadString(IDS_KBS_INVALID); m_stc_warning.SetWindowText(cs_msg); m_stc_warning.ShowWindow(SW_SHOW); // Reset keyboard shortcut wVirtualKeyCode = wHKModifiers = wPWSModifiers = 0; m_KBShortcutCtrl.SetHotKey(wVirtualKeyCode, wHKModifiers); return KBSHORTCUT_INVALID_CHARACTER; } if (m_iAppHotKey == iKBShortcut) { // Same as PWS application HotKey cs_msg.LoadString(IDS_KBS_SAMEASAPP); m_stc_warning.SetWindowText(cs_msg); m_stc_warning.ShowWindow(SW_SHOW); // Reset keyboard shortcut wVirtualKeyCode = wHKModifiers = wPWSModifiers = 0; m_KBShortcutCtrl.SetHotKey(wVirtualKeyCode, wHKModifiers); return KBSHORTCUT_IN_USE_BY_PWS; } if ((wPWSModifiers & PWS_HOTKEYF_ALT) == 0 && (wPWSModifiers & PWS_HOTKEYF_CONTROL) == 0 && !m_bWarnUserKBShortcut) { // Add Alt and/or Ctrl key and tell user but first check not already in use int iRC; pws_os::CUUID chk_uuid; WORD wValidModifierCombos[] = { PWS_HOTKEYF_ALT, PWS_HOTKEYF_ALT | PWS_HOTKEYF_SHIFT, PWS_HOTKEYF_CONTROL, PWS_HOTKEYF_CONTROL | PWS_HOTKEYF_SHIFT, PWS_HOTKEYF_ALT | PWS_HOTKEYF_CONTROL, PWS_HOTKEYF_ALT | PWS_HOTKEYF_CONTROL | PWS_HOTKEYF_SHIFT}; int iActions[] = {IDS_KBS_ADD_ALT, IDS_KBS_ADD_ALTSHIFT, IDS_KBS_ADD_CTRL, IDS_KBS_ADD_CTRLSHIFT, IDS_KBS_ADD_ALTCTRL, IDS_KBS_ADD_ALTCTRLSHIFT}; // Try them in order int iChange, ierror(IDS_KBS_CANTADD); for (iChange = 0; iChange < sizeof(wValidModifierCombos)/sizeof(WORD); iChange++) { int iNewKBShortcut = ((wPWSModifiers | wValidModifierCombos[iChange]) << 16) + wVirtualKeyCode; chk_uuid = M_pcore()->GetKBShortcut(iNewKBShortcut); if (chk_uuid == CUUID::NullUUID() || chk_uuid == M_entry_uuid()) { ierror = iActions[iChange]; break; } } if (ierror == IDS_KBS_CANTADD) { wVirtualKeyCode = wHKModifiers = wPWSModifiers = 0; iRC = KBSHORTCUT_CANT_MAKE_UNIQUE; } else { wPWSModifiers |= wValidModifierCombos[iChange]; wHKModifiers = ConvertModifersPWS2MFC(wPWSModifiers); iRC = KBSHORTCUT_MADE_UNIQUE; } cs_msg.LoadString(ierror); cs_errmsg.Format(IDS_KBS_INVALID, cs_msg); m_stc_warning.SetWindowText(cs_errmsg); m_stc_warning.ShowWindow(SW_SHOW); // Get new keyboard shortcut m_iOldHotKey = iKBShortcut = (wPWSModifiers << 16) + wVirtualKeyCode; ((CHotKeyCtrl *)GetDlgItem(IDC_ENTKBSHCTHOTKEY))->SetFocus(); m_bWarnUserKBShortcut = true; m_KBShortcutCtrl.SetHotKey(wVirtualKeyCode, wHKModifiers); return iRC; } const CString cs_HotKey = m_KBShortcutCtrl.GetHotKeyName(); pws_os::CUUID uuid = M_pcore()->GetKBShortcut(iKBShortcut); if (uuid != CUUID::NullUUID() && uuid != M_entry_uuid()) { // Tell user that it already exists as an entry keyboard shortcut ItemListIter iter = M_pcore()->Find(uuid); const StringX sxGroup = iter->second.GetGroup(); const StringX sxTitle = iter->second.GetTitle(); const StringX sxUser = iter->second.GetUser(); cs_errmsg.Format(IDS_KBS_INUSEBYENTRY, cs_HotKey, sxGroup.c_str(), sxTitle.c_str(), sxUser.c_str()); m_stc_warning.SetWindowText(cs_errmsg); m_stc_warning.ShowWindow(SW_SHOW); ((CHotKeyCtrl *)GetDlgItem(IDC_ENTKBSHCTHOTKEY))->SetFocus(); // Reset keyboard shortcut wVirtualKeyCode = wHKModifiers = wPWSModifiers = 0; m_KBShortcutCtrl.SetHotKey(wVirtualKeyCode, wHKModifiers); return KBSHORTCUT_IN_USE_BY_ENTRY; } StringX sxMenuItemName; unsigned char ucModifiers = wHKModifiers & 0xff; unsigned int nCID = GetMainDlg()->GetMenuShortcut(wVirtualKeyCode, ucModifiers, sxMenuItemName); if (nCID != 0) { // Save this value m_iOldHotKey = iKBShortcut; // Warn user that it is already in use for a menu item // (on this instance for this user!) Remove(sxMenuItemName, L'&'); CString cs_override(MAKEINTRESOURCE(IDS_ENTRYKBST_OVERRIDE)); cs_errmsg.Format(IDS_KBS_INUSEBYMENU, cs_HotKey, sxMenuItemName.c_str(), cs_override); m_stc_warning.SetWindowText(cs_errmsg); m_stc_warning.ShowWindow(SW_SHOW); // We have warned them - so now accept m_bWarnUserKBShortcut = !m_bWarnUserKBShortcut; return KBSHORTCUT_IN_USE_BY_MENU; } // We have warned them - so now accept (we are here, if hotkey was made unique by adding modifier) if (m_bWarnUserKBShortcut) m_bWarnUserKBShortcut = false; } return KBSHORTCUT_UNIQUE; }
BOOL CAddEdit_Additional::OnInitDialog() { CAddEdit_PropertyPage::OnInitDialog(); ModifyStyleEx(0, WS_EX_CONTROLPARENT); m_stc_warning.SetColour(RGB(255, 0, 0)); m_stc_warning.ShowWindow(SW_HIDE); CString cs_dats; StringX sx_dats = PWSprefs::GetInstance()-> GetPref(PWSprefs::DefaultAutotypeString); if (sx_dats.empty()) cs_dats = DEFAULT_AUTOTYPE; else cs_dats.Format(IDS_DEFAULTAUTOTYPE, sx_dats.c_str()); GetDlgItem(IDC_DEFAULTAUTOTYPE)->SetWindowText(cs_dats); if (M_uicaller() != IDS_ADDENTRY) { InitToolTip(); AddTool(IDC_STATIC_AUTO, IDS_CLICKTOCOPYEXPAND); AddTool(IDC_STATIC_RUNCMD, IDS_CLICKTOCOPYEXPAND); AddTool(IDC_ENTKBSHCTHOTKEY, IDS_KBS_TOOLTIP0); ActivateToolTip(); m_stc_autotype.SetHighlight(true, CAddEdit_PropertyPage::crefWhite); m_stc_runcommand.SetHighlight(true, CAddEdit_PropertyPage::crefWhite); } m_KBShortcutCtrl.SetMyParent(this); // These wil be zero for Add entry WORD wVirtualKeyCode = M_KBShortcut() & 0xff; WORD wPWSModifiers = M_KBShortcut() >> 16; // Translate from PWS to CHotKeyCtrl modifiers WORD wHKModifiers = ConvertModifersPWS2MFC(wPWSModifiers); m_KBShortcutCtrl.SetHotKey(wVirtualKeyCode, wHKModifiers); // We could do this to ensure user has at least Alt or Ctrl key // But it gets changed without the user knowing - so we do it elsewhere // instead and tell them. //m_KBShortcutCtrl.SetRules(HKCOMB_NONE | HKCOMB_S, HOTKEYF_ALT); if (M_uicaller() == IDS_VIEWENTRY || M_protected() != 0) { // Disable normal Edit controls GetDlgItem(IDC_AUTOTYPE)->SendMessage(EM_SETREADONLY, TRUE, 0); GetDlgItem(IDC_RUNCMD)->SendMessage(EM_SETREADONLY, TRUE, 0); // Disable HotKey m_KBShortcutCtrl.EnableWindow(FALSE); // Disable Combobox GetDlgItem(IDC_DOUBLE_CLICK_ACTION)->EnableWindow(FALSE); GetDlgItem(IDC_SHIFT_DOUBLE_CLICK_ACTION)->EnableWindow(FALSE); } // For some reason, MFC calls us twice when initializing. // SetupDCAComboBoxes is idempotent SetupDCAComboBoxes(&m_dblclk_cbox, false); SetupDCAComboBoxes(&m_shiftdblclk_cbox, true); short iDCA; if (M_DCA() < PWSprefs::minDCA || M_DCA() > PWSprefs::maxDCA) iDCA = (short)PWSprefs::GetInstance()->GetPref(PWSprefs::DoubleClickAction); else iDCA = M_DCA(); m_dblclk_cbox.SetCurSel(m_DCA_to_Index[iDCA]); if (M_ShiftDCA() < PWSprefs::minDCA || M_ShiftDCA() > PWSprefs::maxDCA) iDCA = (short)PWSprefs::GetInstance()->GetPref(PWSprefs::ShiftDoubleClickAction); else iDCA = M_ShiftDCA(); m_shiftdblclk_cbox.SetCurSel(m_DCA_to_Index[iDCA]); // Password History M_oldMaxPWHistory() = M_MaxPWHistory(); GetDlgItem(IDC_MAXPWHISTORY)->EnableWindow(M_SavePWHistory()); CSpinButtonCtrl* pspin = (CSpinButtonCtrl *)GetDlgItem(IDC_PWHSPIN); pspin->SetBuddy(GetDlgItem(IDC_MAXPWHISTORY)); pspin->SetRange(1, 255); pspin->SetBase(10); pspin->SetPos((int)M_MaxPWHistory()); if (M_uicaller() == IDS_ADDENTRY) { GetDlgItem(IDC_CLEAR_PWHIST)->ShowWindow(SW_HIDE); GetDlgItem(IDC_PWHISTORY_LIST)->ShowWindow(SW_HIDE); GetDlgItem(IDC_PWH_COPY_ALL)->ShowWindow(SW_HIDE); GetDlgItem(IDC_STATIC_PWH_EDIT)->ShowWindow(SW_HIDE); UpdateData(FALSE); m_bInitdone = true; return TRUE; } GetDlgItem(IDC_STATIC_PWH_ADD)->ShowWindow(SW_HIDE); BOOL bpwh_count = M_pwhistlist().empty() ? FALSE : TRUE; GetDlgItem(IDC_CLEAR_PWHIST)->EnableWindow(bpwh_count); GetDlgItem(IDC_PWHISTORY_LIST)->EnableWindow(bpwh_count); GetDlgItem(IDC_PWH_COPY_ALL)->EnableWindow(bpwh_count); if (M_uicaller() == IDS_VIEWENTRY || M_protected() != 0) { GetDlgItem(IDC_MAXPWHISTORY)->EnableWindow(FALSE); GetDlgItem(IDC_PWHSPIN)->EnableWindow(FALSE); GetDlgItem(IDC_SAVE_PWHIST)->EnableWindow(FALSE); GetDlgItem(IDC_CLEAR_PWHIST)->EnableWindow(FALSE); } m_PWHistListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT); m_PWHistListCtrl.UpdateRowHeight(false); CString cs_text; cs_text.LoadString(IDS_SETDATETIME); m_PWHistListCtrl.InsertColumn(0, cs_text); cs_text.LoadString(IDS_PASSWORD); m_PWHistListCtrl.InsertColumn(1, cs_text); PWHistList::iterator iter; DWORD nIdx; for (iter = M_pwhistlist().begin(), nIdx = 0; iter != M_pwhistlist().end(); iter++, nIdx++) { int nPos = 0; const PWHistEntry pwhentry = *iter; if (pwhentry.changetttdate != 0) { const StringX locTime = PWSUtil::ConvertToDateTimeString(pwhentry.changetttdate, PWSUtil::TMC_LOCALE); nPos = m_PWHistListCtrl.InsertItem(nPos, locTime.c_str()); } else { cs_text.LoadString(IDS_UNKNOWN); cs_text.Trim(); nPos = m_PWHistListCtrl.InsertItem(nPos, cs_text); } m_PWHistListCtrl.SetItemText(nPos, 1, pwhentry.password.c_str()); m_PWHistListCtrl.SetItemData(nPos, nIdx); } m_PWHistListCtrl.SetRedraw(FALSE); for (int i = 0; i < 2; i++) { m_PWHistListCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE); int nColumnWidth = m_PWHistListCtrl.GetColumnWidth(i); m_PWHistListCtrl.SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER); int nHeaderWidth = m_PWHistListCtrl.GetColumnWidth(i); m_PWHistListCtrl.SetColumnWidth(i, max(nColumnWidth, nHeaderWidth)); } m_PWHistListCtrl.SetRedraw(TRUE); wchar_t buffer[10]; swprintf_s(buffer, 10, L"%lu", M_NumPWHistory()); if (M_original_entrytype() == CItemData::ET_ALIAS) { GetDlgItem(IDC_MAXPWHISTORY)->EnableWindow(FALSE); GetDlgItem(IDC_PWHSPIN)->EnableWindow(FALSE); GetDlgItem(IDC_SAVE_PWHIST)->EnableWindow(FALSE); GetDlgItem(IDC_CLEAR_PWHIST)->EnableWindow(FALSE); GetDlgItem(IDC_STATIC_OLDPW1)->EnableWindow(FALSE); } m_stc_warning.SetColour(RGB(255, 0, 0)); m_stc_warning.ShowWindow(SW_HIDE); UpdateData(FALSE); m_bInitdone = true; return TRUE; }
int main(int argc, char *argv[]) { UserArgs ua; if (!parseArgs(argc, argv, ua)) { usage(argv[0]); return 1; } PWScore core; if (!pws_os::FileExists(ua.safe.c_str())) { cerr << argv[1] << " - file not found" << endl; return 2; } wstring wpk; cout << "Enter Password: "******"CheckPasskey returned: " << status_text(status) << endl; goto done; } { CUTF8Conv conv; const char *user = getlogin() != NULL ? getlogin() : "unknown"; StringX locker; if (!conv.FromUTF8((const unsigned char *)user, strlen(user), locker)) { cerr << "Could not convert user " << user << " to StringX" << endl; return 2; } stringT lk(locker.c_str()); if (!core.LockFile(ua.safe.c_str(), lk)) { wcout << L"Couldn't lock file " << ua.safe << L": locked by " << locker << endl; status = -1; goto done; } } // Since we may be writing the same file we're reading, // it behooves us to set the Current File and use its' related // functions core.SetCurFile(ua.safe); status = core.ReadCurFile(pk); if (status != PWScore::SUCCESS) { cout << "ReadFile returned: " << status_text(status) << endl; goto done; } if (ua.ImpExp == UserArgs::Export) { CItemData::FieldBits all(~0L); int N; if (ua.Format == UserArgs::XML) { status = core.WriteXMLFile(ua.fname, all, L"", 0, 0, L' ', N); } else { // export text status = core.WritePlaintextFile(ua.fname, all, L"", 0, 0, L' ', N); } } else { // Import if (ua.Format == UserArgs::XML) { status = ImportXML(core, ua.fname); } else { // import text status = ImportText(core, ua.fname); } if (status == PWScore::SUCCESS) status = core.WriteCurFile(); } if (status != PWScore::SUCCESS) { cout << "Operation returned status: " << status_text(status) << endl; goto done; } done: core.UnlockFile(ua.safe.c_str()); return status; }
static int ImportXML(PWScore &core, const StringX &fname) { const std::wstring XSDfn(L"pwsafe.xsd"); std::wstring XSDFilename = PWSdirs::GetXMLDir() + XSDfn; #if USE_XML_LIBRARY == MSXML || USE_XML_LIBRARY == XERCES if (!pws_os::FileExists(XSDFilename)) { wcerr << L"Can't find XML Schema Definition file" << XSDFilename << endl << L"Can't import without it." << endl; return PWScore::XML_FAILED_IMPORT; } #endif std::wstring ImportedPrefix; std::wstring dir; std::wstring strXMLErrors, strSkippedList, strPWHErrorList, strRenameList; int numValidated, numImported, numSkipped, numRenamed, numPWHErrors; bool bImportPSWDsOnly = false; // Create report as we go CReport rpt; std::wstring str_text; rpt.StartReport(L"Import_XML", core.GetCurFile().c_str()); str_text = L"XML file being imported: "; str_text += fname.c_str(); rpt.WriteLine(str_text); rpt.WriteLine(); std::vector<StringX> vgroups; Command *pcmd = NULL; int rc = core.ImportXMLFile(ImportedPrefix.c_str(), fname.c_str(), XSDFilename.c_str(), bImportPSWDsOnly, strXMLErrors, strSkippedList, strPWHErrorList, strRenameList, numValidated, numImported, numSkipped, numPWHErrors, numRenamed, rpt, pcmd); switch (rc) { case PWScore::XML_FAILED_VALIDATION: rpt.WriteLine(strXMLErrors.c_str()); str_text = L"File "; str_text += fname.c_str(); str_text += L" failed to validate."; delete pcmd; break; case PWScore::XML_FAILED_IMPORT: rpt.WriteLine(strXMLErrors.c_str()); str_text = L"File "; str_text += fname.c_str(); str_text += L" validated but hadd errors during import."; delete pcmd; break; case PWScore::SUCCESS: case PWScore::OK_WITH_ERRORS: if (pcmd != NULL) rc = core.Execute(pcmd); if (!strXMLErrors.empty() || numRenamed > 0 || numPWHErrors > 0) { wstring csErrors; if (!strXMLErrors.empty()) csErrors = strXMLErrors + L"\n"; if (!csErrors.empty()) { rpt.WriteLine(csErrors.c_str()); } wstring cs_renamed, cs_PWHErrors, cs_skipped; if (numSkipped > 0) { rpt.WriteLine(wstring(L"The following records were skipped:")); wostringstream oss; oss << L" / skipped " << numSkipped; cs_skipped = oss.str(); rpt.WriteLine(strSkippedList.c_str()); rpt.WriteLine(); } if (numPWHErrors > 0) { rpt.WriteLine(wstring(L"The following records had errors in their Password History:")); wostringstream oss; oss << L" / with Password History errors " << numPWHErrors; cs_PWHErrors = oss.str(); rpt.WriteLine(strPWHErrorList.c_str()); rpt.WriteLine(); } if (numRenamed > 0) { rpt.WriteLine(wstring(L"The following records were renamed as an entry already exists in your database or in the Import file:")); wostringstream oss; oss << L" / renamed " << numRenamed; cs_renamed = oss.str(); rpt.WriteLine(strRenameList.c_str()); rpt.WriteLine(); } wostringstream os2; os2 << L"File " << fname << L" was imported (entries validated" << numValidated << L" / imported " << numImported << cs_skipped << cs_renamed << cs_PWHErrors; str_text = os2.str(); } else { const wstring validate(numValidated == 1 ? L" entry" : L" entries"); const wstring import(numImported == 1 ? L" entry" : L" entries"); wostringstream oss; oss << L"Validated " << numValidated << validate << L'\t' << L"Imported " << numImported << import << endl; str_text = oss.str(); } break; default: ASSERT(0); } // switch // Finish Report rpt.WriteLine(str_text); rpt.EndReport(); return rc; }
void PasswordSafeSearch::FindMatches(const StringX& searchText, bool fCaseSensitive, SearchPointer& searchPtr, const CItemData::FieldBits& bsFields, bool fUseSubgroups, const wxString& subgroupText, CItemData::FieldType subgroupObject, PWSMatch::MatchRule subgroupFunction, bool subgroupFunctionCaseSensitive, Iter begin, Iter end, Accessor afn) { if (searchText.empty()) return; searchPtr.Clear(); typedef StringX (CItemData::*ItemDataFuncT)() const; struct { CItemData::FieldType type; ItemDataFuncT func; } ItemDataFields[] = { {CItemData::GROUP, &CItemData::GetGroup}, {CItemData::TITLE, &CItemData::GetTitle}, {CItemData::USER, &CItemData::GetUser}, {CItemData::PASSWORD, &CItemData::GetPassword}, // {CItemData::NOTES, &CItemData::GetNotes}, {CItemData::URL, &CItemData::GetURL}, {CItemData::EMAIL, &CItemData::GetEmail}, {CItemData::RUNCMD, &CItemData::GetRunCommand}, {CItemData::AUTOTYPE, &CItemData::GetAutoType}, {CItemData::XTIME_INT, &CItemData::GetXTimeInt}, }; for ( Iter itr = begin; itr != end; ++itr) { const int fn = (subgroupFunctionCaseSensitive? -subgroupFunction: subgroupFunction); if (fUseSubgroups && !afn(itr).Matches(stringT(subgroupText.c_str()), subgroupObject, fn)) continue; bool found = false; for (size_t idx = 0; idx < NumberOf(ItemDataFields) && !found; ++idx) { if (bsFields.test(ItemDataFields[idx].type)) { const StringX str = (afn(itr).*ItemDataFields[idx].func)(); found = fCaseSensitive? str.find(searchText) != StringX::npos: FindNoCase(searchText, str); } } if (!found && bsFields.test(CItemData::NOTES)) { StringX str = afn(itr).GetNotes(); found = fCaseSensitive? str.find(searchText) != StringX::npos: FindNoCase(searchText, str); } if (!found && bsFields.test(CItemData::PWHIST)) { size_t pwh_max, err_num; PWHistList pwhistlist; CreatePWHistoryList(afn(itr).GetPWHistory(), pwh_max, err_num, pwhistlist, PWSUtil::TMC_XML); for (PWHistList::iterator iter = pwhistlist.begin(); iter != pwhistlist.end(); iter++) { PWHistEntry pwshe = *iter; found = fCaseSensitive? pwshe.password.find(searchText) != StringX::npos: FindNoCase(searchText, pwshe.password ); if (found) break; // break out of for loop } pwhistlist.clear(); } if (found) { uuid_array_t uuid; afn(itr).GetUUID(uuid); searchPtr.Add(pws_os::CUUID(uuid)); } } }
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; }