AzurePSDriveStorageAccount.psm1

using namespace Microsoft.PowerShell.SHiPS

$script:Azure_Storage = if($IsCoreCLR){'Azure.Storage.NetCore'}else{'Azure.Storage'}
$script:AzureRM_Storage = if($IsCoreCLR){'AzureRM.Storage.NetCore'}else{'AzureRM.Storage'}


[SHiPSProvider(UseCache=$true)]
class StorageAccounts : SHiPSDirectory
{
    StorageAccounts() : base ($this.GetType())
    {
    }

    StorageAccounts([string]$name): base($name)
    {
    }

    [object[]] GetChildItem()
    {
        $obj =  @()                     
        @(& "$script:AzureRM_Storage\Get-AzureRmStorageAccount").Foreach{
             $obj += [StorageAccount]::new($($_.StorageAccountName), $_) 
        }          
        return $obj 
    }
 }

[SHiPSProvider(UseCache=$true)]
class StorageAccount : SHiPSDirectory
{ 
    Hidden [object]$data = $null

    StorageAccount ([string]$name, [object]$data) : base ($name) 
    {
        $this.data = $data
    }

    [object[]] GetChildItem()
    {        
        $obj =  @()
        $ev = $null
        if ($this.data.PrimaryEndpoints.Blob -ne $null)
        {
            try
            {
                $result=& "$script:Azure_Storage\Get-AzureStorageContainer" -Context $this.data.Context -ErrorAction SilentlyContinue -ErrorVariable ev
                if($ev) {
                    Write-Verbose $ev.Exception
                }else{
                    $obj+=[Blobs]::new($this.data, $result);
                }
            }
            catch
            {
                Write-Verbose $_.Exception
            }
        }

        if ($this.data.PrimaryEndpoints.File -ne $null)
        {
            try
            {
                $result=& "$script:Azure_Storage\Get-AzureStorageShare" -Context $this.data.Context -ErrorAction SilentlyContinue -ErrorVariable ev
                if ($ev) {
                    Write-Verbose $ev.Exception
                } else {
                    $obj+=[Files]::new($this.data, $result)
                }
            }
            catch
            {
                Write-Verbose $_.Exception
            }
        }

        if ($this.data.PrimaryEndpoints.Table -ne $null)
        {
            try
            {
                $result=& "$script:Azure_Storage\Get-AzureStorageTable" -Context $this.data.Context  -ErrorAction SilentlyContinue -ErrorVariable ev
                if ($ev){
                    Write-Verbose $ev.Exception 
                } else {
                    $obj+=[Tables]::new($this.data, $result);
                }
            }
            catch
            {
                Write-Verbose $_.Exception
            }
        }

        if ($this.data.PrimaryEndpoints.Queue -ne $null)
        {
            try {
                $result=& "$script:Azure_Storage\Get-AzureStorageQueue" -Context $this.data.Context -ErrorAction SilentlyContinue -ErrorVariable ev
                if ($ev) {
                    Write-Verbose $ev.Exception
                } else {
                    $obj+=[Queues]::new($this.data, $result);
                }
            }
            catch
            {
                Write-Verbose $_.Exception
            }
        }

        return $obj;
    }
}

[SHiPSProvider(UseCache=$true)]
class Blobs : SHiPSDirectory
{
    Hidden [object]$data = $null
    Hidden [object]$result = $null

    Blobs ([object]$data, [object]$result) : base ($this.GetType()) 
    {
        $this.data = $data
        $this.result = $result
    }

    [object[]] GetChildItem()
    {     
        if(-not $this.result)
        {
            Write-Debug "AzurePSDrive: No Blobs."
            return $null
        }

        $obj =  @()
        $this.result | ForEach-Object{     
            $obj+= [Blob]::new($_.Name, $_);                  
        }         
        return $obj     
    }
}

[SHiPSProvider(UseCache=$true)]
class Files : SHiPSDirectory
{
    Hidden [object]$data = $null
    Hidden [object]$result = $null

