RosettaCodeData/Task/Password-generator/Swift/password-generator-3.swift
2023-07-01 13:44:08 -04:00

124 lines
3.9 KiB
Swift

import Foundation
import GameplayKit // for use of inbuilt Fisher-Yates-Shuffle
/* Prints the usage of this code */
func printHelp() -> Void {
print("Usage: PasswordGenerator [-l:length] [-c:count] [-s:seed] [-x:exclude] [-h:help]")
print("\t-l: length of the passwords (at leas 4 characters)")
print("\t-c: number of passwords to generate")
print("\t-s: seed of the random number generator")
print("\t-x: exclude of visually similar characters \"Il1O05S2Z\"")
print("\t-h: print this help")
exit(0)
}
/* Set characters for generating passwords */
let _lower:String = "abcdefghijklmnopqrstuvwxyz"
let _lowerWithoutSimilar:String = "abcdefghijkmnopqrstuvwxyz"
let _upper:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
let _upperWithoutSimilar = "ABCDEFGHJKLMNPQRTUVWXY"
let _number:String = "0123456789"
let _numerWithoutSimilar:String = "1346789"
let _other:String = "!\"#$%&'()*+,-./:;<=>?@[]^_{|}~"
/* Generate character arrays out of strings */
let upper = Array(_upper.characters)
let upperWithoutSimilar = Array(_upperWithoutSimilar.characters)
let lower = Array(_lower.characters)
let lowerWithoutSimilar = Array(_lowerWithoutSimilar.characters)
let other = Array(_other.characters)
let number = Array(_number.characters)
let numberWithoutSimilar = Array(_numerWithoutSimilar.characters)
var length:Int=0, count:Int=0, seed:Int=0, xclude:Bool=false
/* Parse CLI arguments */
for i in 1..<CommandLine.arguments.count{
var arg = CommandLine.arguments[i]
var argument = arg.components(separatedBy: ":")
switch(argument[0]){
case "-l":
length=Int(argument[1])!
if length < 4 {
print("A password must contain of at least 4 characters.")
exit(-1)
}
break
case "-c":
count=Int(argument[1])!
break
case "-s":
seed=Int(argument[1])!
break
case "-x":
xclude=true
break
case "-h":
printHelp()
default:
print("Could not parse CLI arguments. Use -h for help.")
exit(0)
}
}
/* Generate password of given length */
func generatePassword(length len:Int, exclude xcl:Bool) -> String{
var ret:String = "", loopCount:Int = 0
while(loopCount < len){
if ret.characters.count < len {
if xcl {
ret += String(upperWithoutSimilar[Int(getRand(Int32(upperWithoutSimilar.count-1)))])
}
else {
ret += String(upper[Int(getRand(Int32(upper.count)))])
}
}
if ret.characters.count < len {
if xcl {
ret += String(lowerWithoutSimilar[Int(getRand(Int32(lowerWithoutSimilar.count-1)))])
}
else {
ret += String(lower[Int(getRand(Int32(lower.count-1)))])
}
}
if ret.characters.count < len {
if xcl {
ret += String(numberWithoutSimilar[Int(getRand(Int32(numberWithoutSimilar.count-1)))])
}
else {
ret += String(number[Int(getRand(Int32(number.count-1)))])
}
}
if ret.characters.count < len {
ret += String(other[Int(getRand(Int32(other.count-1)))])
}
loopCount += 4
}
// Shuffle the array with an internal shuffle function
let shuffled = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: Array(ret.characters))
ret = ""
for element in shuffled {
ret += String(describing: element)
}
return ret
}
if xclude {
print("Generating \(count) passwords with length \(length) excluding visually similar characters...")
}
else {
print("Generating \(count) passwords with length \(length) not excluding visually similar characters...")
}
initRandom(UInt32(0)) // initialize with C func srand()
// generate the passwords
for i in 1...count {
print("\(i).\t\(generatePassword(length:length,exclude:xclude))")
}