Imports System.Data.SqlClient

Public Class Signature
    Inherits System.Web.UI.UserControl

#Region "Properties"

    ' If set, "Copy from Previous" is visible.
    Property DefaultSigUrl As String
        Get
            Return _DefaultSigUrl
        End Get
        Set(value As String)
            _DefaultSigUrl = value
            phCopy.Visible = Not String.IsNullOrEmpty(value)
        End Set
    End Property
    Private _DefaultSigUrl As String = Nothing

    ' Primary key in web_Signatures database
    Property SignatureId As Integer?
        Get
            _SaveSignature()
            Return _signatureId
        End Get
        Set(value As Integer?)
            _signatureId = value
            If value.HasValue Then
                _LoadSignature()
            End If
        End Set
    End Property
    Private _signatureId As Integer?

    ' Id of the context of the signature
    Property ContextId As String

    ReadOnly Property EmptyData As String
        Get
            Return "image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iMCIgaGVpZ2h0PSIwIiB2aWV3Qm94PSIwIDAgMCAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ0cnVlIj48L3N2Zz4="
        End Get
    End Property

#End Region

#Region "Event Handling"

    Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init

        ' Some browsers block us because of the code for the audit snapshot.
        ' This tells them that we know what we're doing.
        Response.AddHeader("X-XSS-Protection", "0")

        ' An empty XML image that we'll start with
        imgPreview.ImageUrl = "data:" & EmptyData

        litTimestamp.Text = (<p class="hidden timestamp"></p>).ToString()

    End Sub

    Private Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            valSignature.ClientValidationFunction = "(function(v,g){return g.IsValid=valSignature($('#" + ClientID + "'),$('#" + ContextId + "'));})"
        End If
    End Sub

    Private Sub valSignature_ServerValidate(sender As Object, e As ServerValidateEventArgs) Handles valSignature.ServerValidate
        If String.IsNullOrEmpty(txtData.Text) OrElse txtData.Text = EmptyData Then
            e.IsValid = False
        End If
    End Sub

    ' If user hacks the viewstate, our audit trail becomes invalid but 
    ' the current signature should be reliable.  If we want a more 
    ' secure audit history, then we should store this elsewhere.
    Protected Overrides Sub LoadViewState(savedState As Object)
        Dim state = CType(savedState, Object())
        MyBase.LoadViewState(state(0))
        _signatureId = state(1)
        DefaultSigUrl = state(2)
    End Sub

    Protected Overrides Function SaveViewState() As Object
        Dim state(3) As Object
        state(0) = MyBase.SaveViewState()
        state(1) = _signatureId
        state(2) = DefaultSigUrl
        Return state
    End Function

#End Region

#Region "Internals"

    ' Load the signature into the data and image
    Private Sub _LoadSignature()
        Dim cmdGet = "SELECT data, dateSigned FROM web_Signature WHERE id=@sigId"
        Using connection As New SqlConnection(Logic.Database.connectionString)
            connection.Open()

            Dim cmd As New SqlCommand(cmdGet, connection)
            cmd.Parameters.AddWithValue("sigId", _signatureId.Value)

            Dim dReader = cmd.ExecuteReader()
            If dReader.Read() Then
                Dim data = dReader(0)
                Dim dateSigned = Logic.Conversion.ToDate(dReader(1))
                If TypeOf data IsNot DBNull AndAlso data <> EmptyData Then
                    txtData.Text = data
                    imgPreview.ImageUrl = "data:" + data
                    litTimestamp.Text = (<p class="timestamp">Digitally signed on <%= dateSigned.ToString("M/d/yyyy") %> at <%= dateSigned.ToString("H:mm:ss tt") %>.</p>).ToString()
                End If
            End If

        End Using
    End Sub

    ' Save the signature into the database
    Private Sub _SaveSignature()
        If Not chkChanged.Checked Then Exit Sub

        ' save the current sig's data
        Using connection As New SqlConnection(Logic.Database.connectionString)
            connection.Open()

            Dim cmd As New SqlCommand(
                "INSERT INTO web_Signature (previousId, dateSigned, signerIp, data, context)
                VALUES (@previousId, GETDATE(), @signerIp, @data, @context);
                SELECT @@IDENTITY;", connection)
            With cmd.Parameters
                .AddWithValue("previousId", If(_signatureId.HasValue, _signatureId.Value, DBNull.Value))
                .AddWithValue("signerIp", Request.UserHostAddress)
                .AddWithValue("data", If(txtData.Text.Length, txtData.Text, DBNull.Value))
                .AddWithValue("context", txtContext.Text)
            End With

            _signatureId = CInt(cmd.ExecuteScalar())

        End Using
    End Sub

#End Region

End Class