Option Explicit On
Option Strict On

Imports System
Imports System.Text

Public Class PasswordGenerator
    Private PWD_LENGTH As Integer

#Region " Random Number Generation "
    'The following class and code in this region was designed
    'by Phill64 on http://www.vbforums.com.  All credit for 
    'random number generation goes to him.
    Protected Class TrueRandom2
        Public Function GetDouble() As Double
            Dim r As New Security.Cryptography.RNGCryptoServiceProvider

            Dim bt(15) As Byte
            r.GetNonZeroBytes(bt)
            Dim d As Double = bt(0)
            For i As Integer = 1 To 15
                d *= bt(i)
            Next
            d /= (10 ^ (Math.Floor(d).ToString.Length))
            d -= Math.Floor(d)
            Return d
        End Function

        Public Function GetNext(ByVal lower As Integer, ByVal upper As Integer) As Integer
            'returns a random itneger between specified bounds
            'ratio a random decimal number to the required bounds

            'Changed CInt to Convert.ToInt32 Derek
            Return Convert.ToInt32((lower + (GetDouble() * (upper - lower))))
        End Function

        Public Function GetNext() As Integer
            'returns a random integer

            'Changed CInt to Convert.ToInt32 Derek
            Return Convert.ToInt32((GetDouble() * Integer.MaxValue))
        End Function

        Public Function GetLong() As Long
            'Changed CLng to Convert.ToInt64 Derek
            Return Convert.ToInt64((GetDouble() * Long.MaxValue))
        End Function
    End Class
#End Region

    Public Sub New()
        PWD_LENGTH = 13
    End Sub

    Public Sub New(ByVal PasswordLength As Integer)
        PWD_LENGTH = PasswordLength
    End Sub

    Public Function Generate() As String
        Dim pwd As String = String.Empty
        Dim rng As New TrueRandom2

        For i As Integer = 1 To PWD_LENGTH
            Dim GoodValue As Boolean = False

            Do While Not GoodValue
                'ASCII value range 32 to 126.
                Dim value As Integer = rng.GetNext(32, 126)

                pwd += Convert.ToChar(value)
                GoodValue = True
            Loop
        Next

        rng = Nothing
        Return pwd
    End Function

    Public Function Generate(ByVal AsciiMin As Integer, ByVal AsciiMax As Integer) As String
        Dim pwd As String = String.Empty
        Dim rng As New TrueRandom2

        For i As Integer = 1 To PWD_LENGTH
            Dim GoodValue As Boolean = False

            Do While Not GoodValue
                'ASCII value range AsciiMin to AsciiMax, to get the correct 
                'range we need to take AsciiMax - AsciiMin = (Ascii Range)
                Dim value As Integer = rng.GetNext(AsciiMin, AsciiMax)

                pwd += Convert.ToChar(value)
                GoodValue = True
            Loop
        Next

        rng = Nothing
        Return pwd
    End Function

    Public Function Generate(ByVal AsciiMin As Char, ByVal AsciiMax As Char) As String
        Dim pwd As String = String.Empty
        Dim rng As New TrueRandom2
        Dim iAsciiMin As Integer = Convert.ToInt32(AsciiMin)
        Dim iAsciiMax As Integer = Convert.ToInt32(AsciiMax)

        For i As Integer = 1 To PWD_LENGTH
            Dim GoodValue As Boolean = False

            Do While Not GoodValue
                'ASCII value range AsciiMin to AsciiMax, to get the correct 
                'range we need to take AsciiMax - AsciiMin = (Ascii Range)
                Dim value As Integer = rng.GetNext(iAsciiMin, iAsciiMax)

                pwd += Convert.ToChar(value)
                GoodValue = True
            Loop
        Next

        rng = Nothing
        Return pwd
    End Function

    Public Function Generate(ByVal ExcludeValues As String()) As String
        Dim pwd As String = String.Empty
        Dim rng As New TrueRandom2
        Dim ASCII_VAL(ExcludeValues.Length - 1) As Integer

        'Convert the excluded values to the the ASCII
        'equivalent of the character represention and
        'add it to the ASCII_VAL array.
        For i As Integer = 0 To ExcludeValues.Length - 1
            ASCII_VAL(i) = Convert.ToInt32(ExcludeValues(i).Chars(0))
        Next

        Array.Sort(ASCII_VAL)
        For i As Integer = 1 To PWD_LENGTH
            Dim GoodValue As Boolean = False

            Do While Not GoodValue
                'ASCII value range 32 to 126.
                Dim value As Integer = rng.GetNext(32, 126)

                'Determine if the value that was generated is
                'not an excluded value.
                If Array.BinarySearch(ASCII_VAL, value) < 0 Then
                    pwd += Convert.ToChar(value)
                    GoodValue = True
                End If
            Loop
        Next

        rng = Nothing
        Return pwd
    End Function

    Public Function Generate(ByVal AsciiMin As Integer, ByVal AsciiMax As Integer, ByVal ExcludeValues As String()) As String
        Dim pwd As String = String.Empty
        Dim rng As New TrueRandom2
        Dim ASCII_VAL(ExcludeValues.Length - 1) As Integer

        'Convert the excluded values to the the ASCII
        'equivalent of the character represention and
        'add it to the ASCII_VAL array.
        For i As Integer = 0 To ExcludeValues.Length - 1
            ASCII_VAL(i) = Convert.ToInt32(ExcludeValues(i).Chars(0))
        Next

        Array.Sort(ASCII_VAL)
        For i As Integer = 1 To PWD_LENGTH
            Dim GoodValue As Boolean = False

            Do While Not GoodValue
                'ASCII value range AsciiMin to AsciiMax, to get the correct 
                'range we need to take AsciiMax - AsciiMin = (Ascii Range)
                Dim value As Integer = rng.GetNext(AsciiMin, AsciiMax)

                'Determine if the value that was generated is
                'not an excluded value.
                If Array.BinarySearch(ASCII_VAL, value) < 0 Then
                    pwd += Convert.ToChar(value)
                    GoodValue = True
                End If
            Loop
        Next

        rng = Nothing
        Return pwd
    End Function

    Public Function Generate(ByVal AsciiMin As Char, ByVal AsciiMax As Char, ByVal ExcludeValues As String()) As String
        Dim pwd As String = String.Empty
        Dim rng As New TrueRandom2
        Dim iAsciiMin As Integer = Convert.ToInt32(AsciiMin)
        Dim iAsciiMax As Integer = Convert.ToInt32(AsciiMax)
        Dim ASCII_VAL(ExcludeValues.Length - 1) As Integer

        'Convert the excluded values to the the ASCII
        'equivalent of the character represention and
        'add it to the ASCII_VAL array.
        For i As Integer = 0 To ExcludeValues.Length - 1
            ASCII_VAL(i) = Convert.ToInt32(ExcludeValues(i).Chars(0))
        Next

        Array.Sort(ASCII_VAL)
        For i As Integer = 1 To PWD_LENGTH
            Dim GoodValue As Boolean = False

            Do While Not GoodValue
                'ASCII value range AsciiMin to AsciiMax, to get the correct 
                'range we need to take AsciiMax - AsciiMin = (Ascii Range)
                Dim value As Integer = rng.GetNext(iAsciiMin, iAsciiMax)

                'Determine if the value that was generated is
                'not an excluded value.
                If Array.BinarySearch(ASCII_VAL, value) < 0 Then
                    pwd += Convert.ToChar(value)
                    GoodValue = True
                End If
            Loop
        Next

        rng = Nothing
        Return pwd
    End Function
End Class