Add -i/--include option to "generate" CLI command. (#7112)

This commit is contained in:
Patrick Klein
2021-12-08 05:40:09 +01:00
committed by GitHub
parent b3896f2600
commit a0a063b57f
9 changed files with 359 additions and 213 deletions

View File

@@ -53,6 +53,12 @@ const QCommandLineOption Generate::ExcludeCharsOption = QCommandLineOption(QStri
QObject::tr("Exclude character set"),
QObject::tr("chars"));
const QCommandLineOption Generate::CustomCharacterSetOption =
QCommandLineOption(QStringList() << "c"
<< "custom",
QObject::tr("Use custom character set"),
QObject::tr("chars"));
const QCommandLineOption Generate::ExcludeSimilarCharsOption =
QCommandLineOption(QStringList() << "exclude-similar", QObject::tr("Exclude similar looking characters"));
@@ -71,6 +77,7 @@ Generate::Generate()
options.append(Generate::ExcludeCharsOption);
options.append(Generate::ExcludeSimilarCharsOption);
options.append(Generate::IncludeEveryGroupOption);
options.append(Generate::CustomCharacterSetOption);
}
/**
@@ -120,9 +127,15 @@ QSharedPointer<PasswordGenerator> Generate::createGenerator(QSharedPointer<QComm
// The default charset will be used if no explicit class
// option was set.
passwordGenerator->setCharClasses(classes);
passwordGenerator->setFlags(flags);
passwordGenerator->setExcludedChars(parser->value(Generate::ExcludeCharsOption));
if (flags != 0x0) {
passwordGenerator->setFlags(flags);
}
QString customCharacterSet = parser->value(Generate::CustomCharacterSetOption);
if (classes != 0x0 || !customCharacterSet.isNull()) {
passwordGenerator->setCharClasses(classes);
}
passwordGenerator->setCustomCharacterSet(customCharacterSet);
passwordGenerator->setExcludedCharacterSet(parser->value(Generate::ExcludeCharsOption));
if (!passwordGenerator->isValid()) {
err << QObject::tr("Invalid password generator after applying all options") << endl;

View File

@@ -39,6 +39,7 @@ public:
static const QCommandLineOption ExcludeCharsOption;
static const QCommandLineOption ExcludeSimilarCharsOption;
static const QCommandLineOption IncludeEveryGroupOption;
static const QCommandLineOption CustomCharacterSetOption;
};
#endif // KEEPASSXC_GENERATE_H

View File

@@ -20,51 +20,43 @@
#include "crypto/Random.h"
const char* PasswordGenerator::DefaultAdditionalChars = "";
const int PasswordGenerator::DefaultLength = 32;
const char* PasswordGenerator::DefaultCustomCharacterSet = "";
const char* PasswordGenerator::DefaultExcludedChars = "";
PasswordGenerator::PasswordGenerator()
: m_length(0)
, m_classes(nullptr)
, m_flags(nullptr)
, m_additional(PasswordGenerator::DefaultAdditionalChars)
: m_length(PasswordGenerator::DefaultLength)
, m_classes(PasswordGenerator::CharClass::DefaultCharset)
, m_flags(PasswordGenerator::GeneratorFlag::DefaultFlags)
, m_custom(PasswordGenerator::DefaultCustomCharacterSet)
, m_excluded(PasswordGenerator::DefaultExcludedChars)
{
}
void PasswordGenerator::setLength(int length)
{
if (length <= 0) {
m_length = DefaultLength;
return;
}
m_length = length;
}
void PasswordGenerator::setCharClasses(const CharClasses& classes)
void PasswordGenerator::setCharClasses(const PasswordGenerator::CharClasses& classes)
{
if (classes == 0) {
m_classes = DefaultCharset;
return;
}
m_classes = classes;
}
void PasswordGenerator::setCustomCharacterSet(const QString& customCharacterSet)
{
m_custom = customCharacterSet;
}
void PasswordGenerator::setExcludedCharacterSet(const QString& excludedCharacterSet)
{
m_excluded = excludedCharacterSet;
}
void PasswordGenerator::setFlags(const GeneratorFlags& flags)
{
m_flags = flags;
}
void PasswordGenerator::setAdditionalChars(const QString& chars)
{
m_additional = chars;
}
void PasswordGenerator::setExcludedChars(const QString& chars)
{
m_excluded = chars;
}
QString PasswordGenerator::generatePassword() const
{
Q_ASSERT(isValid());
@@ -114,9 +106,9 @@ QString PasswordGenerator::generatePassword() const
bool PasswordGenerator::isValid() const
{
if (m_classes == 0 && m_additional.isEmpty()) {
if (m_classes == CharClass::NoClass && m_custom.isEmpty()) {
return false;
} else if (m_length == 0) {
} else if (m_length <= 0) {
return false;
}
@@ -266,10 +258,10 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups() const
passwordGroups.append(group);
}
if (!m_additional.isEmpty()) {
if (!m_custom.isEmpty()) {
PasswordGroup group;
for (auto ch : m_additional) {
for (auto ch : m_custom) {
group.append(ch);
}
@@ -302,38 +294,43 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups() const
int PasswordGenerator::numCharClasses() const
{
int numClasses = 0;
if (m_classes & LowerLetters) {
numClasses++;
}
if (m_classes & UpperLetters) {
numClasses++;
}
if (m_classes & Numbers) {
numClasses++;
}
if (m_classes & Braces) {
numClasses++;
}
if (m_classes & Punctuation) {
numClasses++;
}
if (m_classes & Quotes) {
numClasses++;
}
if (m_classes & Dashes) {
numClasses++;
}
if (m_classes & Math) {
numClasses++;
}
if (m_classes & Logograms) {
numClasses++;
}
if (m_classes & EASCII) {
numClasses++;
}
return numClasses;
// Actually compute the non empty password groups
auto non_empty_groups = passwordGroups();
return non_empty_groups.size();
}
int PasswordGenerator::getMinLength() const
{
if ((m_flags & CharFromEveryGroup)) {
return numCharClasses();
}
return 1;
}
void PasswordGenerator::reset()
{
m_classes = CharClass::DefaultCharset;
m_flags = GeneratorFlag::DefaultFlags;
m_custom = DefaultCustomCharacterSet;
m_excluded = DefaultExcludedChars;
m_length = DefaultLength;
}
int PasswordGenerator::getLength() const
{
return m_length;
}
const PasswordGenerator::GeneratorFlags& PasswordGenerator::getFlags() const
{
return m_flags;
}
const PasswordGenerator::CharClasses& PasswordGenerator::getActiveClasses() const
{
return m_classes;
}
const QString& PasswordGenerator::getCustomCharacterSet() const
{
return m_custom;
}
const QString& PasswordGenerator::getExcludedCharacterSet() const
{
return m_excluded;
}

View File

@@ -19,6 +19,7 @@
#ifndef KEEPASSX_PASSWORDGENERATOR_H
#define KEEPASSX_PASSWORDGENERATOR_H
#include <QObject>
#include <QVector>
typedef QVector<QChar> PasswordGroup;
@@ -28,6 +29,7 @@ class PasswordGenerator
public:
enum CharClass
{
NoClass = 0,
LowerLetters = (1 << 0),
UpperLetters = (1 << 1),
Numbers = (1 << 2),
@@ -41,10 +43,11 @@ public:
EASCII = (1 << 9),
DefaultCharset = LowerLetters | UpperLetters | Numbers
};
Q_DECLARE_FLAGS(CharClasses, CharClass)
Q_DECLARE_FLAGS(CharClasses, CharClass);
enum GeneratorFlag
{
NoFlags = 0,
ExcludeLookAlike = (1 << 0),
CharFromEveryGroup = (1 << 1),
AdvancedMode = (1 << 2),
@@ -56,17 +59,25 @@ public:
PasswordGenerator();
void setLength(int length);
void setCharClasses(const CharClasses& classes);
void setFlags(const GeneratorFlags& flags);
void setAdditionalChars(const QString& chars);
void setExcludedChars(const QString& chars);
void setCharClasses(const CharClasses& classes);
void setCustomCharacterSet(const QString& customCharacterSet);
void setExcludedCharacterSet(const QString& excludedCharacterSet);
void reset();
bool isValid() const;
int getMinLength() const;
int getLength() const;
const GeneratorFlags& getFlags() const;
const CharClasses& getActiveClasses() const;
const QString& getCustomCharacterSet() const;
const QString& getExcludedCharacterSet() const;
QString generatePassword() const;
static const int DefaultLength = 32;
static const char* DefaultAdditionalChars;
static const int DefaultLength;
static const char* DefaultCustomCharacterSet;
static const char* DefaultExcludedChars;
private:
@@ -76,10 +87,8 @@ private:
int m_length;
CharClasses m_classes;
GeneratorFlags m_flags;
QString m_additional;
QString m_custom;
QString m_excluded;
Q_DISABLE_COPY(PasswordGenerator)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::CharClasses)

View File

@@ -576,51 +576,15 @@ void PasswordGeneratorWidget::updateGenerator()
auto classes = charClasses();
auto flags = generatorFlags();
int length = 0;
if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) {
if (classes.testFlag(PasswordGenerator::LowerLetters)) {
++length;
}
if (classes.testFlag(PasswordGenerator::UpperLetters)) {
++length;
}
if (classes.testFlag(PasswordGenerator::Numbers)) {
++length;
}
if (classes.testFlag(PasswordGenerator::Braces)) {
++length;
}
if (classes.testFlag(PasswordGenerator::Punctuation)) {
++length;
}
if (classes.testFlag(PasswordGenerator::Quotes)) {
++length;
}
if (classes.testFlag(PasswordGenerator::Dashes)) {
++length;
}
if (classes.testFlag(PasswordGenerator::Math)) {
++length;
}
if (classes.testFlag(PasswordGenerator::Logograms)) {
++length;
}
if (classes.testFlag(PasswordGenerator::EASCII)) {
++length;
}
}
length = qMax(length, m_ui->spinBoxLength->value());
m_passwordGenerator->setLength(length);
m_passwordGenerator->setCharClasses(classes);
m_passwordGenerator->setFlags(flags);
m_passwordGenerator->setLength(m_ui->spinBoxLength->value());
if (m_ui->buttonAdvancedMode->isChecked()) {
m_passwordGenerator->setAdditionalChars(m_ui->editAdditionalChars->text());
m_passwordGenerator->setExcludedChars(m_ui->editExcludedChars->text());
m_passwordGenerator->setCharClasses(classes);
m_passwordGenerator->setCustomCharacterSet(m_ui->editAdditionalChars->text());
m_passwordGenerator->setCustomCharacterSet(m_ui->editExcludedChars->text());
} else {
m_passwordGenerator->setAdditionalChars("");
m_passwordGenerator->setExcludedChars("");
m_passwordGenerator->setCharClasses(classes);
}
m_passwordGenerator->setFlags(flags);
if (m_passwordGenerator->isValid()) {
m_ui->buttonGenerate->setEnabled(true);