Beispiel #1
0
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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
/////////////////////////////////////////////////////////////////
// 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'-';
}
Beispiel #5
0
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
}
Beispiel #6
0
/**
 * 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;
}
Beispiel #11
0
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();
}
Beispiel #12
0
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;
}
Beispiel #13
0
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;
}
Beispiel #15
0
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 &currentfile)
{
  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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
  }
}
Beispiel #19
0
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;
}
Beispiel #20
0
static void ExtractURL(StringX &notesStr, 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;
}
Beispiel #22
0
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);
}
Beispiel #23
0
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;
}
Beispiel #24
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));
    }
  }
}
Beispiel #30
0
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;
}