classes/PSCronJobObject.ps1

using namespace System.IO
using namespace System.Collections
using namespace System.Management.Automation
using namespace Microsoft.PowerShell

class PSCronJobObject {

    [ValidatePattern('^(?:\S+\s?){5}(?<!\s)$')][string]$Schedule
    [string]$Name
    [string]$Description
    [string]$Source
    hidden [System.IO.FileInfo]$__FilePath
    hidden [ExecutionPolicy]$__ExecutionPolicy = ( Get-ExecutionPolicy )
    [scriptblock]$Definition
    [System.IO.DirectoryInfo]$WorkingDirectory = ( [Environment]::SystemDirectory )
    [PSCronDateTime]$ReferenceDate = ( Get-PSCronDate )
    [PSCronDateTime]$StartDate = ( Get-PSCronDate -Resolution Millisecond )
    [PSCronDateTIme]$EndDate
    [nullable[timespan]]$RunTime
    [PSInvocationState]$State
    hidden [ArrayList]$__Log = @()
    [FileInfo]$LogPath
    hidden [bool]$__Append = $false
    [int]$TimeOut = 60
    [PSDataCollection[pscustomobject]]$Output
    [PSDataCollection[ErrorRecord]]$Errors
    [Exception]$TerminatingError
    [bool]$HadErrors
    [ActionPreference]$JobInformationPreference = 'Continue'
    [ActionPreference]$JobDebugPreference = 'SilentlyContinue'
    [ActionPreference]$JobWarningPreference = 'Continue'
    [ActionPreference]$JobErrorActionPreference = 'Stop'

    PSCronJobObject( [hashtable]$Hashtable ) {

        $this.__Init( $Hashtable )

    }

    hidden [void] __Init( [hashtable]$Hashtable ) {

        # get all object properties
        [string[]]$MyProperties = $this |
            Get-Member -MemberType Property -Force |
            Select-Object -ExpandProperty Name

        # set initial property values and property readers for hidden
        # properties
        $MyProperties | ForEach-Object {

            $KeyName = $_ -replace '^__'
            
            # initialize property values
            if ( $KeyName -in $Hashtable.Keys ) {

                $this.$_ = $Hashtable.$KeyName

            }

            # configure read only properties, except Log which is handled
            # below
            if ( $KeyName -ne $_ ) {

                $this | Add-Member -MemberType ScriptProperty -Name $KeyName -Value ( [scriptblock]::Create( "`$this.$_" ) )            

            }

        }

        # configure the SigningStatus property
        $this | Add-Member -Name SigningStatus -MemberType ScriptProperty -Value {

            if ( -not $this.FilePath ) { [SignatureStatus]::NotSupportedFileFormat }

            return ( Get-AuthenticodeSignature $this.FilePath ).Status

        }

        # configure the SignatureRequired property
        $this | Add-Member -Name SignatureRequired -MemberType ScriptProperty -Value {

            return $this.__SignatureRequired( $this.FilePath, $this.ExecutionPolicy )

        }

        # override the Log property since we handle that in a special way
        $this | Add-Member -Name Log -MemberType ScriptProperty -Value {

            $this.__Log | Out-String

        } -Force

        # override the FilePath property since we handle that in a special way
        $this | Add-Member -Name FilePath -MemberType ScriptProperty -Value {

            $this.__FilePath

        } -SecondValue {

            param(

                [ValidateNotNullOrEmpty()]
                [System.IO.FileInfo]
                $FilePath

            )

            $this.__FilePath = $FilePath

            if ( -not $this.SignatureRequired -or  $this.SigningStatus -eq 'Valid' ) {

                $this.Definition = [scriptblock]::Create( ( Get-Content $this.__FilePath | Out-String ) )
    
            } else {
    
                Write-Warning 'Failed authenticode signature validation for file:'
                Write-Warning $this.__FilePath
    
                $this.Definition = {
    
                    throw [System.Management.Automation.PSSecurityException]::new( 'Invalid Authenticode Signature' )
    
                }
    
            }
        } -Force

        # rerun assignment for $FilePath to initialize properly
        if ( $Hashtable.FilePath ) { $this.FilePath = $Hashtable.FilePath }

        # setup the default display property set
        [string[]]$DefaultProperties = 'Name', 'Description', 'Schedule', 'Source', 'StartDate', 'EndDate', 'RunTime', 'Output', 'State', 'HadErrors'

        $DefaultDisplayPropertySet = [PSPropertySet]::new( 'DefaultDisplayPropertySet', $DefaultProperties )

        $PSStandardMembers = [PSMemberInfo[]]$DefaultDisplayPropertySet

        $this | Add-Member -MemberType MemberSet -Name 'PSStandardMembers' -Value $PSStandardMembers

    }

