Forms and Passwords

J

Joshua Kendall

I have a script in which it keeps opening the same form
instead of only one instance. I also need help with a
form that has a password. Where do I put the actual
password? can I use a database for multiple users?

opens multiple instances of password form instead of one:

Public Class Splash
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component
list.
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the
Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents SplashIMG As
System.Windows.Forms.PictureBox
Friend WithEvents SplashTimer As
System.Windows.Forms.Timer
<System.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent()
Me.components = New
System.ComponentModel.Container()
Dim resources As System.Resources.ResourceManager
= New System.Resources.ResourceManager(GetType(Splash))
Me.SplashIMG = New System.Windows.Forms.PictureBox
()
Me.SplashTimer = New System.Windows.Forms.Timer
(Me.components)
Me.SuspendLayout()
'
'SplashIMG
'
Me.SplashIMG.Image = CType(resources.GetObject
("SplashIMG.Image"), System.Drawing.Bitmap)
Me.SplashIMG.Name = "SplashIMG"
Me.SplashIMG.Size = New System.Drawing.Size(600,
300)
Me.SplashIMG.TabIndex = 0
Me.SplashIMG.TabStop = False
'
'SplashTimer
'
Me.SplashTimer.Enabled = True
Me.SplashTimer.Interval = 1000
'
'Splash
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5,
13)
Me.ClientSize = New System.Drawing.Size(600, 300)
Me.Controls.AddRange(New
System.Windows.Forms.Control() {Me.SplashIMG})
Me.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.None
Me.Name = "Splash"
Me.ShowInTaskbar = False
Me.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = "KS.IntraNet"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub SplashIMG_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
SplashIMG.Click

End Sub

Private Sub Timer1_Tick(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
SplashTimer.Tick
Dim frmLogin As New Login()
frmLogin.Show()
End Sub

End Class

Password Form:

Public Class Login
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component
list.
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the
Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents UserLbl As
System.Windows.Forms.Label
Friend WithEvents UserINP As
System.Windows.Forms.TextBox
Friend WithEvents PassINP As
System.Windows.Forms.TextBox
Friend WithEvents PassLbl As
System.Windows.Forms.Label
Friend WithEvents LoginBTN As
System.Windows.Forms.Button
Friend WithEvents CancelBTN As
System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent()
Me.UserLbl = New System.Windows.Forms.Label()
Me.UserINP = New System.Windows.Forms.TextBox()
Me.PassINP = New System.Windows.Forms.TextBox()
Me.PassLbl = New System.Windows.Forms.Label()
Me.LoginBTN = New System.Windows.Forms.Button()
Me.CancelBTN = New System.Windows.Forms.Button()
Me.SuspendLayout()
'
'UserLbl
'
Me.UserLbl.Location = New System.Drawing.Point(0,
10)
Me.UserLbl.Name = "UserLbl"
Me.UserLbl.Size = New System.Drawing.Size(64, 16)
Me.UserLbl.TabIndex = 0
Me.UserLbl.Text = "Username:"
'
'UserINP
'
Me.UserINP.Location = New System.Drawing.Point
(56, 8)
Me.UserINP.Name = "UserINP"
Me.UserINP.Size = New System.Drawing.Size(120, 20)
Me.UserINP.TabIndex = 1
Me.UserINP.Text = ""
'
'PassINP
'
Me.PassINP.Location = New System.Drawing.Point
(56, 32)
Me.PassINP.Name = "PassINP"
Me.PassINP.PasswordChar =
Microsoft.VisualBasic.ChrW(42)
Me.PassINP.Size = New System.Drawing.Size(120, 20)
Me.PassINP.TabIndex = 2
Me.PassINP.Text = ""
Me.Validate.Equals(3224)
'
'PassLbl
'
Me.PassLbl.Location = New System.Drawing.Point(0,
34)
Me.PassLbl.Name = "PassLbl"
Me.PassLbl.Size = New System.Drawing.Size(64, 16)
Me.PassLbl.TabIndex = 3
Me.PassLbl.Text = "Password:"
'
'LoginBTN
'
Me.LoginBTN.Location = New System.Drawing.Point
(16, 56)
Me.LoginBTN.Name = "LoginBTN"
Me.LoginBTN.Size = New System.Drawing.Size(66, 24)
Me.LoginBTN.TabIndex = 4
Me.LoginBTN.Text = "Login"
'
'CancelBTN
'
Me.CancelBTN.Location = New System.Drawing.Point
(96, 56)
Me.CancelBTN.Name = "CancelBTN"
Me.CancelBTN.Size = New System.Drawing.Size(66,
24)
Me.CancelBTN.TabIndex = 5
Me.CancelBTN.Text = "Cancel"
'
'Login
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5,
13)
Me.ClientSize = New System.Drawing.Size(186, 88)
Me.Controls.AddRange(New
System.Windows.Forms.Control() {Me.CancelBTN,
Me.LoginBTN, Me.UserINP, Me.PassINP, Me.PassLbl,
Me.UserLbl})
Me.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedToolWindow
Me.Name = "Login"
Me.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = " Network Login"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Login_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

