Private/Metadata/Write-AvmModuleInitializationPlan.ps1
|
function Write-AvmModuleInitializationPlan { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [OutputType([bool])] param( [Parameter(Mandatory)] [string] $Root, [Parameter(Mandatory)] [AllowEmptyCollection()] [object[]] $Plan ) Set-StrictMode -Version 3.0 $ErrorActionPreference = 'Stop' if ($Plan.Count -eq 0) { return $false } Test-AvmModuleInitializationPlan -Root $Root -Plan $Plan $comparison = if ($IsWindows) { [System.StringComparison]::OrdinalIgnoreCase } else { [System.StringComparison]::Ordinal } $rootPath = [System.IO.Path]::GetFullPath($Root) if (-not $PSCmdlet.ShouldProcess($rootPath, 'Write validated module initialization files')) { return $false } $createdDirectories = [System.Collections.Generic.List[string]]::new() $createdFiles = [System.Collections.Generic.List[object]]::new() $replacedFiles = [System.Collections.Generic.List[object]]::new() $utf8NoBom = [System.Text.UTF8Encoding]::new($false) try { foreach ($item in $Plan) { $target = [System.IO.Path]::GetFullPath([string]$item.Path) $parent = Split-Path -Path $target -Parent $existingDirectory = Get-AvmExistingDirectory -Path $parent $pending = [System.Collections.Generic.Stack[string]]::new() $directory = $parent while (-not [string]::Equals($directory, $existingDirectory, $comparison)) { $pending.Push($directory) $next = Split-Path -Path $directory -Parent if (-not $next -or [string]::Equals($directory, $next, $comparison)) { throw [System.IO.IOException]::new("Cannot locate the existing parent of $target.") } $directory = $next } while ($pending.Count -gt 0) { $directory = $pending.Pop() if (-not (Test-Path -LiteralPath $directory -PathType Container)) { $null = New-Item -ItemType Directory -Path $directory -ErrorAction Stop $createdDirectories.Add($directory) } } $originalBytes = $null $originalWriteTime = $null if ($null -ne $item.Original) { if ((Get-Content -LiteralPath $target -Raw) -cne $item.Original) { throw [System.IO.IOException]::new("Source changed during initialization: $target") } $originalBytes = [System.IO.File]::ReadAllBytes($target) $originalWriteTime = [System.IO.File]::GetLastWriteTimeUtc($target) } $contentBytes = $utf8NoBom.GetBytes([string]$item.Content) $temporaryPath = Join-Path -Path $parent -ChildPath ('.avm-initialize-' + [guid]::NewGuid().ToString('N') + '.tmp') try { [System.IO.File]::WriteAllBytes($temporaryPath, $contentBytes) [System.IO.File]::Move($temporaryPath, $target, ($null -ne $item.Original)) if ($null -eq $item.Original) { $createdFiles.Add([pscustomobject]@{ Path = $target; Bytes = $contentBytes }) } else { $replacedFiles.Add([pscustomobject]@{ Path = $target; OriginalBytes = $originalBytes OriginalWriteTime = $originalWriteTime; Bytes = $contentBytes }) } } finally { if ([System.IO.File]::Exists($temporaryPath)) { [System.IO.File]::Delete($temporaryPath) } } } } catch { for ($i = $createdFiles.Count - 1; $i -ge 0; $i--) { $created = $createdFiles[$i] try { if ([System.IO.File]::Exists($created.Path)) { $current = [System.IO.File]::ReadAllBytes($created.Path) if ([System.Linq.Enumerable]::SequenceEqual([byte[]]$current, [byte[]]$created.Bytes)) { [System.IO.File]::Delete($created.Path) } else { Write-Warning "Cannot roll back '$($created.Path)': content changed after initialization." } } } catch { Write-Warning "Cannot roll back '$($created.Path)': $($_.Exception.Message)" } } for ($i = $replacedFiles.Count - 1; $i -ge 0; $i--) { $replaced = $replacedFiles[$i] try { $current = [System.IO.File]::ReadAllBytes($replaced.Path) if ([System.Linq.Enumerable]::SequenceEqual([byte[]]$current, [byte[]]$replaced.Bytes)) { [System.IO.File]::WriteAllBytes($replaced.Path, $replaced.OriginalBytes) [System.IO.File]::SetLastWriteTimeUtc($replaced.Path, $replaced.OriginalWriteTime) } else { Write-Warning "Cannot restore '$($replaced.Path)': content changed after initialization." } } catch { Write-Warning "Cannot restore '$($replaced.Path)': $($_.Exception.Message)" } } for ($i = $createdDirectories.Count - 1; $i -ge 0; $i--) { $directory = $createdDirectories[$i] try { if ([System.IO.Directory]::Exists($directory)) { if (@(Get-ChildItem -LiteralPath $directory -Force).Count -eq 0) { [System.IO.Directory]::Delete($directory) } else { Write-Warning "Cannot roll back '$directory': directory is no longer empty." } } } catch { Write-Warning "Cannot roll back '$directory': $($_.Exception.Message)" } } throw } return $true } # SIG # Begin signature block # MIInNQYJKoZIhvcNAQcCoIInJjCCJyICAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBeyaQ6Hb/lNfRj # zlSufB8AjJtsXV0NQ2c5PVeBVkauj6CCDMkwggYEMIID7KADAgECAhMzAAACHPrN # xZvoL37EAAAAAAIcMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD # b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQxWhcNMjcwNDE1MTg1 # OTQxWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD # VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB # DwAwggEKAoIBAQDVsZfgOKmM31HPfoWOoNEiw0SlCiIxUMC0I9NMWbucKOw/e9lP # oAoehQVu6SG65V4EPzrYsnBnFPNoi4/HoOdjhz1qkrEt4I6tEcxXU6oOeY9zGveC # /3iBeuhLYxM3M/PkcUoebF+Nednm8OkdSPoDu8imViHPQq/8CQUu0WRR4rE+dMRf # rpVqfmNi2qWCX94T4MsepijGVkwE//tJg0ryAiYdHT34LSnlG/RSBZmQRGWZ5g8j # qnKjRParSqMft1gvjuUTVgtWNZfgcLFSK5Wa0myrq8OPcgTGGsRgun+tnSS+IxDT # xVsAPH1OzvPjwomguByhUe/OcvUN0D5Wmp7xAgMBAAGjggGqMIIBpjAOBgNVHQ8B # Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O # BBYEFNoH7a2YDjOSwpkp6DHcmUS7J+0yMFQGA1UdEQRNMEukSTBHMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxFjAUBgNVBAUT # DTIzMDAxMis1MDc1NjkwHwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEw # YAYDVR0fBFkwVzBVoFOgUYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w # cy9jcmwvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy # bDBtBggrBgEFBQcBAQRhMF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmcl # MjBQQ0ElMjAyMDI0LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IC # AQAUnEqhaRXe0T3hIJjvdQErEkrA/7bByjn6t5IArODkkRjzkYwtKMc2yYj2quaN # rLutWw2YZcngKPy1b71YyDJQTy4NDRwaSh9Tw5thrk3NmcPrAHia5vtcBJ1CgtKK # 7mQbIcQ22d/N3813ayCDDFewu1+jsZmX+r/aTEqaOM4TVxVtRSkuCy8nAXKuChOK # Li/zA4XuH8iEYqIsj2YoNaeSxVmeGiERXpKdo3dDmYi0kO5w2D8VS4c3+9h6gElY # BaAAg/dYErBg27qT3vv0zRDJhJufvCNylA8S7/+8H5E/PV5cng6na9VV/w9OV3qu # uND6zdGa2EX38Glp50F9AIQk3p2xXmcvorDeM4XJ7UlWYBi6g80J1SSOQnInCYFE # msfUNn3+1AaTJKSJL83quKArTac2pKhu0Yzzzrzo6HrsRiQKzpnRBb1/dMa6P3hz # 75XbMRBctNsFhZC07WCmjExdLg2eHW5uV0TY8D5+6wozJf7vF3+WHkYPO85Z+BC6 # U4FkNbYNycZ9cE4j1tXRdyDCfml6c0HWPHjNVDObrv9lKt3qUqFpX38VCqVCyNOO # 1UcXfQiVjJw32U2WUKZjt/neJKHEBsm9kFsLuWzkQ53+qcaSaytmsCnk2gOglrlD # 5d3kKyvvAw+rzm0lT8K38P6PLxfZQHhu4W8dV7Av8N2ZmDCCBr0wggSloAMCAQIC # EzMAAAA5O7Y3Gb8GHWcAAAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS # b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoX # DTM2MDMyMjIyMTMwNFowVzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ # Q0EgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeq # lRYHNa265v4IY9fH8TKhemHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo # 0dtS/EW6I/yEL/bLSY8hKpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATv # QVL4tcf03aTycsz8QeCdM0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a # 1uv1zerOYMnsneRRwCbpyW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1 # FyQfK0fVkaya8SmVHQ/tOf23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfO # GSWHIIV4YrTJTT6PNty5REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7 # ttOu1bVnXfHaqPYl2rPs20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJ # uz2MXMCt7iw7lFPG9LXKGjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxS # CwyoGIq0PhaA7Y+VPct5pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOm # VQop36wUVUYklUy++vDWeEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3 # SkE/xIkgpfl22MM1itkZ35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8E # BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPX # LQaUEggxMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMB # Af8wHwYDVR0jBBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBP # oE2gS4ZJaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv # TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAw # TgYIKwYBBQUHMAKGQmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMv # TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOC # AgEAFJQfOChP7onn6fLIMKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D # 5W4wMwYeLystcEqfkjz4NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBY # nbu0+THSuVHTe0VTTPVhily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSI # vgn0JksVBVMYVI5QFu/qhnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6 # aR9y34aiM1qmxaxBi6OUnyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4w # PKC5OmHm1DQIt/MNokbbH3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7 # RTX8AdBPo0I6OEojf39zuFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK # /fg8B2qjW88MT/WF5V5uvZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSK # YBv0VisCzfxgeU+dquXW9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkw # YTu/9dLeH2pDqeJZAABVDWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVT # Ql0v4q8J/AUmQN5W4n101cY2L4A7GTQG1h32HHAvfQESWP0xghnCMIIZvgIBATBu # MFcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # KDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIc # +s3Fm+gvfsQAAAAAAhwwDQYJYIZIAWUDBAIBBQCggZAwGQYJKoZIhvcNAQkDMQwG # CisGAQQBgjcCAQQwLwYJKoZIhvcNAQkEMSIEIBPWApEl+XBb9+puzMxANKvJW/48 # BJuJAENXMI92i/O7MEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv # AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAE # ggEAwBZ04PgakDfeccdxm8nr5ScVrDPvESatE0S6jMlE3TUSWp1niD8lHUV6nLgS # 63qgmz2LLlMnZRV1dKKr2JOmE2gPLeK//q3y6C4ZtcT8xdxhNg8HQXiA2B4HWelY # y1xCHKoLOzBDOYGpF2Jt0cyhPsBp8yqT+6KBJNZVGgOtR2+aZBBqVBdvwlcWvntp # L9UHjq59Qoa+SAFu6yv6/sUGDO/qmZEe6L9G90YIsQgrb9FKPUqi5t44Q0RS+7a5 # FZ5hxRJnPm/YWX6Ar/oOG2CZem0mnS4dgDGkBf9XhpCyzgZc64XTBYMDA5x2bY2N # 0vqPfvef1KgzHcIo9HO9nXBOyaGCF5IwgheOBgorBgEEAYI3AwMBMYIXfjCCF3oG # CSqGSIb3DQEHAqCCF2swghdnAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFQBgsqhkiG # 9w0BCRABBKCCAT8EggE7MIIBNwIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQC # AQUABCB58kOMZ3PkcQyr7olT2e56ytysWCHxkpoFBL10hZ1W8gIGaqlt+FaJGBEy # MDI2MTAwODA4MDQzNy45WjAEgAIB9KCB0aSBzjCByzELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg # T3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjkyMDAtMDVFMC1E # OTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIR6jCC # ByAwggUIoAMCAQICEzMAAAIjT9lgJFPP/isAAQAAAiMwDQYJKoZIhvcNAQELBQAw # fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd # TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjYwMjE5MTkzOTU3WhcN # MjcwNTE3MTkzOTU3WjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUG # A1UECxMeblNoaWVsZCBUU1MgRVNOOjkyMDAtMDVFMC1EOTQ3MSUwIwYDVQQDExxN # aWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEFAAOC # Ag8AMIICCgKCAgEAiukNp5OVlHSs0gkmn6flI1AEbFsRykut6yYRQv80mmxbpkwb # midEDa5qnr7m+Q2+30o+arcMCp4yDvdvh1xeu9fdn7oy+wxaLeVhI/wLRGf168xR # 4pipTdYeoBEMD+SOu8Is2j1uWc0gTaWiwYOaB7wEjzmbcHTVKGfg0Chd4SZdSmbq # CJVSvqou3C44GpOrOaDmXEQjKyp7gt2qFWusEQ22LylLo+65BcfSjtD7Byf5Pi52 # TIIEYXoeAFXWsMofqDsyj45UBlDX0nllIMptlPQi2vLbdJkF+A8Q8+vq2pudII9a # AH8kOk0O6/ejwAxTigYGlO/nKR52mRvPXU3oEOsnQURiMnDsNXUV9nig0Uc84it3 # J9FmiJv+znhrMkCoyMxELlEw79CY//c0O7a7izjqSQ/fASVTiu43vOEs9oW9x71E # k+49Y9jfKXg+qJZKRR0f9WfCc+BfppK1BezJjwIq2B0c7p2yINx6wzDcBWDe8gZA # wOP1TKPQmNMvaBlKKtso2wsE4m8/VWJfd5wd0EIkwk/Z1tzPkzlgfjzK2aRMatQU # h5ij8yKnoSqq1A6DN9zyvnRCsKWCxE+rl6uB7kETF1k//7D7m1J0AGmlDH0IQGUs # ttx7ccLTd3ivfk+MAmr9sEBbee3lDsFFufwwszBfbbmuR3tYTb4HAF2ohtcCAwEA # AaOCAUkwggFFMB0GA1UdDgQWBBTWwIfPb9vZz2PW8EG9UGAs8VYHlzAfBgNVHSME # GDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5odHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBUaW1l # LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwGCCsG # AQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p # Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNVHRMB # Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDAN # BgkqhkiG9w0BAQsFAAOCAgEAh0MHu8+baeDWcAH9XAfuHPSeLL8Nz+lqhgTMbas5 # 0ug3c1M0rVxwmj2YTONYNYihzZ5nJy48C7ozhGjY4Up1A4gGakI1uWWqTgcYHOxI # IIYfZPq+/KlgHt6yeEKIQW4UhnWbSor00Wnkapp4cvPk4ayocwnhMGmq1yYpmcEq # XUEFA24Xlh3sgMQEqrpbXeSjtJv1BbztN7X3qahlwOLQoP1hhAsCqjoyc6UQHzyA # estR8la5Pr5i+a6RG08MCzrV+1sRRhvPnGC5PR42g5Ma2gPx2JSkEcdbHc2vsP4L # pS8IDpwckSShdq6/DOxTSJcKIussBaWjXPAOx3sGho4MP7X3BNutCNV3pBpbgDSP # R5zjTmFpSOwSgUG1hNrXqOr7ENVYPAfK02Unj1XZly9Tz6qrNylXRSjOZGKHDwgz # PulS99iFferBEn9k+w48Wp6QoNg9lGI+GdYu3MvFNSywxoOeSlrOGn9kUQYx9jLp # R4AJluaGysYmQg0I0Wq6CdlxJV1IYoBPQc74QhW0/xw2Nr6VaZeR50qXAksZi+Yu # ZSE/8WwEDCOy7oe+V65viLJXxVjhjhjJQqftuKhCRIJVxD+8cLKJTXQTZ3V4oYci # Hn1RpSNQ0e8RhC4ia5PIn1VmKPVxGxF7/5W76ehdkdlLJ8HlnJL6tMtR1pyxw6h+ # nT4wggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3DQEB # CwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD # VQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAe # Fw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0 # YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5OGm # TOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/H # ZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1hlDc # wUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62A # W36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3KNi1w # jjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCG # MFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF803RKJ # 1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQcNIIP # 8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahhaYQFz # ymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkLiWHz # NgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV2xo3 # xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIGCSsG # AQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/ # LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBTMFEG # DCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29m # dC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYB # BQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8G # A1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186aGMQw # VgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9j # cmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUF # BwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br # aS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcNAQEL # BQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1OdfC # cTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AF # vonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbzaN9l # 9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn # 8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3mSj5m # O0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyx # TkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxkoJLo4 # S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFmPWn9 # y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC4822rpM # +Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7vzhw # RNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDTTCCAjUC # AQEwgfmhgdGkgc4wgcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNV # BAsTHm5TaGllbGQgVFNTIEVTTjo5MjAwLTA1RTAtRDk0NzElMCMGA1UEAxMcTWlj # cm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAOEVhbPpE # 4mZ6GYgI9QbWI/MwjWqggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg # MjAxMDANBgkqhkiG9w0BAQsFAAIFAO5xkpwwIhgPMjAyNjEwMDgwMzU1MDhaGA8y # MDI2MTAwOTAzNTUwOFowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA7nGSnAIBADAH # AgEAAgInfDAHAgEAAgISFjAKAgUA7nLkHAIBADA2BgorBgEEAYRZCgQCMSgwJjAM # BgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEB # CwUAA4IBAQAavrHWQj9orciJVmF0uLO9ozlAJtG5bp5nFdzMigP3ep2E4q5MAfY/ # mRZU5q6QBh3pl6Vxz4LAgY1MHmpJprxNIdb2JO8pDiJBQjQrnOJ7QdIOTsr3dNqt # LTeWHkjUnqg/NX6uF44hZDCwMaym2FyDHvILFeGDNiP1JQS9tmIWKQKU+C/EqZbZ # Q2RtlRI3wHYEd7Zf4Nx8vFaAhG4cVF2Wt33aXi3iTx59h1z7GhdRSWtPXniIVIyn # qDZXaR/K1Xil8cqqOcSZhKqsQYPKJlxgV8yOLM2Dsq/8qH34nHTTeAs5o66qtyLq # vCU0P/cewUgyLctmWaBky34c6ShZ5uFHMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0 # IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIjT9lgJFPP/isAAQAAAiMwDQYJYIZI # AWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG # 9w0BCQQxIgQgQ0/Cd1j31wl7DtnzI3zQNAePUzvzhJdMVDwWye/DS2EwgfoGCyqG # SIb3DQEJEAIvMYHqMIHnMIHkMIG9BCCW8DMsEW73Bosp458IwKnGg+O8mL3mymUQ # L7RAEebuszCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n # dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y # YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMz # AAACI0/ZYCRTz/4rAAEAAAIjMCIEIHR1VlPflR/MiBTgLnBqpnIHdV8yKJa0sKit # B+PoGvmXMA0GCSqGSIb3DQEBCwUABIICAFSGT5Ka3QCcC2Pz57PBFKcEglBXgHbP # GjNmpBlxwBbBTOTTrqR0fEoJ1wSH7gfqNyaFG5ZQnckW6qyPhcU29ynHt+etLuJ2 # jMoDCEZM7jhPOwp5wi2ip7q2sm1Nr7tVbb65AWFh/95YIrBeZLxXTDuYEfq6ggdK # UUQx4HJqLIzngtBmQ3AaU+GRVtbGbMg1sdirGRL5vQvw3SyfAv294tmplWOTlf8O # u7MlYI8MWR2OWKziGSCqTwlkZOQ2jqNWtvz20nTY67/xOXHPphtwtwXmUWii67TO # 7J35LEgrLq57NnkGLRrAN/tPsSlZs6rYis4G9JccDgWQ9tcLQYVoVuEpjvWSSaar # zEXiaU7UnT9iRaHgEmC1px0sifI1pYjw6hNrTe/slKIwaZD9cKLtCjmpyqf+815S # Up3Y7X48yB/wiVEXhg1n/me4kuunWGnOH9ucvvCe/AOf1whPqt/4cTrkrPal3QaC # BiG0aejtdd1YEdohdKAiVI9Z/eloopV80WJ3qOXN3ITNscckDFvjHN19XyinWFHm # MLrexeKW43rK4hEr0Y0YuUyBM6Eu8UJ2X7ALJnX2imng5nGejzz9lc/N49J1zhUC # y+VpNaxutVyYWxcBMXX5duT146OvbF/B3+vl1sjvRIIHdfttAtLv41IgJSFSCwm3 # xTOkEXjZ6cfK # SIG # End signature block |