public/New-AppVentiXShortcutUserSetting.ps1

<#
.SYNOPSIS
    Creates an AppVentiX UserSetting XML file for a Shortcuts configuration.
.DESCRIPTION
    Builds and saves an AppVentiX UserSetting XML file that defines one or more shortcuts,
    including executable path, arguments, working directory, desktop placement, and icon data.
    Supports two input modes:
 
    - ShortcutEntries mode: accepts an array of hashtables describing individual shortcut entries.
    - InputObject mode: accepts a pre-structured PSCustomObject (e.g. from Get-IvantiWCShortcut),
      which includes shortcut metadata and icon data (base64) ready for direct use.
 
    Icon data handling:
    - If the InputObject or ShortcutEntry already contains base64 icon data, it is used as-is.
    - If icon data is absent and an IconFile path is provided, the function generates all icon
      sizes (16, 32, 48, 256 and default 32) from that file.
    - If neither is available, a warning is issued and icon fields are left empty.
.PARAMETER FriendlyName
    Display name for the AppVentiX UserSetting.
.PARAMETER Description
    Optional description for the UserSetting.
.PARAMETER ExecutionOrder
    Execution order for the UserSetting. Defaults to 0.
.PARAMETER ProcessAtLogin
    Whether the setting is applied at login. Defaults to $true.
.PARAMETER ProcessAtRefresh
    Whether the setting is applied at refresh. Defaults to $true.
.PARAMETER ProcessAtReconnectAndUnlock
    Whether the setting is applied at reconnect and unlock. Defaults to $false.
.PARAMETER MachineGroupFriendlyName
    One or more machine group friendly names to apply the setting to. Defaults to 'All Machine Groups'.
.PARAMETER ShortcutEntries
    Array of hashtables describing shortcut entries. Each entry must contain: ShortcutName, ExecutablePath.
    Optional keys: Arguments, WorkingDirectory, PlaceOnDesktop, IconData, IconData16, IconData32,
    IconData48, IconData256, IconFile.
.PARAMETER InputObject
    Pre-structured PSCustomObject containing shortcut metadata and entries.
.PARAMETER IconFile
    Path to a PNG, ICO, or EXE file used as icon source when icon data is absent in the entries.
    The function will generate all required icon sizes from this file.
.PARAMETER ConfigShare
    Path to the AppVentiX config share. Defaults to the module variable.
.NOTES
    Function : New-AppVentiXShortcutUserSetting
    Author : John Billekens
    Copyright : (c) John Billekens Consultancy & AppVentiX
    Version : 2026.321.1000
#>