    [string] ToString() {

        return $this.Log

    }

    [void] LogRaw( [string]$MessageData ) {

        # the first time this function is called ( $this-__Log.Count -eq 0 )
        # and we are overwritting the log ( -not $this.__Append ) and the log
        # path is set we overwrite any existing log
        $Append = -not ( $this.__Log.Count -eq 0 -and -not $this.__Append -and $this.LogPath )

        $this.__Log.Add( $MessageData )

        if ( $this.LogPath ) {
            
            $MessageData | Out-File -FilePath $this.LogPath.FullName -Append:$Append -Encoding UTF8
            
        }
    
    }

    [void] LogMessage( [datetime]$TimeStamp, [string]$OutputStream, [string[]]$MessageData ) {
    
        $MessageData |
            ForEach-Object { $_  -split '[\r\n]+' } |
            ForEach-Object { '[{0:HH:mm:ss}] {1,-7} {2}' -f $TimeStamp, $OutputStream, $_ } |
            ForEach-Object { $this.LogRaw( $_ ) }

    }

    hidden [bool] __SignatureRequired( [FileInfo]$FilePath, [ExecutionPolicy]$ExecutionPolicy ) {
    
        switch ( $ExecutionPolicy ) {
        
            'Bypass' {
                
                return $false
            
            }
    
            'Unrestricted' {
                
                return $false
            
            }
    
            'Default' {
            
                [bool]$ServerOS = Get-WmiObject -Query 'SELECT ProductType FROM Win32_OperatingSystem WHERE ProductType > 1'
    
                return $this.SignatureRequired( $FilePath, ( 'Restricted', 'RemoteSigned' )[ $ServerOS ] )
            
            }
    
            'RemoteSigned' {
            
                # if the file is downloaded then we will require a signature
                if ( [bool]( Get-Item $FilePath -Stream * | Where-Object { $_.Stream -eq 'Zone.Identifier' } ) ) {
                    
                    return $true
                
                }
    
                # otherwise we check if the file is on a UNC path
                $Uri = $null
                if ( [System.Uri]::TryCreate( $FilePath.FullName, [System.UriKind]::Absolute, ( [ref]$Uri ) ) -and $Uri.IsUnc ) {
                    
                    return $true
                
                }
    
                # in other cases file is local file and we should return false
                return $false
            
            }
        
        }

        # AllSigned / Restricted / Undefined
        return $true
    
    }

}


