Пример #1
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;
}