<%
'=============================================================================
' FILE: validation.asp
' PURPOSE: Input validation library for secure user input handling
' AUTHOR: System
' CREATED: 2025-10-10
'
' USAGE: Include this file in any page that processes user input
'        <!--#include file="./includes/validation.asp"-->
'=============================================================================

'-----------------------------------------------------------------------------
' FUNCTION: ValidateInteger
' PURPOSE: Validates that input is an integer within optional range
' PARAMETERS:
'   value - The value to validate
'   minVal - Minimum allowed value (optional, pass Empty to skip)
'   maxVal - Maximum allowed value (optional, pass Empty to skip)
' RETURNS: True if valid integer within range, False otherwise
'-----------------------------------------------------------------------------
Function ValidateInteger(value, minVal, maxVal)
    ValidateInteger = False

    ' Check if numeric
    If Not IsNumeric(value) Then
        Exit Function
    End If

    Dim intValue
    intValue = CLng(value)

    ' Check if it's actually an integer (not a decimal)
    If intValue <> CDbl(value) Then
        Exit Function
    End If

    ' Check minimum value
    If Not IsEmpty(minVal) Then
        If intValue < minVal Then
            Exit Function
        End If
    End If

    ' Check maximum value
    If Not IsEmpty(maxVal) Then
        If intValue > maxVal Then
            Exit Function
        End If
    End If

    ValidateInteger = True
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ValidateString
' PURPOSE: Validates string length and optional pattern
' PARAMETERS:
'   value - The string to validate
'   minLen - Minimum length
'   maxLen - Maximum length
'   pattern - Regular expression pattern (optional, pass "" to skip)
' RETURNS: True if valid, False otherwise
'-----------------------------------------------------------------------------
Function ValidateString(value, minLen, maxLen, pattern)
    ValidateString = False

    Dim strValue
    strValue = CStr(value)

    ' Check length
    If Len(strValue) < minLen Or Len(strValue) > maxLen Then
        Exit Function
    End If

    ' Check pattern if provided
    If pattern <> "" Then
        Dim objRegEx
        Set objRegEx = New RegExp
        objRegEx.Pattern = pattern
        objRegEx.IgnoreCase = True

        If Not objRegEx.Test(strValue) Then
            Set objRegEx = Nothing
            Exit Function
        End If
        Set objRegEx = Nothing
    End If

    ValidateString = True
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ValidateIPAddress
' PURPOSE: Validates IPv4 address format
' PARAMETERS: ipAddress - The IP address string to validate
' RETURNS: True if valid IPv4 format, False otherwise
'-----------------------------------------------------------------------------
Function ValidateIPAddress(ipAddress)
    Dim objRegEx, pattern
    Set objRegEx = New RegExp

    ' Pattern matches XXX.XXX.XXX.XXX where each octet is 0-255
    pattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
    objRegEx.Pattern = pattern

    ValidateIPAddress = objRegEx.Test(ipAddress)
    Set objRegEx = Nothing
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ValidateEmail
' PURPOSE: Validates email address format
' PARAMETERS: email - The email address to validate
' RETURNS: True if valid email format, False otherwise
'-----------------------------------------------------------------------------
Function ValidateEmail(email)
    Dim objRegEx, pattern
    Set objRegEx = New RegExp

    pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
    objRegEx.Pattern = pattern
    objRegEx.IgnoreCase = True

    ValidateEmail = objRegEx.Test(email)
    Set objRegEx = Nothing
End Function

'-----------------------------------------------------------------------------
' FUNCTION: SanitizeInput
' PURPOSE: Removes potentially dangerous characters from user input
' PARAMETERS:
'   value - The value to sanitize
'   allowHTML - True to allow HTML tags, False to strip them
' RETURNS: Sanitized string
'-----------------------------------------------------------------------------
Function SanitizeInput(value, allowHTML)
    Dim sanitized
    sanitized = Trim(value)

    If Not allowHTML Then
        ' Remove HTML tags
        Dim objRegEx
        Set objRegEx = New RegExp
        objRegEx.Pattern = "<[^>]+>"
        objRegEx.Global = True
        sanitized = objRegEx.Replace(sanitized, "")
        Set objRegEx = Nothing
    End If

    ' Escape single quotes for SQL (though parameterized queries are preferred)
    sanitized = Replace(sanitized, "'", "''")

    SanitizeInput = sanitized
End Function