function New-AppVentiXShortcutUserSetting {
    [CmdletBinding()]
    [Alias("New-AppVentiXShortcut")]
    param (
        [Parameter(Mandatory = $true, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [string]$FriendlyName,

        [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [string]$Description,

        [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [int]$ExecutionOrder = 0,

        [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [bool]$ProcessAtLogin = $true,

        [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [bool]$ProcessAtRefresh = $true,

        [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [bool]$ProcessAtReconnectAndUnlock = $false,

        [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [string[]]$MachineGroupFriendlyName = @("All Machine Groups"),

        [Parameter(Mandatory = $true, ParameterSetName = "ShortcutEntries")]
        [hashtable[]]$ShortcutEntries = @(),

        [Parameter(Mandatory = $true, ParameterSetName = "InputObject")]
        [PSCustomObject]$InputObject,

        [Parameter(Mandatory = $false, ParameterSetName = "ShortcutEntries")]
        [Parameter(Mandatory = $false, ParameterSetName = "InputObject")]
        [ValidateScript({ Test-Path $_ -PathType Leaf })]
        [string]$IconFile,

        [Parameter(DontShow)]
        [ValidateNotNullOrEmpty()]
        [string]$ConfigShare = $Script:AppVentix.ConfigShare
    )

    #region functions

    function ConvertFrom-IconFilePath {
        <#
        .SYNOPSIS
            Converts an image file to a base64 PNG string, optionally resized.
        #>

        [CmdletBinding()]
        [OutputType([string])]
        param(
            [Parameter(Mandatory = $true)]
            [string]$Path,

            [Parameter(Mandatory = $false)]
            [ValidateRange(16, 256)]
            [int]$Size = 32
        )
        try {
            Add-Type -AssemblyName System.Drawing -ErrorAction Stop
            $originalImage = [System.Drawing.Image]::FromFile($Path)
            if ($originalImage.Width -eq $Size -and $originalImage.Height -eq $Size) {
                $ms = New-Object System.IO.MemoryStream
                $originalImage.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
                $result = [Convert]::ToBase64String($ms.ToArray())
                $ms.Dispose()
            } else {
                $resized = New-Object System.Drawing.Bitmap $Size, $Size
                $g = [System.Drawing.Graphics]::FromImage($resized)
                $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
                $g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
                $g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
                $g.DrawImage($originalImage, 0, 0, $Size, $Size)
                $g.Dispose()
                $ms = New-Object System.IO.MemoryStream
                $resized.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
                $result = [Convert]::ToBase64String($ms.ToArray())
                $ms.Dispose()
                $resized.Dispose()
            }
            $originalImage.Dispose()
            return $result
        } catch {
            Write-Error "Failed to convert icon file '$Path' to Base64: $_"
            return ""
        }
    }

    function New-ShortcutUserSettingXml {
        [CmdletBinding()]
        param ()

        $XmlDoc = New-Object System.Xml.XmlDocument

        $Root = $XmlDoc.CreateElement("UserSetting")
        [void]$XmlDoc.AppendChild($Root)

        function Add-TextElement {
            param (
                [System.Xml.XmlElement]$Parent,
                [string]$Name,
                [string]$Text
            )
            $el = $XmlDoc.CreateElement($Name)
            $el.InnerText = $Text
            [void]$Parent.AppendChild($el)
            return $el
        }

        [void](Add-TextElement -Parent $Root -Name "Id"                          -Text $SettingId)
        [void](Add-TextElement -Parent $Root -Name "FriendlyName"                -Text $FriendlyName)
        [void](Add-TextElement -Parent $Root -Name "Description"                 -Text $Description)
        [void](Add-TextElement -Parent $Root -Name "Type"                        -Text $Type)
        [void](Add-TextElement -Parent $Root -Name "ExecutionOrder"              -Text $ExecutionOrder)
        [void](Add-TextElement -Parent $Root -Name "CreatedDate"                 -Text $CreatedDate)
        [void](Add-TextElement -Parent $Root -Name "LastModifiedDate"            -Text $LastModifiedDate)
        [void](Add-TextElement -Parent $Root -Name "ProcessAtLogin"              -Text (ConvertTo-BooleanString -Value $ProcessAtLogin))
        [void](Add-TextElement -Parent $Root -Name "ProcessAtRefresh"            -Text (ConvertTo-BooleanString -Value $ProcessAtRefresh))
        [void](Add-TextElement -Parent $Root -Name "ProcessAtReconnectAndUnlock" -Text (ConvertTo-BooleanString -Value $ProcessAtReconnectAndUnlock))

        $MachineGroupsElement = $XmlDoc.CreateElement("MachineGroups")
        foreach ($Group in $MachineGroups) {
            [void](Add-TextElement -Parent $MachineGroupsElement -Name "MachineGroup" -Text $Group)
        }
        [void]$Root.AppendChild($MachineGroupsElement)

        $MachineGroupFriendlyNamesElement = $XmlDoc.CreateElement("MachineGroupFriendlyNames")
        foreach ($GroupFriendlyName in $MachineGroupFriendlyNames) {
            [void](Add-TextElement -Parent $MachineGroupFriendlyNamesElement -Name "FriendlyName" -Text $GroupFriendlyName)
        }
        [void]$Root.AppendChild($MachineGroupFriendlyNamesElement)

        $ShortcutEntriesElement = $XmlDoc.CreateElement("ShortcutEntries")
        foreach ($EntryData in $NewShortcutEntries) {
            $ShortcutEntryElement = $XmlDoc.CreateElement("ShortcutEntry")
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "ShortcutName"     -Text $EntryData.ShortcutName)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "ExecutablePath"   -Text $EntryData.ExecutablePath)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "Arguments"        -Text $EntryData.Arguments)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "WorkingDirectory" -Text $EntryData.WorkingDirectory)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "PlaceOnDesktop"   -Text (ConvertTo-BooleanString -Value ([bool]$EntryData.PlaceOnDesktop)))
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData"         -Text $EntryData.IconData)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData16"       -Text $EntryData.IconData16)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData32"       -Text $EntryData.IconData32)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData48"       -Text $EntryData.IconData48)
            [void](Add-TextElement -Parent $ShortcutEntryElement -Name "IconData256"      -Text $EntryData.IconData256)
            [void]$ShortcutEntriesElement.AppendChild($ShortcutEntryElement)
        }
        [void]$Root.AppendChild($ShortcutEntriesElement)

        return $XmlDoc
    }
    #endregion functions

    if (Test-AppVentiXIsLicensed -ConfigShare $ConfigShare) {

        $SettingId = [guid]::NewGuid().ToString()
        $Type = "Shortcuts"
        $userSettingsPath = Join-Path -Path $ConfigShare -ChildPath $Script:AppVentix.UserSettingsPath

        # Process InputObject
        if ($PSBoundParameters.ContainsKey("InputObject")) {
            Write-Verbose "Processing InputObject parameter..."
            if (-not [string]::IsNullOrEmpty($InputObject.FriendlyName)) {
                $FriendlyName = $InputObject.FriendlyName
            }
            if (-not [string]::IsNullOrEmpty($InputObject.Description)) {
                $Description = $InputObject.Description
            }
            if ($PSBoundParameters.ContainsKey("ProcessAtLogin") -eq $false -and $null -ne $InputObject.ProcessAtLogin) {
                $ProcessAtLogin = [bool]$InputObject.ProcessAtLogin
            }
            if ($PSBoundParameters.ContainsKey("ProcessAtRefresh") -eq $false -and $null -ne $InputObject.ProcessAtRefresh) {
                $ProcessAtRefresh = [bool]$InputObject.ProcessAtRefresh
            }
            if ($PSBoundParameters.ContainsKey("ProcessAtReconnectAndUnlock") -eq $false -and $null -ne $InputObject.ProcessAtReconnectAndUnlock) {
                $ProcessAtReconnectAndUnlock = [bool]$InputObject.ProcessAtReconnectAndUnlock
            }
            $ShortcutEntries = @(
                $InputObject.ShortcutEntries | ForEach-Object {
                    @{
                        ShortcutName     = "$($_.ShortcutName)"
                        ExecutablePath   = "$($_.ExecutablePath)"
                        Arguments        = "$($_.Arguments)"
                        WorkingDirectory = "$($_.WorkingDirectory)"
                        PlaceOnDesktop   = $_.PlaceOnDesktop
                        IconData         = "$($_.IconData)"
                        IconData16       = "$($_.IconData16)"
                        IconData32       = "$($_.IconData32)"
                        IconData48       = "$($_.IconData48)"
                        IconData256      = "$($_.IconData256)"
                    }
                }
            )
        }

        # Resolve MachineGroups
        if ($MachineGroupFriendlyName.Count -gt 0) {
            if ($MachineGroupFriendlyName -notcontains "All Machine Groups" -and $MachineGroupFriendlyName -notcontains "All" -and $MachineGroupFriendlyName.Count -gt 0) {
                $AvailableGroups = Get-AppVentiXMachineGroup
                $MachineGroups = @()
                $MachineGroupFriendlyNames = @()
                foreach ($Group in $MachineGroupFriendlyName) {
                    $selectedGroup = $AvailableGroups | Where-Object { $_.FriendlyName -ieq $Group }
                    if ($selectedGroup) {
                        $MachineGroups += $selectedGroup.GroupName.ToString()
                        $MachineGroupFriendlyNames += $selectedGroup.FriendlyName.ToString()
                    }
                }
            } else {
                $MachineGroups = @("All")
                $MachineGroupFriendlyNames = @("All Machine Groups")
            }
        } else {
            $MachineGroups = @("All")
            $MachineGroupFriendlyNames = @("All Machine Groups")
        }

        #region --- Build $NewShortcutEntries ---
        $NewShortcutEntries = @()

        foreach ($entry in $ShortcutEntries) {
            if (-not ($entry.ContainsKey("ShortcutName") -and $entry.ContainsKey("ExecutablePath"))) {
                Write-Error "Each shortcut entry must be a hashtable containing at least the keys: ShortcutName, ExecutablePath"
                return
            }

            $NewEntry = [ordered]@{
                ShortcutName     = "$($entry.ShortcutName)"
                ExecutablePath   = "$($entry.ExecutablePath)"
                Arguments        = "$($entry.Arguments)"
                WorkingDirectory = "$($entry.WorkingDirectory)"
                PlaceOnDesktop   = $false
                IconData         = "$($entry.IconData)"
                IconData16       = "$($entry.IconData16)"
                IconData32       = "$($entry.IconData32)"
                IconData48       = "$($entry.IconData48)"
                IconData256      = "$($entry.IconData256)"
            }

            # Normalize PlaceOnDesktop
            switch ($entry.PlaceOnDesktop) {
                "True"  { $NewEntry.PlaceOnDesktop = $true }
                "False" { $NewEntry.PlaceOnDesktop = $false }
                "1"     { $NewEntry.PlaceOnDesktop = $true }
                "0"     { $NewEntry.PlaceOnDesktop = $false }
                $true   { $NewEntry.PlaceOnDesktop = $true }
                $false  { $NewEntry.PlaceOnDesktop = $false }
                default { $NewEntry.PlaceOnDesktop = $false }
            }

            # Icon resolution: use base64 from entry if present, otherwise fall back to IconFile
            $iconSizes = @{ IconData = 32; IconData16 = 16; IconData32 = 32; IconData48 = 48; IconData256 = 256 }
            $hasAnyIconData = $iconSizes.Keys | Where-Object { -not [string]::IsNullOrEmpty($NewEntry[$_]) }

            if (-not $hasAnyIconData) {
                if ($PSBoundParameters.ContainsKey("IconFile")) {
                    Write-Verbose "No icon data in entry '$($NewEntry.ShortcutName)'. Generating from IconFile '$IconFile'."
                    foreach ($iconField in $iconSizes.GetEnumerator()) {
                        $NewEntry[$iconField.Key] = ConvertFrom-IconFilePath -Path $IconFile -Size $iconField.Value
                    }
                } else {
                    Write-Warning "No icon data found for shortcut '$($NewEntry.ShortcutName)' and no -IconFile specified. Icon fields will be empty."
                }
            } elseif ($PSBoundParameters.ContainsKey("IconFile")) {
                Write-Verbose "Entry '$($NewEntry.ShortcutName)' already contains icon data. -IconFile parameter will be ignored for this entry."
            }

            $NewShortcutEntries += $NewEntry
        }
        #endregion --- Build $NewShortcutEntries ---

        $policyFilename = "$($Type)-$($SettingId).xml"
        $policyFullname = Join-Path -Path $userSettingsPath -ChildPath $policyFilename

        $CreatedDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
        $LastModifiedDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")

        if ([string]::IsNullOrEmpty($FriendlyName)) {
            Write-Error "FriendlyName is required. Please provide a value for the FriendlyName parameter or include it in the InputObject."
            return
        }

        try {
            Write-Verbose "Building UserSetting XML..."

            $XmlDocument = New-ShortcutUserSettingXml

            $XmlWriterSettings = New-Object System.Xml.XmlWriterSettings
            $XmlWriterSettings.Indent = $true
            $XmlWriterSettings.IndentChars = " "
            $XmlWriterSettings.Encoding = [System.Text.Encoding]::UTF8
            $XmlWriterSettings.OmitXmlDeclaration = $true

            Write-Verbose "Saving UserSetting XML to $policyFullname"
            $XmlWriter = [System.Xml.XmlWriter]::Create($policyFullname, $XmlWriterSettings)
            $XmlDocument.Save($XmlWriter)
            $XmlWriter.Close()

            Write-AppVentiXLogEntry -Feature UserSettings -Action $($MyInvocation.MyCommand.Name) -Details "New Shortcut User Setting '$FriendlyName' added with $($NewShortcutEntries.Count) shortcut(s)."

            Write-Output (
                [PSCustomObject]@{
                    Id           = $SettingId
                    FriendlyName = $FriendlyName
                    FileName     = $policyFilename
                }
            )
        } catch {
            Write-Error "Failed to generate XML: $($_.Exception.Message)"
        }
    } else {
        Write-Warning 'AppVentiX is not licensed!'
    }
}

# SIG # Begin signature block
# MIImdwYJKoZIhvcNAQcCoIImaDCCJmQCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDcKsO4LgW2pbvG
# sXZfXHAMX9amKJxM4nmUBpHoya/adaCCIAowggYUMIID/KADAgECAhB6I67aU2mW
# D5HIPlz0x+M/MA0GCSqGSIb3DQEBDAUAMFcxCzAJBgNVBAYTAkdCMRgwFgYDVQQK
# Ew9TZWN0aWdvIExpbWl0ZWQxLjAsBgNVBAMTJVNlY3RpZ28gUHVibGljIFRpbWUg
# U3RhbXBpbmcgUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5
# WjBVMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSwwKgYD
# VQQDEyNTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIENBIFIzNjCCAaIwDQYJ
# KoZIhvcNAQEBBQADggGPADCCAYoCggGBAM2Y2ENBq26CK+z2M34mNOSJjNPvIhKA
# VD7vJq+MDoGD46IiM+b83+3ecLvBhStSVjeYXIjfa3ajoW3cS3ElcJzkyZlBnwDE
# JuHlzpbN4kMH2qRBVrjrGJgSlzzUqcGQBaCxpectRGhhnOSwcjPMI3G0hedv2eNm
# GiUbD12OeORN0ADzdpsQ4dDi6M4YhoGE9cbY11XxM2AVZn0GiOUC9+XE0wI7CQKf
# OUfigLDn7i/WeyxZ43XLj5GVo7LDBExSLnh+va8WxTlA+uBvq1KO8RSHUQLgzb1g
# bL9Ihgzxmkdp2ZWNuLc+XyEmJNbD2OIIq/fWlwBp6KNL19zpHsODLIsgZ+WZ1AzC
# s1HEK6VWrxmnKyJJg2Lv23DlEdZlQSGdF+z+Gyn9/CRezKe7WNyxRf4e4bwUtrYE
# 2F5Q+05yDD68clwnweckKtxRaF0VzN/w76kOLIaFVhf5sMM/caEZLtOYqYadtn03
# 4ykSFaZuIBU9uCSrKRKTPJhWvXk4CllgrwIDAQABo4IBXDCCAVgwHwYDVR0jBBgw
# FoAU9ndq3T/9ARP/FqFsggIv0Ao9FCUwHQYDVR0OBBYEFF9Y7UwxeqJhQo1SgLqz
# YZcZojKbMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0gADBMBgNVHR8ERTBDMEGg
# P6A9hjtodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNUaW1lU3Rh
# bXBpbmdSb290UjQ2LmNybDB8BggrBgEFBQcBAQRwMG4wRwYIKwYBBQUHMAKGO2h0
# dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ1Jv
# b3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAN
# BgkqhkiG9w0BAQwFAAOCAgEAEtd7IK0ONVgMnoEdJVj9TC1ndK/HYiYh9lVUacah
# RoZ2W2hfiEOyQExnHk1jkvpIJzAMxmEc6ZvIyHI5UkPCbXKspioYMdbOnBWQUn73
# 3qMooBfIghpR/klUqNxx6/fDXqY0hSU1OSkkSivt51UlmJElUICZYBodzD3M/SFj
# eCP59anwxs6hwj1mfvzG+b1coYGnqsSz2wSKr+nDO+Db8qNcTbJZRAiSazr7KyUJ
# Go1c+MScGfG5QHV+bps8BX5Oyv9Ct36Y4Il6ajTqV2ifikkVtB3RNBUgwu/mSiSU
# ice/Jp/q8BMk/gN8+0rNIE+QqU63JoVMCMPY2752LmESsRVVoypJVt8/N3qQ1c6F
# ibbcRabo3azZkcIdWGVSAdoLgAIxEKBeNh9AQO1gQrnh1TA8ldXuJzPSuALOz1Uj
# b0PCyNVkWk7hkhVHfcvBfI8NtgWQupiaAeNHe0pWSGH2opXZYKYG4Lbukg7HpNi/
# KqJhue2Keak6qH9A8CeEOB7Eob0Zf+fU+CCQaL0cJqlmnx9HCDxF+3BLbUufrV64
# EbTI40zqegPZdA+sXCmbcZy6okx/SjwsusWRItFA3DE8MORZeFb6BmzBtqKJ7l93
# 9bbKBy2jvxcJI98Va95Q5JnlKor3m0E7xpMeYRriWklUPsetMSf2NvUQa/E5vVye
# fQIwggZFMIIELaADAgECAhAIMk+dt9qRb2Pk8qM8Xl1RMA0GCSqGSIb3DQEBCwUA
# MFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMu
# QS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQTAeFw0yNDA0
# MDQxNDA0MjRaFw0yNzA0MDQxNDA0MjNaMGsxCzAJBgNVBAYTAk5MMRIwEAYDVQQH
# DAlTY2hpam5kZWwxIzAhBgNVBAoMGkpvaG4gQmlsbGVrZW5zIENvbnN1bHRhbmN5
# MSMwIQYDVQQDDBpKb2huIEJpbGxla2VucyBDb25zdWx0YW5jeTCCAaIwDQYJKoZI
# hvcNAQEBBQADggGPADCCAYoCggGBAMslntDbSQwHZXwFhmibivbnd0Qfn6sqe/6f
# os3pKzKxEsR907RkDMet2x6RRg3eJkiIr3TFPwqBooyXXgK3zxxpyhGOcuIqyM9J
# 28DVf4kUyZHsjGO/8HFjrr3K1hABNUszP0o7H3o6J31eqV1UmCXYhQlNoW9FOmRC
# 1amlquBmh7w4EKYEytqdmdOBavAD5Xq4vLPxNP6kyA+B2YTtk/xM27TghtbwFGKn
# u9Vwnm7dFcpLxans4ONt2OxDQOMA5NwgcUv/YTpjhq9qoz6ivG55NRJGNvUXsM3w
# 2o7dR6Xh4MuEGrTSrOWGg2A5EcLH1XqQtkF5cZnAPM8W/9HUp8ggornWnFVQ9/6M
# ga+ermy5wy5XrmQpN+x3u6tit7xlHk1Hc+4XY4a4ie3BPXG2PhJhmZAn4ebNSBwN
# Hh8z7WTT9X9OFERepGSytZVeEP7hgyptSLcuhpwWeR4QdBb7dV++4p3PsAUQVHFp
# wkSbrRTv4EiJ0Lcz9P1HPGFoHiFAQQIDAQABo4IBeDCCAXQwDAYDVR0TAQH/BAIw
# ADA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY2NzY2EyMDIxLmNybC5jZXJ0dW0u
# cGwvY2NzY2EyMDIxLmNybDBzBggrBgEFBQcBAQRnMGUwLAYIKwYBBQUHMAGGIGh0
# dHA6Ly9jY3NjYTIwMjEub2NzcC1jZXJ0dW0uY29tMDUGCCsGAQUFBzAChilodHRw
# Oi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwvY2NzY2EyMDIxLmNlcjAfBgNVHSMEGDAW
# gBTddF1MANt7n6B0yrFu9zzAMsBwzTAdBgNVHQ4EFgQUO6KtBpOBgmrlANVAnyiQ
# C6W6lJwwSwYDVR0gBEQwQjAIBgZngQwBBAEwNgYLKoRoAYb2dwIFAQQwJzAlBggr
# BgEFBQcCARYZaHR0cHM6Ly93d3cuY2VydHVtLnBsL0NQUzATBgNVHSUEDDAKBggr
# BgEFBQcDAzAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBAEQsN8wg
# PMdWVkwHPPTN+jKpdns5AKVFjcn00psf2NGVVgWWNQBIQc9lEuTBWb54IK6Ga3hx
# QRZfnPNo5HGl73YLmFgdFQrFzZ1lnaMdIcyh8LTWv6+XNWfoyCM9wCp4zMIDPOs8
# LKSMQqA/wRgqiACWnOS4a6fyd5GUIAm4CuaptpFYr90l4Dn/wAdXOdY32UhgzmSu
# xpUbhD8gVJUaBNVmQaRqeU8y49MxiVrUKJXde1BCrtR9awXbqembc7Nqvmi60tYK
# lD27hlpKtj6eGPjkht0hHEsgzU0Fxw7ZJghYG2wXfpF2ziN893ak9Mi/1dmCNmor
# GOnybKYfT6ff6YTCDDNkod4egcMZdOSv+/Qv+HAeIgEvrxE9QsGlzTwbRtbm6gwY
# YcVBs/SsVUdBn/TSB35MMxRhHE5iC3aUTkDbceo/XP3uFhVL4g2JZHpFfCSu2TQr
# rzRn2sn07jfMvzeHArCOJgBW1gPqR3WrJ4hUxL06Rbg1gs9tU5HGGz9KNQMfQFQ7
# 0Wz7UIhezGcFcRfkIfSkMmQYYpsc7rfzj+z0ThfDVzzJr2dMOFsMlfj1T6l22GBq
# 9XQx0A4lcc5Fl9pRxbOuHHWFqIBD/BCEhwniOCySzqENd2N+oz8znKooSISStnkN
# aYXt6xblJF2dx9Dn89FK7d1IquNxOwt0tI5dMIIGYjCCBMqgAwIBAgIRAKQpO24e
# 3denNAiHrXpOtyQwDQYJKoZIhvcNAQEMBQAwVTELMAkGA1UEBhMCR0IxGDAWBgNV
# BAoTD1NlY3RpZ28gTGltaXRlZDEsMCoGA1UEAxMjU2VjdGlnbyBQdWJsaWMgVGlt
# ZSBTdGFtcGluZyBDQSBSMzYwHhcNMjUwMzI3MDAwMDAwWhcNMzYwMzIxMjM1OTU5
# WjByMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOV2VzdCBZb3Jrc2hpcmUxGDAWBgNV
# BAoTD1NlY3RpZ28gTGltaXRlZDEwMC4GA1UEAxMnU2VjdGlnbyBQdWJsaWMgVGlt
# ZSBTdGFtcGluZyBTaWduZXIgUjM2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEA04SV9G6kU3jyPRBLeBIHPNyUgVNnYayfsGOyYEXrn3+SkDYTLs1crcw/
# ol2swE1TzB2aR/5JIjKNf75QBha2Ddj+4NEPKDxHEd4dEn7RTWMcTIfm492TW22I
# 8LfH+A7Ehz0/safc6BbsNBzjHTt7FngNfhfJoYOrkugSaT8F0IzUh6VUwoHdYDpi
# ln9dh0n0m545d5A5tJD92iFAIbKHQWGbCQNYplqpAFasHBn77OqW37P9BhOASdmj
# p3IijYiFdcA0WQIe60vzvrk0HG+iVcwVZjz+t5OcXGTcxqOAzk1frDNZ1aw8nFhG
# EvG0ktJQknnJZE3D40GofV7O8WzgaAnZmoUn4PCpvH36vD4XaAF2CjiPsJWiY/j2
# xLsJuqx3JtuI4akH0MmGzlBUylhXvdNVXcjAuIEcEQKtOBR9lU4wXQpISrbOT8ux
# +96GzBq8TdbhoFcmYaOBZKlwPP7pOp5Mzx/UMhyBA93PQhiCdPfIVOCINsUY4U23
# p4KJ3F1HqP3H6Slw3lHACnLilGETXRg5X/Fp8G8qlG5Y+M49ZEGUp2bneRLZoyHT
# yynHvFISpefhBCV0KdRZHPcuSL5OAGWnBjAlRtHvsMBrI3AAA0Tu1oGvPa/4yeei
# Ayu+9y3SLC98gDVbySnXnkujjhIh+oaatsk/oyf5R2vcxHahajMCAwEAAaOCAY4w
# ggGKMB8GA1UdIwQYMBaAFF9Y7UwxeqJhQo1SgLqzYZcZojKbMB0GA1UdDgQWBBSI
# YYyhKjdkgShgoZsx0Iz9LALOTzAOBgNVHQ8BAf8EBAMCBsAwDAYDVR0TAQH/BAIw
# ADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBKBgNVHSAEQzBBMDUGDCsGAQQBsjEB
# AgEDCDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZn
# gQwBBAIwSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2NybC5zZWN0aWdvLmNvbS9T
# ZWN0aWdvUHVibGljVGltZVN0YW1waW5nQ0FSMzYuY3JsMHoGCCsGAQUFBwEBBG4w
# bDBFBggrBgEFBQcwAoY5aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVi
# bGljVGltZVN0YW1waW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2Nz
# cC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAYEAAoE+pIZyUSH5ZakuPVKK
# 4eWbzEsTRJOEjbIu6r7vmzXXLpJx4FyGmcqnFZoa1dzx3JrUCrdG5b//LfAxOGy9
# Ph9JtrYChJaVHrusDh9NgYwiGDOhyyJ2zRy3+kdqhwtUlLCdNjFjakTSE+hkC9F5
# ty1uxOoQ2ZkfI5WM4WXA3ZHcNHB4V42zi7Jk3ktEnkSdViVxM6rduXW0jmmiu71Z
# pBFZDh7Kdens+PQXPgMqvzodgQJEkxaION5XRCoBxAwWwiMm2thPDuZTzWp/gUFz
# i7izCmEt4pE3Kf0MOt3ccgwn4Kl2FIcQaV55nkjv1gODcHcD9+ZVjYZoyKTVWb4V
# qMQy/j8Q3aaYd/jOQ66Fhk3NWbg2tYl5jhQCuIsE55Vg4N0DUbEWvXJxtxQQaVR5
# xzhEI+BjJKzh3TQ026JxHhr2fuJ0mV68AluFr9qshgwS5SpN5FFtaSEnAwqZv3IS
# +mlG50rK7W3qXbWwi4hmpylUfygtYLEdLQukNEX1jiOKMIIGgjCCBGqgAwIBAgIQ
# NsKwvXwbOuejs902y8l1aDANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYD
# VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBS
# U0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMjEwMzIyMDAwMDAwWhcNMzgw
# MTE4MjM1OTU5WjBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1p
# dGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3Qg
# UjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAiJ3YuUVnnR3d6Lkm
# gZpUVMB8SQWbzFoVD9mUEES0QUCBdxSZqdTkdizICFNeINCSJS+lV1ipnW5ihkQy
# C0cRLWXUJzodqpnMRs46npiJPHrfLBOifjfhpdXJ2aHHsPHggGsCi7uE0awqKggE
# /LkYw3sqaBia67h/3awoqNvGqiFRJ+OTWYmUCO2GAXsePHi+/JUNAax3kpqstbl3
# vcTdOGhtKShvZIvjwulRH87rbukNyHGWX5tNK/WABKf+Gnoi4cmisS7oSimgHUI0
# Wn/4elNd40BFdSZ1EwpuddZ+Wr7+Dfo0lcHflm/FDDrOJ3rWqauUP8hsokDoI7D/
# yUVI9DAE/WK3Jl3C4LKwIpn1mNzMyptRwsXKrop06m7NUNHdlTDEMovXAIDGAvYy
# nPt5lutv8lZeI5w3MOlCybAZDpK3Dy1MKo+6aEtE9vtiTMzz/o2dYfdP0KWZwZIX
# bYsTIlg1YIetCpi5s14qiXOpRsKqFKqav9R1R5vj3NgevsAsvxsAnI8Oa5s2oy25
# qhsoBIGo/zi6GpxFj+mOdh35Xn91y72J4RGOJEoqzEIbW3q0b2iPuWLA911cRxgY
# 5SJYubvjay3nSMbBPPFsyl6mY4/WYucmyS9lo3l7jk27MAe145GWxK4O3m3gEFEI
# kv7kRmefDR7Oe2T1HxAnICQvr9sCAwEAAaOCARYwggESMB8GA1UdIwQYMBaAFFN5
# v1qqK0rPVIDh2JvAnfKyA2bLMB0GA1UdDgQWBBT2d2rdP/0BE/8WoWyCAi/QCj0U
# JTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUEDDAKBggr
# BgEFBQcDCDARBgNVHSAECjAIMAYGBFUdIAAwUAYDVR0fBEkwRzBFoEOgQYY/aHR0
# cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdFJTQUNlcnRpZmljYXRpb25B
# dXRob3JpdHkuY3JsMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDov
# L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEADr5lQe1oRLjl
# ocXUEYfktzsljOt+2sgXke3Y8UPEooU5y39rAARaAdAxUeiX1ktLJ3+lgxtoLQhn
# 5cFb3GF2SSZRX8ptQ6IvuD3wz/LNHKpQ5nX8hjsDLRhsyeIiJsms9yAWnvdYOdEM
# q1W61KE9JlBkB20XBee6JaXx4UBErc+YuoSb1SxVf7nkNtUjPfcxuFtrQdRMRi/f
# InV/AobE8Gw/8yBMQKKaHt5eia8ybT8Y/Ffa6HAJyz9gvEOcF1VWXG8OMeM7Vy7B
# s6mSIkYeYtddU1ux1dQLbEGur18ut97wgGwDiGinCwKPyFO7ApcmVJOtlw9FVJxw
# /mL1TbyBns4zOgkaXFnnfzg4qbSvnrwyj1NiurMp4pmAWjR+Pb/SIduPnmFzbSN/
# G8reZCL4fvGlvPFk4Uab/JVCSmj59+/mB2Gn6G/UYOy8k60mKcmaAZsEVkhOFuoj
# 4we8CYyaR9vd9PGZKSinaZIkvVjbH/3nlLb0a7SBIkiRzfPfS9T+JesylbHa1LtR
# V9U/7m0q7Ma2CQ/t392ioOssXW7oKLdOmMBl14suVFBmbzrt5V5cQPnwtd3UOTpS
# 9oCG+ZZheiIvPgkDmA8FzPsnfXW5qHELB43ET7HHFHeRPRYrMBKjkb8/IN7Po0d0
# hQoF4TeMM+zYAJzoKQnVKOLg8pZVPT8wgga5MIIEoaADAgECAhEAmaOACiZVO2Wr
# 3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwxIjAgBgNVBAoT
# GVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0
# aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0
# d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIxOFowVjELMAkG
# A1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIG
# A1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjANBgkqhkiG9w0B
# AQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5cTbq96y34vuTm
# flN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7VS5+djSoMcbv
# IKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1PH9ud0IF+njvM
# k2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOouu9Tj1yHIohzu
# C8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv8aGUsRdaCtVD
# 2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtMLK+Wo837Q4QO
# ZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9lDV2nT8mFSkc
# SkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/JHuurfTI5XDY
# O962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkKbWpQ5boufUnq
# 1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADaCi2JSplKShBS
# ND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAWd18Jx5n858JS
# qPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFN10XUwA
# 23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8+tT4HKbROg79
# MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAwBgNVHR8EKTAn
# MCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3JsMGwGCCsGAQUF
# BwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3AtY2VydHVtLmNv
# bTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2N0bmNh
# Mi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEWGGh0dHA6Ly93
# d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhYD+WPUCiaU58Q
# 7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUStJl490L94C9L
# GF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChDUyuQy6rGDxLU
# UAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiRsWrhWM2f8pXd
# d3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7bWRLDm0CdY9rN
# LqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mATwZWwSD+B7eMc
# ZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3/bFAEloMU+vU
# BfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESYkOh1/w1tVxTp
# V2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR+x+zPF/2DaGg
# K2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C+xN4YaNjt2yw
# zOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qwt4HOUBCrW602
# NCmvO1nm+/80nLy5r0AZvCQxaQ4xggXDMIIFvwIBATBqMFYxCzAJBgNVBAYTAlBM
# MSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0Nl
# cnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQCDJPnbfakW9j5PKjPF5dUTANBglg
# hkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3
# DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV
# MC8GCSqGSIb3DQEJBDEiBCAeoRimG5w/NrjNn3mNeEYIdiAqSbWvJVyHcxWXjsC2
# dzANBgkqhkiG9w0BAQEFAASCAYCJZdddAxIDEyq//MHDfu7U8E8ivDzbWdd6hzwg
# Xewr3AN6JGZz7suIFwosTbJ2y1danElg0X9bv1/ZH+f94qBQebmh4hDkjzGWgUm1
# UDqPPK0+UFmOP0+uTLTdBWEYEl6/Z0ORnIkHRW/CbTAKYnhNcRIQJjc/VqR/azSq
# NZa2OJhdiXPxEZlIP5BIoUrpGyWao0X+BcQAmBS41dWsdeFHIVgy0bBBkMPUjfai
# 0XD1hS3ayd7dJHAuzbnB+apejkU9Db9lHmY9+1f1zKbOaWH+e+WbAyyTh3elybeW
# GPNkmMfiEMtzGCb5/7n+i1VJpBnDrJNKWU5Qh6UxpB7ZZk3mBnmjEwCRIt2cdXRs
# PnSKNUxcX+rlf2Cbd/01aYWHFR+LCQ8d9rd/2n9tw64V+uFlxZdp6LWciz3fiYf+
# FF56mlBK2JbuFi2q/FMGaQtR05yWj4tkDQ/l+dORBkAuq0ca9jH7QPurdHFvqUok
# L0Jnwgb5KuQhRshiaNk/cyw+uHyhggMjMIIDHwYJKoZIhvcNAQkGMYIDEDCCAwwC
# AQEwajBVMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSww
# KgYDVQQDEyNTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIENBIFIzNgIRAKQp
# O24e3denNAiHrXpOtyQwDQYJYIZIAWUDBAICBQCgeTAYBgkqhkiG9w0BCQMxCwYJ
# KoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjA2MTYxODMzMzdaMD8GCSqGSIb3
# DQEJBDEyBDAylDFyz5bTYKVpgaaiOtd1VpQPHqYl37lmGhb6U+xGCjREDWfCFbOb
# pFc2dc3rgNkwDQYJKoZIhvcNAQEBBQAEggIAphawqv79ni0VrLfIZXTHeLAafmDn
# G4f+8rdcQoh0yq5crtLeQ1l8vLURJS5WK/KJ4NlHT/NHxzQ7syp6ltD1+9dscRAT
# 2LYpUN8XPJpUoo5Q7MVtBRMLZSg3q8BNtVrVgQLk3n4Y6Aifr7hAJJnJlyRN3ZBH
# CighvQ/CWd8uXBLZUtMBmwEe2T1PRDfbz+i8RK7AsGfbx7+/16D4kP1luMEwOEMO
# cO59YkkbiG8Sq8awLJGFFaADX88P+44bQXtqtxNUZlPM1hvMw6UIoPIBeAHHAc4u
# WEjAKtO1qxGd4BjHUol/aTSlxO5OeMOR41u3muj7zxMvJB62XjkDCuj1JhVz1lnC
# o4ZXby8DxRkXQZvWG4ZvtMhzNtNNC1PJAHX0F2LjRLNc8UBxORj1AeTh84R/OH48
# HQ/k0uuOr1GdjXSG1AnaQ85GkqcI1yzpSozt2YqMPW10mqVHgtusShNoZ1kVVmvT
# ap64DqHHGJkVEN6wFfs7g6pq9mm5gRP0CalR0pXlJs4t643/tkuDVpULqpQ0tSEZ
# l7hKzmaTjHxAEhOyKi2vwngiDqLN+mH1uqcCpzskrGtOmKdpH+yt0tZxzdf5iir4
# N6DiEHW+tD8GMXL70X/82GQxch5ofBwQYiUc4hUR/06nvIOHb2XqG/UDNE3IyFs5
# 7bELsznSWRjPSrg=
# SIG # End signature block