    Files ([object]$data, [object]$result) : base ($this.GetType()) 
    {
        $this.data = $data
        $this.result = $result        
    }

    [object[]] GetChildItem()
    {      
        if(-not $this.result)
        {
            Write-Debug "AzurePSDrive: No Files found."
            return $null
        }

        <# ConnectionString from cmdlet returns something like below:
            BlobEndpoint=https://<accountname>.blob.core.windows.net/;QueueEndpoint=https://<accountname>.queue.core.windows.net/;
            TableEndpoint=https://<accountname>.table.core.windows.net/;FileEndpoint=https://<accountname>.file.core.windows.net/;AccountName=<accountname>;AccountKey=<token>
        #>

        # Parse the orginal connection string, extract FileEndpoint, and make it net use-able.
        $conectstring = $this.data.Context.ConnectionString -split ';'
        $accountInfo=$conectstring | Where-Object { $_ -match 'AccountName' -or $_ -match 'AccountKey'}
        $fileEndPoint = $conectstring  | Where-Object {$_ -match 'FileEndpoint'}
        $fileshare = $fileEndPoint

        if($fileEndPoint) {
            $index = $fileEndPoint.IndexOf('//')
            if ($index -gt 0) {
                $temp = $fileEndPoint.Substring($index)
                if($temp) {
                    $fileshare = $temp.Replace('/', '\') 
                }   
            }
        }

        return  $this.result | ForEach-Object {           
             [FileShare]::new($_.Name, $this.data.Context, "$fileshare$($_.Name);$($accountInfo)");
            }
    }
}

[SHiPSProvider(UseCache=$true)]
class Tables : SHiPSDirectory
{
    Hidden [object]$data = $null
    Hidden [object]$result = $null

    Tables ([object]$data, [object]$result) : base ($this.GetType()) 
    {
        $this.data = $data
        $this.result = $result        
    }

    [object[]] GetChildItem()
    {     
        return @($this.result | Sort-Object Name)    
    }
}

[SHiPSProvider(UseCache=$true)]
class Queues : SHiPSDirectory
{
    Hidden [object]$data = $null
    Hidden [object]$result = $null

    Queues ([object]$data, [object]$result) : base ($this.GetType()) 
    {
        $this.data = $data
        $this.result = $result                
    }

    [object[]] GetChildItem()
    {     
        return @($this.result | Sort-Object Name)  
    }
}

[SHiPSProvider(UseCache=$true)]
class FileShare : SHiPSDirectory
{ 
    Hidden [string]$shareName = $null
    [object]$Context = $null
    [string]$ConnectionString = $null

    FileShare ([string]$name, [object]$context, [string]$connectionString) : base ($name) 
    {
        $this.shareName = $name        
        $this.context = $context
        $this.ConnectionString = $connectionString
    }

    [object[]] GetChildItem()
    {
        $obj =  @()

        & "$script:Azure_Storage\Get-AzureStorageFile" -Context $this.context -ShareName $this.shareName | ForEach-Object {
            if($_.GetType().Name -eq "CloudFileDirectory") {
                $obj+=[FileFolder]::new($_.Name, $_)
            } else {
                $obj+=[FileShareLeaf]::new($_.Name)
            }
        }

        return $obj
    }
}

class FileShareLeaf : SHiPSLeaf
{
    FileShareLeaf([string]$name): base($name)
    {
    }
}

[SHiPSProvider(UseCache=$true)]
class FileFolder : SHiPSDirectory
{
    Hidden [string]$DirectoryName = $null
    Hidden [object]$CloudFileDirectory = $null

    FileFolder ([string]$name, [object]$cloudFileDirectory) : base ($name) 
    {
        $this.DirectoryName = $name
        $this.CloudFileDirectory = $cloudFileDirectory
    }


