| Server IP : 121.121.20.254 / Your IP : 216.73.217.141 Web Server : Microsoft-IIS/10.0 System : Windows NT WEB-SERVER 10.0 build 20348 (Windows Server 2022) AMD64 User : IUSR ( 0) PHP Version : 8.3.28 Disable Function : NONE MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/Program Files (x86)/WindowsPowerShell/Modules/Pester/3.4.0/Functions/ |
Upload File : |
if ($PSVersionTable.PSVersion.Major -le 2)
{
function Exit-CoverageAnalysis { }
function Get-CoverageReport { }
function Show-CoverageReport { }
function Enter-CoverageAnalysis {
param ( $CodeCoverage )
if ($CodeCoverage) { & $SafeCommands['Write-Error'] 'Code coverage analysis requires PowerShell 3.0 or later.' }
}
return
}
function Enter-CoverageAnalysis
{
[CmdletBinding()]
param (
[object[]] $CodeCoverage,
[object] $PesterState
)
$coverageInfo =
foreach ($object in $CodeCoverage)
{
Get-CoverageInfoFromUserInput -InputObject $object
}
$PesterState.CommandCoverage = @(Get-CoverageBreakpoints -CoverageInfo $coverageInfo)
}
function Exit-CoverageAnalysis
{
param ([object] $PesterState)
& $SafeCommands['Set-StrictMode'] -Off
$breakpoints = @($PesterState.CommandCoverage.Breakpoint) -ne $null
if ($breakpoints.Count -gt 0)
{
& $SafeCommands['Remove-PSBreakpoint'] -Breakpoint $breakpoints
}
}
function Get-CoverageInfoFromUserInput
{
param (
[Parameter(Mandatory = $true)]
[object]
$InputObject
)
if ($InputObject -is [System.Collections.IDictionary])
{
$unresolvedCoverageInfo = Get-CoverageInfoFromDictionary -Dictionary $InputObject
}
else
{
$unresolvedCoverageInfo = New-CoverageInfo -Path ([string]$InputObject)
}
Resolve-CoverageInfo -UnresolvedCoverageInfo $unresolvedCoverageInfo
}
function New-CoverageInfo
{
param ([string] $Path, [string] $Function = $null, [int] $StartLine = 0, [int] $EndLine = 0)
return [pscustomobject]@{
Path = $Path
Function = $Function
StartLine = $StartLine
EndLine = $EndLine
}
}
function Get-CoverageInfoFromDictionary
{
param ([System.Collections.IDictionary] $Dictionary)
[string] $path = Get-DictionaryValueFromFirstKeyFound -Dictionary $Dictionary -Key 'Path', 'p'
if ([string]::IsNullOrEmpty($path))
{
throw "Coverage value '$Dictionary' is missing required Path key."
}
$startLine = Get-DictionaryValueFromFirstKeyFound -Dictionary $Dictionary -Key 'StartLine', 'Start', 's'
$endLine = Get-DictionaryValueFromFirstKeyFound -Dictionary $Dictionary -Key 'EndLine', 'End', 'e'
[string] $function = Get-DictionaryValueFromFirstKeyFound -Dictionary $Dictionary -Key 'Function', 'f'
$startLine = Convert-UnknownValueToInt -Value $startLine -DefaultValue 0
$endLine = Convert-UnknownValueToInt -Value $endLine -DefaultValue 0
return New-CoverageInfo -Path $path -StartLine $startLine -EndLine $endLine -Function $function
}
function Convert-UnknownValueToInt
{
param ([object] $Value, [int] $DefaultValue = 0)
try
{
return [int] $Value
}
catch
{
return $DefaultValue
}
}
function Resolve-CoverageInfo
{
param ([psobject] $UnresolvedCoverageInfo)
$path = $UnresolvedCoverageInfo.Path
try
{
$resolvedPaths = & $SafeCommands['Resolve-Path'] -Path $path -ErrorAction Stop
}
catch
{
& $SafeCommands['Write-Error'] "Could not resolve coverage path '$path': $($_.Exception.Message)"
return
}
$filePaths =
foreach ($resolvedPath in $resolvedPaths)
{
$item = & $SafeCommands['Get-Item'] -LiteralPath $resolvedPath
if ($item -is [System.IO.FileInfo] -and ('.ps1','.psm1') -contains $item.Extension)
{
$item.FullName
}
elseif (-not $item.PsIsContainer)
{
& $SafeCommands['Write-Warning'] "CodeCoverage path '$path' resolved to a non-PowerShell file '$($item.FullName)'; this path will not be part of the coverage report."
}
}
$params = @{
StartLine = $UnresolvedCoverageInfo.StartLine
EndLine = $UnresolvedCoverageInfo.EndLine
Function = $UnresolvedCoverageInfo.Function
}
foreach ($filePath in $filePaths)
{
$params['Path'] = $filePath
New-CoverageInfo @params
}
}
function Get-CoverageBreakpoints
{
[CmdletBinding()]
param (
[object[]] $CoverageInfo
)
$fileGroups = @($CoverageInfo | & $SafeCommands['Group-Object'] -Property Path)
foreach ($fileGroup in $fileGroups)
{
& $SafeCommands['Write-Verbose'] "Initializing code coverage analysis for file '$($fileGroup.Name)'"
$totalCommands = 0
$analyzedCommands = 0
:commandLoop
foreach ($command in Get-CommandsInFile -Path $fileGroup.Name)
{
$totalCommands++
foreach ($coverageInfoObject in $fileGroup.Group)
{
if (Test-CoverageOverlapsCommand -CoverageInfo $coverageInfoObject -Command $command)
{
$analyzedCommands++
New-CoverageBreakpoint -Command $command
continue commandLoop
}
}
}
& $SafeCommands['Write-Verbose'] "Analyzing $analyzedCommands of $totalCommands commands in file '$($fileGroup.Name)' for code coverage"
}
}
function Get-CommandsInFile
{
param ([string] $Path)
$errors = $null
$tokens = $null
$ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref] $tokens, [ref] $errors)
if ($PSVersionTable.PSVersion.Major -ge 5)
{
# In PowerShell 5.0, dynamic keywords for DSC configurations are represented by the DynamicKeywordStatementAst
# class. They still trigger breakpoints, but are not a child class of CommandBaseAst anymore.
$predicate = {
$args[0] -is [System.Management.Automation.Language.DynamicKeywordStatementAst] -or
$args[0] -is [System.Management.Automation.Language.CommandBaseAst]
}
}
else
{
$predicate = { $args[0] -is [System.Management.Automation.Language.CommandBaseAst] }
}
$searchNestedScriptBlocks = $true
$ast.FindAll($predicate, $searchNestedScriptBlocks)
}
function Test-CoverageOverlapsCommand
{
param ([object] $CoverageInfo, [System.Management.Automation.Language.Ast] $Command)
if ($CoverageInfo.Function)
{
Test-CommandInsideFunction -Command $Command -Function $CoverageInfo.Function
}
else
{
Test-CoverageOverlapsCommandByLineNumber @PSBoundParameters
}
}
function Test-CommandInsideFunction
{
param ([System.Management.Automation.Language.Ast] $Command, [string] $Function)
for ($ast = $Command; $null -ne $ast; $ast = $ast.Parent)
{
$functionAst = $ast -as [System.Management.Automation.Language.FunctionDefinitionAst]
if ($null -ne $functionAst -and $functionAst.Name -like $Function)
{
return $true
}
}
return $false
}
function Test-CoverageOverlapsCommandByLineNumber
{
param ([object] $CoverageInfo, [System.Management.Automation.Language.Ast] $Command)
$commandStart = $Command.Extent.StartLineNumber
$commandEnd = $Command.Extent.EndLineNumber
$coverStart = $CoverageInfo.StartLine
$coverEnd = $CoverageInfo.EndLine
# An EndLine value of 0 means to cover the entire rest of the file from StartLine
# (which may also be 0)
if ($coverEnd -le 0) { $coverEnd = [int]::MaxValue }
return (Test-RangeContainsValue -Value $commandStart -Min $coverStart -Max $coverEnd) -or
(Test-RangeContainsValue -Value $commandEnd -Min $coverStart -Max $coverEnd)
}
function Test-RangeContainsValue
{
param ([int] $Value, [int] $Min, [int] $Max)
return $Value -ge $Min -and $Value -le $Max
}
function New-CoverageBreakpoint
{
param ([System.Management.Automation.Language.Ast] $Command)
if (IsIgnoredCommand -Command $Command) { return }
$params = @{
Script = $Command.Extent.File
Line = $Command.Extent.StartLineNumber
Column = $Command.Extent.StartColumnNumber
Action = { }
}
$breakpoint = & $SafeCommands['Set-PSBreakpoint'] @params
[pscustomobject] @{
File = $Command.Extent.File
Function = Get-ParentFunctionName -Ast $Command
Line = $Command.Extent.StartLineNumber
Command = Get-CoverageCommandText -Ast $Command
Breakpoint = $breakpoint
}
}
function IsIgnoredCommand
{
param ([System.Management.Automation.Language.Ast] $Command)
if (-not $Command.Extent.File)
{
# This can happen if the script contains "configuration" or any similarly implemented
# dynamic keyword. PowerShell modifies the script code and reparses it in memory, leading
# to AST elements with no File in their Extent.
return $true
}
if ($PSVersionTable.PSVersion.Major -ge 4)
{
if ($Command.Extent.Text -eq 'Configuration')
{
# More DSC voodoo. Calls to "configuration" generate breakpoints, but their HitCount
# stays zero (even though they are executed.) For now, ignore them, unless we can come
# up with a better solution.
return $true
}
if (IsChildOfHashtableDynamicKeyword -Command $Command)
{
# The lines inside DSC resource declarations don't trigger their breakpoints when executed,
# just like the "configuration" keyword itself. I don't know why, at this point, but just like
# configuration, we'll ignore it so it doesn't clutter up the coverage analysis with useless junk.
return $true
}
}
if (IsClosingLoopCondition -Command $Command)
{
# For some reason, the closing expressions of do/while and do/until loops don't trigger their breakpoints.
# To avoid useless clutter, we'll ignore those lines as well.
return $true
}
return $false
}
function IsChildOfHashtableDynamicKeyword
{
param ([System.Management.Automation.Language.Ast] $Command)
for ($ast = $Command.Parent; $null -ne $ast; $ast = $ast.Parent)
{
if ($PSVersionTable.PSVersion.Major -ge 5)
{
# The ast behaves differently for DSC resources with version 5+. There's a new DynamicKeywordStatementAst class,
# and they no longer are represented by CommandAst objects.
if ($ast -is [System.Management.Automation.Language.DynamicKeywordStatementAst] -and
$ast.CommandElements[-1] -is [System.Management.Automation.Language.HashtableAst])
{
return $true
}
}
else
{
if ($ast -is [System.Management.Automation.Language.CommandAst] -and
$null -ne $ast.DefiningKeyword -and
$ast.DefiningKeyword.BodyMode -eq [System.Management.Automation.Language.DynamicKeywordBodyMode]::Hashtable)
{
return $true
}
}
}
return $false
}
function IsClosingLoopCondition
{
param ([System.Management.Automation.Language.Ast] $Command)
$ast = $Command
while ($null -ne $ast.Parent)
{
if (($ast.Parent -is [System.Management.Automation.Language.DoWhileStatementAst] -or
$ast.Parent -is [System.Management.Automation.Language.DoUntilStatementAst]) -and
$ast.Parent.Condition -eq $ast)
{
return $true
}
$ast = $ast.Parent
}
return $false
}
function Get-ParentFunctionName
{
param ([System.Management.Automation.Language.Ast] $Ast)
$parent = $Ast.Parent
while ($null -ne $parent -and $parent -isnot [System.Management.Automation.Language.FunctionDefinitionAst])
{
$parent = $parent.Parent
}
if ($null -eq $parent)
{
return ''
}
else
{
return $parent.Name
}
}
function Get-CoverageCommandText
{
param ([System.Management.Automation.Language.Ast] $Ast)
$reportParentExtentTypes = @(
[System.Management.Automation.Language.ReturnStatementAst]
[System.Management.Automation.Language.ThrowStatementAst]
[System.Management.Automation.Language.AssignmentStatementAst]
[System.Management.Automation.Language.IfStatementAst]
)
$parent = Get-ParentNonPipelineAst -Ast $Ast
if ($null -ne $parent)
{
if ($parent -is [System.Management.Automation.Language.HashtableAst])
{
return Get-KeyValuePairText -HashtableAst $parent -ChildAst $Ast
}
elseif ($reportParentExtentTypes -contains $parent.GetType())
{
return $parent.Extent.Text
}
}
return $Ast.Extent.Text
}
function Get-ParentNonPipelineAst
{
param ([System.Management.Automation.Language.Ast] $Ast)
$parent = $null
if ($null -ne $Ast) { $parent = $Ast.Parent }
while ($parent -is [System.Management.Automation.Language.PipelineAst])
{
$parent = $parent.Parent
}
return $parent
}
function Get-KeyValuePairText
{
param (
[System.Management.Automation.Language.HashtableAst] $HashtableAst,
[System.Management.Automation.Language.Ast] $ChildAst
)
& $SafeCommands['Set-StrictMode'] -Off
foreach ($keyValuePair in $HashtableAst.KeyValuePairs)
{
if ($keyValuePair.Item2.PipelineElements -contains $ChildAst)
{
return '{0} = {1}' -f $keyValuePair.Item1.Extent.Text, $keyValuePair.Item2.Extent.Text
}
}
# This shouldn't happen, but just in case, default to the old output of just the expression.
return $ChildAst.Extent.Text
}
function Get-CoverageMissedCommands
{
param ([object[]] $CommandCoverage)
$CommandCoverage | & $SafeCommands['Where-Object'] { $_.Breakpoint.HitCount -eq 0 }
}
function Get-CoverageHitCommands
{
param ([object[]] $CommandCoverage)
$CommandCoverage | & $SafeCommands['Where-Object'] { $_.Breakpoint.HitCount -gt 0 }
}
function Get-CoverageReport
{
param ([object] $PesterState)
$totalCommandCount = $PesterState.CommandCoverage.Count
$missedCommands = @(Get-CoverageMissedCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command)
$hitCommands = @(Get-CoverageHitCommands -CommandCoverage $PesterState.CommandCoverage | & $SafeCommands['Select-Object'] File, Line, Function, Command)
$analyzedFiles = @($PesterState.CommandCoverage | & $SafeCommands['Select-Object'] -ExpandProperty File -Unique)
$fileCount = $analyzedFiles.Count
$executedCommandCount = $totalCommandCount - $missedCommands.Count
[pscustomobject] @{
NumberOfCommandsAnalyzed = $totalCommandCount
NumberOfFilesAnalyzed = $fileCount
NumberOfCommandsExecuted = $executedCommandCount
NumberOfCommandsMissed = $missedCommands.Count
MissedCommands = $missedCommands
HitCommands = $hitCommands
AnalyzedFiles = $analyzedFiles
}
}
function Show-CoverageReport
{
param ([object] $CoverageReport)
if ($null -eq $CoverageReport -or $CoverageReport.NumberOfCommandsAnalyzed -eq 0)
{
return
}
$totalCommandCount = $CoverageReport.NumberOfCommandsAnalyzed
$fileCount = $CoverageReport.NumberOfFilesAnalyzed
$executedPercent = ($CoverageReport.NumberOfCommandsExecuted / $CoverageReport.NumberOfCommandsAnalyzed).ToString("P2")
$commandPlural = $filePlural = ''
if ($totalCommandCount -gt 1) { $commandPlural = 's' }
if ($fileCount -gt 1) { $filePlural = 's' }
$commonParent = Get-CommonParentPath -Path $CoverageReport.AnalyzedFiles
$report = $CoverageReport.MissedCommands | & $SafeCommands['Select-Object'] -Property @(
@{ Name = 'File'; Expression = { Get-RelativePath -Path $_.File -RelativeTo $commonParent } }
'Function'
'Line'
'Command'
)
Write-Screen ''
Write-Screen 'Code coverage report:'
Write-Screen "Covered $executedPercent of $totalCommandCount analyzed command$commandPlural in $fileCount file$filePlural."
if ($CoverageReport.MissedCommands.Count -gt 0)
{
Write-Screen ''
Write-Screen 'Missed commands:'
$report | & $SafeCommands['Format-Table'] -AutoSize | & $SafeCommands['Out-String'] | Write-Screen
}
}
function Get-CommonParentPath
{
param ([string[]] $Path)
$pathsToTest = @( $Path | & $SafeCommands['Select-Object'] -Unique )
if ($pathsToTest.Count -gt 0)
{
$parentPath = & $SafeCommands['Split-Path'] -Path $pathsToTest[0] -Parent
while ($parentPath.Length -gt 0)
{
$nonMatches = $pathsToTest -notmatch "^$([regex]::Escape($parentPath))"
if ($nonMatches.Count -eq 0)
{
return $parentPath
}
else
{
$parentPath = & $SafeCommands['Split-Path'] -Path $parentPath -Parent
}
}
}
return [string]::Empty
}
function Get-RelativePath
{
param ( [string] $Path, [string] $RelativeTo )
return $Path -replace "^$([regex]::Escape($RelativeTo))\\?"
}
# SIG # Begin signature block
# MIInZAYJKoZIhvcNAQcCoIInVTCCJ1ECAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCqG+zazlxP++cv
# 0EUGZRX6zP2XM6BmoNh/fiywwj2BLqCCC7QwggXLMIIEs6ADAgECAhMzAAABQGf2
# mGsxCLhyAAAAAAFAMA0GCSqGSIb3DQEBCwUAMIGOMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMTgwNgYDVQQDEy9NaWNyb3NvZnQgV2luZG93cyBU
# aGlyZCBQYXJ0eSBDb21wb25lbnQgQ0EgMjAxMjAeFw0yNTExMTMxOTU5NDNaFw0y
# NjExMTAxOTU5NDNaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMS4wLAYDVQQDEyVNaWNyb3NvZnQgV2luZG93cyAzcmQgcGFydHkgQ29tcG9u
# ZW50MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEArGt4Hrjs3D7+IIab
# GkPGtg4XeWQFi8nKsdeF+N6nkYF9wsmw0qPk4OovEiJnCSRiEtLfYy3Icn4iOp7L
# 24oCa0zlgYCND3OnNfYOuVpMsq3CSkXYg3H+VMiB11hOLcctTu4RWy4ZRKsL5NVI
# AduJFgd/1Qs2mQpUuOyFfLKhu/+Z+T2c9YALxsfnPvqn8Tn8Tt8wdZuFwz7kK3jl
# e2T3YBofybAR2aH678TnOxhLe2/hEpTdKaVfcqyrIX0Mw/LwqEJnj4G8amBbQ7OG
# RnKm1VNd4nMpRt1SflNlVo1Q3Qqnj9K6mSPw99YGMCTaVr6jKPylsWyW4nsvu8m0
# MbBJJiLOi0sOTHtwQEVcBH6WM7xbODqwPaklS1wDbED1wfzImIUR8WsXJVjDm7Fg
# x4JDo8oLIjKFrEvzBfrYWsvlDg8p9XgR7EB/IJwXGuJbFzo/S+r3D5DkUZXX/72k
# XA4FeRJAgLePAuGChPvyQiLtKJeJm9ftJeukrIcs7JpJVHObAgMBAAGjggGoMIIB
# pDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUB9FDBUZ0W11vsv6qqb9t
# vKspCIowRQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEWMBQGA1UEBRMNMjMwODA5KzUwNjIyOTAfBgNVHSMEGDAWgBRhcaeHr/9p
# 1SF2T1KTKAC+eRKrhDB0BgNVHR8EbTBrMGmgZ6BlhmNodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBXaW5kb3dzJTIwVGhpcmQl
# MjBQYXJ0eSUyMENvbXBvbmVudCUyMENBJTIwMjAxMi5jcmwwgYEGCCsGAQUFBwEB
# BHUwczBxBggrBgEFBQcwAoZlaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w
# cy9jZXJ0cy9NaWNyb3NvZnQlMjBXaW5kb3dzJTIwVGhpcmQlMjBQYXJ0eSUyMENv
# bXBvbmVudCUyMENBJTIwMjAxMi5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0B
# AQsFAAOCAQEAmFzJPKhkAXPOcfy9S4q1nP3XCvmABVGv/VRzFZ1e+oVtVzOFkbZ6
# osY1OpZqa9CEvtgcrtciv1y9mV1SpxAMwfEqq+Nhw2GdZ3IWqFzWFsEe2S9U196s
# XRIRIxglZMBWyzdy8rQ+P7L2+LciW4qcaw2wtv6YoI0q1isgk0t1OF5kEL0t9hhx
# UrBavTdoqZ3b5JtwDqzmIsxuLtGbE9Pqbz2gx/me+7yduYpIcYlmEmPQkg3gmWkZ
# lnSRePu7/5RXS2TGW1O5JP8aqVcMn0ZkHEhtT368pE/CxQVAkAYHNz6+enP9n+HC
# 2udu395c0fVlRHy/d53f32RukfbjakH8uzCCBeEwggPJoAMCAQICCmELqsEAAAAA
# AAkwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1
# dGhvcml0eSAyMDEwMB4XDTEyMDQxODIzNDgzOFoXDTI3MDQxODIzNTgzOFowgY4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xODA2BgNVBAMTL01p
# Y3Jvc29mdCBXaW5kb3dzIFRoaXJkIFBhcnR5IENvbXBvbmVudCBDQSAyMDEyMIIB
# IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo5wwhAmnYy7PCkfw6iT5ozAg
# D15XMSaBmjEHslDUzmcJCGUKWqVLrtXtEC7npZm1n2gvmItYAqwgtCnEcb0oHKX9
# PJtk5MXr32ElvPDuaL/Rp8t+KgKBTmRcDFOGeVcZN2G3mPkMoE4iWZv5Gy1nPCc8
# VpBm4/1/ZX0Phr01R+iKzPTajulqTqunVeyiiR7VM0VTy/med73NLPkFuH90AR3o
# +xjhQ9EN6arcN2+9/rgP7R1NAUZOCqz8gujsVoMTjjoB7RRkdOpksmYQtmhtyHAA
# fVBILj1D7uAklcbNjsf9uOSVz91++5VeoQHNQ7EH16Qw7puGGipuwQtZonRviwID
# AQABo4IBQzCCAT8wEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFGFxp4ev/2nV
# IXZPUpMoAL55EquEMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ
# W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv
# bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBa
# BggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqG
# SIb3DQEBCwUAA4ICAQBaimfazNX9DSZBd78KRni0s94SaSt3I8JlLwFf0gP0YbpQ
# nS6MOXLzbD5qsR52bey384LczLvFaXAoc2YXP1Tr7gEWSMRG2RuAroE6jQ95bWiw
# nuotPznTyjh+vV58CG4Z3MbC9DgzaGHiUkeD4QABVtK6y4eCBTEKQYtO539fX+1f
# 0zktReuiE7/9HsKYQXFhFl/ICnAlfFlpMSTkcecKuwQX959yHsnSuxq+PQL+CQyy
# Q7RZGplTk5YhX+DWtyYBQpU2rCf9vvSFd2g9GL30vpiIIhGGUhbzRewDlxBwh6Nw
# Q3E828mGAxcM9XNbxn3hXGTt18VI1+0y4tGq08+n9ldOYfl362fyiLPeANoDj9CK
# NDc+HdhiuNKx8+Evi3I7gZZ8b/zsZnZyYBsk8qCJbVttAC7vKN2GhwXCtLnlvmTC
# KvJKFVyY4sQnhf9S42J+D7ICC9dmxwqy0z0gBBRQMlmDCn2b7Vo4EgFSui9eIHKO
# SvH953ECjDvhB77Jc/TdR9i077SkszC5iT52yrkAmFZ+q+qKuKXQOKtpdxMLFC/p
# qkEf97q9Ois0iu4Kq2PmY/eIJI4gDSs7nePCSVKsnx8OOTtd1G5QauZ9UjqqfDMV
# KQ0mXgFYp06pPXqEb3Q/YJ/kMk82AK9tcdM+pkZlX4F08f7BcdpMoEFagt3xHzGC
# GwYwghsCAgEBMIGmMIGOMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMTgwNgYDVQQDEy9NaWNyb3NvZnQgV2luZG93cyBUaGlyZCBQYXJ0eSBDb21w
# b25lbnQgQ0EgMjAxMgITMwAAAUBn9phrMQi4cgAAAAABQDANBglghkgBZQMEAgEF
# AKCCARgwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEICONwWKXH7dsutIwpVdzGbC2
# Jltl5fqVrNgeaNFAr39gMFAGCisGAQQBgjcKAxwxQgxAQjVGNDdGRDM1MjdFQTI3
# MUEyQUNCRjRGMjYxQUNGMDZBRkEwQjE0OUNBOTZCMjZCMDBENTY0NDY5MzlGMTFC
# MTBaBgorBgEEAYI3AgEMMUwwSqAkgCIATQBpAGMAcgBvAHMAbwBmAHQAIABXAGkA
# bgBkAG8AdwBzoSKAIGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS93aW5kb3dzMA0G
# CSqGSIb3DQEBAQUABIIBgCmimQVjfcAzBPkoKvQ2pYY229q4oEyJSvrImizlVCNG
# AIvrFa1iOiGbgWnIokN+TnlH7QAe0VMGGdM5ciV3jheXQfSnGpdOf5bHMBJmLFJF
# puFB9pbXzkFuOak78Lmd/vW4WXDZXid0B+wHIKpmGWTbOwFejDHX6Vykg8heqcCq
# 1TQXQhUnZ1goDXmezPb1x+M/YOwi3u1tlMmfLqS3k16HMWsuahlmb1TX67AVuRBw
# 386Zm0JFlAS+Su4UN9k9WzJ44Ln5oqly0FDjhUbIk1Uhrez6X9WdJxKHjgXeBIP+
# IzWZO04D5EyuZfIXz2KEEWotNX7trEq86tH0/MZvONIwOaggxNVTS1iFLNlJxzP5
# m9OgXiZ0JC5n9eTKQFqS795OacWFeVOjHGShUwz0yA9RbeZ1gdo7LHeUMWCa3+fo
# iOaWD28WcW88sVxG+TzADOZCHU/zJWYALynNREYX1i2i7ChOOY8XEJvLSVrvYUMz
# D0azXmn3d+fZ9EoLinGXY6GCF5QwgheQBgorBgEEAYI3AwMBMYIXgDCCF3wGCSqG
# SIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsqhkiG9w0B
# CRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUA
# BCD/+dOqzvYliLvG6Nlnz2HPt1kHJk/NfgniIXIQcnvEpAIGal/E4LWSGBMyMDI2
# MDgwODE4MDIyMC42OThaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP
# cGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046ODYwMy0wNUUwLUQ5
# NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WgghHqMIIH
# IDCCBQigAwIBAgITMwAAAiWAxzfGzap3SQABAAACJTANBgkqhkiG9w0BAQsFADB8
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N
# aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yNjAyMTkxOTQwMDFaFw0y
# NzA1MTcxOTQwMDFaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYD
# VQQLEx5uU2hpZWxkIFRTUyBFU046ODYwMy0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUAA4IC
# DwAwggIKAoICAQCm8RIP0eLA46VcCPovvmqsIlN6qkmz5IsHWmUU0neUqp8uGxad
# eo+SwWBCwQ5alZI/DNdpXfyiZLZR6XYgpRPFzepIl7OCDb4NtEskJCIZDkQMNwrH
# 9YwUyu71GGigsLIxeleHtA3utoVTeHjS1b8UnwORRtknKkyrUArT6ZpB2rodIcmc
# Lcv3x3wwgYlOs0FEg5EsVrZb7LNc/nd0bXDp+HTOWWui8eoTVwJeLxcVP869oF8l
# i5SU81aa2tGJ6/Jsejiz9JMW8SJXKBT2DCXMOUkCsGjonPZRqfvoMSIQZgtaOTyA
# Jlrvsy0TZ78XrGqoygtQimQnbOAL4KNLSCuW5TZEQGTHLOQJGgggb3j5gKC778+R
# IPJA+n/hmHJ/x4qT/HTTPoVeMCcuBKWrQXR1+/pYau3Fwe0tWIyG+LWzkRr/ZNPP
# upcA2Yci3qn8HR9RwvQopqSNJwn2Ri6am8AQyfVVy/BBw0t6jpoRPjwKvuUjfCzp
# ae6duOxQtQ1XDN9PA2yl9sDko/+AXV/SOe8ea8QoQcv3s3ErkG+Lp6hnvw6OMPia
# n4ggNkRtgtB7ro1OiopOUXJn9Y5EO3JUAXNcuM9m+5My1VEuvGytgAH3uxmslTnW
# 3YbrfazaySCSSnWkhaOZ33hgbuUQfH7n2NFEAUc/cFzfmCQUikWisnJYywIDAQAB
# o4IBSTCCAUUwHQYDVR0OBBYEFLE40qoXTuMHX3AfZUu1n8nx2h93MB8GA1UdIwQY
# MBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6
# Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRpbWUt
# U3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYIKwYB
# BQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj
# cm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB
# /wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0G
# CSqGSIb3DQEBCwUAA4ICAQAHnfc2yUyoHZbvvyVKFuXh5HxxHIvIaR9JWpIfITJl
# c/Ki03juR+vckzq3tp5fFH5LL7eIFXRIuoewMsvWeFrWufrrW4HhmhCwkqArfA1C
# 0xk+HaYs2O48YSxMX9lgS1kTTIb3YsfoFdFpKurPf2nc2Yd4wLg+FgwmkxkeyE3M
# UKVna8SZeVpEjnS5ucFck4srPwK2ORAf70I23GGyPhqgIKZphNXhSscTAQsyIqB5
# GwDMdRV5LK37NfU4YmxvCYh3TFYE/Gh01Q6yJvf9HxiEZpwW+oUk0gruHobg3sgI
# R5rfgUo8l30vUnaDYMcPAClaFMC/QbHZSaUhWXZG1OOcMp0g9vYQNLDEqFX2jlqu
# vzVSSwtHtm1KTldCjRED+kdCybcPxbPalwJigXc1BsI9CitnTf0ljwb9NkZ/JVI8
# /D62rXXzhz4F3u0iVGzwncGaxRxHG/Xv4nTrpkOeepoYbNBbMWS2G1qP3Xj7pVf0
# +4qRyAqJ0stjQjoVOJImVPWRjz5PR3Dn6adQVMBJDM6gDrj1rZTFVgCtTijqGZSG
# zvXpGkF3vYsyE6ZDma/kGdiUe5saeI6lH66PiWWXgqxt7sy2Ezv0yIjSVv+eMOT2
# QMUiZ6WCc7gVtAmXpfeIus+NmgFvM+Ic1X58e4I9EL4ZSAidSpWW0GZTLNC02mry
# LjCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQEL
# BQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV
# BAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4X
# DTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh
# bXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM
# 57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm
# 95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzB
# RMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBb
# fowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCO
# Mcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYw
# XE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW
# /aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/w
# EPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPK
# Z6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2
# BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfH
# CBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYB
# BAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8v
# BO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYM
# KwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEF
# BQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBW
# BgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUH
# AQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
# L2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsF
# AAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518Jx
# Nj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+
# iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2
# pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefw
# C2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7
# T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFO
# Ry3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhL
# mm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3L
# wUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5
# m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE
# 0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNNMIICNQIB
# ATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UE
# CxMeblNoaWVsZCBUU1MgRVNOOjg2MDMtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNy
# b3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQBTb+bKOPAj
# CBflhzw5EXBuSWxeDqCBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy
# MDEwMA0GCSqGSIb3DQEBCwUAAgUA7iFTETAiGA8yMDI2MDgwODA3MDI0MVoYDzIw
# MjYwODA5MDcwMjQxWjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDuIVMRAgEAMAcC
# AQACAgo5MAcCAQACAhMTMAoCBQDuIqSRAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwG
# CisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEL
# BQADggEBAFMU6cX32ZimGPfiDrU8T+H1GCVvnQnL2FpNHBc/lQgzk5J/1X9iynH6
# fPRrJjO0lgtYktcM+Za9b0cMl9MHLkWsZTISxFVJ0C3/u7c9LFdCKQjPUBPvedik
# nCwQOnAy9XsrW+Z+0BKDMVNJ2CQbvrYuEEL+iRODL/hC+uxlX91ScK7iQhxb6sKU
# su6yZYzNKmCnz6Ai6MM6sVfpovL+itkkwTeC2hXri3jQTo8aC4wggEKhW7yXUPyB
# OgrLpL6xTEDW7UonSHVFklcBtnN60qBdWnuOYt67+xYmP7RWadkHBcmMHUaBtYXR
# Ha2XRiUGCqqpLTG/Nx+TN3ql/2oKwHIxggQNMIIECQIBATCBkzB8MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg
# VGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAiWAxzfGzap3SQABAAACJTANBglghkgB
# ZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3
# DQEJBDEiBCA9OEbgneCn1QZ1ZXMwdKv85x+BLzRoI7HJsaFRgB5UtzCB+gYLKoZI
# hvcNAQkQAi8xgeowgecwgeQwgb0EIFYN7oh6ON3y92CmAl/lF0CYwrjWWQP6dCUx
# ajPSHKEQMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMA
# AAIlgMc3xs2qd0kAAQAAAiUwIgQgcO1LjuRVcoKlS1820ahOSVKLePxrZJqB2CUs
# kBDTiu0wDQYJKoZIhvcNAQELBQAEggIAVI4M9nGWZ6xzsG8iXbmGTKPjpA3ryCUK
# P8y368QiK/N0R4gQws2qk2TDKNVxnAcaTs/M1Qs7KyODEATt0ZnS9qev5tC2gMKb
# 3jgbwqhFPHduvzD2GgvQcvLuWoZE9T3tbMDdS9WogkFC9oal1fu1g4M1d3+er4f1
# cpYwg7Z5gdsKZZte3k0xS+1kuvP26T/pew6f33cHztlyV38gxlB6xwKj6wOjDq1G
# xBbij9Yu7KyejJJUdNAD9RrEQck5D0RIIguqz7MY6qByrCRMk5O3bsSRnTgkWhcK
# wCUkP1mN6jSQpNkTuxZXDwxUXC03ugTtI3KAXU67ktNignakJmb17QxCxPU/tZJN
# 1OVpSEi6191xpE5spWgLjlck77uTb57Cp3BIcSwwjGm3FoGzfQ8j7rV2VDEOV243
# DC0YAqsDnqO+PHJ39LMeXIlfQibEjK0jl1okVrTFR/MSyb7bsylgOBnBR8Afi0m1
# 8hdhNUO1Z8N9955WuhuNcVDvRz6TZfjtSqwIbzq4EQedYGpungn7FzutVLaSxo3w
# fzIgPxQlWDqfN6YJPardP+VR4UGVNWOoYcFUxJUHR+7siSryR7Uctj/oFDeyGFPY
# 9rF1ziAPxpw0/StXK1ImBo6SaofQKBhuZpfBN0BvBSiyW+yvZ04BWHo1dAZxVKSw
# FGCkgbWzYss=
# SIG # End signature block