PsUntis.psm1

# Copyright (c) STÜBER SYSTEMS GmbH. All rights reserved.
# Licensed under the MIT License.

Import-LocalizedData -BindingVariable stringTable

<#
    .Synopsis
    Lists all terms of a given Untis .gpn file
 
    .Description
    This cmdlet reads all defined terms from the Untis .gpn file and lists them. If no term is defined nothing is listed.
 
    .Parameter File
    The file name of an Untis .gpn file.
 
    .Example
    Get-UntisTerms -File example.gpn
#>

function Get-UntisTerms {
    param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $File
    )
    process
    {
        try
        {
            $UntisContent = Get-Content -Path $File -Raw

            $RegExPattern = '(?<prefix>0P\s*),"?(?<sname>[^,"]*)"?,"?(?<lname>[^,"]*)"?,(?<fdate>\d*),(?<tdate>\d*),"?(?<pname>[^,"]*)"?,(?<status>A?)'
            $RegExMatches = [regex]::matches($UntisContent, $RegExPattern)

            $table = @()

            foreach($match in $RegExMatches)
            {
                $term = New-Object PSCustomObject
                $term | Add-Member -type NoteProperty -name ShortName -Value $match.Groups["sname"].value
                $term | Add-Member -type NoteProperty -name LongName -Value $match.Groups["lname"].value
                $term | Add-Member -type NoteProperty -name FromDate -Value (FormatDate $match.Groups["fdate"].value)
                $term | Add-Member -type NoteProperty -name ToDate -Value (FormatDate $match.Groups["tdate"].value)
                $term | Add-Member -type NoteProperty -name Active -Value (FormatStatus $match.Groups["status"].value)
                $table += $term
            }

            return $table
        }
        catch
        {
            $ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
        }
    }
}

<#
    .Synopsis
    Activates a choosen term in a given Untis .gpn file
 
    .Description
    This cmdlet changes the active term within a given Untis .gpn file. This cmdlet will modify the gpn file. Please be carefull while
    testing and always backup first.
 
    .Parameter File
    The file name of an Untis .gpn file.
 
    .Parameter ShortName
    Name of the term.
 
    .Example
    Set-UntisTermAsActive -File example.gpn -ShortName Periode1
    .Example
    Set-UntisTermAsActive -File example.gpn -ShortName 'Periode 2'
#>

function Set-UntisTermAsActive {
    param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $File,
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]
        $ShortName
    )
    process
    {
        try
        {
            $UntisContent = Get-Content -Path $File -Raw

            $RegExPattern = '(?<prefix>0P\s*),"?(?<sname>[^,"]*)"?,"?(?<lname>[^,"]*)"?,(?<fdate>\d*),(?<tdate>\d*),"?(?<pname>[^,"]*)"?,A'
            $UntisContent = $UntisContent -Replace $RegExPattern, '${prefix},"${sname}","${lname}",${fdate},${tdate},"${pname}",'

            $RegExPattern = '(?<prefix>0P\s*),"?(?<sname>' + $ShortName + ')"?,"?(?<lname>[^,"]*)"?,(?<fdate>\d*),(?<tdate>\d*),"?(?<pname>[^,"]*)"?,'
            $UntisContent = $UntisContent -Replace $RegExPattern, '${prefix},"${sname}","${lname}",${fdate},${tdate},"${pname}",A'

            Set-Content -Path $File -Value $UntisContent
        }
        catch
        {
            $ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
        }
    }
}

<#
    .Synopsis
    Exports data from an Untis file (.gpn or .untis) or from an Untis database (Untis MultiUser)
 
    .Description
    This cmdlet exports data from an Untis file (.gpn or .untis) or from an Untis database (Untis MultiUser).
    Supported are XML export and GPU export. You can export single GPU files (e.g. GPU001.TXT) or all GPU files at once.
 
    .Parameter File
    The file name of an Untis file (.gpn or .untis). This parameter is mandatory for file access
 
    .Parameter SchoolNo
    The school no for accessing the Untis database. This parameter is mandatory for database access
 
    .Parameter SchoolYear
    The school year for accessing the Untis database. This parameter is mandatory for database access
 
    .Parameter Version
    The schedule version for accessing the Untis database. This parameter is optional. By default its version 1.
 
    .Parameter User
    The user name for accessing the Untis database. This parameter is mandatory for database access
 
    .Parameter Password
    The password as securestring for accessing the Untis database. This parameter is mandatory for database access.
 
    .Parameter Date
    A date within a defined Untis term. This paremeter is optional and only needed if the Untis file (.gpn or .untis) or the
    Untis database defines more than one term.
 
    .Parameter BackupFile
    The file name for the Untis backup file (.gpn or .untis). This paremeter is optional. By default a generated file name
    is used.
 
    .Parameter OutputFolder
    The folder in which all export files are created. This paremeter is optional. By default the current folder is used.
 
    .Parameter OutputType
    The type of export data. Possible values are GPU, GPU001, ..., GPU021 and XML. Since this parameter is definend as array
    you can freely combine the values.
 
    .Example
    Start-UntisExport -File example.gpn -OutputFolder c:\output -OutputType GPU
    .Example
    Start-UntisExport -File example.gpn -OutputFolder c:\output -OutputType GPU001
    .Example
    Start-UntisExport -File example.gpn -OutputFolder c:\output -OutputType XML
    .Example
    Start-UntisExport -File example.gpn -OutputFolder c:\output -OutputType GPU001,GPU002
    .Example
    Start-UntisExport -File example.gpn -Date 2009-07-11 -OutputFolder c:\output -OutputType GPU,XML
    .Example
    Start-UntisExport -SchoolNo 40042 -SchoolYear 2020-2021 -User Administrator -Password (ConvertTo-SecureString qwertz -AsPlainText -Force) -OutputFolder c:\output -OutputType GPU
    .Example
    Start-UntisExport -SchoolNo 40042 -SchoolYear 2020-2021 -User Administrator -Password (ConvertTo-SecureString qwertz -AsPlainText -Force) -Date 2009-07-11 -OutputFolder c:\output -OutputType GPU001,GPU002
