PSFileObjectId.psm1

# PSFileObjectId.psm1
# Track files by NTFS Object ID so you can find them after they're moved
# or renamed anywhere on the same volume.

if (-not ('Win32.FileId' -as [type])) {
    Add-Type -Namespace Win32 -Name FileId -MemberDefinition @'
[StructLayout(LayoutKind.Sequential)]
public struct FILE_ID_DESCRIPTOR {
    public uint dwSize;
    public int Type;
    public System.Guid Id;
}
 
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern Microsoft.Win32.SafeHandles.SafeFileHandle CreateFileW(
    string lpFileName, uint dwDesiredAccess, uint dwShareMode,
    IntPtr lpSecurityAttributes, uint dwCreationDisposition,
    uint dwFlagsAndAttributes, IntPtr hTemplateFile);
 
[DllImport("kernel32.dll", SetLastError=true)]
public static extern Microsoft.Win32.SafeHandles.SafeFileHandle OpenFileById(
    Microsoft.Win32.SafeHandles.SafeFileHandle hVolumeHint,
    ref FILE_ID_DESCRIPTOR lpFileId,
    uint dwDesiredAccess, uint dwShareMode,
    IntPtr lpSecurityAttributes, uint dwFlagsAndAttributes);
 
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern uint GetFinalPathNameByHandleW(
    Microsoft.Win32.SafeHandles.SafeFileHandle hFile,
    System.Text.StringBuilder lpszFilePath,
    uint cchFilePath, uint dwFlags);
'@

}

function ConvertFrom-ObjectIdLine {
    # Private helper: parses the "Object ID : <hex>" line from fsutil output into a [Guid].
    param([Parameter(Mandatory)]$Line)
    $hex = ($Line.ToString() -split ':',2)[1].Trim()
    ConvertTo-GuidFromHex $hex
}

function Find-ObjectIdLine {
    # Private helper: returns the first line of fsutil objectid output whose
    # value is a 32-char hex string. fsutil always prints the Object ID line
    # first (before BirthVolume ID, BirthObjectId ID, and Domain ID), and its
    # labels are MUI-localized, so match on the hex payload rather than the
    # English "Object ID" label.
    param($Output)
    $Output | Select-String ':\s*[0-9a-fA-F]{32}\s*$' | Select-Object -First 1
}

function Get-Win32ErrorMessage {
    # Private helper: renders a Win32 error code as its system message plus
    # the numeric code, e.g. "Access is denied. (error 5)".
    param([Parameter(Mandatory)][int]$Code)
    '{0} (error {1})' -f [System.ComponentModel.Win32Exception]::new($Code).Message, $Code
}

function Get-FsutilErrorDetail {
    # Private helper: the Crescendo wrappers swallow fsutil's stderr into an
    # unread queue, so re-invoke fsutil directly to recover the error text.
    # Always uses the read-only `query` verb so repeating the call can't
    # mutate state. Returns the first non-empty line of fsutil output, or
    # $null if fsutil produced nothing or couldn't be invoked. Callers own
    # the formatting of the result into their error message.
    #
    # Uses a fully-qualified System32 path rather than a PATH lookup so a
    # rogue fsutil.exe earlier in PATH or the working directory can't be
    # substituted for the system binary.
    param([Parameter(Mandatory)][string]$Path)
    $fsutil = Join-Path $env:SystemRoot 'System32\fsutil.exe'
    try {
        & $fsutil objectid query $Path 2>&1 |
            ForEach-Object { $_.ToString().Trim() } |
            Where-Object { $_ } |
            Select-Object -First 1
    } catch {
        $null
    }
}

function ConvertTo-GuidFromHex {
    <#
    .SYNOPSIS
        Converts a 32-character hex string (as printed by fsutil objectid) into a [Guid].
    .DESCRIPTION
        Takes a raw 32-character hex string in the byte order used by fsutil objectid
        query and converts it to a [Guid]. Dashes, spaces, and other non-hex characters
        are stripped before conversion.
    .PARAMETER Hex
        A 32-character hexadecimal string in fsutil's raw on-disk byte order.
        Dashes and spaces are allowed and will be stripped automatically.
        Do not pass the dashed display form of an existing [Guid] (for example
        the string printed by Get-FileObjectId): the first three fields would
        be silently byte-swapped and a different Guid returned. To parse a
        dashed Guid string, cast it with [Guid] instead.
    .EXAMPLE
        ConvertTo-GuidFromHex '0102030405060708090a0b0c0d0e0f10'
    .OUTPUTS
        [Guid]
    .LINK
        https://github.com/Slacksarenice/PS_FileObjectId
    #>

    param([Parameter(Mandatory)][AllowEmptyString()][string]$Hex)
    $Hex = $Hex -replace '[^0-9a-fA-F]',''
    if ($Hex.Length -ne 32) { throw "Expected 32 hex chars, got $($Hex.Length)" }
    $bytes = [byte[]]::new(16)
    for ($i = 0; $i -lt 16; $i++) {
        $bytes[$i] = [Convert]::ToByte($Hex.Substring($i * 2, 2), 16)
    }
    [Guid]::new($bytes)
}

