mirror of
https://github.com/wneessen/apg-go.git
synced 2024-11-22 13:50:49 +01:00
v0.2.8: De-cluttered the config flags stuff
This commit is contained in:
parent
dd1a6b2b62
commit
1130a698f6
5 changed files with 196 additions and 199 deletions
46
apg.go
46
apg.go
|
@ -2,29 +2,59 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/wneessen/apg.go/config"
|
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const DefaultPwLenght int = 20
|
||||||
|
const VersionString string = "0.2.8"
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
minPassLen int
|
||||||
|
maxPassLen int
|
||||||
|
numOfPass int
|
||||||
|
useComplex bool
|
||||||
|
useLowerCase bool
|
||||||
|
useUpperCase bool
|
||||||
|
useNumber bool
|
||||||
|
useSpecial bool
|
||||||
|
humanReadable bool
|
||||||
|
excludeChars string
|
||||||
|
newStyleModes string
|
||||||
|
spellPassword bool
|
||||||
|
ShowHelp bool
|
||||||
|
showVersion bool
|
||||||
|
outputMode int
|
||||||
|
}
|
||||||
|
|
||||||
// Main function that generated the passwords and returns them
|
// Main function that generated the passwords and returns them
|
||||||
func main() {
|
func main() {
|
||||||
// Log config
|
// Log config
|
||||||
log.SetFlags(log.Ltime | log.Ldate | log.Lshortfile)
|
log.SetFlags(log.Ltime | log.Ldate | log.Lshortfile)
|
||||||
|
|
||||||
// Create config
|
// Read and parse flags
|
||||||
conf := config.NewConfig()
|
var config = parseFlags()
|
||||||
conf.ParseParams()
|
|
||||||
pwLength := conf.GetPwLengthFromParams()
|
// Show version and exit
|
||||||
charRange := getCharRange(conf)
|
if config.showVersion {
|
||||||
|
_, _ = os.Stderr.WriteString("Advanced Password Generator Clone (apg.go) v" + VersionString + "\n")
|
||||||
|
_, _ = os.Stderr.WriteString("(C) 2021 by Winni Neessen\n")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set PW length and available characterset
|
||||||
|
pwLength := getPwLengthFromParams(&config)
|
||||||
|
charRange := getCharRange(&config)
|
||||||
|
|
||||||
// Generate passwords
|
// Generate passwords
|
||||||
for i := 1; i <= conf.NumOfPass; i++ {
|
for i := 1; i <= config.numOfPass; i++ {
|
||||||
pwString, err := getRandChar(&charRange, pwLength)
|
pwString, err := getRandChar(&charRange, pwLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("getRandChar returned an error: %q\n", err)
|
log.Fatalf("getRandChar returned an error: %q\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch conf.OutputMode {
|
switch config.outputMode {
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
spelledPw, err := spellPasswordString(pwString)
|
spelledPw, err := spellPasswordString(pwString)
|
||||||
|
|
56
apg_test.go
56
apg_test.go
|
@ -1,9 +1,15 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "testing"
|
||||||
"github.com/wneessen/apg.go/config"
|
|
||||||
"testing"
|
var config Config
|
||||||
)
|
|
||||||
|
// Make sure the flags are initalized
|
||||||
|
var _ = func() bool {
|
||||||
|
testing.Init()
|
||||||
|
config = parseFlags()
|
||||||
|
return true
|
||||||
|
}()
|
||||||
|
|
||||||
// Test getRandNum with max 1000
|
// Test getRandNum with max 1000
|
||||||
func TestGetRandNum(t *testing.T) {
|
func TestGetRandNum(t *testing.T) {
|
||||||
|
@ -114,16 +120,14 @@ func TestGetCharRange(t *testing.T) {
|
||||||
{"special_only_human", specialHumanBytes, false, false, false, true, true},
|
{"special_only_human", specialHumanBytes, false, false, false, true, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := config.NewConfig()
|
|
||||||
conf.ParseParams()
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.testName, func(t *testing.T) {
|
t.Run(testCase.testName, func(t *testing.T) {
|
||||||
conf.UseLowerCase = testCase.useLowerCase
|
config.useLowerCase = testCase.useLowerCase
|
||||||
conf.UseUpperCase = testCase.useUpperCase
|
config.useUpperCase = testCase.useUpperCase
|
||||||
conf.UseNumber = testCase.useNumber
|
config.useNumber = testCase.useNumber
|
||||||
conf.UseSpecial = testCase.useSpecial
|
config.useSpecial = testCase.useSpecial
|
||||||
conf.HumanReadable = testCase.humanReadable
|
config.humanReadable = testCase.humanReadable
|
||||||
charRange := getCharRange(conf)
|
charRange := getCharRange(&config)
|
||||||
for _, curChar := range charRange {
|
for _, curChar := range charRange {
|
||||||
searchAllowedBytes := containsByte(testCase.allowedBytes, int(curChar), t)
|
searchAllowedBytes := containsByte(testCase.allowedBytes, int(curChar), t)
|
||||||
if !searchAllowedBytes {
|
if !searchAllowedBytes {
|
||||||
|
@ -147,8 +151,6 @@ func TestConvert(t *testing.T) {
|
||||||
{"convert_0_to_ZERO", '0', "ZERO", false},
|
{"convert_0_to_ZERO", '0', "ZERO", false},
|
||||||
{"convert_/_to_SLASH", '/', "SLASH", false},
|
{"convert_/_to_SLASH", '/', "SLASH", false},
|
||||||
}
|
}
|
||||||
conf := config.NewConfig()
|
|
||||||
conf.ParseParams()
|
|
||||||
|
|
||||||
for _, testCase := range testTable {
|
for _, testCase := range testTable {
|
||||||
t.Run(testCase.testName, func(t *testing.T) {
|
t.Run(testCase.testName, func(t *testing.T) {
|
||||||
|
@ -171,12 +173,12 @@ func TestConvert(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("all_chars_must_return_a_conversion_string", func(t *testing.T) {
|
t.Run("all_chars_must_return_a_conversion_string", func(t *testing.T) {
|
||||||
conf.UseUpperCase = true
|
config.useUpperCase = true
|
||||||
conf.UseLowerCase = true
|
config.useLowerCase = true
|
||||||
conf.UseNumber = true
|
config.useNumber = true
|
||||||
conf.UseSpecial = true
|
config.useSpecial = true
|
||||||
conf.HumanReadable = false
|
config.humanReadable = false
|
||||||
charRange := getCharRange(conf)
|
charRange := getCharRange(&config)
|
||||||
for _, curChar := range charRange {
|
for _, curChar := range charRange {
|
||||||
_, err := convertCharToName(byte(curChar))
|
_, err := convertCharToName(byte(curChar))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -215,15 +217,13 @@ func BenchmarkGetRandChar(b *testing.B) {
|
||||||
|
|
||||||
// Benchmark: Random char generation
|
// Benchmark: Random char generation
|
||||||
func BenchmarkConvertChar(b *testing.B) {
|
func BenchmarkConvertChar(b *testing.B) {
|
||||||
conf := config.NewConfig()
|
|
||||||
conf.ParseParams()
|
|
||||||
|
|
||||||
conf.UseUpperCase = true
|
config.useUpperCase = true
|
||||||
conf.UseLowerCase = true
|
config.useLowerCase = true
|
||||||
conf.UseNumber = true
|
config.useNumber = true
|
||||||
conf.UseSpecial = true
|
config.useSpecial = true
|
||||||
conf.HumanReadable = false
|
config.humanReadable = false
|
||||||
charRange := getCharRange(conf)
|
charRange := getCharRange(&config)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
charToConv, _ := getRandChar(&charRange, 1)
|
charToConv, _ := getRandChar(&charRange, 1)
|
||||||
charBytes := []byte(charToConv)
|
charBytes := []byte(charToConv)
|
||||||
|
|
17
chars.go
17
chars.go
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wneessen/apg.go/config"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,12 +14,12 @@ const PwNumbersHuman string = "23456789"
|
||||||
const PwNumbers string = "1234567890"
|
const PwNumbers string = "1234567890"
|
||||||
|
|
||||||
// Provide the range of available characters based on provided parameters
|
// Provide the range of available characters based on provided parameters
|
||||||
func getCharRange(config *config.Config) string {
|
func getCharRange(config *Config) string {
|
||||||
pwUpperChars := PwUpperChars
|
pwUpperChars := PwUpperChars
|
||||||
pwLowerChars := PwLowerChars
|
pwLowerChars := PwLowerChars
|
||||||
pwNumbers := PwNumbers
|
pwNumbers := PwNumbers
|
||||||
pwSpecialChars := PwSpecialChars
|
pwSpecialChars := PwSpecialChars
|
||||||
if config.HumanReadable {
|
if config.humanReadable {
|
||||||
pwUpperChars = PwUpperCharsHuman
|
pwUpperChars = PwUpperCharsHuman
|
||||||
pwLowerChars = PwLowerCharsHuman
|
pwLowerChars = PwLowerCharsHuman
|
||||||
pwNumbers = PwNumbersHuman
|
pwNumbers = PwNumbersHuman
|
||||||
|
@ -28,20 +27,20 @@ func getCharRange(config *config.Config) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var charRange string
|
var charRange string
|
||||||
if config.UseLowerCase {
|
if config.useLowerCase {
|
||||||
charRange = charRange + pwLowerChars
|
charRange = charRange + pwLowerChars
|
||||||
}
|
}
|
||||||
if config.UseUpperCase {
|
if config.useUpperCase {
|
||||||
charRange = charRange + pwUpperChars
|
charRange = charRange + pwUpperChars
|
||||||
}
|
}
|
||||||
if config.UseNumber {
|
if config.useNumber {
|
||||||
charRange = charRange + pwNumbers
|
charRange = charRange + pwNumbers
|
||||||
}
|
}
|
||||||
if config.UseSpecial {
|
if config.useSpecial {
|
||||||
charRange = charRange + pwSpecialChars
|
charRange = charRange + pwSpecialChars
|
||||||
}
|
}
|
||||||
if config.ExcludeChars != "" {
|
if config.excludeChars != "" {
|
||||||
regExp := regexp.MustCompile("[" + regexp.QuoteMeta(config.ExcludeChars) + "]")
|
regExp := regexp.MustCompile("[" + regexp.QuoteMeta(config.excludeChars) + "]")
|
||||||
charRange = regExp.ReplaceAllLiteralString(charRange, "")
|
charRange = regExp.ReplaceAllLiteralString(charRange, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
122
config.go
Normal file
122
config.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Parse the CLI flags
|
||||||
|
func parseFlags() Config {
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
// Read and set all flags
|
||||||
|
flag.BoolVar(&config.useLowerCase, "L", true, "Use lower case characters in passwords")
|
||||||
|
flag.BoolVar(&config.useUpperCase, "U", true, "Use upper case characters in passwords")
|
||||||
|
flag.BoolVar(&config.useNumber, "N", true, "Use numbers in passwords")
|
||||||
|
flag.BoolVar(&config.useSpecial, "S", false, "Use special characters in passwords")
|
||||||
|
flag.BoolVar(&config.useComplex, "C", false, "Generate complex passwords (implies -L -U -N -S, disables -H)")
|
||||||
|
flag.BoolVar(&config.spellPassword, "l", false, "Spell generated password")
|
||||||
|
flag.BoolVar(&config.humanReadable, "H", false, "Generate human-readable passwords")
|
||||||
|
flag.BoolVar(&config.showVersion, "v", false, "Show version")
|
||||||
|
flag.IntVar(&config.minPassLen, "m", DefaultPwLenght, "Minimum password length")
|
||||||
|
flag.IntVar(&config.maxPassLen, "x", DefaultPwLenght, "Maxiumum password length")
|
||||||
|
flag.IntVar(&config.numOfPass, "n", 1, "Number of passwords to generate")
|
||||||
|
flag.StringVar(&config.excludeChars, "E", "", "Exclude list of characters from generated password")
|
||||||
|
flag.StringVar(&config.newStyleModes, "M", "",
|
||||||
|
"New style password parameters (higher priority than single parameters)")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Parse additional parameters
|
||||||
|
parseParams(&config)
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the parameters and set the according config flags
|
||||||
|
func parseParams(config *Config) {
|
||||||
|
parseNewStyleParams(config)
|
||||||
|
|
||||||
|
// Complex overrides everything
|
||||||
|
if config.useComplex {
|
||||||
|
config.useUpperCase = true
|
||||||
|
config.useLowerCase = true
|
||||||
|
config.useSpecial = true
|
||||||
|
config.useNumber = true
|
||||||
|
config.humanReadable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.useUpperCase == false &&
|
||||||
|
config.useLowerCase == false &&
|
||||||
|
config.useNumber == false &&
|
||||||
|
config.useSpecial == false {
|
||||||
|
log.Fatalf("No password mode set. Cannot generate password from empty character set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set output mode
|
||||||
|
if config.spellPassword {
|
||||||
|
config.outputMode = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the password length from the given cli flags
|
||||||
|
func getPwLengthFromParams(config *Config) int {
|
||||||
|
pwLength := config.minPassLen
|
||||||
|
if pwLength < config.minPassLen {
|
||||||
|
pwLength = config.minPassLen
|
||||||
|
}
|
||||||
|
if pwLength > config.maxPassLen {
|
||||||
|
pwLength = config.maxPassLen
|
||||||
|
}
|
||||||
|
|
||||||
|
return pwLength
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the new style parameters
|
||||||
|
func parseNewStyleParams(config *Config) {
|
||||||
|
if config.newStyleModes == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, curParam := range config.newStyleModes {
|
||||||
|
switch curParam {
|
||||||
|
case 'S':
|
||||||
|
config.useSpecial = true
|
||||||
|
break
|
||||||
|
case 's':
|
||||||
|
config.useSpecial = false
|
||||||
|
break
|
||||||
|
case 'N':
|
||||||
|
config.useNumber = true
|
||||||
|
break
|
||||||
|
case 'n':
|
||||||
|
config.useNumber = false
|
||||||
|
break
|
||||||
|
case 'L':
|
||||||
|
config.useLowerCase = true
|
||||||
|
break
|
||||||
|
case 'l':
|
||||||
|
config.useLowerCase = false
|
||||||
|
break
|
||||||
|
case 'U':
|
||||||
|
config.useUpperCase = true
|
||||||
|
break
|
||||||
|
case 'u':
|
||||||
|
config.useUpperCase = false
|
||||||
|
break
|
||||||
|
case 'H':
|
||||||
|
config.humanReadable = true
|
||||||
|
break
|
||||||
|
case 'h':
|
||||||
|
config.humanReadable = false
|
||||||
|
break
|
||||||
|
case 'C':
|
||||||
|
config.useComplex = true
|
||||||
|
break
|
||||||
|
case 'c':
|
||||||
|
config.useComplex = false
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
log.Fatalf("Unknown password style parameter: %q\n", string(curParam))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
154
config/config.go
154
config/config.go
|
@ -1,154 +0,0 @@
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
const DefaultPwLenght int = 20
|
|
||||||
const VersionString string = "0.2.7"
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
MinPassLen int
|
|
||||||
MaxPassLen int
|
|
||||||
NumOfPass int
|
|
||||||
UseComplex bool
|
|
||||||
UseLowerCase bool
|
|
||||||
UseUpperCase bool
|
|
||||||
UseNumber bool
|
|
||||||
UseSpecial bool
|
|
||||||
HumanReadable bool
|
|
||||||
ExcludeChars string
|
|
||||||
NewStyleModes string
|
|
||||||
SpellPassword bool
|
|
||||||
ShowHelp bool
|
|
||||||
showVersion bool
|
|
||||||
OutputMode int
|
|
||||||
}
|
|
||||||
|
|
||||||
var config Config
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Bool flags
|
|
||||||
flag.BoolVar(&config.UseLowerCase, "L", true, "Use lower case characters in passwords")
|
|
||||||
flag.BoolVar(&config.UseUpperCase, "U", true, "Use upper case characters in passwords")
|
|
||||||
flag.BoolVar(&config.UseNumber, "N", true, "Use numbers in passwords")
|
|
||||||
flag.BoolVar(&config.UseSpecial, "S", false, "Use special characters in passwords")
|
|
||||||
flag.BoolVar(&config.UseComplex, "C", false, "Generate complex passwords (implies -L -U -N -S, disables -H)")
|
|
||||||
flag.BoolVar(&config.SpellPassword, "l", false, "Spell generated password")
|
|
||||||
flag.BoolVar(&config.HumanReadable, "H", false, "Generate human-readable passwords")
|
|
||||||
flag.BoolVar(&config.showVersion, "v", false, "Show version")
|
|
||||||
|
|
||||||
// Int flags
|
|
||||||
flag.IntVar(&config.MinPassLen, "m", DefaultPwLenght, "Minimum password length")
|
|
||||||
flag.IntVar(&config.MaxPassLen, "x", DefaultPwLenght, "Maxiumum password length")
|
|
||||||
flag.IntVar(&config.NumOfPass, "n", 1, "Number of passwords to generate")
|
|
||||||
|
|
||||||
// String flags
|
|
||||||
flag.StringVar(&config.ExcludeChars, "E", "", "Exclude list of characters from generated password")
|
|
||||||
flag.StringVar(&config.NewStyleModes, "M", "",
|
|
||||||
"New style password parameters (higher priority than single parameters)")
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfig() *Config {
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if config.showVersion {
|
|
||||||
_, _ = os.Stderr.WriteString("Advanced Password Generator Clone (apg.go) v" + VersionString + "\n")
|
|
||||||
_, _ = os.Stderr.WriteString("(C) 2021 by Winni Neessen\n")
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &config
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the parameters and set the according config flags
|
|
||||||
func (config *Config) ParseParams() {
|
|
||||||
config.parseNewStyleParams()
|
|
||||||
|
|
||||||
// Complex overrides everything
|
|
||||||
if config.UseComplex {
|
|
||||||
config.UseUpperCase = true
|
|
||||||
config.UseLowerCase = true
|
|
||||||
config.UseSpecial = true
|
|
||||||
config.UseNumber = true
|
|
||||||
config.HumanReadable = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.UseUpperCase == false &&
|
|
||||||
config.UseLowerCase == false &&
|
|
||||||
config.UseNumber == false &&
|
|
||||||
config.UseSpecial == false {
|
|
||||||
log.Fatalf("No password mode set. Cannot generate password from empty character set.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set output mode
|
|
||||||
if config.SpellPassword {
|
|
||||||
config.OutputMode = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the password length from the given cli flags
|
|
||||||
func (config *Config) GetPwLengthFromParams() int {
|
|
||||||
pwLength := config.MinPassLen
|
|
||||||
if pwLength < config.MinPassLen {
|
|
||||||
pwLength = config.MinPassLen
|
|
||||||
}
|
|
||||||
if pwLength > config.MaxPassLen {
|
|
||||||
pwLength = config.MaxPassLen
|
|
||||||
}
|
|
||||||
|
|
||||||
return pwLength
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the new style parameters
|
|
||||||
func (config *Config) parseNewStyleParams() {
|
|
||||||
if config.NewStyleModes == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, curParam := range config.NewStyleModes {
|
|
||||||
switch curParam {
|
|
||||||
case 'S':
|
|
||||||
config.UseSpecial = true
|
|
||||||
break
|
|
||||||
case 's':
|
|
||||||
config.UseSpecial = false
|
|
||||||
break
|
|
||||||
case 'N':
|
|
||||||
config.UseNumber = true
|
|
||||||
break
|
|
||||||
case 'n':
|
|
||||||
config.UseNumber = false
|
|
||||||
break
|
|
||||||
case 'L':
|
|
||||||
config.UseLowerCase = true
|
|
||||||
break
|
|
||||||
case 'l':
|
|
||||||
config.UseLowerCase = false
|
|
||||||
break
|
|
||||||
case 'U':
|
|
||||||
config.UseUpperCase = true
|
|
||||||
break
|
|
||||||
case 'u':
|
|
||||||
config.UseUpperCase = false
|
|
||||||
break
|
|
||||||
case 'H':
|
|
||||||
config.HumanReadable = true
|
|
||||||
break
|
|
||||||
case 'h':
|
|
||||||
config.HumanReadable = false
|
|
||||||
break
|
|
||||||
case 'C':
|
|
||||||
config.UseComplex = true
|
|
||||||
break
|
|
||||||
case 'c':
|
|
||||||
config.UseComplex = false
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
log.Fatalf("Unknown password style parameter: %q\n", string(curParam))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue