VaultCommands.ps1

#requires -Version 5.1

$Script:PathDelimiter = [System.IO.Path]::DirectorySeparatorChar

function getVault {
    if (-not $Script:Context.Auth) {
        Write-Error -Message "Not Connected" -ErrorAction Stop
    }
    if (-not $Script:Context.Vault) {
        Write-Error -Message "Not Connected to Keeper vault. Please login first." -ErrorAction Stop
    }
    $Script:Context.Vault
}

function Get-KeeperLocation {
    <#
    .Synopsis
    Get current Keeper folder
#>

    [CmdletBinding()]

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault

    [string]$currentFolder = $Script:Context.CurrentFolder
    [KeeperSecurity.Vault.FolderNode]$folder = $vault.RootFolder
    if ($currentFolder) {
        $vault.TryGetFolder($currentFolder, [ref]$folder) | Out-Null
    }
    exportKeeperNode $folder
}
New-Alias -Name kpwd -Value Get-KeeperLocation


function Set-KeeperLocation {
    <#
    .Synopsis
    Change current Keeper folder

    .Parameter Path
    New location
#>


    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    Param (
        [Parameter(Position = 0)][string] $Path
    )
    [KeeperSecurity.Vault.VaultOnline]$vault = getVault

    if ($Path) {
        [KeeperSecurity.Vault.FolderNode]$folder = $null
        if (!$vault.TryGetFolder($Script:Context.CurrentFolder, [ref]$folder)) {
            $folder = $vault.RootFolder
        }

        $components = splitKeeperPath $Path
        $rs = parseKeeperPath $components $vault $folder
        if ($rs -and !$rs[1]) {
            $folder = $rs[0]
            $uid = $folder.FolderUid
            if ($vault.TryGetFolder($uid, [ref]$folder)) {
                $Script:Context.CurrentFolder = $uid
            }
            else {
                $Script:Context.CurrentFolder = ''
            }
        }
    }
    getVaultFolderPath $vault $Script:Context.CurrentFolder
}