function Set-FileObjectId {
    <#
    .SYNOPSIS
        Ensures a file has an NTFS Object ID, creating one if needed, and returns it.
    .DESCRIPTION
        Checks whether the file already has an NTFS Object ID. If not, creates one
        using fsutil objectid create. Returns the Object ID as a [Guid] either way.
    .PARAMETER Path
        Path to the file to assign an Object ID to.
    .EXAMPLE
        $id = Set-FileObjectId C:\notes\todo.txt
    .OUTPUTS
        [Guid]
    .LINK
        https://github.com/Slacksarenice/PS_FileObjectId
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param([Parameter(Mandatory)][string]$Path)
    $query = Get-FsutilObjectId -Path $Path -ErrorAction SilentlyContinue
    $match = Find-ObjectIdLine $query
    if (-not $match) {
        if (-not $PSCmdlet.ShouldProcess($Path, 'Create NTFS Object ID')) { return }
        $create = New-FsutilObjectId -Path $Path -ErrorAction SilentlyContinue
        $query = Get-FsutilObjectId -Path $Path -ErrorAction SilentlyContinue
        $match = Find-ObjectIdLine $query
        if (-not $match) {
            # fsutil writes its error text to stdout, so the create call's own
            # output is the most accurate detail (e.g. "Error 5: Access is
            # denied."). Fall back to re-querying, but drop a "no object id"
            # detail there: it restates what we already know and would mask
            # the create failure.
            $detail = $create | ForEach-Object { $_.ToString().Trim() } |
                Where-Object { $_ -and $_ -notmatch ':\s*[0-9a-fA-F]{32}\s*$' } |
                Select-Object -First 1
            if (-not $detail) {
                $detail = Get-FsutilErrorDetail -Path $Path
                if ($detail -match '(?i)no object id') { $detail = $null }
            }
            $suffix = if ($detail) { ": $detail" } else { '' }
            throw "Failed to create Object ID on '$Path'$suffix"
        }
    }
    ConvertFrom-ObjectIdLine $match
}

function Get-FileObjectId {
    <#
    .SYNOPSIS
        Reads the existing NTFS Object ID from a file and returns it as a [Guid].
    .DESCRIPTION
        Queries the file's NTFS Object ID using fsutil objectid query. Throws if
        the file has no Object ID assigned. Use Set-FileObjectId to assign one first.
    .PARAMETER Path
        Path to the file to query.
    .EXAMPLE
        Get-FileObjectId C:\notes\todo.txt
    .OUTPUTS
        [Guid]
    .LINK
        https://github.com/Slacksarenice/PS_FileObjectId
    #>

    param([Parameter(Mandatory)][string]$Path)
    $line = Find-ObjectIdLine (Get-FsutilObjectId -Path $Path -ErrorAction SilentlyContinue)
    if (-not $line) {
        $detail = Get-FsutilErrorDetail -Path $Path
        # "The specified file has no object id" is fsutil's way of telling us the
        # file exists but lacks an ID, so redirect the user to Set-FileObjectId.
        # For any other error (missing file, access denied, ...) surface the detail.
        if (-not $detail -or $detail -match '(?i)no object id') {
            throw "No Object ID on '$Path' (use Set-FileObjectId first)"
        }
        throw "No Object ID on '$Path': $detail"
    }
    ConvertFrom-ObjectIdLine $line
}

function Resolve-FileObjectId {
    <#
    .SYNOPSIS
        Looks up a file by its NTFS Object ID and returns its current path.
    .DESCRIPTION
        Opens the volume root as a directory handle, then uses OpenFileById to
        locate the file by its Object ID. Returns the file's current full path.
        No admin privileges are required.
    .PARAMETER ObjectId
        The NTFS Object ID to look up, as a [Guid].
    .PARAMETER Volume
        The volume to search. Defaults to 'C:'. Object IDs are per-volume, so
        you must specify the correct drive.
    .EXAMPLE
        $id = Set-FileObjectId C:\notes\todo.txt
        Move-Item C:\notes\todo.txt C:\archive\todo.txt
        Resolve-FileObjectId $id
        # Returns: C:\archive\todo.txt
    .EXAMPLE
        Resolve-FileObjectId $id -Volume D:
    .OUTPUTS
        [String]
    .LINK
        https://github.com/Slacksarenice/PS_FileObjectId
    #>

    param(
        [Parameter(Mandatory)][Guid]$ObjectId,
        [string]$Volume = 'C:'
    )

    $FILE_SHARE_RWD             = [uint32]7  # read, write, delete
    $OPEN_EXISTING              = [uint32]3
    $FILE_FLAG_BACKUP_SEMANTICS = [uint32]0x02000000

    # Open the volume root as a directory hint (no admin required)
    $vol = [Win32.FileId]::CreateFileW("$Volume\",
        [uint32]0, $FILE_SHARE_RWD, [IntPtr]::Zero,
        $OPEN_EXISTING, $FILE_FLAG_BACKUP_SEMANTICS, [IntPtr]::Zero)
    if ($vol.IsInvalid) {
        $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
        $vol.Dispose()
        throw "CreateFileW failed: $(Get-Win32ErrorMessage $err)"
    }

    try {
        $desc = New-Object Win32.FileId+FILE_ID_DESCRIPTOR
        $desc.dwSize = [System.Runtime.InteropServices.Marshal]::SizeOf($desc)
        $desc.Type = 1  # ObjectId
        $desc.Id = $ObjectId

        # Attribute-only open (access 0, share all): resolving a path needs no
        # read access, and this way files that are ACL-denied for reading,
        # exclusively locked, or delete-pending can still be resolved.
        $h = [Win32.FileId]::OpenFileById($vol, [ref]$desc,
            [uint32]0, $FILE_SHARE_RWD, [IntPtr]::Zero, $FILE_FLAG_BACKUP_SEMANTICS)
        if ($h.IsInvalid) {
            $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
            $h.Dispose()
            throw "OpenFileById failed: $(Get-Win32ErrorMessage $err)"
        }

        try {
            # 1024 handles most paths; grow once if the full path is longer (up to 32767).
            # Casts to [int] are required because $written is [uint32] and
            # `New-Object StringBuilder $uint` binds to the (string) overload.
            $sb = New-Object System.Text.StringBuilder 1024
            $written = [Win32.FileId]::GetFinalPathNameByHandleW($h, $sb, $sb.Capacity, 0)
            if ($written -eq 0) {
                $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
                throw "GetFinalPathNameByHandleW failed: $(Get-Win32ErrorMessage $err)"
            }
            if ($written -ge $sb.Capacity) {
                $sb = New-Object System.Text.StringBuilder ([int]($written + 1))
                $written = [Win32.FileId]::GetFinalPathNameByHandleW($h, $sb, $sb.Capacity, 0)
                if ($written -eq 0 -or $written -ge $sb.Capacity) {
                    $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
                    throw "GetFinalPathNameByHandleW failed after resize: $(Get-Win32ErrorMessage $err)"
                }
            }

            # Strip the \\?\ prefix that GetFinalPathNameByHandle prepends
            $sb.ToString() -replace '^\\\\\?\\',''
        } finally {
            $h.Dispose()
        }
    } finally {
        $vol.Dispose()
    }
}