Private Sub Login_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
UserLbl.Click

End Sub

Private Sub CancelBTN_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
CancelBTN.Click
End
End Sub

Private Sub PassINP_TextChanged(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
PassINP.TextChanged

End Sub
End Class

Thanks for the help in advance

Joshua Kendall
 
H

Herfried K. Wagner [MVP]

* "Joshua Kendall said:
I have a script in which it keeps opening the same form
instead of only one instance. I also need help with a
form that has a password. Where do I put the actual
password? can I use a database for multiple users?

This depends on the type of the application. Storing a password in a
database doesn't make sense if the user is able to read it from the
database. Maybe it's easier to find a good solution if you provide more
information on the purpose of your application.
 
G

Guest

It's kind of like a network interface for a program. Only
one user can be logged in with that information at one
time and a database would be hidden and encrypted.
 
W

William Ryan

I'd store the passwords in a config file/registry or in a database
encrypted. If you store them in the DB, then make a totally gimped out
account that you call when the program opens that can verify the password,
but don't store your passwords in clear text unless you are 10000000%
certain that unwanted eyes will never see it.

If you want only one instance of your class to ever be open at once (form,
not app), then a Singleton pattern is made to order.... here's a good link
on the implementation
http://www.ondotnet.com/pub/a/dotnet/2002/11/11/singleton.html

As far as database for multiple users...the short answer is probably . Most
every commercial Database supports multi-users, although desktop databases
like Access don't do a very good job of handling more than a few users in
most cases.

As far as form with a Password, what do you need help with? The above will
show you how to ensure only one instance. As far as the form itself, drag a
textbox onto your form (you mention Forms so I'm assuming this is a Windows
program, not a web program) and then set the PasswordChar property of the
textbox which will hold the password to some character like "*".
http://msdn.microsoft.com/library/d...windowsformstextboxclasspasswordchartopic.asp
Then, when a user types in a password, they will see "*****" instead of
"mypassword"
there are many good examples of encrypting text, here's one good link
http://www.dotnetsmart.com/showpost.aspx?PostID=255 . So all you need to do
is encrypt the password when you submit it to the DB the first time through.
Each request tot he DB gets the cypher text and decrypts it. Do this
locally in your BusinessLogic component so that you send encrypted data
over your network, unless you are 100000 sure that no one is sniffiing it
(and even then, I'd still recommend sending it wrapped under a strong crypto
algorithm).

Let me know if you are having any specific problems though that I can help
you with..or If I was unclear about anything.

Cheers,

Bill
 
H

Herfried K. Wagner [MVP]

* said:
It's kind of like a network interface for a program. Only
one user can be logged in with that information at one
time and a database would be hidden and encrypted.

Thanks for providing this information. What's exactly your problem with
storing the information in this database?
 
J

Joshua Kendall

What do I type to get the program to see what the
password is? I know that "me.PassINP.PasswordChar = *"
makes them asterics, but for the time being it will only
be one password so how do I program the password in? I'll
leave the database till after I get the program to my
specifications.

Thanks In advanced!

Joshua Kendall
 
F

Fergus Cooney

Hi Joshua,

The <User> will see asterisks but PassINP.Text will be what they
actually typed. For now, just to get it working, have an array (or just a
single string) with the passwords.

Private sExamplePassword As String = "FooBar"
or
Private asExamplePassword() As String = { "Foo", "Bar"}

Then test against the string or the array on [Go 4 It!].

Regards,
Fergus

--
(Please ignore this - there's a feud going on)
==================================================
Quote of the day
Herfried:
I don't need/want human interaction.
==================================================
 
J

Joshua Kendall

The form that loads the password area won't open it once
it opens it until otherwise stopped in VB. What can I do
to make it open once.

Code:

Private Sub Timer1_Tick(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles SplashTimer.Tick
Dim frmLogin As New Login()
frmLogin.ShowDialog()
End Sub

Thanks!

Joshua Kendall
 
F

Fergus Cooney

Hi Joshua,

|| The form that loads the password area
|| won't open it once it opens it

??

|| until otherwise stopped in VB

We've done this already in the other thread.
Stop the Timer like I showed you.

Regards,
Fergus
 
H

Herfried K. Wagner [MVP]

* "Joshua Kendall said:
What do I type to get the program to see what the
password is? I know that "me.PassINP.PasswordChar = *"

The textbox's 'Text' property will still return the text entered without
the password character.
makes them asterics, but for the time being it will only
be one password so how do I program the password in? I'll
leave the database till after I get the program to my
specifications.

I don't really understand what the point of your question is... Do you
have problem storing the passoword, entering the password or in checking
if the password is valid?
 
J

Joshua Kendall

Stopping the timer didn't work for my program the splash
screen never opened the other form. It just stayed the
same.

Here's the code:

Public Class Splash
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component
list.
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the
Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents SplashIMG As
System.Windows.Forms.PictureBox
Friend WithEvents SplashTimer As
System.Windows.Forms.Timer
<System.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent()
Me.components = New
System.ComponentModel.Container()
Dim resources As System.Resources.ResourceManager
= New System.Resources.ResourceManager(GetType(Splash))
Me.SplashIMG = New System.Windows.Forms.PictureBox
()
Me.SplashTimer = New System.Windows.Forms.Timer
(Me.components)
Me.SuspendLayout()
'
'SplashIMG
'
Me.SplashIMG.Image = CType(resources.GetObject
("SplashIMG.Image"), System.Drawing.Bitmap)
Me.SplashIMG.Name = "SplashIMG"
Me.SplashIMG.Size = New System.Drawing.Size(600,
300)
Me.SplashIMG.TabIndex = 0
Me.SplashIMG.TabStop = False
'
'SplashTimer
'
Me.SplashTimer.Interval = 1000
'
'Splash
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5,
13)
Me.ClientSize = New System.Drawing.Size(600, 300)
Me.Controls.AddRange(New
System.Windows.Forms.Control() {Me.SplashIMG})
Me.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.None
Me.Name = "Splash"
Me.ShowInTaskbar = False
Me.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = "KS.IntraNet"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub SplashIMG_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
SplashIMG.Click

End Sub

Private Sub Timer1_Tick(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
SplashTimer.Tick
Dim frmLogin As New Login()
frmLogin.Show()
End Sub

End Class


Thanks!

Joshua Kendall
 
F

Fergus Cooney

Hi Joshua,

That's the code that keeps creating new Forms. What about the code that doesn't show
anything? Where did you stop the Timer? Did you do it where I showed or somewhere else?

Regards,
Fergus

--
(Please ignore this - there's a feud going on)
==================================================
Quote of the day
Herfried:
I don't need/want human interaction.
==================================================
 
T

Tom Leylan

Joshua... I'm a little nervous to jump in (it's going so well already) :)
But let me offer a few ideas. Break your tasks down. You are clearly trying
to solve multiple tasks and running into a problem with each of them... when
that is all run together you get a mess.

First, handle the password input. Skip the "timer" for gosh sake... you
can't be fooling around with automatic pop-up password forms if you can't
get the password validation routine under control. Ultimately the timer is
going to turn out to be a bad idea because people may want to log out or log
in again and without a manual way of selecting this stuff they will have to
quit the program to let the timer handle it.

Create the password form, have it load and return the password to your main
app. When that works, add the "asterisks" to hide the data entry. When
that works (and only then) validate the password. Where do you get the
password from? From "GetPassword" You can create a function that returns a
fixed string. By doing it that way you can substitute the "guts" of
GetPassword and have it grab the password out of a database table at some
future date.

There is a wrinkle though. When you study up on passwords you will find
that it shouldn't be "exposed" in what is known as "clear text". It would
only travel the wires in an encrypted form. Your password input routine
should encode it and pass it along to PasswordValidate() and that routine
should simply return True or False and not actually return a decrypted
password. Ultimately this routine would reside on the server that has the
account/password pairs probably in the form of a stored procedure.

When you have all that working (and only then) you can attack the need to
pop-up the password form automatically. You might not have to but if you
insist you still don't use a timer to pop up the password form... you at
best would use the timer to time the wait period before you pop up the
password form. Once you decide that it is time to pop-up the password form,
turn off the timer... it's usefulness is over since the period of time has
elapsed.

I can read in your postings (at least I think I can) that you're running all
this stuff together and so it gets confusing. Everything is a discrete step,
keep it that way.

Tom
 
G

Guest

Tom (Above) gave me some good ideas of what to do about
the password. I'm going to skip the seperate form for
passwords, and place the login controls on the Splash
screen.

Thanks for all of your help,

Joshua Kendall.
 
J

Joshua Kendall

Where should I put the GetPassword in the "Login" button
sub? Here's my code if you could offer some help. I
decided not to have the seperate form it's all on the
splash screen.

Code:

Public Class Splash
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form
Designer.
InitializeComponent()

'Add any initialization after the
InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component
list.
Protected Overloads Overrides Sub Dispose(ByVal
disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the
Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents SplashIMG As
System.Windows.Forms.PictureBox
Friend WithEvents CancelBTN As
System.Windows.Forms.Button
Friend WithEvents LoginBTN As
System.Windows.Forms.Button
Friend WithEvents UserINP As
System.Windows.Forms.TextBox
Friend WithEvents PassINP As
System.Windows.Forms.TextBox
Friend WithEvents PassLbl As
System.Windows.Forms.Label
Friend WithEvents UserLbl As
System.Windows.Forms.Label
<System.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent()
Dim resources As System.Resources.ResourceManager
= New System.Resources.ResourceManager(GetType(Splash))
Me.SplashIMG = New System.Windows.Forms.PictureBox
()
Me.CancelBTN = New System.Windows.Forms.Button()
Me.LoginBTN = New System.Windows.Forms.Button()
Me.UserINP = New System.Windows.Forms.TextBox()
Me.PassINP = New System.Windows.Forms.TextBox()
Me.PassLbl = New System.Windows.Forms.Label()
Me.UserLbl = New System.Windows.Forms.Label()
Me.SuspendLayout()
'
'SplashIMG
'
Me.SplashIMG.BackColor =
System.Drawing.Color.MediumBlue
Me.SplashIMG.Image = CType(resources.GetObject
("SplashIMG.Image"), System.Drawing.Bitmap)
Me.SplashIMG.Location = New System.Drawing.Point
(0, -48)
Me.SplashIMG.Name = "SplashIMG"
Me.SplashIMG.Size = New System.Drawing.Size(600,
336)
Me.SplashIMG.TabIndex = 0
Me.SplashIMG.TabStop = False
'
'CancelBTN
'
Me.CancelBTN.BackColor =
System.Drawing.Color.SteelBlue
Me.CancelBTN.ForeColor =
System.Drawing.Color.White
Me.CancelBTN.Location = New System.Drawing.Point
(296, 256)
Me.CancelBTN.Name = "CancelBTN"
Me.CancelBTN.Size = New System.Drawing.Size(66,
24)
Me.CancelBTN.TabIndex = 11
Me.CancelBTN.Text = "Cancel"
'
'LoginBTN
'
Me.LoginBTN.BackColor =
System.Drawing.Color.SteelBlue
Me.LoginBTN.ForeColor = System.Drawing.Color.White
Me.LoginBTN.Location = New System.Drawing.Point
(216, 256)
Me.LoginBTN.Name = "LoginBTN"
Me.LoginBTN.Size = New System.Drawing.Size(66, 24)
Me.LoginBTN.TabIndex = 10
Me.LoginBTN.Text = "Login"
'
'UserINP
'
Me.UserINP.BorderStyle =
System.Windows.Forms.BorderStyle.FixedSingle
Me.UserINP.Location = New System.Drawing.Point
(256, 190)
Me.UserINP.Name = "UserINP"
Me.UserINP.Size = New System.Drawing.Size(120, 20)
Me.UserINP.TabIndex = 7
Me.UserINP.Text = ""
'
'PassINP
'
Me.PassINP.BorderStyle =
System.Windows.Forms.BorderStyle.FixedSingle
Me.PassINP.Location = New System.Drawing.Point
(256, 214)
Me.PassINP.Name = "PassINP"
Me.PassINP.PasswordChar =
Microsoft.VisualBasic.ChrW(42)
Me.PassINP.Size = New System.Drawing.Size(120, 20)
Me.PassINP.TabIndex = 8
Me.PassINP.Text = ""
'
'PassLbl
'
Me.PassLbl.ForeColor = System.Drawing.Color.White
Me.PassLbl.Location = New System.Drawing.Point
(200, 216)
Me.PassLbl.Name = "PassLbl"
Me.PassLbl.Size = New System.Drawing.Size(64, 16)
Me.PassLbl.TabIndex = 9
Me.PassLbl.Text = "Password:"
'
'UserLbl
'
Me.UserLbl.ForeColor = System.Drawing.Color.White
Me.UserLbl.Location = New System.Drawing.Point
(200, 192)
Me.UserLbl.Name = "UserLbl"
Me.UserLbl.Size = New System.Drawing.Size(64, 16)
Me.UserLbl.TabIndex = 6
Me.UserLbl.Text = "Username:"
'
'Splash
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5,
13)
Me.BackColor = System.Drawing.Color.MediumBlue
Me.ClientSize = New System.Drawing.Size(600, 300)
Me.Controls.AddRange(New
System.Windows.Forms.Control() {Me.CancelBTN,
Me.LoginBTN, Me.UserINP, Me.PassINP, Me.PassLbl,
Me.UserLbl, Me.SplashIMG})
Me.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.None
Me.Name = "Splash"
Me.ShowInTaskbar = False
Me.StartPosition =
System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = "KS.IntraNet"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub SplashIMG_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
SplashIMG.Click

End Sub

Private Sub Timer1_Tick(ByVal sender As
System.Object, ByVal e As System.EventArgs)

End Sub

Private Sub CancelBTN_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
CancelBTN.Click
End
End Sub

Private Sub UserINP_TextChanged(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
UserINP.TextChanged

End Sub

Private Sub LoginBTN_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
LoginBTN.Click

End Sub
End Class
 
T

Tom Leylan

Joshua Kendall said:
Where should I put the GetPassword in the "Login" button
sub? Here's my code if you could offer some help. I
decided not to have the seperate form it's all on the
splash screen.

Most of the answers to these kinds of questions are going to be the same...
"it depends" and you don't want that kind of answer. But it depends upon
what you want to do. Do you want to endlessly loop around if the password
is incorrect?

We can see you have five event handlers defined but it looks like Cancel is
the only one that actually does something. And it is exiting the app which
may not be the best choice.

You can add some code to LoginBTN_Clicked that compares the text in UserINP
with the value returned by GetPassword(). The function itself could for
testing purposes exist in the form class. You can also put it into a
separate module or you can implement a class that validates passwords.

In the future... we probably don't need all the "Windows Form Designer
generated code."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top