$Keeper_FolderPathRecordCompleter = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)

    $result = @()
    [KeeperSecurity.Vault.VaultOnline]$vault = $Script:Context.Vault
    if ($vault) {
        [KeeperSecurity.Vault.FolderNode] $folder = $null
        if (!$vault.TryGetFolder($Script:Context.CurrentFolder, [ref]$folder)) {
            $folder = $vault.RootFolder
        }

        $pattern = ''
        $toComplete = $wordToComplete
        if ($toComplete.Length -ge 2) {
            if ($toComplete[0] -eq '''' -and $toComplete[-1] -eq '''') {
                $toComplete = $toComplete.Substring(1, $toComplete.Length - 2)
                $toComplete = $toComplete -replace '''', ''''
            }
        }
        if ($toComplete) {
            $components = splitKeeperPath $toComplete
            if ($components.Count -gt 1) {
                if ($components[-1]) {
                    $pattern = $components[-1]
                    $components[-1] = ''
                }
                $rs = parseKeeperPath $components $vault $folder
                if ($rs -and $rs.Count -eq 2) {
                    if (!$rs[1]) {
                        $folder = $rs[0]
                    }
                    else {
                        $folder = $null
                    }
                }
            }
            else {
                if ($components) {
                    $pattern = $components
                    $components = @('')
                }
                else {
                    $folder = $vault.RootFolder
                    $pattern = ''
                    $components = @('')
                }
            }
        }
        else {
            $components = @('')
            $pattern = $wordToComplete
        }

        if ($folder) {
            $pattern += '*'
            foreach ($uid in $folder.Subfolders) {
                $subfolder = $null
                if ($vault.TryGetFolder($uid, [ref]$subfolder)) {
                    if ($subfolder.Name -like $pattern) {
                        $path = @()
                        $components | ForEach-Object { $path += $_ }
                        $path[-1] = $subfolder.Name
                        $expansion = ($path | ForEach-Object { $_ -replace '\\', '\\' }) -join $Script:PathDelimiter
                        if ($expansion -match '[\s'']') {
                            $expansion = $expansion -replace '''', ''''''
                            $expansion = "'${expansion}'"
                        }
                        $result += $expansion
                    }
                }
            }
        }
    }
    if ($result.Count -gt 0) {
        return $result
    }
    else {
        return $null
    }
}
Register-ArgumentCompleter -CommandName Set-KeeperLocation -ParameterName Path -ScriptBlock $Keeper_FolderPathRecordCompleter
New-Alias -Name kcd -Value Set-KeeperLocation


function Get-KeeperChildItem {
    <#
    .Synopsis
    Get the content of Keeper folder. Output and parameters are similar to Get-ChildItem cmdlet

    .Parameter Path
    Keeper folder

    .Parameter Filter
    Match the string in Title, Uid, Login, and Link fields

    .Parameter Recursive
    Get child items in subfolders recursively

    .Parameter Depth
    Recursion depth

    .Parameter SkipGrouping
    Do not group result set by folder

    .Parameter ObjectType
    Limit result set to Folders or Records only
#>


    [CmdletBinding()]
    Param (
        [Parameter(Position = 0)][string] $Path,
        [string] $Filter,
        [Switch] $Recursive,
        [int] $Depth,
        [Switch] $SkipGrouping,
        [ValidateSet('Folder' , 'Record')][string] $ObjectType
    )

    $showFolder = $true
    $showRecord = $true
    if ($ObjectType) {
        $showFolder = $ObjectType -eq 'Folder'
        $showRecord = !$showFolder
    }

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault
    [KeeperSecurity.Vault.FolderNode] $currentDir = $null
    if (!$vault.TryGetFolder($Script:Context.CurrentFolder, [ref]$currentDir)) {
        $currentDir = $vault.RootFolder
    }

    [KeeperSecurity.Vault.FolderNode] $baseDir = $null
    if ($Path) {
        if (-not $vault.TryGetFolder($Path, [ref]$baseDir)) {
            $components = splitKeeperPath $Path
            $rs = parseKeeperPath $components $vault $currentDir
            if ($rs -is [array]) {
                if (-not $rs[1]) {
                    $baseDir = $rs[0]
                }
            }
        }
    } else {
        $baseDir = $currentDir
    }
    if (-not $baseDir) {
        Write-Error -Message "Cannot find path '$Path'" -ErrorAction Stop            
    }

    [KeeperSecurity.Vault.FolderNode[]]$folders = @($baseDir)
    if ($Recursive.IsPresent) {
        $pos = 0
        $dep = 0
        while ($pos -lt $folders.Count) {
            if ($Depth -gt 0) {
                if ($dep -ge $Depth) {
                    break
                }
            }
            $lastPos = $folders.Count
            for ($i = $pos; $i -lt $lastPos; $i++) {
                foreach ($uid in $folders[$i].Subfolders) {
                    [KeeperSecurity.Vault.FolderNode] $sf = $null;
                    if ($vault.TryGetFolder($uid, [ref]$sf)) {
                        $folders += $sf
                    }
                }
            }
            $pos = $lastPos
            $dep++
        }
    }
    $entries = @()
    $recordEntries = @{}
    for ($i = 0; $i -lt $folders.Count; $i++) {
        [KeeperSecurity.Vault.FolderNode]$f = $folders[$i]
        $path = getVaultFolderPath $vault $f.FolderUid
        if ($showFolder) {
            foreach ($uid in $f.Subfolders) {
                [KeeperSecurity.Vault.FolderNode]$sf = $null
                if ($vault.TryGetFolder($uid, [ref]$sf)) {
                    $match = $true
                    if ($Filter) {
                        $match = @($sf.Name, $sf.FolderUid) | Select-String $Filter | Select-Object -First 1
                    }
                    if ($match) {
                        $entry = [PSCustomObject]@{
                            PSTypeName  = "KeeperSecurity.Commander.FolderEntry$(if ($SkipGrouping.IsPresent) {'Flat'} else {''})"
                            Uid         = $sf.FolderUid
                            Name        = $sf.Name
                            OwnerFolder = $path
                            FolderType  = $sf.FolderType
                            Shared      = $sf.FolderType -ne [KeeperSecurity.Vault.FolderType]::UserFolder
                            SortGroup   = 0
                        }
                        $entries += $entry
                    }
                }
            }
        }
        if ($showRecord) {
            foreach ($uid in $f.Records) {
                [KeeperSecurity.Vault.KeeperRecord] $r = $null
                if ($vault.TryGetKeeperRecord($uid, [ref]$r)) {
                    if ($r.Version -ne 2 -and $r.Version -ne 3) {
                        continue
                    }
                    $match = $true
                    if ($Filter) {
                        $match = @($r.Title, $r.Uid) | Select-String $Filter | Select-Object -First 1
                    }
                    if ($match) {
                        if ($Flat.IsPresent -and $recordEntries.ContainsKey($uid)) {
                            $entry = $recordEntries[$uid]
                            $entry.OwnerFolder += $path
                        }
                        else {
                            $type = [KeeperSecurity.Utils.RecordTypesUtils]::KeeperRecordType($r)
                            $publicInfo = [KeeperSecurity.Utils.RecordTypesUtils]::KeeperRecordPublicInformation($r)
                            $entry = [PSCustomObject]@{
                                PSTypeName        = "KeeperSecurity.Commander.RecordEntry$(if ($SkipGrouping.IsPresent) {'Flat'} else {''})"
                                Uid               = $r.Uid
                                Name              = $r.Title
                                Shared            = $r.Shared
                                Owner             = $r.Owner
                                Type              = $type
                                PublicInformation = $publicInfo
                                HasAttachments    = ($vault.RecordAttachments($r).Count -gt 0)
                                SortGroup         = 1
                            }
                            if ($SkipGrouping.IsPresent) {
                                Add-Member -InputObject $entry -NotePropertyName OwnerFolder -NotePropertyValue @($path)
                            }
                            else {
                                Add-Member -InputObject $entry -NotePropertyName OwnerFolder -NotePropertyValue $path
                            }

                            $recordEntries[$uid] = $entry
                            $entry = $null
                        }
                    }
                }
            }
        }
    }
    if ($recordEntries) {
        $entries += $recordEntries.Values
    }
    if ($entries) {
        if ($SkipGrouping.IsPresent) {
            $entries | Sort-Object SortGroup, Name
        }
        else {
            $entries | Sort-Object OwnerFolder, SortGroup, Name
        }
    }
}
Register-ArgumentCompleter -CommandName Get-KeeperChildItem -ParameterName Path -ScriptBlock $Keeper_FolderPathRecordCompleter
New-Alias -Name kdir -Value Get-KeeperChildItem


function Get-KeeperObject {
    <#
    .Synopsis
    Get Keeper object by Uid

    .Parameter Uid
    Keeper UID

    .Parameter ObjectType
    One of the following Record, SharedFolder, Folder, Team

    .Parameter PropertyName
    Return object property not the entire object
#>

    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)][string[]] $Uid,
        [string] [ValidateSet('Record' , 'SharedFolder', 'Folder', 'Team')] $ObjectType,
        [string] $PropertyName
    )

    Begin {
        [KeeperSecurity.Vault.VaultOnline]$vault = getVault

        $testRecord = if ($ObjectType) { $ObjectType -eq 'Record' } else { $true }
        $testSharedFolder = if ($ObjectType) { $ObjectType -eq 'SharedFolder' } else { $true }
        $testFolder = if ($ObjectType) { $ObjectType -eq 'Folder' } else { $true }
        $testTeam = if ($ObjectType) { $ObjectType -eq 'Team' } else { $true }
    }
    Process {
        ForEach ($oid in $Uid) {
            if ($testRecord) {
                [KeeperSecurity.Vault.KeeperRecord] $record = $null
                if ($vault.TryGetKeeperRecord($oid, [ref]$record)) {
                    if ($PropertyName) {
                        $mp = $record | Get-Member -MemberType Properties -Name $PropertyName
                        if ($mp) {
                            $record | Select-Object -ExpandProperty $PropertyName
                        }
                    }
                    else {
                        $record
                    }
                    continue
                }
            }
            if ($testSharedFolder) {
                [KeeperSecurity.Vault.SharedFolder] $sf = $null
                if ($vault.TryGetSharedFolder($oid, [ref]$sf)) {
                    if ($PropertyName) {
                        $mp = $sf | Get-Member -MemberType Properties -Name $PropertyName
                        if ($mp) {
                            $sf | Select-Object -ExpandProperty $PropertyName
                        }
                    }
                    else {
                        $sf
                    }
                    continue
                }
            }
            if ($testFolder) {
                [KeeperSecurity.Vault.FolderNode] $f = $null
                if ($vault.TryGetFolder($oid, [ref]$f)) {
                    if ($PropertyName) {
                        $mp = $f | Get-Member -MemberType Properties -Name $PropertyName
                        if ($mp) {
                            $f | Select-Object -ExpandProperty $PropertyName
                        }
                    }
                    else {
                        $f
                    }
                    continue
                }
            }
            if ($testTeam) {
                [KeeperSecurity.Vault.Team] $t = $null
                if ($vault.TryGetTeam($oid, [ref]$t)) {
                    if ($PropertyName) {
                        $mp = $t | Get-Member -MemberType Properties -Name $PropertyName
                        if ($mp) {
                            $t | Select-Object -ExpandProperty $PropertyName
                        }
                    }
                    else {
                        $t
                    }
                    continue
                }
                ensureAvalableLoaded
                [KeeperSecurity.Vault.TeamInfo] $teamInfo = $null
                $teamInfo = $Script:Context.AvailableTeams | Where-Object { $_.TeamUid -ceq $oid } | Select-Object -First 1
                if ($teamInfo) {
                    if ($PropertyName) {
                        $mp = $teamInfo | Get-Member -MemberType Properties -Name $PropertyName
                        if ($mp) {
                            $teamInfo | Select-Object -ExpandProperty $PropertyName
                        }
                    }
                    else {
                        $teamInfo
                    }
                    continue
                }
            }
        }
    }
}
New-Alias -Name ko -Value Get-KeeperObject

function parseKeeperPath {
    Param (
        [string[]]$components,
        [KeeperSecurity.Vault.VaultOnline]$vault,
        [KeeperSecurity.Vault.FolderNode]$folder
    )
    if ($components) {
        if (!$components[0]) {
            $folder = $vault.RootFolder
            $_, $components = $components
        }
        while ($components) {
            $resume = $false
            $component, $rest = $components
            if ($component -eq '..') {
                if ($folder.ParentUid) {
                    $resume = $vault.TryGetFolder($folder.ParentUid, [ref]$folder)
                }
                else {
                    $folder = $vault.RootFolder
                    $resume = $true
                }
            }
            elseif (!$component -or $component -eq '.') {
                $resume = $true
            }
            else {
                foreach ($x in $folder.Subfolders) {
                    [KeeperSecurity.Vault.FolderNode] $subfolder = $null
                    if ($vault.TryGetFolder($x, [ref]$subfolder)) {
                        if ($subfolder.Name -eq $component) {
                            $resume = $true
                            $folder = $subfolder
                            break
                        }
                    }
                }
            }

            if ($resume) {
                $components = $rest
            }
            else {
                break
            }
        }
        $folder
        $components -join $Script:PathDelimiter
    }
    else {
        $folder
        $path
    }
}

function splitKeeperPath {
    Param ([string] $path)

    [bool]$isDelimiter = $false
    [string]$component = ''
    foreach ($x in $path.ToCharArray()) {
        if ($x -eq $Script:PathDelimiter) {
            if ($isDelimiter) {
                $component += $x
                $isDelimiter = $false
            }
            else {
                $isDelimiter = $true
            }
        }
        else {
            if ($isDelimiter) {
                $component
                $component = ''
                $isDelimiter = $false
            }
            $component += $x
        }
    }
    $component
    if ($isDelimiter) {
        ''
    }
}

function exportKeeperNode {
    Param ([KeeperSecurity.Vault.FolderNode] $folder)
    [PSCustomObject]@{
        PSTypeName = 'KeeperSecurity.Commander.FolderInfo'
        FolderUid  = $folder.FolderUid
        Path       = getVaultFolderPath $vault $folder.FolderUid
        Name       = $folder.Name
        ParentUid  = $folder.ParentUid
        FolderType = $folder.FolderType
    }
}

function escapePathComponent {
    Param ([string] $component)

    $component = $component -replace '\\', '\\'
    $component = $component -replace '''', ''''''
    if ($component -match '[\s'']') {
        "'${component}'"
    }
    else {
        $component
    }
}

function getVaultFolderPath {
    Param (
        [KeeperSecurity.Vault.VaultOnline]$vault,
        [string] $folderUid
    )

    $comps = @()
    traverseFolderToRoot $vault $folderUid ([ref]$comps)
    $path = ''
    if ($comps) {
        [Array]::Reverse($comps)
        $comps += ''
        $path = ($comps | ForEach-Object { $_ -replace [Regex]::Escape($Script:PathDelimiter), "${Script:PathDelimiter}${Script:PathDelimiter}" }) -join $Script:PathDelimiter
    }
    "${Script:PathDelimiter}${path}"
}

function traverseFolderToRoot ([KeeperSecurity.Vault.VaultOnline]$vault, [string] $folderUid, [ref] $components) {
    if ($folderUid) {
        [KeeperSecurity.Vault.FolderNode]$folder = $null
        if ($vault.TryGetFolder($folderUid, [ref]$folder)) {
            $components.Value += $folder.Name
            traverseFolderToRoot $vault $folder.ParentUid $components
        }
    }
}


function Export-KeeperVault {
    <#
    .Synopsis
    Export vault data to a JSON file

    .Parameter FileName
    JSON export filename (will automatically add .json extension if not present)

    .Parameter Force
    Overwrite existing file without prompting

    .Parameter ExcludeSharedFolders
    Exclude shared folders from export

    .Description
    Exports all vault records and optionally shared folders to a JSON file.
    The JSON format is compatible with Keeper's import functionality.

    .Example
    Export-KeeperVault -FileName "vault_backup"
    Exports vault to "vault_backup.json" and prompts if file exists

    .Example
    Export-KeeperVault -FileName "vault.json" -Force
    Exports vault and overwrites existing file without prompting

    .Example
    Export-KeeperVault -FileName "records_only.json" -ExcludeSharedFolders
    Exports only records, excluding shared folders
#>


    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string] $FileName,

        [Parameter(Mandatory = $false)]
        [switch] $Force,

        [Parameter(Mandatory = $false)]
        [switch] $ExcludeSharedFolders
    )

    [KeeperSecurity.Vault.VaultOnline]$vault = getVault

    if (-not $FileName.EndsWith(".json", [StringComparison]::OrdinalIgnoreCase)) {
        $FileName += ".json"
    }

    if ((Test-Path $FileName) -and -not $Force) {
        $response = Read-Host "File `"$FileName`" already exists. Overwrite? (y/n)"
        if ($response -notmatch '^y(es)?$') {
            Write-Host "Export cancelled."
            return
        }
    }

    Write-Host "Exporting vault data..."

    $logger = [Action[KeeperSecurity.Vault.Severity, string]] {
        param($severity, $message)
        
        if ($severity -eq [KeeperSecurity.Vault.Severity]::Warning -or 
            $severity -eq [KeeperSecurity.Vault.Severity]::Error) {
            Write-Host $message
        }
        Write-Debug $message
    }

    $includeSharedFolders = -not $ExcludeSharedFolders.IsPresent
    $jsonContent = [KeeperSecurity.Vault.KeeperExport]::ExportVaultToJson(
        $vault,
        $null,
        $includeSharedFolders,
        $logger
    )

    $fullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($FileName)
    
    $directory = [System.IO.Path]::GetDirectoryName($fullPath)
    if (-not [string]::IsNullOrEmpty($directory) -and -not (Test-Path $directory)) {
        New-Item -ItemType Directory -Path $directory -Force | Out-Null
    }
    
    [System.IO.File]::WriteAllText($fullPath, $jsonContent)
    
    Write-Debug "Exported to $fullPath"

    $fileInfo = Get-Item $fullPath

    $recordCount = ($vault.KeeperRecords | Where-Object { $_.Version -eq 2 -or $_.Version -eq 3 }).Count
    $sharedFolderCount = if ($ExcludeSharedFolders) { 0 } else { $vault.SharedFolders.Count }

    Write-Host ""
    Write-Host "Export Summary:"
    Write-Host " Records Exported: $recordCount"
    if (-not $ExcludeSharedFolders) {
        Write-Host " Shared Folders: $sharedFolderCount"
    }
    Write-Host " File Size: $($fileInfo.Length.ToString('N0')) bytes"
    Write-Host " Output File: $fullPath"
    Write-Host ""
    Write-Host "Export completed successfully." -ForegroundColor Green
}
New-Alias -Name kexport -Value Export-KeeperVault

# SIG # Begin signature block
# MIInvgYJKoZIhvcNAQcCoIInrzCCJ6sCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCASikw5lZnTm09Z
# tnaQx7U3SHjvSSrX5ceLk9AqRwFrc6CCITswggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0GCSqG
# SIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTlaMGkx
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4
# RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEzODQg
# MjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C0Cit
# eLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce2vnS
# 1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0daE6ZM
# swEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6TSXBC
# Mo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoAFdE3
# /hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7OhD26j
# q22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM1bL5
# OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z8ujo
# 7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05huzU
# tw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNYmtwm
# KwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP/2NP
# TLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0TAQH/
# BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYDVR0j
# BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E
# PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATANBgkq
# hkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95RysQDK
# r2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HLIvda
# qpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5BtfQ/g+
# lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnhOE7a
# brs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIhdXNS
# y0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV9zeK
# iwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/jwVYb
# KyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYHKi8Q
# xAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmCXBVm
# zGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l/aCn
# HwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZWeE4w
# gga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0GCSqGSIb3DQEBCwUAMGIx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH
# NDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTlaMGkxCzAJBgNVBAYTAlVT
# MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1
# c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEwggIi
# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHTCphBcr48RsAcrHXbo0Zo
# dLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPhof6pvF4uGjwjqNjfEvUi
# 6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mAxAHeHYNnQxqXmRinvuNg
# xVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBvMgEdgkFiDNYiOTx4OtiF
# cMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps0wjUjsZvkgFkriK9tUKJ
# m/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF83bRVFLeGkuAhHiGPMvS
# GmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXiUOeSLsJygoLPp66bkDX1
# ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOMCZIVNSaz7BX8VtYGqLt9
# MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydPpOjL6s36czwzsucuoKs7
# Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrUG2ZdSoQbU2rMkpLiQ6bG
# RinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+sdFUeEY0qVjPKOWug/G6
# X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAd
# BgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYDVR0jBBgwFoAU7NfjgtJx
# XWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUF
# BwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
# aWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJo
# dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNy
# bDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQEL
# BQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WIGjB/T8ObXAZz8OjuhUxj
# aaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+IQhQE7jU/kXjjytJgnn0
# hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8Myb9rEVKChHyfpzee5kH0
# F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2th9y1IsA0QF8dTXqvcnT
# mpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjajV/gxdEkMx1NKU4uHQcKf
# ZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2Lr3ty9qIijanrUR3anzE
# wlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFzeGxcytL5TTLL4ZaoBdqbh
# OhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG7uEBYTptMSbhdhGQDpOX
# gpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+NJpud/v4+7RWsWCiKi9EO
# LLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckTetiSuEtQvLsNz3Qbp7wG
# WqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszWkPZPubdcMIIG7TCCBNWg
# AwIBAgIQCoDvGEuN8QWC0cR2p5V0aDANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQG
# EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0
# IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0Ex
# MB4XDTI1MDYwNDAwMDAwMFoXDTM2MDkwMzIzNTk1OVowYzELMAkGA1UEBhMCVVMx
# FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBTSEEy
# NTYgUlNBNDA5NiBUaW1lc3RhbXAgUmVzcG9uZGVyIDIwMjUgMTCCAiIwDQYJKoZI
# hvcNAQEBBQADggIPADCCAgoCggIBANBGrC0Sxp7Q6q5gVrMrV7pvUf+GcAoB38o3
# zBlCMGMyqJnfFNZx+wvA69HFTBdwbHwBSOeLpvPnZ8ZN+vo8dE2/pPvOx/Vj8Tch
# TySA2R4QKpVD7dvNZh6wW2R6kSu9RJt/4QhguSssp3qome7MrxVyfQO9sMx6ZAWj
# FDYOzDi8SOhPUWlLnh00Cll8pjrUcCV3K3E0zz09ldQ//nBZZREr4h/GI6Dxb2Uo
# yrN0ijtUDVHRXdmncOOMA3CoB/iUSROUINDT98oksouTMYFOnHoRh6+86Ltc5zjP
# KHW5KqCvpSduSwhwUmotuQhcg9tw2YD3w6ySSSu+3qU8DD+nigNJFmt6LAHvH3KS
# uNLoZLc1Hf2JNMVL4Q1OpbybpMe46YceNA0LfNsnqcnpJeItK/DhKbPxTTuGoX7w
# JNdoRORVbPR1VVnDuSeHVZlc4seAO+6d2sC26/PQPdP51ho1zBp+xUIZkpSFA8vW
# doUoHLWnqWU3dCCyFG1roSrgHjSHlq8xymLnjCbSLZ49kPmk8iyyizNDIXj//cOg
# rY7rlRyTlaCCfw7aSUROwnu7zER6EaJ+AliL7ojTdS5PWPsWeupWs7NpChUk555K
# 096V1hE0yZIXe+giAwW00aHzrDchIc2bQhpp0IoKRR7YufAkprxMiXAJQ1XCmnCf
# gPf8+3mnAgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTkO/zy
# Me39/dfzkXFjGVBDz2GM6DAfBgNVHSMEGDAWgBTvb1NK6eQGfHrK4pBW9i/USezL
# TjAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwgZUGCCsG
# AQUFBwEBBIGIMIGFMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j
# b20wXQYIKwYBBQUHMAKGUWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZTSEEyNTYyMDI1Q0ExLmNy
# dDBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGln
# aUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5j
# cmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEB
# CwUAA4ICAQBlKq3xHCcEua5gQezRCESeY0ByIfjk9iJP2zWLpQq1b4URGnwWBdEZ
# D9gBq9fNaNmFj6Eh8/YmRDfxT7C0k8FUFqNh+tshgb4O6Lgjg8K8elC4+oWCqnU/
# ML9lFfim8/9yJmZSe2F8AQ/UdKFOtj7YMTmqPO9mzskgiC3QYIUP2S3HQvHG1FDu
# +WUqW4daIqToXFE/JQ/EABgfZXLWU0ziTN6R3ygQBHMUBaB5bdrPbF6MRYs03h4o
# bEMnxYOX8VBRKe1uNnzQVTeLni2nHkX/QqvXnNb+YkDFkxUGtMTaiLR9wjxUxu2h
# ECZpqyU1d0IbX6Wq8/gVutDojBIFeRlqAcuEVT0cKsb+zJNEsuEB7O7/cuvTQasn
# M9AWcIQfVjnzrvwiCZ85EE8LUkqRhoS3Y50OHgaY7T/lwd6UArb+BOVAkg2oOvol
# /DJgddJ35XTxfUlQ+8Hggt8l2Yv7roancJIFcbojBcxlRcGG0LIhp6GvReQGgMgY
# xQbV1S3CrWqZzBt1R9xJgKf47CdxVRd/ndUlQ05oxYy2zRWVFjF7mcr4C34Mj3oc
# CVccAvlKV9jEnstrniLvUxxVZE/rptb7IRE2lskKPIJgbaP5t2nGj/ULLi49xTcB
# ZU8atufk+EMF/cWuiC7POGT75qaL6vdCvHlshtjdNXOCIUjsarfNZzCCB0kwggUx
# oAMCAQICEAe0P3SLJmcoVNrErUyxTt0wDQYJKoZIhvcNAQELBQAwaTELMAkGA1UE
# BhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2Vy
# dCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENB
# MTAeFw0yNTEyMzEwMDAwMDBaFw0yOTAxMDIyMzU5NTlaMIHRMRMwEQYLKwYBBAGC
# NzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMR0wGwYDVQQPDBRQ
# cml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UEBRMHMzQwNzk4NTELMAkGA1UEBhMC
# VVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQHEwdDaGljYWdvMR0wGwYDVQQK
# ExRLZWVwZXIgU2VjdXJpdHkgSW5jLjEdMBsGA1UEAxMUS2VlcGVyIFNlY3VyaXR5
# IEluYy4wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCUcNMoSVmxAi0a
# vG+StFJMNFFTUIOo3HdBZ+0gqA1XpNgUx11vB1vCZrvFsD9m5oA58tdp4gZN3LmQ
# aMvCl2ANUT7MilI02Hf1RWlygBzon6iE0GpU3lgRrwrk1dhtLpGsR6dbMKUUHprc
# vKpXk90/VN+vhzY1uik1tCTxkDCPu/AYJg7m9+tR2KqvMuYMaMLhii66eWUAGsBC
# h/uZxjkGoJF6qZ0DgFd7rW7VYljbfYSNPeZNGTDgB0J/wOsKl0mn612DTseIvAKt
# 4vra/FLFukyEyStnfQ8lWYDcLLCMCjNVrzGipmT5E2iyx7Y1RZCIpNwVogp3Ixbk
# Gbq5A/41YNOLLd4cFewyB2F037RevBCRsUODZEt1qBf7Jbu3DiYo1G+zTj9E0R1s
# FzyijcfdsTm6X5ble+yCJeGkX5XgsyPnZpyz/FX9Fr0N9pMPGWwW2PKyHEnSytXm
# 0Dxdq2P4mA4CBUxq7YoV26L2PF6QEh9BQdXTPcnLysUv7SI/a0ECAwEAAaOCAgIw
# ggH+MB8GA1UdIwQYMBaAFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB0GA1UdDgQWBBRG
# 4H6CH8pvNX632bsdnrda4MtJLDA9BgNVHSAENjA0MDIGBWeBDAEDMCkwJwYIKwYB
# BQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMC
# B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwgbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25p
# bmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI
# QTM4NDIwMjFDQTEuY3JsMIGUBggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8vY2Fj
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JT
# QTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUA
# A4ICAQA1Wlq0WzJa3N6DgjgBU7nagIJBab1prPARXZreX1MOv9VjnS5o0CrfQLr6
# z3bmWHw7xT8dt6bcSwRixqvPJtv4q8Rvo80O3eUMvMxQzqmi7z1zf+HG+/3G4F+2
# IYegvPc8Ui151XCV9rjA8tvFWRLRMX0ZRxY1zfT027HMw0iYL20z44+Cky//FAnL
# iRwoNDGiRkZiHbB9YOftPAYNMG3gm1z3zOW5RdfKPrqvMuijE+dfyLIAA6Immpzu
# FMH+Wgn8NnSlot9b4YKycaqqdjd7wXDjPub/oQ7VShuCSBWj+UNOTVh0vcZGackc
# H1DLVgwp2dcKlxJiQKtkHT/T6LloY6LTe6+8wkVkr8EAv1W+q/+M1a4Ao+ykFbIA
# 2LBEmA9qdgoLtenAYIiEg+48SjMPgyBbVPE3bhL1vIqjEIxYCfdmi6wx33oYX7HB
# +bJ7zitHw4GgtpfPV8y8QRZImKmeDOKyXjQPDmQM/Eglm/Ns0GzBkVXM8h6UI34b
# WZrHz9sbLSE20m5Svmxftvw5zju+I3WsmS/stNfWlOkwU0niUgwPHaz21kjXEA5A
# g+aqv26wodqZcnGOlChoWDvSJ8KKgdOFbeAYKAMp1NY7iWV315zpGH19RipCR1NH
# 0ND8iIubk3WGNf2rzEfqlOi3h2ywqVkU6AKXHdO5JV4otSKKEDGCBdkwggXVAgEB
# MH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYD
# VQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNI
# QTM4NCAyMDIxIENBMQIQB7Q/dIsmZyhU2sStTLFO3TANBglghkgBZQMEAgEFAKCB
# hDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEE
# AYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJ
# BDEiBCCkZeVYj+oOVm+37SKqRpSsF0sNZykblA97Vl/f6r0iJjANBgkqhkiG9w0B
# AQEFAASCAYBbIGdLtvw4ey4JJKPUR5QUd6gjXqauBPlb/h6HkPNBRH/Are9CqUiv
# 1Z7zPOY01BsqPrXlY3z4b7Hw9816rGzK+zbu0N8D3dVGiBJAQiT5vrO82X5W2JBm
# X1/kAl6jnMiKzfuDc2g5So7iEFhCd6XmcHEILN7r2FhQI8pv9RNQ5hrTsYPcbvHj
# mcBzDFNrS9W/cWeiFw7f8XvQddgTTvCUtNbtsIuC2AKLajc1jMbhjoJnBcP5eAA9
# jivF8D8BsXEkXohlMKuTC6B1kWQrJ8D2ikPdd2cFPUkrp2567u+EJrVPBJcEmR2V
# X3jwaF5+jriJL1qIxhqTS7YgJi72wl/at/0Q6ZZ//XYIc5qaoAn+6uMwKCXqY/fP
# vxuuAfVobu33BPUFbpQV/sEE9Zm6sfWl6EhqE0ciMnIskiTfwFJJHN5ga5v4AI5i
# bPnjh2JwbnKjiV8tPlwHFxHxy7XoMrX3KHspCULLO+afkZJUPnh5Nc156c+rhwt+
# DE/v9HB5VSWhggMmMIIDIgYJKoZIhvcNAQkGMYIDEzCCAw8CAQEwfTBpMQswCQYD
# VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD
# ZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUg
# Q0ExAhAKgO8YS43xBYLRxHanlXRoMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcN
# AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjYwMTIzMjMzOTI4WjAv
# BgkqhkiG9w0BCQQxIgQgSCcdOAgn8A353djsSRZzFg3vLM1bIAGsAyC9VoVQ77kw
# DQYJKoZIhvcNAQEBBQAEggIAoH7mxXXZUe4Bi4M2bp/aOe7Rq7l9dEbbDlnlkTw9
# JdG8hqR4ZWx2cx4iGKQCrPWNSskaRvyPo1O8rX4I8PwcUytgAuY2jQY7D0Pz4Sde
# /1r7pFIltLJD0oAcNpniQ8iV3b1SKwcN6O0YVSMtRDr+NSc/YDjpN641lGPwiYRE
# WrX4VGlsODoFf3etOpHuOr7oh5aLU0iJdNwPRFJHc0EIahoMtFeqOq33H6cAXj/T
# Pb44CB1YlWEBSXj0Hs/Qa7XUb9NKblTSj3cZ6Z3ZXIXwJ1tZamcIgjUBtpVu20iu
# 3yMLcOOM3ttq1Wu7WBb3IygFAkbc0dy1cy/woQUxAfaKUMCie5JyeqmedV+3egD0
# C1Z+RvSQnBKu5dU37ezx2JY+UijJFA3Lgn6pF6jWfx3GGl6WNmhXQSWkPaYWhvS5
# Bw1mCpINKXD+W1ZlC5sKcn6Mq4ZIvmxoUJQaaZ6rgJIr6TQK92We/zvmebLRrvfi
# HHXWmjyT1ww8uYL4MdBEZm7c8hymTDTUEAV+9EJsZ3mqvrDnRipclQOxoUhdzscR
# gpDVfTMdna3sbqims5xyK4lvPeZkUrVn2DjRZjlZglponRT4qJ/n0xPRxY8r5Z5Y
# 9xSWwCOW9Xzkmuy/PvEDccAztliAXD9OiWiUcWjWGTZdbS/B16wdYlrQcv0Lxsku
# SmA=
# SIG # End signature block