Export-ModuleMember -Function Set-FileObjectId, Get-FileObjectId, Resolve-FileObjectId, ConvertTo-GuidFromHex

# SIG # Begin signature block
# MII3GAYJKoZIhvcNAQcCoII3CTCCNwUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBqMN6b+Su0hTel
# Ji5c3HBM8hlnAqttuVs8USa0U6bd1aCCG0YwggXMMIIDtKADAgECAhBUmNLR1FsZ
# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu
# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy
# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv
# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo
# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD
# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH
# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD
# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV
# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70
# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1
# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3
# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK
# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg
# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj
# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7
# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ
# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn
# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c
# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF
# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx
# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8
# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY
# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2
# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY
# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al
# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk
# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggakMIIEjKADAgECAhMzAAMT1Tam
# iLJLLAE3AAAAAxPVMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDMwHhcNMjYwNzEyMDE1NDQ1WhcNMjYwNzE1
# MDE1NDQ1WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWExFzAVBgNV
# BAcTDlZpcmdpbmlhIEJlYWNoMRQwEgYDVQQKEwtTZXRoIE1JbGxlcjEUMBIGA1UE
# AxMLU2V0aCBNSWxsZXIwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCM
# kMd90vrZv6PJKFDD36fjQOK13ftnaPdxIrYBwqOmZe7JxLK9XxMHV/7Y5lqD88hx
# Q3pJ7ic3bEb52eeDc6hmQMbDhGL86pNjdwNWYhaiB8+Fws1axkASXNpynXWeD0wo
# /GoWluwBvrmTnJoJ2bL9TzM8/hT9fU19l8u/UdJGmIg/4VqzFFiL1bGCHfbFqtN/
# VIqRk2PPRUtPnL9skV5lub0XiFWqesuryJRhDDkKNsYDH+jgv78p/gC8G3S4HoCY
# bYBsfatReYUUxSWNs9jir2Mx0km8b/V/Otq0mahEDKAvl5hYWnejVnL9z/qvYL8s
# YIMaMNRKrsA7S2p78DcbMgQi6eBXCMoUNd5OGo5TyGDQbkg4T5Oy5idGTOfrKgs6
# WgYUVmkRhS694bve0TLKfBkHl2DTTmC0FnPu+xZ5QNm2D9cUujTezdOByPRktXpX
# +oh+bkX1/TP1/GijiNh3OudiAP0WK0QmwKKy6HICr+gurvCF/ZJmnggalkwqVKsC
# AwEAAaOCAdYwggHSMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMD0GA1Ud
# JQQ2MDQGCisGAQQBgjdhAQAGCCsGAQUFBwMDBhwrBgEEAYI3YYHR5Y4pgv7dj0iB
# laOJIoHu469rMB0GA1UdDgQWBBS/3a5hxBgajiCRLA9cBJX5yth1VzAfBgNVHSME
# GDAWgBRrXqU0wwXFYkohWo6rc2Bi1KxjhTBnBgNVHR8EYDBeMFygWqBYhlZodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJRCUy
# MFZlcmlmaWVkJTIwQ1MlMjBFT0MlMjBDQSUyMDAzLmNybDB0BggrBgEFBQcBAQRo
# MGYwZAYIKwYBBQUHMAKGWGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
# Y2VydHMvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0El
# MjAwMy5jcnQwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6
# Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTAN
# BgkqhkiG9w0BAQwFAAOCAgEAU9RCTDlw+Pf7De8nMDr7lChj8TTi0nYYxvyWeTml
# 29msvELX85lukok9mxSJDEMbC652pZ/JCeJ5PH+l20N84CfoSdgd8+akuJo5mzfE
# 2dsnlMTjpCJ/ic6CnJxXu6AXY8HtbksDe0zzgtBWYP0yFTeBAofsl9/b6zNteFrr
# vDqJ3zxunAN4ioZYeQCUxaWdSq5E+KVTCUWV4vcw7uPrtet30drh9hlPLy5s4AlL
# 55UklvX3jgUYH5t28JcKYQlhaeZZb01nKPb2FTwVEutmrGsR12PWMB5Ui0ADDEB2
# f5m68Ro70PqOjQP8R7un42dAePUNSQlTMdPKPAPTvHQS0rT2ABIt/+lJADqE2Jhp
# f7/kuk374QmDkchpwEe+WXgRLxMwWJLK5u4dqJeiGQt72R4lhpGIBBstLvxOLOdZ
# rfT1RqWNmf8Kqle0vJJ6qMl79FPAOvg1Shj9VVf9TTfzZ6lCw85fyE/P5f7D+lDD
# L1lSMDkf4scBmr5F1PPEWYGvDjWMZE8kuXMCIxcmn/p4F3gJQKXxZPF7/z3Q2pQ0
# /Uk1bmmW1IPYnVwqLMOHo7XYF+Lj4JIvWiZbVtGKWVPtMCj4eYXSjJpVDZjXC24e
# kbrDv+oQg10PCiQqsg5rPUdyUGWLZwbNhk4r3HFLICkjbNsls6fY8xgp/7iAq5ch
# vqIwggcoMIIFEKADAgECAhMzAAAAFQU+bhmOkynZAAAAAAAVMA0GCSqGSIb3DQEB
# DAUAMGMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xNDAyBgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcg
# UENBIDIwMjEwHhcNMjYwMzI2MTgxMTI4WhcNMzEwMzI2MTgxMTI4WjBaMQswCQYD
# VQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQD
# EyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDAzMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEA4PTLPQKqLw5zHj7zDnvism4QnfPpaJM2DkZU
# t5AVV7HnnG8hsAXLHp5ZuWy7TBj44iBS8wUBfoIZVVf1NvauRnHXhBAQh00xoS9p
# KCKy3OFK5YjEXG7/ZjjLUf5e/8QJr9BceASR59XR7d+376wal5ioynxn+Q6cjv/o
# Z1e0xK3jLUtfYjvm42f/R56YNzwpNHu2Em0UxZMfexWcEVqQuLNzXqUX0V0If1jA
# I+yZrGHlWaIYuExecltiTKyWasB3MsyWWLQ9h5Z6OWRCZHYmXBGsRzqG5sDtOmdS
# fXNt6bPTxiIRmqtbCixAM/Q6HOay5GFhrXg67HCoQKdpCHP6GJR/SI+gZDqqoFiD
# RJBLQvGTRtTGpPod6OuWo9IkCpncVuyGWhzuXLsqDIvirWH13iCIN7FSG0thC/JF
# LbAxnRKjagKv4rKk4tY16i3uoiqdZ4tUj3bz1vRtNwk7GBevG/8riEEcG3aAQl3p
# jDSQktHaKwkWOG9lgAMuJ4O0gDXBIKwYGX+d+fkHy1OYRs6yoyKWzGm2rlm+RSll
# CpDLD3FxZF0VjuJ6Cj5uClpRcqajqWyfyjjVUXiJcR0EXoADgcyIUQe4K/SA0NbH
# NjIDoEPsVRluKKuBw9JnwIsIsi7JGa5GkOyaGp2IwTXEfUUtumMQFW3AbS4rRU8w
# iBIOWXUCAwEAAaOCAdwwggHYMA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEE
# AwIBADAdBgNVHQ4EFgQUa16lNMMFxWJKIVqOq3NgYtSsY4UwVAYDVR0gBE0wSzBJ
# BgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBi
# AEMAQTASBgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAPD2Ns72nX
# 9c0pnqRIajDmMHAGA1UdHwRpMGcwZaBjoGGGX2h0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDb2Rl
# JTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3JsMH0GCCsGAQUFBwEBBHEwbzBtBggr
# BgEFBQcwAoZhaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9N
# aWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0El
# MjAyMDIxLmNydDANBgkqhkiG9w0BAQwFAAOCAgEAXW4iPM8Fy1/IJSRIf/ENtlDA
# lIVgTuOmfRT4cDkd5nZakVS5GDqJ/zHM1MK4w4cd1/fUjx+T0n5ZBqE75zvWVhzO
# WBVWKTuzWLgfpn1UhgBmcIhjgElpNItge75/ZxJSSZqIl8boHx+WHQbK1IE7dABT
# V5M5qk4JPktR8W9bv9BwqhB1WT5NgP+niV2G7aUTORXM9NI4rFJfQUWYEnmzg1fO
# Wwczr3qsgt39D5xwsUSTYTG/MT/7Af1SO6X9q4Xkle86lEr/L5/3yDG5V3mlSJaa
# qKvEj/QSTIxPwqFVycZ5GUETNRWu5Dfcs7b0XjocUoD4KWcf15f45MMhBVSUwXwa
# d7E4HyHP6Zqr9nobWpC9gBI+/BJjj0KIcSU98Ml/j+/BgNubS6QL8490TDB3fM9f
# GbrlYvutDAMxqTgEh9S/DZa932UWZ0Dvqcsntgwr2Jh2iH3VIGCap+56McRlb/Pf
# kWhE4dbYAg78DaRQkhu75eQOGpKPtn8eNPa/U1o1wuzon9SEOWScweEX/BrwYh2I
# 7zJh6ZXnadRRkS3UkRVaQt/ziqWWOmryKmae/vKT/1kD/dNw3YK7wE+luMTzgcVz
# 2uLRpLDd0rqiWohWB0jcngbn5/IrHro1uCGwUmxw+AT6mxd6mfu5xvXf3fxtvy8e
# JB/XApgX5rGXUpB5rpAwggeeMIIFhqADAgECAhMzAAAAB4ejNKN7pY4cAAAAAAAH
# MA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVudGl0eSBWZXJp
# ZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAeFw0yMTA0
# MDEyMDA1MjBaFw0zNjA0MDEyMDE1MjBaMGMxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAyBgNVBAMTK01pY3Jvc29mdCBJRCBW
# ZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIwMjEwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQCy8MCvGYgo4t1UekxJbGkIVQm0Uv96SvjB6yUo92cXdylN
# 65Xy96q2YpWCiTas7QPTkGnK9QMKDXB2ygS27EAIQZyAd+M8X+dmw6SDtzSZXyGk
# xP8a8Hi6EO9Zcwh5A+wOALNQbNO+iLvpgOnEM7GGB/wm5dYnMEOguua1OFfTUITV
# MIK8faxkP/4fPdEPCXYyy8NJ1fmskNhW5HduNqPZB/NkWbB9xxMqowAeWvPgHtpz
# yD3PLGVOmRO4ka0WcsEZqyg6efk3JiV/TEX39uNVGjgbODZhzspHvKFNU2K5MYfm
# Hh4H1qObU4JKEjKGsqqA6RziybPqhvE74fEp4n1tiY9/ootdU0vPxRp4BGjQFq28
# nzawuvaCqUUF2PWxh+o5/TRCb/cHhcYU8Mr8fTiS15kRmwFFzdVPZ3+JV3s5MulI
# f3II5FXeghlAH9CvicPhhP+VaSFW3Da/azROdEm5sv+EUwhBrzqtxoYyE2wmuHKw
# s00x4GGIx7NTWznOm6x/niqVi7a/mxnnMvQq8EMse0vwX2CfqM7Le/smbRtsEeOt
# bnJBbtLfoAsC3TdAOnBbUkbUfG78VRclsE7YDDBUbgWt75lDk53yi7C3n0WkHFU4
# EZ83i83abd9nHWCqfnYa9qIHPqjOiuAgSOf4+FRcguEBXlD9mAInS7b6V0UaNwID
# AQABo4ICNTCCAjEwDgYDVR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0G
# A1UdDgQWBBTZQSmwDw9jbO9p1/XNKZ6kSGow5jBUBgNVHSAETTBLMEkGBFUdIAAw
# QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E
# b2NzL1JlcG9zaXRvcnkuaHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8G
# A1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89QEE9oqKIw
# gYQGA1UdHwR9MHsweaB3oHWGc2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv
# cHMvY3JsL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9v
# dCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcmwwgcMGCCsGAQUF
# BwEBBIG2MIGzMIGBBggrBgEFBQcwAoZ1aHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlv
# biUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3J0MC0G
# CCsGAQUFBzABhiFodHRwOi8vb25lb2NzcC5taWNyb3NvZnQuY29tL29jc3AwDQYJ
# KoZIhvcNAQEMBQADggIBAH8lKp7+1Kvq3WYK21cjTLpebJDjW4ZbOX3HD5ZiG84v
# jsFXT0OB+eb+1TiJ55ns0BHluC6itMI2vnwc5wDW1ywdCq3TAmx0KWy7xulAP179
# qX6VSBNQkRXzReFyjvF2BGt6FvKFR/imR4CEESMAG8hSkPYso+GjlngM8JPn/ROU
# rTaeU/BRu/1RFESFVgK2wMz7fU4VTd8NXwGZBe/mFPZG6tWwkdmA/jLbp0kNUX7e
# lxu2+HtHo0QO5gdiKF+YTYd1BGrmNG8sTURvn09jAhIUJfYNotn7OlThtfQjXqe0
# qrimgY4Vpoq2MgDW9ESUi1o4pzC1zTgIGtdJ/IvY6nqa80jFOTg5qzAiRNdsUvzV
# koYP7bi4wLCj+ks2GftUct+fGUxXMdBUv5sdr0qFPLPB0b8vq516slCfRwaktAxK
# 1S40MCvFbbAXXpAZnU20FaAoDwqq/jwzwd8Wo2J83r7O3onQbDO9TyDStgaBNlHz
# MMQgl95nHBYMelLEHkUnVVVTUsgC0Huj09duNfMaJ9ogxhPNThgq3i8w3DAGZ61A
# MeF0C1M+mU5eucj1Ijod5O2MMPeJQ3/vKBtqGZg4eTtUHt/BPjN74SsJsyHqAdXV
# S5c+ItyKWg3Eforhox9k3WgtWTpgV4gkSiS4+A09roSdOI4vrRw+p+fL4WrxSK5n
# MYIbKDCCGyQCAQEwcTBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1Mg
# RU9DIENBIDAzAhMzAAMT1TamiLJLLAE3AAAAAxPVMA0GCWCGSAFlAwQCAQUAoIH1
# MBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgor
# BgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCB9xvskEKfoibA4G+CTOQXdnTJdw55w
# xFq9wCi8KN8ZZTCBiAYKKwYBBAGCNwIBDDF6MHigQoBAAFAAUwBGAGkAbABlAE8A
# YgBqAGUAYwB0AEkAZAAgAFAAbwB3AGUAcgBTAGgAZQBsAGwAIABtAG8AZAB1AGwA
# ZaEygDBodHRwczovL2dpdGh1Yi5jb20vU2xhY2tzYXJlbmljZS9QU19GaWxlT2Jq
# ZWN0SWQwDQYJKoZIhvcNAQEBBQAEggGAhI1lKRTOrVlJOVpOe1tnw1EeUi2l1kbx
# l84bH08qPLQcw3n9obo/yc7ALB1AxzXvY/4EYLu5T0alxOyYF1tStcpVAOTVoOUz
# Px2hhecZhjf6giqzSSdl2S1hBTWud/lHdqYo0AQJ9IGYX9++V2tN2C0HaJsRH3/l
# 5CxWdtxliFRQVcetaeS8E3osMO7dd0ZzDVkE18jPxzEQTOGv7nvP59+T/u5xhLJy
# QJBNenKn9HpLjy6ssruwO6+kTiK18f0cCIUibyy1VfzIz9FRABzwEkarhV6QZTqr
# mCSG/gZ2mSXLPjKMBLWn9MqL46cIci/j24AFY34O0AjgzJRwbNRqOOGS1TaiM12m
# /Z7B3qj4Y7QNBW7gP4Ra7bqcChgsVVrk6GkI4okEjnBg+b1GtAEWDc0ajvdTkVBi
# slHYAc+aKU0wUJczRTjcTwKW+GaBX6tiVo12gEOHghNGoNXHn+AP4dWwkvq8PiDu
# LSixZSoSu2RC37n2qjPRHj/NnrLZf3A7oYIYEDCCGAwGCisGAQQBgjcDAwExghf8
# MIIX+AYJKoZIhvcNAQcCoIIX6TCCF+UCAQMxDzANBglghkgBZQMEAgEFADCCAWEG
# CyqGSIb3DQEJEAEEoIIBUASCAUwwggFIAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZI
# AWUDBAIBBQAEIPrbl2aRPg4G/M5FSPfDFWIK+KNRnNAX3PJ8QZJPjt/eAgZqT9J6
# sDoYEjIwMjYwNzEzMTgwNDQ1LjExWjAEgAIB9KCB4aSB3jCB2zELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFt
# ZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjdEMDAt
# MDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0
# YW1waW5nIEF1dGhvcml0eaCCDyEwggeCMIIFaqADAgECAhMzAAAABeXPD/9mLsmH
# AAAAAAAFMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVudGl0
# eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAe
# Fw0yMDExMTkyMDMyMzFaFw0zNTExMTkyMDQyMzFaMGExCzAJBgNVBAYTAlVTMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29m
# dCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwMIICIjANBgkqhkiG9w0B
# AQEFAAOCAg8AMIICCgKCAgEAnnznUmP94MWfBX1jtQYioxwe1+eXM9ETBb1lRkd3
# kcFdcG9/sqtDlwxKoVIcaqDb+omFio5DHC4RBcbyQHjXCwMk/l3TOYtgoBjxnG/e
# ViS4sOx8y4gSq8Zg49REAf5huXhIkQRKe3Qxs8Sgp02KHAznEa/Ssah8nWo5hJM1
# xznkRsFPu6rfDHeZeG1Wa1wISvlkpOQooTULFm809Z0ZYlQ8Lp7i5F9YciFlyAKw
# n6yjN/kR4fkquUWfGmMopNq/B8U/pdoZkZZQbxNlqJOiBGgCWpx69uKqKhTPVi3g
# VErnc/qi+dR8A2MiAz0kN0nh7SqINGbmw5OIRC0EsZ31WF3Uxp3GgZwetEKxLms7
# 3KG/Z+MkeuaVDQQheangOEMGJ4pQZH55ngI0Tdy1bi69INBV5Kn2HVJo9XxRYR/J
# PGAaM6xGl57Ei95HUw9NV/uC3yFjrhc087qLJQawSC3xzY/EXzsT4I7sDbxOmM2r
# l4uKK6eEpurRduOQ2hTkmG1hSuWYBunFGNv21Kt4N20AKmbeuSnGnsBCd2cjRKG7
# 9+TX+sTehawOoxfeOO/jR7wo3liwkGdzPJYHgnJ54UxbckF914AqHOiEV7xTnD1a
# 69w/UTxwjEugpIPMIIE67SFZ2PMo27xjlLAHWW3l1CEAFjLNHd3EQ79PUr8FUXet
# Xr0CAwEAAaOCAhswggIXMA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIB
# ADAdBgNVHQ4EFgQUa2koOjUvSGNAz3vYr0npPtk92yEwVAYDVR0gBE0wSzBJBgRV
# HSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv
# cHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkr
# BgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQY
# MBaAFMh+0mqFKhvKGZgEByfPUBBPaKiiMIGEBgNVHR8EfTB7MHmgd6B1hnNodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJZGVu
# dGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhv
# cml0eSUyMDIwMjAuY3JsMIGUBggrBgEFBQcBAQSBhzCBhDCBgQYIKwYBBQUHMAKG
# dWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0
# JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUl
# MjBBdXRob3JpdHklMjAyMDIwLmNydDANBgkqhkiG9w0BAQwFAAOCAgEAX4h2x35t
# tVoVdedMeGj6TuHYRJklFaW4sTQ5r+k77iB79cSLNe+GzRjv4pVjJviceW6AF6yc
# WoEYR0LYhaa0ozJLU5Yi+LCmcrdovkl53DNt4EXs87KDogYb9eGEndSpZ5ZM74LN
# vVzY0/nPISHz0Xva71QjD4h+8z2XMOZzY7YQ0Psw+etyNZ1CesufU211rLslLKsO
# 8F2aBs2cIo1k+aHOhrw9xw6JCWONNboZ497mwYW5EfN0W3zL5s3ad4Xtm7yFM7Uj
# rhc0aqy3xL7D5FR2J7x9cLWMq7eb0oYioXhqV2tgFqbKHeDick+P8tHYIFovIP7Y
# G4ZkJWag1H91KlELGWi3SLv10o4KGag42pswjybTi4toQcC/irAodDW8HNtX+cbz
# 0sMptFJK+KObAnDFHEsukxD+7jFfEV9Hh/+CSxKRsmnuiovCWIOb+H7DRon9Tlxy
# diFhvu88o0w35JkNbJxTk4MhF/KgaXn0GxdH8elEa2Imq45gaa8D+mTm8LWVydt4
# ytxYP/bqjN49D9NZ81coE6aQWm88TwIf4R4YZbOpMKN0CyejaPNN41LGXHeCUMYm
# Bx3PkP8ADHD1J2Cr/6tjuOOCztfp+o9Nc+ZoIAkpUcA/X2gSMkgHAPUvIdtoSAHE
# UKiBhI6JQivRepyvWcl+JYbYbBh7pmgAXVswggeXMIIFf6ADAgECAhMzAAAAVdnd
# aSYo+fjiAAAAAABVMA0GCSqGSIb3DQEBDAUAMGExCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQ
# dWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwMB4XDTI1MTAyMzIwNDY0OVoX
# DTI2MTAyMjIwNDY0OVowgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAl
# BgNVBAsTHm5TaGllbGQgVFNTIEVTTjo3RDAwLTA1RTAtRDk0NzE1MDMGA1UEAxMs
# TWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHkwggIi
# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9uR+SHllIs/QwJRZp9rD8pmhV
# m72JDHyvknCFm92tSLzpSMIIVA42NBqesjEYX2FEYhktBnnSAessL7h+lQQl9/m3
# ThXAHJYLb9tY66To2ZpOH0mk9kNwbM1H3lCWvKN8SO2X6DGPXbM08R0AM+mVV/O3
# xxhFYUHH8Vt9yHTyTo/2nuNfarWMU9tTFZgn7E7IYLVoqEMZjlv7zAvf2/qoLQcU
# jH+/fL5t6n5oReigrxWh5Yr6zN9oWNejxhNy9DxQvizO70cVO5k2/q++gnsm76jl
# pOPnWymH7T4VdbfxOUv+sMF3mJrv2OyQu054dsOORuWOKXDN6BzG/2Lj0XTlmtL/
# kQtkIJjVVqo7sQ4spVrHF0A7mjLW9vQHHRlFVfWbEWNjNrLYQLTnWTrIYkebnzLW
# h7YgpFr9IzX4FMax7q8c2LlDZ3lmehH0A4BQMPAkgipEjitnPYxKKeHXVatdMb26
# sXa6jJ3lV77yHF6z0AF4/Y9hAqVdhMDG91p5qcNND+/Cacz7JNxbOtWbzhnfxdUX
# Dgbun9k1naexy+/q6u7YB69dzJXW3yFruJaaGGBNYE0GtWK4OVzeI+87PZJU9s96
# qHJj81fA1kICBzYfmk7O27ozBDEMiO17dcz8WQoHEeh9LZps1P/Qcb7Fm0WpQkNr
# GBslrqU3XOHuymO5DwIDAQABo4IByzCCAccwHQYDVR0OBBYEFFYEXxBt3AgD8Mi/
# qckWysHXrGW2MB8GA1UdIwQYMBaAFGtpKDo1L0hjQM972K9J6T7ZPdshMGwGA1Ud
# HwRlMGMwYaBfoF2GW2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3Js
# L01pY3Jvc29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIw
# MjAyMC5jcmwweQYIKwYBBQUHAQEEbTBrMGkGCCsGAQUFBzAChl1odHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFB1YmxpYyUy
# MFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIwMjAyMC5jcnQwDAYDVR0TAQH/BAIw
# ADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwZgYDVR0g
# BF8wXTBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5t
# aWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEE
# AjANBgkqhkiG9w0BAQwFAAOCAgEAUh7hklR72pQpxZ5bKlyEHnx9cT9kha/YPlc/
# n+T+0HssI30G+Y1JUpndV5yVAz3vzB8S+690xBJS/pjbRuggzwMrUrUhT1w/bUwb
# QTGIfFqqOuKR/apt+tciKngR/e/Zs1gpDELE3dJzOnVJfQfu6orYvk6F8MSJd/Xm
# Ki7mGH4Q9pqqnj1zM1CkkM5H+98mCFRz+pyyUM+GgJmlnHxvY4O/LAZA1fCqVuyY
# JLbi4aYSRDdQfklR43pz3XJqxVyFLvyuIyubpH1mkCI7ml80owZTYwubUDemnT3w
# NxsVMBz3keHpC+SH//bwX9d7ZswVvoMvtLDRk73m/SC/RlPIl/FL8sLF+tp4Qgj0
# VIU4oAwSnXM0VKza57QYaMG33IQQxTC/Gr0TEXPRpnNibyK8l99+khUOdf/6tVFN
# hzEiRDIViyUiFiVYX1KMLDmvj2pqSMxE2Hxb07tpqiiVJVmV5BmMa3QrwnMyXKnq
# GnaVtbpepHHZw4dtvEkPGYQ3OiEZTOIjXeUjaDYF/mqJt8Lhso1Gkmj2VsTwdRtj
# SomITy7dJTx4NBrJI9c4SEmPFEJDDA696NiYEbk/sJyRA0FKeeXXb4UpEqA+iPQy
# /7Pk4yGP3PYy2luccsCR6nSh1AKUTLIIb+5Hm0rmtbqZkfk6rnpRZLQ0jo1XUkZL
# smuLqMUxggdDMIIHPwIBATB4MGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNB
# IFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAAVdndaSYo+fjiAAAAAABVMA0GCWCG
# SAFlAwQCAQUAoIIEnDARBgsqhkiG9w0BCRACDzECBQAwGgYJKoZIhvcNAQkDMQ0G
# CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjA3MTMxODA0NDVaMC8GCSqG
# SIb3DQEJBDEiBCACbOV6SWCmb8KSmYmEmWfM1h24Q5I9wIG1iZH31VijiTCBuQYL
# KoZIhvcNAQkQAi8xgakwgaYwgaMwgaAEINi5PJdkhmK7v33+/g9qqyZ5LMHGHSuq
# Riruxhhq+P7NMHwwZaRjMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRp
# bWVzdGFtcGluZyBDQSAyMDIwAhMzAAAAVdndaSYo+fjiAAAAAABVMIIDXgYLKoZI
# hvcNAQkQAhIxggNNMIIDSaGCA0UwggNBMIICKQIBATCCAQmhgeGkgd4wgdsxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jv
# c29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVT
# Tjo3RDAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0Eg
# VGltZSBTdGFtcGluZyBBdXRob3JpdHmiIwoBATAHBgUrDgMCGgMVAB07VAGCZb+2
# 4FlXkQaOF+xXhw3qoGcwZaRjMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNB
# IFRpbWVzdGFtcGluZyBDQSAyMDIwMA0GCSqGSIb3DQEBCwUAAgUA7f+W+DAiGA8y
# MDI2MDcxMzE2NTUyMFoYDzIwMjYwNzE0MTY1NTIwWjB0MDoGCisGAQQBhFkKBAEx
# LDAqMAoCBQDt/5b4AgEAMAcCAQACAht2MAcCAQACAhJwMAoCBQDuAOh4AgEAMDYG
# CisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEA
# AgMBhqAwDQYJKoZIhvcNAQELBQADggEBAE0zFpWhJhWJEcMLIGkveziA49lGUyCa
# amiteEJhyHq4ETwQ8pQAXuivE0XsYSNECOOFpF+NqpL7Kicc2sIpXQc6JOSf37Yd
# QK3XQazkbOoHf996upe04+6NPyGNYUtWs92SQcsazYoibtEsnPmydoc775kOpA/J
# Y41mEuSEXEVIUKEJ24VFYBYcM7DabUq1PMrP1AXQcS5BeLRL5+vp8AJDYRcZP8et
# O8u5Kh2tKKt/pARLgTwP/traxXixZJ290w3HZvNjbfmQjgJSRS8AvRHfHH/eGedk
# zjdu1CBJ2Yc1eKAAqpM0UU2IKnznpUqTeTi9nKE/DDXKAtcNKFZQ5AswDQYJKoZI
# hvcNAQEBBQAEggIAjM/NyvRSlSSI3ozx6zLHhKMPcnQyc5S1yJRvLTTSBrYV9kd7
# kqjGl7vYwj7cgaV+gmOLN9IaOgaYCIpLLAljanXMSy0+VotmH0ZFEc1YjYsmGi1z
# m7EEk1qr32RE1SGbMsN4B/P7sfczjyb58iN03jGiExQ9N3rnZFbY1lznIr/RqFQy
# 5BMBY5R6+fpYwgE+tPRsGc7m6WDtB5VPJulJe84nMWR2BIbjJ/mwWMP7ZXkm6KX2
# AHLtaKpdyGbr0A/W16ubKZc6pOc/JTUwIA18NoXawvHXuK8iywUS8XnM6au+aGhB
# tBDHrPVrqjbKxCx64k3JFlxuzh65+tw5Pw9h7NG8y/M839vMPn4DURr5ZC3VFz2f
# dwsijiKBKGfYBB2P8u7e88btA4E6aOZ4A1uJCfabAE+CTwNowA6ZzFBaf7oh80t9
# pch6rh0uWrQ3MYq4U476rVt4WCcq1XU4LceCX7WWBLU9bd+4bLFtV+RjKQtofcOK
# xESNswRAKaJZuvdXEznr5RtkWTOOfeuYZ4u/TkaWVnzwZzEZ07qfujAR9HWI3WST
# WgSu5sxb7u/+st0s1haeZ/H56lqK5VR6v58eVNZflBafaRqR0wNdP2MXUNHa1SPw
# TJI25/RRLpCGxO1njl3VhkDUXXuZ2+x4bWRrPGaZlkJgXiqm+etqm4EhKno=
# SIG # End signature block