Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 24 additions & 41 deletions xkcdpass/xkcd_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,10 @@ def validate_options(parser, options):
"""

if options.max_length < options.min_length:
sys.stderr.write("Warning: maximum word length less than minimum. "
"Setting maximum equal to minimum.\n")
# sys.exit(1)
raise SystemExit("Error: Maximum word length can't be less than minimum word length.\n")

wordfile = locate_wordfile(options.wordfile)
if not wordfile:
sys.stderr.write("Could not find a word file, or word file does "
"not exist.\n")
sys.exit(1)
if not locate_wordfile(options.wordfile):
raise SystemExit("Wordfile not found. Is the path correct?\n")


def locate_wordfile(wordfile=None):
Expand Down Expand Up @@ -119,10 +114,6 @@ def generate_wordlist(wordfile=None,
valid_chars is a regular expression match condition (default - all chars)
"""

# deal with inconsistent min and max, erring toward security
if min_length > max_length:
max_length = min_length

words = set()

regexp = re.compile("^{0}{{{1},{2}}}$".format(valid_chars,
Expand All @@ -141,7 +132,7 @@ def generate_wordlist(wordfile=None,
if len(words):
return list(words) # deduplicate, just in case
else:
raise SystemExit("Error: provided arguments result in zero-length wordlist, exiting.")
raise SystemExit("Error: Provided arguments result in emtpy wordlist. (Probably because there aren't any words that match your --min and --max options) Exiting.")


def wordlist_to_worddict(wordlist):
Expand Down Expand Up @@ -201,8 +192,7 @@ def find_acrostic(acrostic, worddict):
try:
words.append(rng().choice(worddict[letter]))
except KeyError:
sys.stderr.write("No words found starting with " + letter + "\n")
sys.exit(1)
raise SystemExit("No words found starting with " + letter + "\n")
return words


Expand All @@ -227,7 +217,6 @@ def try_input(prompt, validate):
print("")
sys.exit(0)

# validate input
return validate(answer)


Expand Down Expand Up @@ -346,14 +335,15 @@ def generate_xkcdpassword(wordlist,
worddict = wordlist_to_worddict(wordlist)

def gen_passwd():
if not acrostic:
words = choose_words(wordlist, numwords)
else:
if acrostic:
words = find_acrostic(acrostic, worddict)
else:
words = choose_words(wordlist, numwords)

if not random_delimiters:
if random_delimiters:
return randomized_delimiter_join(set_case(words, method=case), valid_delimiters)
else:
return delimiter.join(set_case(words, method=case))
return randomized_delimiter_join(set_case(words, method=case), valid_delimiters)

# useful if driving the logic from other code
if not interactive:
Expand Down Expand Up @@ -408,8 +398,7 @@ def n_words_validator(answer):
raise ValueError
return number
except ValueError:
sys.stderr.write("Please enter a positive integer\n")
sys.exit(1)
raise SystemExit("Please enter a positive integer\n")

if not options.acrostic:
n_words_prompt = ("Enter number of words (default {0}):\n".format(options.numwords))
Expand All @@ -419,26 +408,19 @@ def n_words_validator(answer):


def emit_passwords(wordlist, options):
""" Generate the specified number of passwords and output them. """
count = options.count
if options.valid_delimiters:
valid_delimiters = list(options.valid_delimiters) + [""]
else:
valid_delimiters = DEFAULT_DELIMITERS
while count > 0:
print(
generate_xkcdpassword(
""" Generate the specified number of passwords and output them to stdout. """

for _ in range(options.count):
print(generate_xkcdpassword(
wordlist,
interactive=options.interactive,
numwords=options.numwords,
acrostic=options.acrostic,
delimiter=options.delimiter,
random_delimiters=options.random_delimiters,
valid_delimiters=valid_delimiters,
case=options.case,
),
end=options.separator)
count -= 1
valid_delimiters=list(options.valid_delimiters) if options.valid_delimiters else DEFAULT_DELIMITERS,
case=options.case),
end=options.separator)


class XkcdPassArgumentParser(argparse.ArgumentParser):
Expand Down Expand Up @@ -510,12 +492,13 @@ def _add_arguments(self):
self.add_argument(
"-D", "--valid-delimiters",
dest="valid_delimiters", default="", metavar="VALID_DELIMITERS",
help=("A string with all valid delimiter characters."
" For example, '^&*' would use ^, &, or *"))
help=("When --random-delimiters is specified, use ANY of these characters to separate words."
" For example, --random-delimiters='^&*' would use ^, &, or * as separators."
" This option has no effect if --random-delimiters is not supplied."))
self.add_argument(
"-s", "--separator",
dest="separator", default="\n", metavar="SEP",
help="Separate generated passphrases with SEP.")
help="Separate generated passphrases with SEP. (default: newline)")
self.add_argument(
"-C", "--case",
dest="case", type=str, metavar="CASE",
Expand Down Expand Up @@ -571,5 +554,5 @@ def main(argv=None):


if __name__ == '__main__':
exit_status = main(sys.argv)
raise SystemExit(main(sys.argv))
sys.exit(exit_status)