#>

function Start-UntisExport {
    param(
        [Parameter(Mandatory=$true, ParameterSetName='File')]
        [ValidateNotNullOrEmpty()]
        [string]
        $File,
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [string]
        $SchoolNo,
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [string]
        $SchoolYear,
        [Parameter(ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [int]
        $Version = 1,
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [string]
        $User,
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [securestring]
        $Password,
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [DateTime]
        $Date = 0,
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]
        $BackupFile,
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]
        $OutputFolder,
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [OutputType[]]
        $OutputType
    )
    process
    {
        try
        {
            $Stopwatch =  [system.diagnostics.stopwatch]::StartNew()

            Write-Host ([string]::Format($stringTable.StartExport, [Environment]::NewLine, [Environment]::NewLine))

            if (-not $BackupFile)
            {
                $BackupFile = Join-Path -Path $OutputFolder -ChildPath "untis.backup"
            }

            if ($File)
            {
                Copy-Item $File -Destination $BackupFile
            }
            else
            {
                RunUntisBackup -SchoolNo $SchoolNo -SchoolYear $SchoolYear -Version $Version -BackupFile $BackupFile -User $User -Password $Password
            }

            if ($OutputType.Contains([OutputType]::GPU))
            {
                RunUntisGpuExport -File $BackupFile -Date $Date -OutputFolder $OutputFolder
            }
            else
            {
                $gpuTable = @(
                    @([OutputType]::GPU001, "001"),
                    @([OutputType]::GPU002, "002"),
                    @([OutputType]::GPU003, "003"),
                    @([OutputType]::GPU004, "004"),
                    @([OutputType]::GPU005, "005"),
                    @([OutputType]::GPU006, "006"),
                    @([OutputType]::GPU007, "007"),
                    @([OutputType]::GPU008, "008"),
                    @([OutputType]::GPU009, "009"),
                    @([OutputType]::GPU010, "010"),
                    @([OutputType]::GPU011, "011"),
                    @([OutputType]::GPU012, "012"),
                    @([OutputType]::GPU013, "013"),
                    @([OutputType]::GPU014, "014"),
                    @([OutputType]::GPU015, "015"),
                    @([OutputType]::GPU016, "016"),
                    @([OutputType]::GPU017, "017"),
                    @([OutputType]::GPU018, "018"),
                    @([OutputType]::GPU019, "019"),
                    @([OutputType]::GPU020, "020"),
                    @([OutputType]::GPU021, "021"),
                    @([OutputType]::GPU022, "022"),
                    @([OutputType]::GPU023, "023")
                )
                foreach($gpu in $gpuTable)
                {
                    if ($OutputType.Contains($gpu[0]))
                    {
                        RunUntisSingleGpuExport -File $BackupFile -Date $Date -OutputFolder $OutputFolder -OutputType $gpu[1]
                    }
                }
            }
            if ($OutputType.Contains([OutputType]::XML))
            {
                $XmlFile = Join-Path -Path $OutputFolder -ChildPath "untis.xml"
                RunUntisXmlExport -File $BackupFile -Date $Date -XmlFile $XmlFile
            }

            $Stopwatch.Stop()

            Write-Host ([string]::Format($stringTable.TimeElapsed, [Environment]::NewLine, $Stopwatch.Elapsed))
        }
        catch
        {
            $ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
        }
    }
}

<#
    .Synopsis
    Creates an Untis backup file (.gpn or .untis) from an Untis database (Untis MultiUser)
 
    .Description
    This cmdlet exports all data from an Untis database (Untis MultiUser) to a newly created Untis file (.gpn or .untis).
 
    .Parameter SchoolNo
    The school no for accessing the Untis database. This parameter is mandatory.
 
    .Parameter SchoolYear
    The school year for accessing the Untis database. This parameter is mandatory.
 
    .Parameter Version
    The schedule version for accessing the Untis database. This parameter is optional. By default its version 1.
 
    .Parameter User
    The user name for accessing the Untis database. This parameter is mandatory.
 
    .Parameter Password
    The password as securestring for accessing the Untis database. This parameter is mandatory.
 
    .Parameter BackupFile
    The file name for the Untis backup file (.gpn or .untis). This paremeter is mandatory.
 
    .Example
    Start-UntisBackup -SchoolNo 40042 -SchoolYear 2020-2021 -User Administrator -Password (ConvertTo-SecureString qwertz -AsPlainText -Force) -BackupFile c:\output\backup.gpn
    .Example
    Start-UntisBackup -SchoolNo 40042 -SchoolYear 2021-2022 -User Administrator -Password (ConvertTo-SecureString qwertz -AsPlainText -Force) -BackupFile c:\output\backup.untis
