bool PWSclip::SetData(const StringX &text) { if (wxTheClipboard->Open()) { wxTheClipboard->SetData(new wxTextDataObject(text.c_str())); wxTheClipboard->Close(); return true; } else return false; }
LRESULT CPasswordSubsetDlg::OnDisplayStatus(WPARAM /* wParam */, LPARAM /* lParam */) { UpdateData(TRUE); m_stcwarningmsg.SetWindowText(L""); m_stcwarningmsg.ResetColour(); m_subset.Trim(); int icurpos(0); std::vector<int> vpos; CString resToken(m_subset); const size_t ipwlengh = m_passwd.length(); while (resToken != L"" && icurpos != -1) { int lastpos = icurpos; resToken = m_subset.Tokenize(L";, ", icurpos); if (resToken == L"") continue; int ipos = _wtoi(resToken); // ipos can't be zero but is valid if: // a. Positive: 1 <= ipos <= password_length // b. Negative: -password_lengh < ipos <= -1 if (abs(ipos) > (int)ipwlengh) { m_warningmsg.Format(ipos > 0 ? IDS_SUBSETINDEXTOOBIG : IDS_SUBSETINDEXTOOSMALL, ipwlengh); m_stcwarningmsg.SetWindowText(m_warningmsg); m_stcwarningmsg.SetColour(RGB(255, 0, 0)); m_stcwarningmsg.Invalidate(); vpos.clear(); m_ne_subset.SetSel(lastpos, icurpos); m_ne_subset.SetFocus(); // Disable Copy to Clipboard GetDlgItem(IDC_COPYPASSWORD)->EnableWindow(FALSE); return 0L; } if (ipos < 0) ipos = (int)ipwlengh + ipos + 1; vpos.push_back(ipos - 1); }; std::vector<int>::const_iterator citer; StringX sSubset; for (citer = vpos.begin(); citer != vpos.end(); citer++) { sSubset += m_passwd[*citer]; sSubset += L" "; } m_results.SetWindowText(sSubset.c_str()); m_bshown = true; // Enable Copy to Clipboard GetDlgItem(IDC_COPYPASSWORD)->EnableWindow(TRUE); return 1L; }
stringT CPasswordCharPool::GetDefaultSymbols() { stringT symbols; const StringX sx_symbols = PWSprefs::GetInstance()->GetPref(PWSprefs::DefaultSymbols); if (!sx_symbols.empty()) symbols = sx_symbols.c_str(); else symbols = std_symbol_chars; return symbols; }
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; }
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 }
void CPasswordPolicyDlg::OnGeneratePassword() { UpdateData(TRUE); PWPolicy st_pp; if (m_UseNamedPolicy == BST_UNCHECKED) { // Use specific policy but validate it first if (Validate() == FALSE) return; if (m_PWUseLowercase == TRUE) st_pp.flags |= PWPolicy::UseLowercase; if (m_PWUseUppercase == TRUE) st_pp.flags |= PWPolicy::UseUppercase; if (m_PWUseDigits == TRUE) st_pp.flags |= PWPolicy::UseDigits; if (m_PWUseSymbols == TRUE) st_pp.flags |= PWPolicy::UseSymbols; if (m_PWUseHexdigits == TRUE) st_pp.flags |= PWPolicy::UseHexDigits; if (m_PWEasyVision == TRUE) st_pp.flags |= PWPolicy::UseEasyVision; if (m_PWMakePronounceable == TRUE) st_pp.flags |= PWPolicy::MakePronounceable; st_pp.length = m_PWDefaultLength; st_pp.digitminlength = m_PWDigitMinLength; st_pp.lowerminlength = m_PWLowerMinLength; st_pp.symbolminlength = m_PWSymbolMinLength; st_pp.upperminlength = m_PWUpperMinLength; m_SymbolsEdit.GetWindowText(m_Symbols); st_pp.symbols = LPCWSTR(m_Symbols); } else { // Use named policy if (m_PolicyNameEdit.IsWindowVisible()) { m_PolicyNameEdit.GetWindowText((CString &)m_policyname); } else { int index = m_cbxPolicyNames.GetCurSel(); m_cbxPolicyNames.GetLBText(index, m_policyname); } StringX sxPolicyName(m_policyname); GetMainDlg()->GetPolicyFromName(sxPolicyName, st_pp); } StringX passwd; GetMainDlg()->MakeRandomPassword(passwd, st_pp); m_password = passwd.c_str(); m_ex_password.SetWindowText(m_password); m_ex_password.Invalidate(); UpdateData(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 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; }
void CCompareWithSelectDlg::InsertItemIntoGUITree(CItemData &ci) { HTREEITEM ti; StringX treeDispString = (LPCWSTR)m_cwItemTree.MakeTreeDisplayString(ci); // get path, create if necessary, add title as last node ti = m_cwItemTree.AddGroup(ci.GetGroup().c_str()); ti = m_cwItemTree.InsertItem(treeDispString.c_str(), ti, TVI_SORT); m_cwItemTree.SetItemData(ti, (DWORD_PTR)&ci); int nImage = m_cwItemTree.GetEntryImage(ci); m_cwItemTree.SetItemImage(ti, nImage, nImage); }
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; }
void CSafeCombinationSetup::OnOkClick( wxCommandEvent& /* evt */ ) { if (Validate() && TransferDataFromWindow()) { if (m_password != m_verify) { wxMessageDialog err(this, _("The two entries do not match."), _("Error"), wxOK | wxICON_EXCLAMATION); err.ShowModal(); return; } if (m_password.empty()) { wxMessageDialog err(this, _("Please enter the key and verify it."), _("Error"), wxOK | wxICON_EXCLAMATION); err.ShowModal(); return; } // Vox populi vox dei - folks want the ability to use a weak // passphrase, best we can do is warn them... // If someone want to build a version that insists on proper // passphrases, then just define the preprocessor macro // PWS_FORCE_STRONG_PASSPHRASE in the build properties/Makefile // (also used in CPasskeyChangeDlg) #ifndef _DEBUG // for debug, we want no checks at all, to save time StringX errmess; if (!CPasswordCharPool::CheckPassword(tostringx(m_password), errmess)) { wxString cs_msg; cs_msg = _("Weak passphrase:"); cs_msg += wxT("\n\n"); cs_msg += errmess.c_str(); #ifndef PWS_FORCE_STRONG_PASSPHRASE cs_msg += wxT("\n"); cs_msg += _("Use it anyway?"); wxMessageDialog mb(this, cs_msg, _("Warning"), wxYES_NO | wxNO_DEFAULT | wxICON_HAND); int rc = mb.ShowModal(); if (rc == wxID_NO) return; #else cs_msg += wxT("\n"); cs_msg += _("Please try another"); wxMessageDialog mb(this, cs_msg, _("Error"), wxOK | wxICON_HAND); mb.ShowModal(); return; #endif // PWS_FORCE_STRONG_PASSPHRASE } #endif // _DEBUG EndModal(wxID_OK); } }
/////////////////////////////////// // dispatcher. Called from main() ///////// int Diff(PWScore &core, const UserArgs &ua) { CompareData current, comparison, conflicts, identical; PWScore otherCore; const StringX otherSafe{std2stringx(ua.opArg)}; CItemData::FieldBits safeFields{ua.fields}; for( auto ft: diff_fields ) { if (ua.fields.test(ft) && CItemData::IsTextField(ft)) { safeFields.set(ft); } } safeFields.reset(CItem::RMTIME); int status = OpenCore(otherCore, otherSafe); if ( status == PWScore::SUCCESS ) { constexpr bool treatWhitespacesAsEmpty = false; core.Compare( &otherCore, safeFields, ua.subset.valid(), treatWhitespacesAsEmpty, ua.subset.value, ua.subset.field, ua.subset.rule, current, comparison, conflicts, identical); switch (ua.dfmt) { case UserArgs::DiffFmt::Unified: unified_diff(core, otherCore, current, comparison, conflicts, identical); break; case UserArgs::DiffFmt::Context: context_diff(core, otherCore, current, comparison, conflicts, identical); break; case UserArgs::DiffFmt::SideBySide: sidebyside_diff(core, otherCore, current, comparison, conflicts, identical, safeFields, ua.colwidth); break; default: assert(false); break; } otherCore.UnlockFile(otherSafe.c_str()); } return status; }
void CSafeCombinationSetup::OnYubibtnClick( wxCommandEvent& /* event */ ) { if (Validate() && TransferDataFromWindow()) { if (m_password != m_verify) { wxMessageDialog err(this, _("The two entries do not match."), _("Error"), wxOK | wxICON_EXCLAMATION); err.ShowModal(); return; } StringX response; bool oldYubiChallenge = ::wxGetKeyState(WXK_SHIFT); // for pre-0.94 databases if (PerformChallengeResponse(this, tostringx(m_password), response, oldYubiChallenge)) { m_password = response.c_str(); EndModal(wxID_OK); } } }
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; }
void CSafeCombinationChange::OnOkClick( wxCommandEvent& /* evt */ ) { if (Validate() && TransferDataFromWindow()) { StringX errmess; const StringX old = m_oldresponse.empty() ? m_oldpasswd : m_oldresponse; int rc = m_core.CheckPasskey(m_core.GetCurFile(), old); if (rc == PWScore::WRONG_PASSWORD) { wxMessageDialog err(this, _("The old safe combination is not correct"), _("Error"), wxOK | wxICON_EXCLAMATION); err.ShowModal(); } else if (rc == PWScore::CANT_OPEN_FILE) { wxMessageDialog err(this, _("Cannot verify old safe combination - file gone?"), _("Error"), wxOK | wxICON_EXCLAMATION); err.ShowModal(); } else if (m_confirm != m_newpasswd) { wxMessageDialog err(this, _("New safe combination and confirmation do not match"), _("Error"), wxOK | wxICON_EXCLAMATION); err.ShowModal(); // Vox populi vox dei - folks want the ability to use a weak // passphrase, best we can do is warn them... // If someone want to build a version that insists on proper // passphrases, then just define the preprocessor macro // PWS_FORCE_STRONG_PASSPHRASE in the build properties/Makefile // (also used in CPasskeySetup) } else if (!CPasswordCharPool::CheckPassword(m_newpasswd, errmess)) { wxString msg = _("Weak passphrase:"); msg += wxT("\n\n"); msg += errmess.c_str(); #ifndef PWS_FORCE_STRONG_PASSPHRASE msg += wxT("\n"); msg += _("Use it anyway?"); wxMessageDialog err(this, msg, _("Error"), wxYES_NO | wxICON_HAND); int rc1 = err.ShowModal(); if (rc1 == wxID_YES) EndModal(wxID_OK); #else wxMessageDialog err(this, msg, _("Error"), wxOK | wxICON_HAND); err.ShowModal(); #endif // PWS_FORCE_STRONG_PASSPHRASE } else { // password checks out OK. EndModal(wxID_OK); } } }
CheckVersion::CheckStatus CAboutDlg::CheckLatestVersion(std::wstring &latest) { CInternetSession session(L"PasswordSafe Version Check"); CStdioFile *fh; // Put up hourglass...this might take a while CWaitCursor waitCursor; try { // Loading the file as binary since we're treating it as UTF-8 fh = session.OpenURL(L"https://pwsafe.org/latest.xml", 1, (INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD)); } catch (CInternetException *) { // throw; return CheckVersion::CANT_CONNECT; } ASSERT(fh != NULL); CString latest_xml; unsigned char buff[BUFSIZ + 1]; StringX chunk; UINT nRead; CUTF8Conv conv; while ((nRead = fh->Read(buff, BUFSIZ)) != 0) { buff[nRead] = '\0'; // change to widechar representation if (!conv.FromUTF8(buff, nRead, chunk)) { fh->Close(); delete fh; session.Close(); return CheckVersion::CANT_READ; } else latest_xml += chunk.c_str(); } fh->Close(); delete fh; session.Close(); waitCursor.Restore(); // restore normal cursor CheckVersion vh(m_nMajor, m_nMinor, m_nBuild); return vh.CheckLatestVersion(LPCWSTR(latest_xml), latest); }
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; }
void CPasskeySetup::OnOK() { UpdateData(TRUE); CGeneralMsgBox gmb; if (m_passkey != m_verify) { gmb.AfxMessageBox(IDS_ENTRIESDONOTMATCH); ((CEdit*)GetDlgItem(IDC_VERIFY))->SetFocus(); return; } if (m_passkey.IsEmpty()) { gmb.AfxMessageBox(IDS_ENTERKEYANDVERIFY); ((CEdit*)GetDlgItem(IDC_PASSKEY))->SetFocus(); return; } // Vox populi vox dei - folks want the ability to use a weak // passphrase, best we can do is warn them... // If someone want to build a version that insists on proper // passphrases, then just define the preprocessor macro // PWS_FORCE_STRONG_PASSPHRASE in the build properties/Makefile // (also used in CPasskeyChangeDlg) #ifndef _DEBUG // for debug, we want no checks at all, to save time StringX errmess; if (!CPasswordCharPool::CheckPassword(m_passkey, errmess)) { CString cs_msg, cs_text; cs_msg.Format(IDS_WEAKPASSPHRASE, static_cast<LPCWSTR>(errmess.c_str())); #ifndef PWS_FORCE_STRONG_PASSPHRASE cs_text.LoadString(IDS_USEITANYWAY); cs_msg += cs_text; INT_PTR rc = gmb.AfxMessageBox(cs_msg, NULL, MB_YESNO | MB_ICONSTOP); if (rc == IDNO) return; #else cs_text.LoadString(IDS_TRYANOTHER); cs_msg += cs_text; gmb.AfxMessageBox(cs_msg, NULL, MB_OK | MB_ICONSTOP); return; #endif // PWS_FORCE_STRONG_PASSPHRASE } #endif // _DEBUG CPKBaseDlg::OnOK(); }
BOOL CConfirmDeleteDlg::OnInitDialog() { CString cs_text; if (m_numchildren > 0) { // Group delete if (m_numchildren == 1) cs_text.LoadString(IDS_NUMCHILD); else cs_text.Format(IDS_NUMCHILDREN, m_numchildren); // Disable/hide entry's info as a group GetDlgItem(IDC_ENTRY)->EnableWindow(FALSE); GetDlgItem(IDC_ENTRY)->ShowWindow(SW_HIDE); // Tell them number of entries in this group & its sub-groups GetDlgItem(IDC_DELETECHILDREN)->EnableWindow(TRUE); GetDlgItem(IDC_DELETECHILDREN)->SetWindowText(cs_text); // Disable/hide checkbox because we *always* ask for groups GetDlgItem(IDC_CLEARCHECK)->EnableWindow(FALSE); GetDlgItem(IDC_CLEARCHECK)->ShowWindow(SW_HIDE); } else { StringX sxEntry; sxEntry = L"\xab" + m_sxGroup + L"\xbb " + L"\xab" + m_sxTitle + L"\xbb " + L"\xab" + m_sxUser + L"\xbb"; GetDlgItem(IDC_ENTRY)->SetWindowText(sxEntry.c_str()); // Get Add/Edit font CFont *pFont = Fonts::GetInstance()->GetAddEditFont(); GetDlgItem(IDC_ENTRY)->SetFont(pFont); // Disable/hide children info - n/a for a single entry GetDlgItem(IDC_DELETECHILDREN)->EnableWindow(FALSE); GetDlgItem(IDC_DELETECHILDREN)->ShowWindow(SW_HIDE); // Allow user to select not to be asked again GetDlgItem(IDC_CLEARCHECK)->EnableWindow(TRUE); } cs_text.LoadString((m_numchildren > 0) ? IDS_DELGRP : IDS_DELENT); GetDlgItem(IDC_DELITEM)->SetWindowText(cs_text); 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(); }
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 PWSfileV1V2::ReadRecord(CItemData &item) { ASSERT(m_fd != NULL); ASSERT(m_curversion != UNKNOWN_VERSION); StringX tempdata; signed long numread = 0; unsigned char type; switch (m_curversion) { case V17: { // type is meaningless, but why write two versions of ReadCBC? numread += static_cast<signed long>(ReadCBC(type, tempdata)); item.SetName(tempdata, m_defusername); numread += static_cast<signed long>(ReadCBC(type, tempdata)); item.SetPassword(tempdata); numread += static_cast<signed long>(ReadCBC(type, tempdata)); item.SetNotes(tempdata); // No UUID, so we create one here item.CreateUUID(); // No Group - currently leave empty return (numread > 0) ? SUCCESS : END_OF_FILE; } case V20: { int emergencyExit = 255; // to avoid endless loop. signed long fieldLen; // zero means end of file reached bool endFound = false; // set to true when record end detected - happy end do { fieldLen = static_cast<signed long>(ReadCBC(type, tempdata)); if (signed(fieldLen) > 0) { numread += fieldLen; switch (type) { case CItemData::TITLE: item.SetTitle(tempdata); break; case CItemData::USER: item.SetUser(tempdata); break; case CItemData::PASSWORD: item.SetPassword(tempdata); break; case CItemData::NOTES: { StringX autotypeStr, URLStr; ExtractAutoTypeCmd(tempdata, autotypeStr); ExtractURL(tempdata, URLStr); item.SetNotes(tempdata); if (!autotypeStr.empty()) item.SetAutoType(autotypeStr); if (!URLStr.empty()) item.SetURL(URLStr); break; } case CItemData::END: endFound = true; break; case CItemData::UUID: { LPCTSTR ptr = tempdata.c_str(); uuid_array_t uuid_array; for (size_t i = 0; i < sizeof(uuid_array_t); i++) uuid_array[i] = static_cast<unsigned char>(ptr[i]); item.SetUUID(uuid_array); break; } case CItemData::GROUP: item.SetGroup(tempdata); break; // just silently ignore fields we don't support. // this is forward compatability... case CItemData::CTIME: case CItemData::PMTIME: case CItemData::ATIME: case CItemData::XTIME: case CItemData::RMTIME: case CItemData::POLICY: case CItemData::XTIME_INT: default: break; } // switch } // if (fieldLen > 0) } while (!endFound && fieldLen > 0 && --emergencyExit > 0); return (numread > 0 && endFound) ? SUCCESS : END_OF_FILE; } default: ASSERT(0); return UNSUPPORTED_VERSION; } }
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; }
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; }
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; }
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; }