# SIG # Begin signature block
# MIIfWwYJKoZIhvcNAQcCoIIfTDCCH0gCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUVVIYZ4dio2laJ+zEw43yXWZc
# 73GgghlDMIIFTDCCBDSgAwIBAgIRAJXsrVtF2nXJk88FisVsbxUwDQYJKoZIhvcN
# AQELBQAwfDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3Rl
# cjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQw
# IgYDVQQDExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTkxMDE1MDAw
# MDAwWhcNMjAxMDA3MjM1OTU5WjCBlDELMAkGA1UEBhMCVVMxDjAMBgNVBBEMBTYw
# MTIwMREwDwYDVQQIDAhJbGxpbm9pczEOMAwGA1UEBwwFRWxnaW4xGjAYBgNVBAkM
# ETEyODcgQmxhY2toYXdrIERyMRowGAYDVQQKDBFTaGFubm9uIEdyYXlicm9vazEa
# MBgGA1UEAwwRU2hhbm5vbiBHcmF5YnJvb2swggEiMA0GCSqGSIb3DQEBAQUAA4IB
# DwAwggEKAoIBAQDUDfCIlFqVcaV4Jg4top2UPmJmuzCm7gKFKcLHxe+RZ4tH9cFB
# K95slekX32x1XDBR6i4STWLkQDYAhTzwOgTDT7VfELoMBTBgBVeajcz52S87A1ce
# tbBJGo3CaEAEdV6MY4icqyLWNhrcM8jZ0UEvX1OuDR7PSheQxXBsoYOnC31TtZtu
# O94twA+em9Hrl2TcmFv1uYIyKsKcAuNo46cXOUJSJqDH2cOzPPDt9hECV/oQk2eJ
# zDAG6M6YDn2r26vAC4QDv9VdMAykTbCaFWwzjGqxxvMA+zs9JWCQ5OtlHprnWvUd
# ILOtQshJVkrEXSYPj/qo4SWoz9f+d3urt2ZJAgMBAAGjggGuMIIBqjAfBgNVHSME
# GDAWgBQO4TqoUzox1Yq+wbutZxoDha00DjAdBgNVHQ4EFgQUkeJMtbtdIm9ef+Gl
# DOHtvFIhRnYwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAww
# CgYIKwYBBQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEAGA1UdIAQ5MDcwNQYMKwYB
# BAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BT
# MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGln
# b1JTQUNvZGVTaWduaW5nQ0EuY3JsMHMGCCsGAQUFBwEBBGcwZTA+BggrBgEFBQcw
# AoYyaHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBQ29kZVNpZ25pbmdD
# QS5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMCYGA1Ud
# EQQfMB2BG3NoYW5ub24uZ3JheWJyb29rQGdtYWlsLmNvbTANBgkqhkiG9w0BAQsF
# AAOCAQEAI2bbcfka5PxMeiZ9rEEN2A3/iDgWCwKUuzGEDJHJbGqcTi53Gt7HUOrc
# VC11eh5cU9poVhUf/O+YQW6H6jPrkSOiajZY9I5UqIXo1sunFJwdbZzX7I40cOqf
# 9Ma3HT5Gt9SA4WBqj8DO5GrF6L3QKi2BR7vdymYbQk92ZXX6GcwCGiOg7iBuF91v
# r3Lx8JoPMuhObJvPUk59yKdHXZMue01X4N5/YJdo2g5XZU0qlq4CIiHYGQrsuhpv
# IG0w1Bsw0Jjfd3I2r1Xu29XF1g6U9GgA0HdJ8BM+0pAKuLHtPzmqsWhEcEJLFN9g
# UezIZBWejqWYx9Cy0nqr5NAnPWAVxTCCBfUwggPdoAMCAQICEB2iSDBvmyYY0ILg
# ln0z02owDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpO
# ZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVT
# RVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmlj
# YXRpb24gQXV0aG9yaXR5MB4XDTE4MTEwMjAwMDAwMFoXDTMwMTIzMTIzNTk1OVow
# fDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
# A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQD
# ExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQCGIo0yhXoYn0nwli9jCB4t3HyfFM/jJrYlZilAhlRGdDFi
# xRDtsocnppnLlTDAVvWkdcapDlBipVGREGrgS2Ku/fD4GKyn/+4uMyD6DBmJqGx7
# rQDDYaHcaWVtH24nlteXUYam9CflfGqLlR5bYNV+1xaSnAAvaPeX7Wpyvjg7Y96P
# v25MQV0SIAhZ6DnNj9LWzwa0VwW2TqE+V2sfmLzEYtYbC43HZhtKn52BxHJAteJf
# 7wtF/6POF6YtVbC3sLxUap28jVZTxvC6eVBJLPcDuf4vZTXyIuosB69G2flGHNyM
# fHEo8/6nxhTdVZFuihEN3wYklX0Pp6F8OtqGNWHTAgMBAAGjggFkMIIBYDAfBgNV
# HSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUDuE6qFM6MdWK
# vsG7rWcaA4WtNA4wDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
# HQYDVR0lBBYwFAYIKwYBBQUHAwMGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0g
# ADBQBgNVHR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNF
# UlRydXN0UlNBQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEE
# ajBoMD8GCCsGAQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRy
# dXN0UlNBQWRkVHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVz
# ZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIBAE1jUO1HNEphpNveaiqMm/EA
# AB4dYns61zLC9rPgY7P7YQCImhttEAcET7646ol4IusPRuzzRl5ARokS9At3Wpwq
# QTr81vTr5/cVlTPDoYMot94v5JT3hTODLUpASL+awk9KsY8k9LOBN9O3ZLCmI2pZ
# aFJCX/8E6+F0ZXkI9amT3mtxQJmWunjxucjiwwgWsatjWsgVgG10Xkp1fqW4w2y1
# z99KeYdcx0BNYzX2MNPPtQoOCwR/oEuuu6Ol0IQAkz5TXTSlADVpbL6fICUQDRn7
# UJBhvjmPeo5N9p8OHv4HURJmgyYZSJXOSsnBf/M6BZv5b9+If8AjntIeQ3pFMcGc
# TanwWbJZGehqjSkEAnd8S0vNcL46slVaeD68u28DECV3FTSK+TbMQ5Lkuk/xYpMo
# JVcp+1EZx6ElQGqEV8aynbG8HArafGd+fS7pKEwYfsR7MUFxmksp7As9V1DSyt39
# ngVR5UR43QHesXWYDVQk/fBO4+L4g71yuss9Ou7wXheSaG3IYfmm8SoKC6W59J7u
# mDIFhZ7r+YMp08Ysfb06dy6LN0KgaoLtO0qqlBCk4Q34F8W2WnkzGJLjtXX4oemO
# CiUe5B7xn1qHI/+fpFGe+zmAEc3btcSnqIBv5VPU4OOiwtJbGvoyJi1qV3AcPKRY
# LqPzW0sH3DJZ84enGm1YMIIG7DCCBNSgAwIBAgIQMA9vrN1mmHR8qUY2p3gtuTAN
# BgkqhkiG9w0BAQwFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJz
# ZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNU
# IE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBB
# dXRob3JpdHkwHhcNMTkwNTAyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjB9MQswCQYD
# VQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdT
# YWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxJTAjBgNVBAMTHFNlY3Rp
# Z28gUlNBIFRpbWUgU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
# ggIKAoICAQDIGwGv2Sx+iJl9AZg/IJC9nIAhVJO5z6A+U++zWsB21hoEpc5Hg7Xr
# xMxJNMvzRWW5+adkFiYJ+9UyUnkuyWPCE5u2hj8BBZJmbyGr1XEQeYf0RirNxFrJ
# 29ddSU1yVg/cyeNTmDoqHvzOWEnTv/M5u7mkI0Ks0BXDf56iXNc48RaycNOjxN+z
# xXKsLgp3/A2UUrf8H5VzJD0BKLwPDU+zkQGObp0ndVXRFzs0IXuXAZSvf4DP0REK
# V4TJf1bgvUacgr6Unb+0ILBgfrhN9Q0/29DqhYyKVnHRLZRMyIw80xSinL0m/9NT
# IMdgaZtYClT0Bef9Maz5yIUXx7gpGaQpL0bj3duRX58/Nj4OMGcrRrc1r5a+2kxg
# zKi7nw0U1BjEMJh0giHPYla1IXMSHv2qyghYh3ekFesZVf/QOVQtJu5FGjpvzdeE
# 8NfwKMVPZIMC1Pvi3vG8Aij0bdonigbSlofe6GsO8Ft96XZpkyAcSpcsdxkrk5WY
# nJee647BeFbGRCXfBhKaBi2fA179g6JTZ8qx+o2hZMmIklnLqEbAyfKm/31X2xJ2
# +opBJNQb/HKlFKLUrUMcpEmLQTkUAx4p+hulIq6lw02C0I3aa7fb9xhAV3PwcaP7
# Sn1FNsH3jYL6uckNU4B9+rY5WDLvbxhQiddPnTO9GrWdod6VQXqngwIDAQABo4IB
# WjCCAVYwHwYDVR0jBBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYE
# FBqh+GEZIA/DQXdFKI7RNV8GEgRVMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8E
# CDAGAQH/AgEAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0g
# ADBQBgNVHR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNF
# UlRydXN0UlNBQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEE
# ajBoMD8GCCsGAQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRy
# dXN0UlNBQWRkVHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVz
# ZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIBAG1UgaUzXRbhtVOBkXXfA3oy
# Cy0lhBGysNsqfSoF9bw7J/RaoLlJWZApbGHLtVDb4n35nwDvQMOt0+LkVvlYQc/x
# QuUQff+wdB+PxlwJ+TNe6qAcJlhc87QRD9XVw+K81Vh4v0h24URnbY+wQxAPjeT5
# OGK/EwHFhaNMxcyyUzCVpNb0llYIuM1cfwGWvnJSajtCN3wWeDmTk5SbsdyybUFt
# Z83Jb5A9f0VywRsj1sJVhGbks8VmBvbz1kteraMrQoohkv6ob1olcGKBc2NeoLvY
# 3NdK0z2vgwY4Eh0khy3k/ALWPncEvAQ2ted3y5wujSMYuaPCRx3wXdahc1cFaJqn
# yTdlHb7qvNhCg0MFpYumCf/RoZSmTqo9CfUFbLfSZFrYKiLCS53xOV5M3kg9mzSW
# mglfjv33sVKRzj+J9hyhtal1H3G/W0NdZT1QgW6r8NDT/LKzH7aZlib0PHmLXGTM
# ze4nmuWgwAxyh8FuTVrTHurwROYybxzrF06Uw3hlIDsPQaof6aFBnf6xuKBlKjTg
# 3qj5PObBMLvAoGMs/FwWAKjQxH/qEZ0eBsambTJdtDgJK0kHqv3sMNrxpy/Pt/36
# 0KOE2See+wFmd7lWEOEgbsausfm2usg1XTN2jvF8IAwqd661ogKGuinutFoAsYyr
# 4/kKyVRd1LlqdJ69SK6YMIIHBjCCBO6gAwIBAgIQPRo1cjAVgmMw0BNxfoJBCDAN
# BgkqhkiG9w0BAQwFADB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBN
# YW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdvIExp
# bWl0ZWQxJTAjBgNVBAMTHFNlY3RpZ28gUlNBIFRpbWUgU3RhbXBpbmcgQ0EwHhcN
# MTkwNTAyMDAwMDAwWhcNMzAwODAxMjM1OTU5WjCBhDELMAkGA1UEBhMCR0IxGzAZ
# BgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEYMBYG
# A1UECgwPU2VjdGlnbyBMaW1pdGVkMSwwKgYDVQQDDCNTZWN0aWdvIFJTQSBUaW1l
# IFN0YW1waW5nIFNpZ25lciAjMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAMtRUP9W/vx4Y3ABk1qeGPQ7U/YHryFs9aIPfR1wLYR0SIucipUFPVmE+ZGA
# eVEs2Yq3wQuaugqKzWZPA4sBuzDKq73bwE8SXvwKzOJFsAE4irtN59QcVJjtOVjP
# W8IvRZgxCvk1OLgxLm20Hjly4bgqvp+MjBqlRq4LK0yZ/ixL/Ci5IjpmF9CqVooh
# wPOWJLTQhSZruvBvZJh5pq29XNhTaysK1nKKhUbjDRgG2sZ7QVY2mxU+8WoRoPdm
# 9RjQgFVjh2hm6w55VYJco+1JuHGGnpM3sGuj6mJso66W6Ln9i6vG9llbADxXIBgt
# cAOnnO+S63mhx13sfLSPS9/rXfyjIN2SOOVqUTprhZxMoJgIaVsG5yoZ0JWTiztr
# igUJKdjW2tvjcvpcSi97FVaGMr9/BQmdLSrPUOHmYSDbxwaAXE4URr6uV3Giqmww
# kxx+d8sG6VfNkfXVM3Ic4drKbuvzD+x5W7snnuge/i/yu3/p5dBn67gNfKQrWQOL
# le0iKM36LDvHFhGv49axUGdpxY71edCt/4fM+H+q+aLtYfjIjWnasfRRketnV9Fk
# EetkywO9SVU6RUMYLCVs0S8MLW/1QTUkoPJjWRZf2aTpLE7buzESxm34W24D3MsV
# jxuNcuzbDxWQ1hJO7uIAMSWTNW9qW6USY0ABirlpiDqIuA8ZAgMBAAGjggF4MIIB
# dDAfBgNVHSMEGDAWgBQaofhhGSAPw0F3RSiO0TVfBhIEVTAdBgNVHQ4EFgQUb02G
# B9gyJ54sKdLQEwOAgd0FgykwDgYDVR0PAQH/BAQDAgbAMAwGA1UdEwEB/wQCMAAw
# FgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQAYDVR0gBDkwNzA1BgwrBgEEAbIxAQIB
# AwgwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwRAYDVR0f
# BD0wOzA5oDegNYYzaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBVGlt
# ZVN0YW1waW5nQ0EuY3JsMHQGCCsGAQUFBwEBBGgwZjA/BggrBgEFBQcwAoYzaHR0
# cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBVGltZVN0YW1waW5nQ0EuY3J0
# MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0B
# AQwFAAOCAgEAwGjts9jUUJvv03XLDzv3JNN6N0WNLO8W+1GpLB+1JbWKn10Lwhsg
# dI1mDzbLqvY2DQ9+j0tKdENlrA0q9grta23FCTjtABv45dymCkAFR++Eygm8Q2aD
# v5/t24490UFksXACLQNXWxhvHCzLHrIA6LoJL1uBBDW5qWNtjgjFGNHhIaz5EgoU
# wBLbfiWdrB0QwFqlg9IfGmZV/Jsq4uw3V47l35Yw+MCTC0MY+QJvqVGvuFcK8xwH
# aTmPN5xt15GupS5J6Ures9CMvzmQDcCBzvAqBzoMpi1R0nLzU8b5ve/vDGlJd58s
# VsTpoQg9B67FHtaEIse8fUMbWDhiTtEFJYTFQvgfL/bb+quMVOxFimwSTTBaUuWk
# Fwki5u9v9V+GQ9+hLb1KRpKggZYsYZd/QG/YP4w1WqvRxqA7hWZUgO8fGvXxm7Ch
# J32y5wvP9i2cWBOUqYb8RVKiKG1/dA9SkUl66RL4qTuwkv19kRTpW21IlPLIlu4F
# OLPF7DA/4QcgBLHYi7z9sz5v8gJTBvSg7cmacqOXXwD7y2PQ6M10/XXJ1DZFunsS
# WXLt5/J6UAB4+EOaRtjfv1TUXrHH0bwbg/Qr5wvoR8hTnswarPb6inVTbCCFqdW4
# arokjoorCJGfNwQc9m+i3TSqkf/GFS4eQhoJKU/0xs3ikaLTQAyOeOMxggWCMIIF
# fgIBATCBkTB8MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVz
# dGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQx
# JDAiBgNVBAMTG1NlY3RpZ28gUlNBIENvZGUgU2lnbmluZyBDQQIRAJXsrVtF2nXJ
# k88FisVsbxUwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAw
# GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG
# AQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFP3WeznAZApzdAga1927OBTxnScsMA0G
# CSqGSIb3DQEBAQUABIIBAK97TVGMX0/JOyzOBC6GyNUv/NttthxRseXPFooTYZSf
# yDgxqTtVfP9r7kqNPErg291S53+/sMOPRvONA+X4AYXXslsGjcgtPnOaBDl6HUMk
# h/s0BWFS0lUGt5XEvXiO8UguE1KXnnm/pSeUSu/fzaL2eW8gh0RyEhciual1leWo
# UmHFaZWIa88DsjJGNEIGQSMgz5mVbc2Vv8XEs10N6J1SsGjEV2aJS5ERQO51g3Nc
# 9ESYO1lpGOyHJgFmCdbTpin4lSWMw8Vc8eD4TF3II3WQr06gYzmTuXeTYkBixSL2
# gU8UratG38ny0oyZgefdmq/WzOKDKNycmjkwi/BklnKhggNLMIIDRwYJKoZIhvcN
# AQkGMYIDODCCAzQCAQEwgZEwfTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0
# ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGln
# byBMaW1pdGVkMSUwIwYDVQQDExxTZWN0aWdvIFJTQSBUaW1lIFN0YW1waW5nIENB
# AhA9GjVyMBWCYzDQE3F+gkEIMA0GCWCGSAFlAwQCAgUAoHkwGAYJKoZIhvcNAQkD
# MQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwNjIzMTkyOTU0WjA/Bgkq
# hkiG9w0BCQQxMgQwPbZeAULmP8Qq0vC5r+tN8vOmhlNBACbHJQUxyX7OgihE7Nge
# FxmjRfl9wR0ipZE3MA0GCSqGSIb3DQEBAQUABIICALUQJ2S91p14fLI/z95Fi4vb
# sbsTr6+ZLM+ve2MyguxhebWHug66IbTKvIwcoqJkNnlnZMCDezBxmXLcCGdVcZiJ
# DjYiQwI/54CHzYFAEwkwoSEVPnggBwmWniB4UD/6dh30HydZvfwgtunm3zVkDz0n
# 4CAILAZTrhcFLabE+CHpPw2LM26ZmvpedVqnBYeGDwIPuSRcPsSWXgg1LLoXe/Dc
# NUpIu6HJ2PYWGZVZjVa+UH3+S9Yse+susnk5X2yrUax38KJ9qVnzJ9Aihm+nPf08
# HE1PETNCT6Iui+o7VlvMrp8c7m0XRKqud2L2oWcfCy9ZuC+lB5FpaqKklil7Mw7a
# qI7AFPWPlANG+LndmClvLkm1F0ebl/rOsFLLD5USha2OhfeUJfwDJHPr9//1TsRc
# zhGl11DoBFMnGfGK99joA9Llua55XhuVKog9/ZDKWjFrz5H6zeJQ3+MmVJ0781fy
# LPNz7dHJ/pATbzHZ/4TKvmJV4A6xZN8VUgXtolAmMt0pzYIVvmQa5FdoJOzIPPA7
# CGCcpb1b9WT40gV/T4Xj9i/9QrBZX6g+0ndJqIUgv6wMWnmNBvieYC93pTOihOY4
# 6wSr9bQIV5/Q9uSCQkegqqRuC6ZwmOLnZZqIMbBeqm3uyfCWQ9BvTwC1ts5Sm6Qy
# X+R/8LC/HIB2duXQCUoT
# SIG # End signature block