#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Random password generation

@author: Thore Christiansen
@contact: www.unimedia-webservice.com
@version: 1.0

Copyright 2011 by UNIMEDIA webservice UG

License: <http://www.gnu.org/licenses/gpl.txt>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

_help = """
Usage: passgen [-options]
where options include:
    -N <number>      number of generated passwords             ( default: 1 )
    -L <length>      length of generated passwords             ( default: 8 )
    -P False         not printable                             ( default: True )
    
    -U <types>       set types of possible caracters
    -T <types>       at least on caracter of these types will be included
    
    types:                                                     ( default: LUDS )
        L = lowercase
        U = uppercase
        D = digit
        S = special caracters

    -cL <value> [1-9] multiply chance for lowercase caracters  ( default: 2 )
    -cU <value> [1-9] multiply chance for uppercase caracters  ( default: 2 )
    -cD <value> [1-9] multiply chance for digits               ( default: 2 )
    -cS <value> [1-9] multiply chance for special caracters    ( default: 1 )

See: http://blog.unimedia-webservice.de/2011/11/random-passwort-generator.html
Copyright 2011 by UNIMEDIA webservice UG
License: <http://www.gnu.org/licenses/gpl.txt>
"""
import sys
import string
from random import choice

#default settings:

number = 1            # number of generated passwords
length = 8            # lenth of generated password
use_lower   = True    # include lowercase letters
use_upper   = True    # include uppercase letters
use_digit   = True    # include digits
use_special = True    # include special letters
chance_lower   = 2    # multiply frequency of lowercase letters
chance_upper   = 2    # multiply frequency of uppercase letters
chance_digit   = 2    # multiply frequency of digits
chance_special = 1    # multiply frequency of special letters
test_lower   = True   # at least one lowercase letter included
test_upper   = True   # at least one uppercase letter included
test_digit   = True   # at least one digit included
test_special = True   # at least one special letter included
printable = True      # printable passwort: avoid caracters below
avoit_caracters = ['I','l','1','o','O','0','"',"'",'`']

def genPassword():
    # build stream
    stream = ''
    if use_lower:
        stream += string.ascii_lowercase * chance_lower
    if use_upper:
        stream += string.ascii_uppercase * chance_upper
    if use_digit:
        stream += string.digits * chance_digit
    if use_special:
        stream += string.punctuation * chance_special
    if printable:
        for caracter in avoit_caracters:
            stream = stream.replace(caracter,'')
    
    #generate password
    passwords = []
    for n in range(number):
        while True:
            PASS = ''.join([choice(stream) for i in range(length)])
            if checkPassword(PASS):
                break
        passwords.append(PASS)
    return passwords

def checkPassword(PASS):
    if test_lower:
        result_lower = False
        for X in string.ascii_lowercase:
            if X in PASS:
                result_lower = True
                break
        if result_lower == False:
            return False
    if test_upper:
        result_upper = False
        for X in string.ascii_uppercase:
            if X in PASS:
                result_upper = True
                break
        if result_upper == False:
            return False
    if test_digit:
        result_digit = False
        for X in string.digits:
            if X in PASS:
                result_digit = True
                break
        if result_digit == False:
            return False
    if test_special:
        result_special = False
        for X in string.punctuation:
            if X in PASS:
                result_special = True
                break
        if result_special == False:
            return False
    return True

if __name__ == '__main__':
    #pharse argv
    if '-help' in sys.argv:
        print _help
        exit()
    if '-N' in sys.argv:
        try:    number = int(sys.argv[sys.argv.index('-N')+1])
        except: pass
    if '-L' in sys.argv:
        try:    length = int(sys.argv[sys.argv.index('-L')+1])
        except: pass
    if '-P' in sys.argv:
        P = sys.argv[sys.argv.index('-P')+1]
        if P == 'False' or P == 'FALSE' or P == '0':
            printable = False
    if '-T' in sys.argv:
        test = list(sys.argv[sys.argv.index('-T')+1])
        if not 'L' in test: test_lower = False
        if not 'U' in test: test_upper = False
        if not 'D' in test: test_digit = False
        if not 'S' in test: test_special = False
    if '-U' in sys.argv:
        use = list(sys.argv[sys.argv.index('-U')+1])
        if not 'L' in use:
            use_lower = False
            test_lower = False
        if not 'U' in use:
            use_upper = False
            test_upper = False
        if not 'D' in use:
            use_digit = False
            test_digit = False
        if not 'S' in use:
            use_special = False
            test_special = False
    if '-cL' in sys.argv:
        try:
            cL = int(sys.argv[sys.argv.index('-cL')+1])
            if cL < 1: cL = 1
            if cL > 10: cL = 10
            chance_lower = cL
        except: pass
    if '-cU' in sys.argv:
        try:
            cU = int(sys.argv[sys.argv.index('-cU')+1])
            if cU < 1: cU = 1
            if cU > 10: cU = 10
            use_upper = cU
        except: pass
    if '-cD' in sys.argv:
        try:
            cD = int(sys.argv[sys.argv.index('-cD')+1])
            if cD < 1: cD = 1
            if cD > 10: cD = 10
            chance_digit = cD
        except: pass
    if '-cS' in sys.argv:
        try:
            cS = int(sys.argv[sys.argv.index('-cS')+1])
            if cS < 1: cS = 1
            if cS > 10: cS = 10
            chance_special = cS
        except: pass
    passwords = genPassword()
    print ''
    if number == 1: 
        print '1 password generated:'
    else:
        print '%s passwords generated:'%number
    print '-'*length
    for PASS in passwords:
        print PASS
    print '-'*length
    print ''