#>

function Start-UntisBackup{
    param(
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [string]
        $SchoolNo,
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [string]
        $SchoolYear,
        [Parameter(ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [int]
        $Version = 1,
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [string]
        $User,
        [Parameter(Mandatory=$true, ParameterSetName='Database')]
        [ValidateNotNullOrEmpty()]
        [securestring]
        $Password,
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]
        $BackupFile
    )
    process
    {
        try
        {
            $Stopwatch =  [system.diagnostics.stopwatch]::StartNew()

            Write-Host ([string]::Format($stringTable.StartBackup, [Environment]::NewLine, [Environment]::NewLine))

            RunUntisBackup -SchoolNo $SchoolNo -SchoolYear $SchoolYear -Version $Version -User $User -Password $Password -BackupFile $BackupFile

            $Stopwatch.Stop()

            Write-Host ([string]::Format($stringTable.TimeElapsed, [Environment]::NewLine, $Stopwatch.Elapsed))
        }
        catch
        {
            $ErrorMessage = $_.Exception.Message
            Write-Host $ErrorMessage -ForegroundColor Red
        }
    }
}

function RunUntisGpuExport{
    param(
        [string]
        $File,
        [DateTime]
        $Date,
        [string]
        $OutputFolder
    )
    process
    {
        $ConsolePath = GetUntisConsolePath

        if (($ConsolePath) -and (Test-Path -Path $ConsolePath -PathType Leaf))
        {
            $UntisGpuFilePattern = Join-Path -Path $OutputFolder -ChildPath "GPU???.txt"

            Remove-Item $UntisGpuFilePattern

            if ($Date -gt 0)
            {
                Start-Process -FilePath $ConsolePath -ArgumentList "$($File)","/exp*=""$($OutputFolder)""","/date=$($Date.ToString("yyyyMMdd"))" -Wait
            }
            else
            {
                Start-Process -FilePath $ConsolePath -ArgumentList "$($File)","/exp*=""$($OutputFolder)""" -Wait
            }

            $UntisGpuFileCount = (Get-ChildItem -Path (Join-Path -Path $OutputFolder -ChildPath "*") -Include "GPU???.txt" | Measure-Object).Count

            if ($UntisGpuFileCount -gt 0)
            {
                Write-Host ([string]::Format($stringTable.GpuFilesExported, $UntisGpuFileCount, $OutputFolder))
            }
            else
            {
                $ErrorMessage = ([string]::Format($stringTable.ErrorGpuFilesNotCreated, $OutputFolder))
                throw $ErrorMessage
            }
        }
        else
        {
            $ErrorMessage = ([string]::Format($stringTable.ErrorUntisConsoleNotFound, $ConsolePath))
            throw $ErrorMessage
        }
    }
}

function RunUntisSingleGpuExport{
    param(
        [string]
        $File,
        [DateTime]
        $Date,
        [string]
        $OutputFolder,
        [string]
        $OutputType
    )
    process
    {
        $ConsolePath = GetUntisConsolePath

        if (($ConsolePath) -and (Test-Path -Path $ConsolePath -PathType Leaf))
        {
            $UntisGpuFile = Join-Path -Path $OutputFolder -ChildPath "GPU$($OutputType).TXT"

            if (Test-Path -Path $UntisGpuFile -PathType Leaf)
            {
                Remove-Item $UntisGpuFile
            }

            if ($Date -gt 0)
            {
                Start-Process -FilePath $ConsolePath -ArgumentList "$($File)","/exp$($OutputType)=""$($UntisGpuFile)""","/date=$($Date.ToString("yyyyMMdd"))" -Wait
            }
            else
            {
                Start-Process -FilePath $ConsolePath -ArgumentList "$($File)","/exp$($OutputType)=""$($UntisGpuFile)""" -Wait
            }

            if (Test-Path -Path $UntisGpuFile -PathType Leaf)
            {
                Write-Host ([string]::Format($stringTable.GpuFileExported, $UntisGpuFile))
            }
            else
            {
                $ErrorMessage = ([string]::Format($stringTable.ErrorGpuFileNotCreated, $UntisGpuFile))
                throw $ErrorMessage
            }
        }
        else
        {
            $ErrorMessage = ([string]::Format($stringTable.ErrorUntisConsoleNotFound, $ConsolePath))
            throw $ErrorMessage
        }
    }
}

function RunUntisXmlExport{
    param(
        [string]
        $File,
        [DateTime]
        $Date,
        [string]
        $XmlFile
    )
    process
    {
        $ConsolePath = GetUntisConsolePath

        if (($ConsolePath) -and (Test-Path -Path $ConsolePath -PathType Leaf))
        {
            if (Test-Path -Path $XmlFile -PathType Leaf)
            {
                Remove-Item $XmlFile
            }

            if ($Date -gt 0)
            {
                Start-Process -FilePath $ConsolePath -ArgumentList "$($File)","/xml=""$($XmlFile)""","/date=$($Date.ToString("yyyyMMdd"))" -Wait
            }
            else
            {
                Start-Process -FilePath $ConsolePath -ArgumentList "$($File)","/xml=""$($XmlFile)""" -Wait
            }

            if (Test-Path -Path $XmlFile -PathType Leaf)
            {
                Write-Host ([string]::Format($stringTable.XmlFileExported, $XmlFile))
            }
            else
            {
                $ErrorMessage = ([string]::Format($stringTable.ErrorXmlFileNotCreated, $XmlFile))
                throw $ErrorMessage
            }
        }
        else
        {
            $ErrorMessage = ([string]::Format($stringTable.ErrorUntisConsoleNotFound, $ConsolePath))
            throw $ErrorMessage
        }
    }
}

function RunUntisBackup{
    param(
        [string]
        $SchoolNo,
        [string]
        $SchoolYear,
        [int]
        $Version,
        [string]
        $User,
        [securestring]
        $Password,
        [string]
        $BackupFile
    )
    process
    {
        $ConsolePath = GetUntisConsolePath

        if (($ConsolePath) -and (Test-Path -Path $ConsolePath -PathType Leaf))
        {
            if (Test-Path -Path $BackupFile -PathType Leaf)
            {
                Remove-Item $BackupFile
            }

            if (IsPS7OrHigher)
            {
                $Pswd = ConvertFrom-SecureString -SecureString $Password -AsPlainText
            }
            else {
                $Pswd = ConvertFrom-SecureStringToPlainText -SecureString $Password
            }

            Start-Process -FilePath $ConsolePath -ArgumentList "DB~$($SchoolNo)~$($SchoolYear)~$($Version)","/backup=$($BackupFile)","/user=$($User)","/pw=$($Pswd)" -Wait

            if (Test-Path -Path $BackupFile -PathType Leaf)
            {
                Write-Host ([string]::Format($stringTable.BackupFileCreated, $BackupFile))
            }
            else
            {
                $ErrorMessage = ([string]::Format($stringTable.ErrorBackupFileNotCreated, $BackupFile))
                throw $ErrorMessage
            }
        }
        else
        {
            $ErrorMessage = ([string]::Format($stringTable.ErrorUntisConsoleNotFound, $ConsolePath))
            throw $ErrorMessage
        }
    }
}

function GetUntisConsolePath {
    process
    {
        $Versions = @("2024","2023","2022","2021","2020","2019","2018","2017")

        for ($i=0; $i -lt $Versions.Count; $i++)
        {
            $RegKey64 = "HKLM:\SOFTWARE\WOW6432Node\Gruber&Petters\Untis $($Versions[$i])"
            $RegKey32 = "HKLM:\SOFTWARE\Gruber&Petters\Untis $($Versions[$i])"

            if ([Environment]::Is64BitProcess)
            {
                if (Test-Path -Path $RegKey64)
                {
                    $RegKey = Get-ItemProperty -Path $RegKey64 -Name Install_Dir
                    return Join-Path -Path $RegKey.Install_Dir -ChildPath "Untis.exe"
                }
            }
            else
            {
                if (Test-Path -Path $RegKey32)
                {
                    $RegKey = Get-ItemProperty -Path $RegKey32 -Name Install_Dir
                    return Join-Path -Path $RegKey.Install_Dir -ChildPath "Untis.exe"
                }
            }
        }
        return "Untis.exe"
    }
}

function FormatDate {
    param(
        [string]
        $DateNumber
    )
    process
    {
        return [datetime]::parseexact($DateNumber, 'yyyyMMdd', $null).ToString('dd-MM-yyyy')
    }
}

function FormatStatus {
    param(
        [string]
        $Status
    )
    process
    {
        return $Status.Contains("A")
    }
}

# List of supported export formats
Enum OutputType {
    GPU
    GPU001
    GPU002
    GPU003
    GPU004
    GPU005
    GPU006
    GPU007
    GPU008
    GPU009
    GPU010
    GPU011
    GPU012
    GPU013
    GPU014
    GPU015
    GPU016
    GPU017
    GPU018
    GPU019
    GPU020
    GPU021
    GPU022
    GPU023
    XML
}

# Fallback for missing ConvertFrom-SecureString -AsPlainText -Force in PowerShell 5.1
function ConvertFrom-SecureStringToPlainText{
    param(
        [SecureString]
        $SecureString
    )
    process
    {
        $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
        return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
    }
}

# Helper for detecting PowerShell 7+ Version
function IsPS7OrHigher{
    process
    {
        return ($PSVersionTable.PSVersion.Major -ge 7)
    }
}

Export-ModuleMember -Function Get-UntisTerms
Export-ModuleMember -Function Set-UntisTermAsActive
Export-ModuleMember -Function Start-UntisBackup
Export-ModuleMember -Function Start-UntisExport

# SIG # Begin signature block
# MIIoHwYJKoZIhvcNAQcCoIIoEDCCKAwCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBf9GaI4l4y/+qt
# It+3g0k4B5SnxS0SmmnuJKmaCQZJUaCCDYwwggawMIIEmKADAgECAhAIrUCyYNKc
# TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z
# NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
# UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
# ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0
# JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr
# Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF
# LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F
# LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh
# 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ
# wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay
# g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI
# YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp
# QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro
# OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB
# WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+
# YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P
# AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk
# BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC
# hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v
# dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED
# MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql
# +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF
# UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h
# mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw
# YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld
# AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw
# 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP
# LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE
# QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn
# KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji
# WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq
# yK+p/pQd52MbOoZWeE4wggbUMIIEvKADAgECAhAOFWi5aT2uxDD2A7OhH0RwMA0G
# CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
# UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjMwNzIwMDAwMDAwWhcNMjQwNzE5
# MjM1OTU5WjBcMQswCQYDVQQGEwJERTEPMA0GA1UEBxMGQmVybGluMR0wGwYDVQQK
# DBRTVMOcQkVSIFNZU1RFTVMgR21iSDEdMBsGA1UEAwwUU1TDnEJFUiBTWVNURU1T
# IEdtYkgwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC5BKNCumX7lqRP
# dU9R74n+M8b8Mai7Y2jmEp8yZGOV8a+vt5MmZSD57kY3x39vpQIjw5KVoC1oOYvR
# CyNhnyN28NEb66gJTYt8GXQIBmiYkugVl2NZtsH64PDnR+83feSjCZd/qNyVoSU9
# a7fZTmHAuA1wzY13PjX572UYOi99ikutguy0Ynw1KmkwIjup0EMRu7MQkBJDRYfd
# 2O/R0HPqk0aZcX5h7RDrAHRHZ35c4Hj5RlVH/xXDxFL15ZRXPCyQ31x6Ttk/ltiv
# SRbAd9YUxvjZ1B3tnpVbJk4CWg4Vy1nRlWD7dDX7ihxWdQzuWS22DLyD2PNpXvYm
# vz+dhwn6UMU2URVDRVp6CEfeRPuvXkuXXl+rBGRKvGrgZCU6Njl3QS4I73GaMjmQ
# 8LX7ria4BmdFHDWwrW75Yu3HP7vJOXFuAE3MMGanIAhqk70k1w6UPH+rp0TRqBFd
# GDAohiJ/0qKZCE7oGlOp2gOJWPwB3R9KdngOAQV1veN/9FxnAAkCAwEAAaOCAgMw
# ggH/MB8GA1UdIwQYMBaAFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB0GA1UdDgQWBBSD
# SO8reKZAvZoDnEGXlDFEt644XTAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYI
# KwYBBQUHAwMwgbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0cDovL2NybDMuZGlnaWNl
# cnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0
# MjAyMUNBMS5jcmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3Js
# MD4GA1UdIAQ3MDUwMwYGZ4EMAQQBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cu
# ZGlnaWNlcnQuY29tL0NQUzCBlAYIKwYBBQUHAQEEgYcwgYQwJAYIKwYBBQUHMAGG
# GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBcBggrBgEFBQcwAoZQaHR0cDovL2Nh
# Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdS
# U0E0MDk2U0hBMzg0MjAyMUNBMS5jcnQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsF
# AAOCAgEAyKng0r797AQ2JQIVmlISXjsuOJxvvMQhB+Ik8e4MkM8Ui5mLs122sDmI
# gAJba5/Tj9DlK0f0wQjdUFt8jYT5k/BTTKz0z0/dzUaxPdRjKRHKgJkENVIyvAuB
# ybkl07fpUfm2pJaX0bcwxMMydLjgF8++UchEgVAp/bt6cqPIK5X5Vfk3TkHk+qqD
# Tlazh8OoQ5Qd2tHv/SzbZgWvQH4hzeH99ruN8c97tBA/pDIB5yDDbc6sdMavAslw
# ZtbsnsK2CAKmRiNWFmqqAUWFhVEHUkY7+ksqA+bpEu3HkhbdtO7mKyemui/F5YQH
# YdM1rcf4NvKDipDG5qCeZTRQS5bbEfbK+IkBCgLzTyWlSRneql5QbxidQcTWliRV
# cze9sGdrNfCzn8TyBWcxRd//Tb6TvLhriuUx6An9ANaqhfVcWXWz/n4+Y2xUetXb
# HviKaVhCxZq3Ry7sVEjxaCrmOXSGKNqEJOtp/wWJJ6SdrZm8vO0ohSofNAr7VnRg
# I60bmR+MXScETOaGfllA5b0MOVzSQ6KGWfXv0SgCNE8K00KdvJiwwXXJ5rugJtCA
# WJoUHAgmmRqj9Hp/kpS88PqAn556AxdZHVgV3qLF5JL+vI40hwypkbw8rDtctoVq
# h3qEQt/VloE7np65zEpq1Wv1l4OaAnAlXU5HNMzYCaZ76gg9KU8xghnpMIIZ5QIB
# ATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8G
# A1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBT
# SEEzODQgMjAyMSBDQTECEA4VaLlpPa7EMPYDs6EfRHAwDQYJYIZIAWUDBAIBBQCg
# fDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAc
# BgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgfCxC
# Acv7qeVqESn9Q6ShzUYOA1IkYTsI/bofrCk0IjowDQYJKoZIhvcNAQEBBQAEggGA
# ibpnMbwCQVm6t1l5HuokXHw7HH0i5St6JegJBP/wjw481rWynNNGxYkskfM7xdMW
# l176ePj+6sWycdc+BenYHRXDuAVz7vFOnamNbEo7rv8RhoHvs9BGk1ejW7K9Yy9i
# rVKcg6GDy3NYxiiLfvdnl9u6xNMqXCT0A9kAj+ajF0GQ4I9CW+R+v4fbLtnqGVNS
# s5/04Ri2Yw4iOLGHyZZOV/g/q3dMDCChaucHn4NjLjzvraG77fiPdpYWyA/8Y1bD
# hEqf0KS5AIyLjvbjzj0csPALN96o+lusr6sjPgJ5IGAqnaMxRifdOteA6FmlFR1D
# wZSrmlvMsynqIei7f+gKw2h9lliPCm3sr9zUCVefaUJFNiOKVAWhaMoQYtrqFAG1
# PsIULqp98WsbO9LKUM4T0HqvjV0zCcYB/hO3DdH4OVgKVYNG+KOgYYqYCePFgiWr
# yhzB6hmJoxpLQr1dpBAa4D2vmHWlJKZ5AWAyaQI9U4inmK3QxmW6zRaeCRvOXNkk
# oYIXPzCCFzsGCisGAQQBgjcDAwExghcrMIIXJwYJKoZIhvcNAQcCoIIXGDCCFxQC
# AQMxDzANBglghkgBZQMEAgEFADB3BgsqhkiG9w0BCRABBKBoBGYwZAIBAQYJYIZI
# AYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIALl2csObJnRsDZlI9P5ZdvDddmBuC7y
# u0aEXKMDYbUqAhAeNYoLvDBT5mtAhPiJr2u6GA8yMDIzMDkxOTEyMzc1OFqgghMJ
# MIIGwjCCBKqgAwIBAgIQBUSv85SdCDmmv9s/X+VhFjANBgkqhkiG9w0BAQsFADBj
# MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMT
# MkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5n
# IENBMB4XDTIzMDcxNDAwMDAwMFoXDTM0MTAxMzIzNTk1OVowSDELMAkGA1UEBhMC
# VVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSAwHgYDVQQDExdEaWdpQ2VydCBU
# aW1lc3RhbXAgMjAyMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKNT
# RYcdg45brD5UsyPgz5/X5dLnXaEOCdwvSKOXejsqnGfcYhVYwamTEafNqrJq3RAp
# ih5iY2nTWJw1cb86l+uUUI8cIOrHmjsvlmbjaedp/lvD1isgHMGXlLSlUIHyz8sH
# pjBoyoNC2vx/CSSUpIIa2mq62DvKXd4ZGIX7ReoNYWyd/nFexAaaPPDFLnkPG2ZS
# 48jWPl/aQ9OE9dDH9kgtXkV1lnX+3RChG4PBuOZSlbVH13gpOWvgeFmX40QrStWV
# zu8IF+qCZE3/I+PKhu60pCFkcOvV5aDaY7Mu6QXuqvYk9R28mxyyt1/f8O52fTGZ
# ZUdVnUokL6wrl76f5P17cz4y7lI0+9S769SgLDSb495uZBkHNwGRDxy1Uc2qTGaD
# iGhiu7xBG3gZbeTZD+BYQfvYsSzhUa+0rRUGFOpiCBPTaR58ZE2dD9/O0V6MqqtQ
# FcmzyrzXxDtoRKOlO0L9c33u3Qr/eTQQfqZcClhMAD6FaXXHg2TWdc2PEnZWpST6
# 18RrIbroHzSYLzrqawGw9/sqhux7UjipmAmhcbJsca8+uG+W1eEQE/5hRwqM/vC2
# x9XH3mwk8L9CgsqgcT2ckpMEtGlwJw1Pt7U20clfCKRwo+wK8REuZODLIivK8SgT
# IUlRfgZm0zu++uuRONhRB8qUt+JQofM604qDy0B7AgMBAAGjggGLMIIBhzAOBgNV
# HQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
# CDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAU
# uhbZbU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYEFKW27xPn783QZKHVVqllMaPe
# 1eNJMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmww
# gZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5j
# cnQwDQYJKoZIhvcNAQELBQADggIBAIEa1t6gqbWYF7xwjU+KPGic2CX/yyzkzepd
# IpLsjCICqbjPgKjZ5+PF7SaCinEvGN1Ott5s1+FgnCvt7T1IjrhrunxdvcJhN2hJ
# d6PrkKoS1yeF844ektrCQDifXcigLiV4JZ0qBXqEKZi2V3mP2yZWK7Dzp703DNiY
# dk9WuVLCtp04qYHnbUFcjGnRuSvExnvPnPp44pMadqJpddNQ5EQSviANnqlE0Pjl
# SXcIWiHFtM+YlRpUurm8wWkZus8W8oM3NG6wQSbd3lqXTzON1I13fXVFoaVYJmoD
# Rd7ZULVQjK9WvUzF4UbFKNOt50MAcN7MmJ4ZiQPq1JE3701S88lgIcRWR+3aEUuM
# MsOI5ljitts++V+wQtaP4xeR0arAVeOGv6wnLEHQmjNKqDbUuXKWfpd5OEhfysLc
# PTLfddY2Z1qJ+Panx+VPNTwAvb6cKmx5AdzaROY63jg7B145WPR8czFVoIARyxQM
# fq68/qTreWWqaNYiyjvrmoI1VygWy2nyMpqy0tg6uLFGhmu6F/3Ed2wVbK6rr3M6
# 6ElGt9V/zLY4wNjsHPW2obhDLN9OTH0eaHDAdwrUAuBcYLso/zjlUlrWrBciI070
# 7NMX+1Br/wd3H3GXREHJuEbTbDJ8WC9nR2XlG3O2mflrLAZG70Ee8PBf4NvZrZCA
# RK+AEEGKMIIGrjCCBJagAwIBAgIQBzY3tyRUfNhHrP0oZipeWzANBgkqhkiG9w0B
# AQsFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVk
# IFJvb3QgRzQwHhcNMjIwMzIzMDAwMDAwWhcNMzcwMzIyMjM1OTU5WjBjMQswCQYD
# VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lD
# ZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMIIC
# IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxoY1BkmzwT1ySVFVxyUDxPKR
# N6mXUaHW0oPRnkyibaCwzIP5WvYRoUQVQl+kiPNo+n3znIkLf50fng8zH1ATCyZz
# lm34V6gCff1DtITaEfFzsbPuK4CEiiIY3+vaPcQXf6sZKz5C3GeO6lE98NZW1Oco
# LevTsbV15x8GZY2UKdPZ7Gnf2ZCHRgB720RBidx8ald68Dd5n12sy+iEZLRS8nZH
# 92GDGd1ftFQLIWhuNyG7QKxfst5Kfc71ORJn7w6lY2zkpsUdzTYNXNXmG6jBZHRA
# p8ByxbpOH7G1WE15/tePc5OsLDnipUjW8LAxE6lXKZYnLvWHpo9OdhVVJnCYJn+g
# GkcgQ+NDY4B7dW4nJZCYOjgRs/b2nuY7W+yB3iIU2YIqx5K/oN7jPqJz+ucfWmyU
# 8lKVEStYdEAoq3NDzt9KoRxrOMUp88qqlnNCaJ+2RrOdOqPVA+C/8KI8ykLcGEh/
# FDTP0kyr75s9/g64ZCr6dSgkQe1CvwWcZklSUPRR8zZJTYsg0ixXNXkrqPNFYLwj
# jVj33GHek/45wPmyMKVM1+mYSlg+0wOI/rOP015LdhJRk8mMDDtbiiKowSYI+RQQ
# EgN9XyO7ZONj4KbhPvbCdLI/Hgl27KtdRnXiYKNYCQEoAA6EVO7O6V3IXjASvUae
# tdN2udIOa5kM0jO0zbECAwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAw
# HQYDVR0OBBYEFLoW2W1NhS9zKXaaL3WMaiCPnshvMB8GA1UdIwQYMBaAFOzX44LS
# cV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEF
# BQcDCDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp
# Z2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQu
# Y29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYy
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5j
# cmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEB
# CwUAA4ICAQB9WY7Ak7ZvmKlEIgF+ZtbYIULhsBguEE0TzzBTzr8Y+8dQXeJLKftw
# ig2qKWn8acHPHQfpPmDI2AvlXFvXbYf6hCAlNDFnzbYSlm/EUExiHQwIgqgWvalW
# zxVzjQEiJc6VaT9Hd/tydBTX/6tPiix6q4XNQ1/tYLaqT5Fmniye4Iqs5f2MvGQm
# h2ySvZ180HAKfO+ovHVPulr3qRCyXen/KFSJ8NWKcXZl2szwcqMj+sAngkSumScb
# qyQeJsG33irr9p6xeZmBo1aGqwpFyd/EjaDnmPv7pp1yr8THwcFqcdnGE4AJxLaf
# zYeHJLtPo0m5d2aR8XKc6UsCUqc3fpNTrDsdCEkPlM05et3/JWOZJyw9P2un8WbD
# Qc1PtkCbISFA0LcTJM3cHXg65J6t5TRxktcma+Q4c6umAU+9Pzt4rUyt+8SVe+0K
# XzM5h0F4ejjpnOHdI/0dKNPH+ejxmF/7K9h+8kaddSweJywm228Vex4Ziza4k9Tm
# 8heZWcpw8De/mADfIBZPJ/tgZxahZrrdVcA6KYawmKAr7ZVBtzrVFZgxtGIJDwq9
# gdkT/r+k0fNX2bwE+oLeMt8EifAAzV3C+dAjfwAL5HYCJtnwZXZCpimHCUcr5n8a
# pIUP/JiW9lVUKx+A+sDyDivl1vupL0QVSucTDh3bNzgaoSv27dZ8/DCCBY0wggR1
# oAMCAQICEA6bGI750C3n79tQ4ghAGFowDQYJKoZIhvcNAQEMBQAwZTELMAkGA1UE
# BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj
# ZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4X
# DTIyMDgwMTAwMDAwMFoXDTMxMTEwOTIzNTk1OVowYjELMAkGA1UEBhMCVVMxFTAT
# BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEh
# MB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MIICIjANBgkqhkiG9w0B
# AQEFAAOCAg8AMIICCgKCAgEAv+aQc2jeu+RdSjwwIjBpM+zCpyUuySE98orYWcLh
# Kac9WKt2ms2uexuEDcQwH/MbpDgW61bGl20dq7J58soR0uRf1gU8Ug9SH8aeFaV+
# vp+pVxZZVXKvaJNwwrK6dZlqczKU0RBEEC7fgvMHhOZ0O21x4i0MG+4g1ckgHWMp
# Lc7sXk7Ik/ghYZs06wXGXuxbGrzryc/NrDRAX7F6Zu53yEioZldXn1RYjgwrt0+n
# MNlW7sp7XeOtyU9e5TXnMcvak17cjo+A2raRmECQecN4x7axxLVqGDgDEI3Y1Dek
# LgV9iPWCPhCRcKtVgkEy19sEcypukQF8IUzUvK4bA3VdeGbZOjFEmjNAvwjXWkmk
# wuapoGfdpCe8oU85tRFYF/ckXEaPZPfBaYh2mHY9WV1CdoeJl2l6SPDgohIbZpp0
# yt5LHucOY67m1O+SkjqePdwA5EUlibaaRBkrfsCUtNJhbesz2cXfSwQAzH0clcOP
# 9yGyshG3u3/y1YxwLEFgqrFjGESVGnZifvaAsPvoZKYz0YkH4b235kOkGLimdwHh
# D5QMIR2yVCkliWzlDlJRR3S+Jqy2QXXeeqxfjT/JvNNBERJb5RBQ6zHFynIWIgnf
# fEx1P2PsIV/EIFFrb7GrhotPwtZFX50g/KEexcCPorF+CiaZ9eRpL5gdLfXZqbId
# 5RsCAwEAAaOCATowggE2MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOzX44LS
# cV1kTN8uZz/nupiuHA9PMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgP
# MA4GA1UdDwEB/wQEAwIBhjB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0
# dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2Vy
# dHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDBFBgNV
# HR8EPjA8MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRB
# c3N1cmVkSURSb290Q0EuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0B
# AQwFAAOCAQEAcKC/Q1xV5zhfoKN0Gz22Ftf3v1cHvZqsoYcs7IVeqRq7IviHGmlU
# Iu2kiHdtvRoU9BNKei8ttzjv9P+Aufih9/Jy3iS8UgPITtAq3votVs/59PesMHqa
# i7Je1M/RQ0SbQyHrlnKhSLSZy51PpwYDE3cnRNTnf+hZqPC/Lwum6fI0POz3A8eH
# qNJMQBk1RmppVLC4oVaO7KTVPeix3P0c2PR3WlxUjG/voVA9/HYJaISfb8rbII01
# YBwCA8sgsKxYoA5AY8WYIsGyWfVVa88nq2x2zm8jLfR+cWojayL/ErhULSd+2DrZ
# 8LaHlv1b0VysGMNNn3O3AamfV6peKOK5lDGCA3YwggNyAgEBMHcwYzELMAkGA1UE
# BhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2Vy
# dCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQQIQBUSv
# 85SdCDmmv9s/X+VhFjANBglghkgBZQMEAgEFAKCB0TAaBgkqhkiG9w0BCQMxDQYL
# KoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIzMDkxOTEyMzc1OFowKwYLKoZI
# hvcNAQkQAgwxHDAaMBgwFgQUZvArMsLCyQ+CXc6qisnGTxmcz0AwLwYJKoZIhvcN
# AQkEMSIEIAZS6CEjE5hbq/IUCzzCl+yALlpoPHwVMYREF0qdVfHJMDcGCyqGSIb3
# DQEJEAIvMSgwJjAkMCIEINL25G3tdCLM0dRAV2hBNm+CitpVmq4zFq9NGprUDHgo
# MA0GCSqGSIb3DQEBAQUABIICAFUI/YJXajjU1B5CkbyHnoeBeTn5ptlFvrc8Yst5
# kXlZyFjTtRs+YOba2dychIRJrGkU+URxrIyQ8qhZjwQCOcUAGSCq5ZgW7FDI4uKg
# BBsTyc4ql9PslX2jOGDtzsN9gQ9cw4WBRuPFoZ541pan6B07ya5MeN7jCNWAZzyA
# tEcLNa8m6xEqnQeWMmfNbBR9A9tNdY5wI0ASLgGK2Crf75LKTxbVB+n+eTdzxDiw
# MD+bNq5L2qbO81P4D0EN+EycoQqZvSPnlYkEYSZgEqB9mHaGGgNKlsEXLAXLLF8s
# 5Ou5oR68A/AeRfynKAFY9006iQhapfmp1O7OyN0AnxM+l9oNxoMZu4lLRXeZcUot
# PqiPWz0PvnmGllCc0TDWaciug8kEm6UIN43uPyWE/BuWN2ZIqsK2nIkNlnZPdwNP
# 8opRbXouKX9CVbGbQCT45ZiiJf17cDanAPjTNV5pH9/0ljN8QBpN1rug9N4ABoJ4
# x5M796TXdGXNaO5erh8dif6ZrFCGR7J+a/5vzlermgAlC/67aTPYQzqcy/iUFPVH
# 7QxpOx++5CpLxizKidNBibYHipI8NbM8o/YcSZQnahQHVE/mPzOEd+Kw9N0f1vLR
# tQ6lRCdEIzxOqvDA7wicLKTBB+p+jZyzWCAhWS/fARlLpsWKkaHUb+m9bGw7PTTh
# tm0G
# SIG # End signature block