Imports BaseClasses.Data
Imports BaseClasses.Utils.StringUtils
Imports BaseClasses.Utils
Imports BaseClasses.Resources

Namespace UseDAL.UI

' Typical customizations that may be done in this class include
'  - adding custom event handlers
'  - overriding base class methods
'
''' <summary>
''' The superclass (i.e. base class) for all Designer-generated pages in this application.
''' </summary>
''' <remarks>
''' <para>
''' </para>
''' </remarks>


    Public Class BaseApplicationPage
        Inherits BaseClasses.Web.UI.BasePage

        Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'commented out because DataBind is being called multiple times.
            '        If (Not Me.IsPostBack) Then
            '            Me.DataBind()
            '        End If
        End Sub

        ' Variable used to prevent infinite loop
        Private _modifyRedirectUrlInProgress As Boolean = False

        ' Constant used for EvaluateExpressions
        Const PREFIX_NO_ENCODE As String = "NoUrlEncode:"

        ''' Allow for migration from earlier versions which did not have url encryption.
        Public Overridable Function ModifyRedirectUrl(ByVal redirectUrl As String, ByVal redirectArgument As String) As String
            Return EvaluateExpressions(redirectUrl, redirectArgument, False)
        End Function

        Public Overridable Function ModifyRedirectUrl(ByVal redirectUrl As String, ByVal redirectArgument As String, ByVal bEncrypt As Boolean) As String
            Return EvaluateExpressions(redirectUrl, redirectArgument, bEncrypt)
        End Function

        Public Overridable Function EvaluateExpressions( _
                ByVal redirectUrl As String, _
                ByVal redirectArgument As String, _
                ByVal bEncrypt As Boolean) As String
            Return EvaluateExpressions(redirectUrl, redirectArgument, bEncrypt, Me)
        End Function

        Public Overridable Function EvaluateExpressions( _
                ByVal redirectUrl As String, _
                ByVal redirectArgument As String, _
                ByVal bEncrypt As Boolean, _
                ByVal targetCtl As Control) As String

            If (_modifyRedirectUrlInProgress) Then
                Return Nothing
            Else
                _modifyRedirectUrlInProgress = True
            End If

            Dim finalRedirectUrl As String = redirectUrl
            Dim finalRedirectArgument As String = redirectArgument

            If (finalRedirectUrl Is Nothing OrElse finalRedirectUrl.Trim = "") Then
                Return ""
            ElseIf (finalRedirectUrl.IndexOf("{"c) < 0) Then
                'RedirectUrl does not contain any format specifiers
                _modifyRedirectUrlInProgress = False
                Return finalRedirectUrl
            Else
                'The old way was to pass separate URL and arguments and use String.Format to
                'do the replacement.  Example:
                '   URL:        EditProductsRecord?Products={0}
                '   Argument:   PK
                'The new way to is pass the arguments directly in the URL.  Example:
                '   URL:        EditProductsRecord?Products={PK}
                'If the old way is passsed, convert it to the new way.
                If (Len(redirectArgument) > 0) Then
                    Dim arguments() As String = Split(redirectArgument, ",")
                    Dim i As Integer
                    For i = 0 To (arguments.Length - 1)
                        finalRedirectUrl = finalRedirectUrl.Replace("{" & i.ToString & "}", "{" & arguments(i) & "}")
                    Next

                    finalRedirectArgument = ""
                End If

                'First find all the table and record controls in the page.
                Dim controlList As New ArrayList()
                GetAllRecordAndTableControls(targetCtl, controlList)
                If controlList.Count = 0 Then
                    Return finalRedirectUrl
                End If

                ' Store the controls in a hashtable using the control unique name
                ' as the key for easy refrence later in the function.
                Dim controlIdList As New Hashtable
                Dim control As System.Web.UI.Control
                For Each control In controlList
                    controlIdList.Add(control.UniqueID, control)
                Next

                'Look at all of the expressions in the URL and forward processing
                'to the appropriate controls.
                'Expressions can be of the form [ControlName:][NoUrlEncode:]Key[:Value]
                Dim forwardTo As New ArrayList
                Dim remainingUrl As String = finalRedirectUrl
                While (remainingUrl.IndexOf("{"c) >= 0) And (remainingUrl.IndexOf("}"c) > 0) And _
                   (remainingUrl.IndexOf("{"c) < remainingUrl.IndexOf("}"c))

                    Dim leftIndex As Integer = remainingUrl.IndexOf("{"c)
                    Dim rightIndex As Integer = remainingUrl.IndexOf("}"c)
                    Dim expression As String = remainingUrl.Substring(leftIndex + 1, rightIndex - leftIndex - 1)
                    remainingUrl = remainingUrl.Substring(rightIndex + 1)

                    Dim prefix As String = Nothing
                    If (expression.IndexOf(":") > 0) Then
                        prefix = expression.Substring(0, expression.IndexOf(":"))
                    End If
                    If (Not IsNothing(prefix)) AndAlso (prefix.Length > 0) AndAlso _
                       (Not (InvariantLCase(prefix) = InvariantLCase(PREFIX_NO_ENCODE))) AndAlso _
                       (Not BaseRecord.IsKnownExpressionPrefix(prefix)) Then
                        'The prefix is a control name.  Add it to the list of controls that
                        'need to process the URL.
                        If (controlIdList.Contains(prefix)) And (Not forwardTo.Contains(prefix)) Then
                            forwardTo.Add(prefix)
                        End If
                    End If
                End While

                'Forward the request to each control in the forwardTo list
                Dim containerId As String
                For Each containerId In forwardTo
                    Dim ctl As Control = CType(controlIdList.Item(containerId), Control)
                    If (Not IsNothing(ctl)) Then
                        If TypeOf ctl Is BaseApplicationRecordControl Then
                            finalRedirectUrl = DirectCast(ctl, BaseApplicationRecordControl).EvaluateExpressions(finalRedirectUrl, finalRedirectArgument, bEncrypt)
                        ElseIf TypeOf ctl Is BaseApplicationTableControl Then
                            finalRedirectUrl = DirectCast(ctl, BaseApplicationTableControl).EvaluateExpressions(finalRedirectUrl, finalRedirectArgument, bEncrypt)
                        End If
                    End If
                Next

                'If there are any unresolved expressions, let the other naming containers
                'have a crack at modifying the URL
                For Each control In controlList
                    If (forwardTo.IndexOf(control.ID) < 0) Then
                        If TypeOf control Is BaseApplicationRecordControl Then
                            finalRedirectUrl = DirectCast(control, BaseApplicationRecordControl).EvaluateExpressions(finalRedirectUrl, finalRedirectArgument, bEncrypt)
                        ElseIf TypeOf control Is BaseApplicationTableControl Then
                            finalRedirectUrl = DirectCast(control, BaseApplicationTableControl).EvaluateExpressions(finalRedirectUrl, finalRedirectArgument, bEncrypt)
                        End If
                    End If
                Next
            End If

            _modifyRedirectUrlInProgress = False

            Return finalRedirectUrl
        End Function

        Private Function GetAllRecordAndTableControls() As ArrayList
            Dim controlList As ArrayList = New ArrayList()
            GetAllRecordAndTableControls(Me, controlList)
            Return controlList
        End Function

        Private Sub GetAllRecordAndTableControls(ByVal ctl As Control, ByVal controlList As ArrayList)
            If ctl Is Nothing Then
                Return
            End If

            If TypeOf ctl Is BaseApplicationRecordControl OrElse _
               TypeOf ctl Is BaseApplicationTableControl Then
                controlList.Add(ctl)
            End If

            Dim nextCtl As Control
            For Each nextCtl In ctl.Controls()
                GetAllRecordAndTableControls(nextCtl, controlList)
            Next
        End Sub

        Public Function GetResourceValue(ByVal keyVal As String, ByVal appName As String) As String
            Try
                Dim resObj As Object = GetGlobalResourceObject(appName, keyVal)
                If Not resObj Is Nothing Then
                    Return resObj.ToString()
                End If
                Return keyVal
            Catch
                Return keyVal
            End Try

        End Function
        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Register Control buttonCtrl with ScriptManager to perform traditional postback instead of default async postback
        ''' </summary>
        ''' <remarks>
        ''' </remarks>
        ''' <history>
        ''' 	[sramarao]	3/2007	Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Sub RegisterPostBackTrigger(ByVal buttonCtrl As System.Web.UI.Control, ByVal updatePanelCtrl As System.Web.UI.Control)
            Try
                ' Get current ScriptManager
                Dim scriptMgr As ScriptManager = ScriptManager.GetCurrent(Me.Page)
                ' If Scriptmanager not preset return.
                If scriptMgr Is Nothing Then
                    Return
                End If
                ' If buttonCtrl is not surrounded by an UpdatePanel then return.
                Dim CurrentUpdatePanel As System.Web.UI.UpdatePanel = CType(updatePanelCtrl, UpdatePanel)
                If CurrentUpdatePanel Is Nothing Then
                    Return
                End If
                scriptMgr.RegisterPostBackControl(buttonCtrl)
            Catch ex As Exception
                Throw ex
            End Try

        End Sub

        Public Overridable Sub SaveData()

        End Sub



#Region " Methods to manage saving and retrieving control values to session. "
        Private _ShouldSaveControlsToSession As Boolean = False
        Public Property ShouldSaveControlsToSession() As Boolean
            Get
                Return Me._ShouldSaveControlsToSession
            End Get
            Set(ByVal value As Boolean)
                Me._ShouldSaveControlsToSession = value
            End Set
        End Property

        Protected Sub Page_SaveControls_Unload(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Unload
            If Me.ShouldSaveControlsToSession Then
                Me.SaveControlsToSession()
            End If
        End Sub

        Protected Overridable Sub SaveControlsToSession()
        End Sub

        Protected Sub Control_ClearControls_PreRender(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.PreRender
            Me.ClearControlsFromSession()
        End Sub

        Protected Overridable Sub ClearControlsFromSession()
        End Sub

        Public Sub SaveToSession( _
            ByVal control As Control, _
            ByVal value As String)

            SaveToSession(control.UniqueID, value)
        End Sub

        Public Function GetFromSession( _
            ByVal control As Control, _
            ByVal defaultValue As String) As String

            Return GetFromSession(control.UniqueID, defaultValue)
        End Function

        Public Function GetFromSession(ByVal control As Control) As String
            Return GetFromSession(control.UniqueID, Nothing)
        End Function

        Public Sub RemoveFromSession(ByVal control As Control)
            RemoveFromSession(control.UniqueID)
        End Sub

        Public Function InSession(ByVal control As Control) As Boolean
            Return InSession(control.UniqueID)
        End Function

        Public Sub SaveToSession( _
            ByVal control As Control, _
            ByVal variable As String, _
            ByVal value As String)

            SaveToSession(control.UniqueID & variable, value)
        End Sub

        Public Function GetFromSession( _
            ByVal control As Control, _
            ByVal variable As String, _
            ByVal defaultValue As String) As String

            Return GetFromSession(control.UniqueID & variable, defaultValue)
        End Function

        Public Sub RemoveFromSession( _
            ByVal control As Control, _
            ByVal variable As String)

            RemoveFromSession(control.UniqueID & variable)
        End Sub

        Public Function InSession( _
            ByVal control As Control, _
            ByVal variable As String) As Boolean

            Return InSession(control.UniqueID & variable)
        End Function

        Public Sub SaveToSession( _
            ByVal name As String, _
            ByVal value As String)

            Me.Session()(GetValueKey(name)) = value
        End Sub

        Public Function GetFromSession( _
            ByVal name As String, _
            ByVal defaultValue As String) As String

            Dim value As String = CType(Me.Session()(GetValueKey(name)), String)
            If value Is Nothing OrElse value.Trim() = "" Then
                value = defaultValue
            End If

            Return value
        End Function

        Public Function GetFromSession(ByVal name As String) As String
            Return GetFromSession(name, Nothing)
        End Function

        Public Sub RemoveFromSession(ByVal name As String)
            Me.Session.Remove(GetValueKey(name))
        End Sub

        Public Function InSession(ByVal name As String) As Boolean
            Return (Not Me.Session(GetValueKey(name)) Is Nothing)
        End Function

        Public Function GetValueKey(ByVal name As String) As String
            Return Me.Session.SessionID & Me.AppRelativeVirtualPath & name
        End Function
#End Region
#Region " Methods to encrypt and decrypt URL parameters "


        ' The URLEncryptionKey is specified in the web.config.  The rightmost three characters of the current
        ' Session Id are concatenated with the URLEncryptionKey to provide added protection.  You can change
        ' this to anything you like by changing this function for the application.
        ' This function is private and not overridable because each page cannot have its own key - it must
        ' be common across the entire application.
        Private Function GetCryptoKey() As String
            Return Left(Me.Session.SessionID, 6) & BaseClasses.Configuration.ApplicationSettings.Current.URLEncryptionKey & Right(Me.Session.SessionID, 6)
        End Function

        Public Overridable Function Encrypt(ByVal Source As String) As String
            If (Source Is Nothing) Then
                Return ""
            End If
            Dim s As String = ""
            Try
                Dim CheckCrypto As Crypto = New Crypto(Crypto.Providers.DES)
                s = CheckCrypto.Encrypt(Source, Me.GetCryptoKey(), False)
                s = System.Web.HttpUtility.UrlEncode(s)
            Catch ex As Exception
                ' In case of error, just return the source itself without encryption.
                s = Source
            End Try
            Return s
        End Function

        Public Overridable Function Decrypt(ByVal Source As String) As String
            If (Source Is Nothing) Then
                Return ""
            End If
            Dim s As String = ""
            Dim CheckCrypto As Crypto = New Crypto(Crypto.Providers.DES)
            Try
                ' First try decrypting as is.
                s = CheckCrypto.Decrypt(Source, Me.GetCryptoKey(), False)
                s = System.Web.HttpUtility.UrlDecode(s)
            Catch ex As Exception
                Try
                    ' If the first try of decrypting does not work, then
                    ' URL decode it and try again.  This is to ensure that if
                    ' the encrypted key is passed through the URL, it needs to
                    ' be decoded first.
                    Source = System.Web.HttpUtility.UrlDecode(Source)
                    s = CheckCrypto.Decrypt(Source, Me.GetCryptoKey(), False)
                Catch ex1 As Exception
                    ' In case of error, throw new Exception: do not allow to access encrypted page with non-encrypted URL
                    Throw New System.UriFormatException(RU.GetErrMsg(RU.ErrRes.GetRecords))
                End Try
            End Try
            Return s
        End Function

        ' Encrypt url parameter which is enclosed in {}. For eg:..\Shared\SelectFileToImport?TableName=Employees
        Public Function EncryptUrlParameter(ByVal url As String) As String
            If (url Is Nothing) Then
                Return ""
            End If

            If ((url.IndexOf(Microsoft.VisualBasic.ChrW(61)) > 0)) Then
                Dim queryString() As String = url.Split(Microsoft.VisualBasic.ChrW(61))
                Dim expression As String = queryString(1)
                Dim encryptedValue As String = Encrypt(expression)
                url = url.Replace(expression, encryptedValue)

            End If
            Return url
        End Function
#End Region
    End Class

End Namespace