    [object[]] GetChildItem()
    { 
        $obj =  @()

        & "$script:Azure_Storage\Get-AzureStorageFile" -Directory $this.CloudFileDirectory | ForEach-Object {
            if($_.GetType().Name -eq "CloudFileDirectory") {
                $obj+=[FileFolder]::new($_.Name, $_)
            } else {
                $obj+=[FileShareLeaf]::new($_.Name)
            }
        }
        return $obj
    }
}

[SHiPSProvider(UseCache=$true)]
class Blob : SHiPSDirectory
{ 
    Hidden [object]$data = $null

    Blob ([string]$name, [object]$data) : base ($name) 
    {
        $this.data = $data
    }

    [object[]] GetChildItem()
    {      
        return @(& "$script:Azure_Storage\Get-AzureStorageBlob" -Context $this.data.Context -Container $this.data.Name | Sort-Object Name)
    }
}


# SIG # Begin signature block
# MIIjOQYJKoZIhvcNAQcCoIIjKjCCIyYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUblNZmZ2HiAGaJFTHukMXAJTu
# dNeggh4HMIIE2jCCA8KgAwIBAgITMwAAAOdIFbo9kmu+3AAAAAAA5zANBgkqhkiG
# 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw
# HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTgwMTMxMTkwMzA5
# WhcNMTgwOTA3MTkwMzA5WjCByjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEm
# MCQGA1UECxMdVGhhbGVzIFRTUyBFU046QTI0MC00QjgyLTEzMEUxJTAjBgNVBAMT
# HE1pY3Jvc29mdCBUaW1lLVN0YW1wIHNlcnZpY2UwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQDMp9j7gZ5MlOq2SDpndZh+CYb9vq30TqocAVEDAcvH2v9J
# mJU6VemqWp+5Rn/5stiWlACt2KOXzjwmvJTYfFsXS9E4OFWj2okRtlcIxZhrs2Km
# FLqiZgGA0VR1wC1HWX4dSEqlLOI6hKi7VF2ieP4ihT6ESO3pSnzCoEpEeRG6eHds
# tIxdoJ2BQBYg47NPD8XjOXPCpQTG7Q1eDEGBaeCIDW7hU/OPEM92Q9qlIFeMj7ok
# 0f0EsBeSSuFnlyM63wWUIcr4VlAluqF1eFWOgmaFKgYfBQs77/upDY4N9PtIV+pA
# Kvw53l31/wZCRFcR2n/YV1Uvt1wTWvH4Bqsg07c5AgMBAAGjggEJMIIBBTAdBgNV
# HQ4EFgQUrbvUvBXRCTGrDOnDJeleAuatctwwHwYDVR0jBBgwFoAUIzT42VJGcArt
# QPt2+7MrsMM1sw8wVAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5taWNyb3Nv
# ZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljcm9zb2Z0VGltZVN0YW1wUENBLmNy
# bDBYBggrBgEFBQcBAQRMMEowSAYIKwYBBQUHMAKGPGh0dHA6Ly93d3cubWljcm9z
# b2Z0LmNvbS9wa2kvY2VydHMvTWljcm9zb2Z0VGltZVN0YW1wUENBLmNydDATBgNV
# HSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0BAQUFAAOCAQEAYBRDItxtl0ET2whe
# bDv6AXIO9f+YnQ6h4R3eEuJcgv/om3NtSylJzN8X1h1c3XEAZDUSfNXvKwpn4hpk
# l3GL4o1zlKcYHZMfFp6xCFOTHh0EN4ZAmW0gh1m60Kv9v98BNfPKyXDA9mgNiQtw
# 3I+HISmm2EH8zb6uUPLS7C27fH0JjAKMrcxZDcJK6rTFse2Al8aZrY7RA4yJhDC6
# GoIsPPxe74LGsef3Lg505bT9V1bSguIR+/xJeoMmQEGp64Yn+/aIkQ8QvbQHsHlX
# Xok1BhjQ24EB5A65qLmDeabhgwXBmAwuPRJxKKTLeCGosjIzMyF+wKNSIAi8bz1Z
# R2/+MzCCBZkwggOBoAMCAQICEHmtFqFKoKWtTHNY9AcTLmUwDQYJKoZIhvcNAQEF
# BQAwXzETMBEGCgmSJomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jv
# c29mdDEtMCsGA1UEAxMkTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9y
# aXR5MB4XDTAxMDUwOTIzMTkyMloXDTIxMDUwOTIzMjgxM1owXzETMBEGCgmSJomT
# 8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEtMCsGA1UEAxMk
# TWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEA8136gGfUWqepDCyQINA1CDx1hM23B4mcidre
# zsNg+pFoWp6UcSkYdnzC4MgldpQOWPoENDbm36/3gLrpWAsrk+WdBeN3IpH3NGQ8
# IpEdXuEJkLwU/vx1WBnhebcHkqOuiFkI2J8HygNY/GgpbTLX0qjLS/zhC0gyT+br
# uK1P5FxvE5SZ25XVdduoGreUkbR3W/VIDI9qeX0UcAR9ba+Q9dpw2Ee3v5svbOcF
# t+ERYKx5kRR8xdam5OF+1cN+5ZLSPAC1NoLeeeFt87Vu+J8zyctSfXOYNtuLoWui
# lZebo97CTSb/BpZnJQbI56zk7hIzlTGZyDUITjTKeVPVtb5jMllANsClTgRNPdtb
# BzPkWL/vP1Nk2EJZNVf9D0V8JARNntY4dBGXIpDOaER0km/VS2+whuPHNkKg0PzB
# wFr5o2G5MEdxlgoWsJHAQpXvEH8oauMqH7HkzQM/d3EExyD8SQ8dRYik18t+iK2O
# LexF28RRBMkq/OyGnpoRl1vezlOI5uK3/ayVwihA2+8EkN+BMznZskWlI4cGpVWJ
# MbsGLWAOQRh9Hy61l8sR6xXVJKWU7xUUif1Lc/oyW/zRMwD5WWJwBzLqLqtALXvK
# 3SFnGzCZjxaqI6hB0bBuEZs2xN5AdJzhWGXBYB56WzjIj7sEJnzUFkDltmtsqob9
# AL/OwTUCAwEAAaNRME8wCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
# VR0OBBYEFA6sgmBAVieX5SUT/CrhClOVWeSkMBAGCSsGAQQBgjcVAQQDAgEAMA0G
# CSqGSIb3DQEBBQUAA4ICAQDFEU0DOmDdXVIRd4+yuzbIsgW/tLeo2CCdXBMDthwi
# +gYTNbbIY9SaR28mV9JV8QSxJl/WqVBooLzSuG7Mw+ms3xnNeKxZdKxmNDbEGz5s
# OEwzDjASDaMm/lFTAP+vWk6EDQ8f5G0FLk6FS41sM29U0mSrv1CvfXo5oDftYwMP
# /BMGzhY21FQ7lRtRYjrlTRfUBTmSmieoW6q97Lu+4yCJYHFsVrOlE9BtDiN+lQPt
# aD3y2GO4a0226DC14cqUS/eiql2ZMLI9p8JRbCggASQnK0sAt50Ra3C+shCCvAyb
# aNCNOySHqpkocp0zX1mQvfXek546Ylo0OeKIVR25BrDBiWst12nDGRI2hNDJoNr/
# L2l4suV62uvXDMD3vWMXuDkTOKI2W3vyhVZqHWRiwTjiqr9RZqKU9RKcZiIQa/K3
# MJIt8inwPTsUQ2ii8ZwpN8vOOCAlbXxn834kEiQDCIFH7KWel/UY18+71e92lu/9
# zttWnZWgQvmXWOHXMSLTX1nmPm4iAOpDhLYl29nzCFZowGRrHXzstpOiYlduLtjn
# WI/EMUkm3d4pNYf1MHFwWxQ8ab2JEn3rLqP+2H+eglpSCivBQyvZMIifyBD7iY3m
# oYV1M35snttzE2RiaaUvfcqWbZ/4BE0wkj1uIRQhyT3gw/2Ka51K/dGhnZlDdz+w
# 2jCCBf8wggPnoAMCAQICEzMAAAEDXiUcmR+jHrgAAAAAAQMwDQYJKoZIhvcNAQEL
# BQAwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UE
# AxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMTAeFw0xODA3MTIyMDA4
# NDhaFw0xOTA3MjYyMDA4NDhaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xHjAcBgNVBAMTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjCCASIwDQYJ
# KoZIhvcNAQEBBQADggEPADCCAQoCggEBANGUdjbmhqs2/mn5RnyLiFDLkHB/sFWp
# JB1+OecFnw+se5eyznMK+9SbJFwWtTndG34zbBH8OybzmKpdU2uqw+wTuNLvz1d/
# zGXLr00uMrFWK040B4n+aSG9PkT73hKdhb98doZ9crF2m2HmimRMRs621TqMd5N3
# ZyGctloGXkeG9TzRCcoNPc2y6aFQeNGEiOIBPCL8r5YIzF2ZwO3rpVqYkvXIQE5q
# c6/e43R6019Gl7ziZyh3mazBDjEWjwAPAf5LXlQPysRlPwrjo0bb9iwDOhm+aAUW
# nOZ/NL+nh41lOSbJY9Tvxd29Jf79KPQ0hnmsKtVfMJE75BRq67HKBCMCAwEAAaOC
# AX4wggF6MB8GA1UdJQQYMBYGCisGAQQBgjdMCAEGCCsGAQUFBwMDMB0GA1UdDgQW
# BBRHvsDL4aY//WXWOPIDXbevd/dA/zBQBgNVHREESTBHpEUwQzEpMCcGA1UECxMg
# TWljcm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xFjAUBgNVBAUTDTIzMDAx
# Mis0Mzc5NjUwHwYDVR0jBBgwFoAUSG5k5VAF04KqFzc3IrVtqMp1ApUwVAYDVR0f
# BE0wSzBJoEegRYZDaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwv
# TWljQ29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNybDBhBggrBgEFBQcBAQRVMFMw
# UQYIKwYBBQUHMAKGRWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2Vy
# dHMvTWljQ29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNydDAMBgNVHRMBAf8EAjAA
# MA0GCSqGSIb3DQEBCwUAA4ICAQCf9clTDT8NJuyiRNgN0Z9jlgZLPx5cxTOjpMNs
# rx/AAbrrZeyeMxAPp6xb1L2QYRfnMefDJrSs9SfTSJOGiP4SNZFkItFrLTuoLBWU
# KdI3luY1/wzOyAYWFp4kseI5+W4OeNgMG7YpYCd2NCSb3bmXdcsBO62CEhYigIkV
# hLuYUCCwFyaGSa/OfUUVQzSWz4FcGCzUk/Jnq+JzyD2jzfwyHmAc6bAbMPssuwcu
# loSTRShUXM2W/aDbgdi2MMpDsfNIwLJGHF1edipYn9Tu8vT6SEy1YYuwjEHpqrid
# kPT/akIPuT7pDuyU/I2Au3jjI6d4W7JtH/lZwX220TnJeeCDHGAK2j2w0e02v0UH
# 6Rs2buU9OwUDp9SnJRKP5najE7NFWkMxgtrYhK65sB919fYdfVERNyfotTWEcfdX
# qq76iXHJmNKeWmR2vozDfRVqkfEU9PLZNTG423L6tHXIiJtqv5hFx2ay1//OkpB1
# 5OvmhtLIG9snwFuVb0lvWF1pKt5TS/joynv2bBX5AxkPEYWqT5q/qlfdYMb1cSD0
# UaiayunR6zRHPXX6IuxVP2oZOWsQ6Vo/jvQjeDCy8qY4yzWNqphZJEC4OmekB1+g
# /tg7SRP7DOHtC22DUM7wfz7g2QjojCFKQcLe645b7gPDHW5u5lQ1ZmdyfBrqUvYi
# xHI/rjCCBgcwggPvoAMCAQICCmEWaDQAAAAAABwwDQYJKoZIhvcNAQEFBQAwXzET
# MBEGCgmSJomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEt
# MCsGA1UEAxMkTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X
# DTA3MDQwMzEyNTMwOVoXDTIxMDQwMzEzMDMwOVowdzELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMYTWljcm9zb2Z0IFRpbWUtU3Rh
# bXAgUENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn6Fssd/bSJIq
# fGsuGeG94uPFmVEjUK3O3RhOJA/u0afRTK10MCAR6wfVVJUVSZQbQpKumFwwJtoA
# a+h7veyJBw/3DgSY8InMH8szJIed8vRnHCz8e+eIHernTqOhwSNTyo36Rc8J0F6v
# 0LBCBKL5pmyTZ9co3EZTsIbQ5ShGLieshk9VUgzkAyz7apCQMG6H81kwnfp+1pez
# 6CGXfvjSE/MIt1NtUrRFkJ9IAEpHZhEnKWaol+TTBoFKovmEpxFHFAmCn4TtVXj+
# AZodUAiFABAwRu233iNGu8QtVJ+vHnhBMXfMm987g5OhYQK1HQ2x/PebsgHOIktU
# //kFw8IgCwIDAQABo4IBqzCCAacwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
# IzT42VJGcArtQPt2+7MrsMM1sw8wCwYDVR0PBAQDAgGGMBAGCSsGAQQBgjcVAQQD
# AgEAMIGYBgNVHSMEgZAwgY2AFA6sgmBAVieX5SUT/CrhClOVWeSkoWOkYTBfMRMw
# EQYKCZImiZPyLGQBGRYDY29tMRkwFwYKCZImiZPyLGQBGRYJbWljcm9zb2Z0MS0w
# KwYDVQQDEyRNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCEHmt
# FqFKoKWtTHNY9AcTLmUwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC5taWNy
# b3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvbWljcm9zb2Z0cm9vdGNlcnQuY3Js
# MFQGCCsGAQUFBwEBBEgwRjBEBggrBgEFBQcwAoY4aHR0cDovL3d3dy5taWNyb3Nv
# ZnQuY29tL3BraS9jZXJ0cy9NaWNyb3NvZnRSb290Q2VydC5jcnQwEwYDVR0lBAww
# CgYIKwYBBQUHAwgwDQYJKoZIhvcNAQEFBQADggIBABCXisNcA0Q23em0rXfbznlR
# TQGxLnRxW20ME6vOvnuPuC7UEqKMbWK4VwLLTiATUJndekDiV7uvWJoc4R0Bhqy7
# ePKL0Ow7Ae7ivo8KBciNSOLwUxXdT6uS5OeNatWAweaU8gYvhQPpkSokInD79vzk
# eJkuDfcH4nC8GE6djmsKcpW4oTmcZy3FUQ7qYlw/FpiLID/iBxoy+cwxSnYxPSty
# C8jqcD3/hQoT38IKYY7w17gX606Lf8U1K16jv+u8fQtCe9RTciHuMMq7eGVcWwEX
# ChQO0toUmPU8uWZYsy0v5/mFhsxRVuidcJRsrDlM1PZ5v6oYemIp76KbKTQGdxpi
# yT0ebR+C8AvHLLvPQ7Pl+ex9teOkqHQ1uE7FcSMSJnYLPFKMcVpGQxS8s7OwTWfI
# n0L/gHkhgJ4VMGboQhJeGsieIiHQQ+kr6bv0SMws1NgygEwmKkgkX1rqVu+m3pmd
# yjpvvYEndAYR7nYhv5uCwSdUtrFqPYmhdmG0bqETpr+qR/ASb/2KMmyy/t9RyIwj
# yWa9nR2HEmQCPS2vWY+45CHltbDKY7R4VAXUQS5QrJSwpXirs6CWdRrZkocTdSIv
# MqgIbqBbjCW/oO+EyiHW6x5PyZruSeD3AWVviQt9yGnI5m7qp5fOMSn/DsVbXNhN
# G6HY+i+ePy5VFmvJE6P9MIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkqhkiG
# 9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy
# MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw
# MTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29k
# ZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
# AgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03a8YS
# 2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akrrnoJ
# r9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0RrrgOGSs
# bmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy4BI6
# t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9sbKv
# kjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAhdCVf
# GCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8kA/DR
# elsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTBw3J6
# 4HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmnEyim
# p31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90lfdu
# +HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0wggHp
# MBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2oynUC
# lTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0T
# AQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBaBgNV
# HR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9w
# cm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsGAQUF
# BwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNVHSAE
# gZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5t
# aWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsGAQUF
# BwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABlAG0A
# ZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKbC5YR
# 4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11lhJB9
# i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6I/MT
# faaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0wI/z
# Rive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560STkK
# xgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQamASoo
# PoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGaJ+HN
# pZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ahXJbY
# ANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA9Z74
# v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33VtY5E9
# 0Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr/Xmf
# wb1tbWrJUnMTDXpQzTGCBJwwggSYAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTECEzMAAAEDXiUcmR+jHrgAAAAAAQMwCQYFKw4DAhoFAKCBsDAZ
# BgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYB
# BAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUqi+ffv08AuUNbBxi+AoOS0smAKUwUAYK
# KwYBBAGCNwIBDDFCMECgFoAUAFAAbwB3AGUAcgBTAGgAZQBsAGyhJoAkaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL1Bvd2VyU2hlbGwgMA0GCSqGSIb3DQEBAQUABIIB
# AI4JTdjYt31MOBMJEI3wZKxa5ImGZTpWvqosSlanUDihS/hw/jPZs8CQq1YYKU83
# 0j3/gZDvJRDuLz2GC15bKRukEaaZsQTiC/3nFSeUZBMGGmbDtKjArJ0wBv/eHTjA
# aJ2AtVCde5aU2V+2AlPo74XC8r1nxGUo6YApJCz+33zS1m4KAJtjeBPnHqJ6hgGC
# K38Meoa8ygp38P8ISfZsOnMRjRVlvWugW10GWrRn21wrsVA4FWiIZJe8Cc8OwMJ5
# yuyLvudpSxJc/erIXfx4WtULmou+PvAu4HPPhtQQBhGAsNg355x947zL5fw6ELw6
# 4s9BYkSZMYG9oOUNIDmHM9ChggIoMIICJAYJKoZIhvcNAQkGMYICFTCCAhECAQEw
# gY4wdzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UE
# AxMYTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBAhMzAAAA50gVuj2Sa77cAAAAAADn
# MAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3
# DQEJBTEPFw0xODA3MTcyMjUwMDJaMCMGCSqGSIb3DQEJBDEWBBSdDgm1jqmMmVt2
# 5J1OYEiNsJ6BwjANBgkqhkiG9w0BAQUFAASCAQCPOpyIzhaet+zxQgf3hnuNLs6b
# 9Nm6UpLgM37ThL6gVAUJhmtauA9rq/YEV5Ul02xUhJ+zMDEnF9XzKwAKLlUX2GKw
# XpXFgYtKTGKJvasiwqJQJcTyPkIUgFQKn2cSN4Gegcs3nAnSH65j+152LnsJFydZ
# kgnJkOrVVG9wkY9+UbXXnMs8tgYEbeg/cDsCnQ5KRuYVLAbbtfWHQ6YJa6iNKaPp
# USq9gGVajzdWLyRSzt961zDE2bbWFGojv9IHgZcSCQi8ghwX7HV6QDQVl5keJWwE
# g5dkBthwgF1lDj/haMUT3nRaYtQZKiUrqdLPyGWxEuiono4AKvtJa7j4XeR2
# SIG # End signature block