'-----------------------------------------------------------------------------
' FUNCTION: GetSafeInteger
' PURPOSE: Gets integer from request and validates it (combines retrieval + validation)
' PARAMETERS:
'   source - "QS" for QueryString, "FORM" for Form, "COOKIE" for Cookie
'   paramName - Name of the parameter
'   defaultValue - Value to return if parameter is missing or invalid
'   minVal - Minimum allowed value (optional)
'   maxVal - Maximum allowed value (optional)
' RETURNS: Validated integer or default value
'-----------------------------------------------------------------------------
Function GetSafeInteger(source, paramName, defaultValue, minVal, maxVal)
    Dim value

    ' Get value from appropriate source
    If UCase(source) = "QS" Then
        value = Request.QueryString(paramName)
    ElseIf UCase(source) = "FORM" Then
        value = Request.Form(paramName)
    ElseIf UCase(source) = "COOKIE" Then
        value = Request.Cookies(paramName)
    Else
        GetSafeInteger = defaultValue
        Exit Function
    End If

    ' Return default if empty
    If value = "" Then
        GetSafeInteger = defaultValue
        Exit Function
    End If

    ' Validate
    If Not ValidateInteger(value, minVal, maxVal) Then
        GetSafeInteger = defaultValue
        Exit Function
    End If

    GetSafeInteger = CLng(value)
End Function

'-----------------------------------------------------------------------------
' FUNCTION: GetSafeString
' PURPOSE: Gets string from request and validates it
' PARAMETERS:
'   source - "QS" for QueryString, "FORM" for Form, "COOKIE" for Cookie
'   paramName - Name of the parameter
'   defaultValue - Value to return if parameter is missing or invalid
'   minLen - Minimum length
'   maxLen - Maximum length
'   pattern - Regular expression pattern (optional, pass "" to skip)
' RETURNS: Validated string or default value
'-----------------------------------------------------------------------------
Function GetSafeString(source, paramName, defaultValue, minLen, maxLen, pattern)
    Dim value

    ' Get value from appropriate source
    If UCase(source) = "QS" Then
        value = Request.QueryString(paramName)
    ElseIf UCase(source) = "FORM" Then
        value = Request.Form(paramName)
    ElseIf UCase(source) = "COOKIE" Then
        value = Request.Cookies(paramName)
    Else
        GetSafeString = defaultValue
        Exit Function
    End If

    value = Trim(value)

    ' Return default if empty
    If value = "" Then
        GetSafeString = defaultValue
        Exit Function
    End If

    ' Validate
    If Not ValidateString(value, minLen, maxLen, pattern) Then
        GetSafeString = defaultValue
        Exit Function
    End If

    GetSafeString = value
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ValidateAlphanumeric
' PURPOSE: Validates that a string contains only alphanumeric characters
' PARAMETERS: value - The string to validate
' RETURNS: True if only alphanumeric, False otherwise
'-----------------------------------------------------------------------------
Function ValidateAlphanumeric(value)
    ValidateAlphanumeric = False

    Dim objRegEx
    Set objRegEx = Server.CreateObject("VBScript.RegExp")
    objRegEx.Pattern = "^[a-zA-Z0-9]+$"
    ValidateAlphanumeric = objRegEx.Test(value)
    Set objRegEx = Nothing
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ValidateURL
' PURPOSE: Validates URL format
' PARAMETERS: url - The URL to validate
' RETURNS: True if valid URL format, False otherwise
'-----------------------------------------------------------------------------
Function ValidateURL(url)
    ValidateURL = False

    If Len(url) = 0 Then Exit Function

    Dim objRegEx
    Set objRegEx = New RegExp
    objRegEx.Pattern = "^https?://[^\s]+$"
    objRegEx.IgnoreCase = True

    ValidateURL = objRegEx.Test(url)
    Set objRegEx = Nothing
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ValidateID
' PURPOSE: Validates that a value is a positive integer (for database IDs)
' PARAMETERS: id - The ID value to validate
' RETURNS: True if valid positive integer, False otherwise
'-----------------------------------------------------------------------------
Function ValidateID(id)
    ValidateID = False

    If Not IsNumeric(id) Then Exit Function

    Dim numId
    numId = CLng(id)

    ' Must be positive integer
    If numId < 1 Then Exit Function

    ' Check if it's actually an integer (not a decimal)
    If numId <> CDbl(id) Then Exit Function

    ValidateID = True
End Function

'-----------------------------------------------------------------------------
' FUNCTION: ValidateSerialNumber
' PURPOSE: Validates serial number format (alphanumeric with some special chars)
' PARAMETERS: serial - The serial number to validate
' RETURNS: True if valid format, False otherwise
'-----------------------------------------------------------------------------
Function ValidateSerialNumber(serial)
    ValidateSerialNumber = False

    If Len(serial) = 0 Then Exit Function
    If Len(serial) > 100 Then Exit Function

    ' Allow alphanumeric, hyphens, underscores, and spaces
    Dim objRegEx
    Set objRegEx = New RegExp
    objRegEx.Pattern = "^[a-zA-Z0-9\-_ ]+$"
    objRegEx.IgnoreCase = True

    ValidateSerialNumber = objRegEx.Test(serial)
    Set objRegEx = Nothing
End Function

%>
