NestedModules/SkypeOnlineConnector/SkypeOnlineConnectorStartup.psm1

# This script contains the custom function that creates the new-pssession using the webticket
function New-CsOnlineSession()
{
    <#
    .SYNOPSIS
    Creates a persistent connection to Microsoft Skype For Business Online DataCenter.
 
    .Description
     Creates a remote session to Microsoft Skype For Business Online DataCenter. In this session, tenant administrator can run Skype For Business cmdlets to manage users, policies and configurations.
 
    .Parameter Credential
 
    Specifies a user account that is Tenant Administrator, or Syndicated Partner Administrator.
 
    Type a user name, such as "User@Domain.com", or enter a PSCredential object, such as one returned by the Get-Credential cmdlet.
 
    When you type a user name, you will be prompted for a password.
 
    .Parameter OverrideAdminDomain
 
    Specifies a domain to be managed. This could be home domain of signed in user, or a different one that he/she has permission to manage. Optional.
 
    .Parameter OverrideDiscoveryUri
 
    Specifies Skype For Business Auto Discovery URI. Optional.
 
    .Parameter OverridePowershellUri
 
    Specifies Skype For Business Remote Powershell URI. Optional.
 
    .Parameter SessionOption
 
    Sets advanced options for the session. Enter a SessionOption object, such as one that you create by using the New-PSSessionOption cmdlet, or a hash table in which the keys are session option names and the values are session option values.
 
    .EXAMPLE
    New-CsOnlineSession -Credential User@Domain.com
 
    Establishes a Skype For Business Remote PowerShell Session, supplying the credentials of an administrator account of the tenant.
 
    .EXAMPLE
    New-CsOnlineSession -Credential User@Domain.com -OverrideAdminDomain TargetDomain.com
 
    Establishes a Skype For Business Remote PowerShell Session, with an administrator account that has permission to manage the tenant TargetDomain.com.
    Please change the OverrideAdminDomain to your target Tenant domain.
 
 
    #>


    [CmdletBinding(DefaultParameterSetName="UserName")]
    param
    (
        [Parameter(Mandatory = $false, Position=0, ParameterSetName="UserName")] [string] $UserName,
        [Parameter(Mandatory = $false, Position=0, ParameterSetName="Credential")] [PSCredential] [System.Management.Automation.Credential()] $Credential,
        [Parameter(Mandatory = $false)] [string] $OverrideAdminDomain,
        [Parameter(Mandatory = $false)] [Uri] $OverrideDiscoveryUri,
        [Parameter(Mandatory = $false)] [Uri] $OverridePowershellUri,
        [Parameter(Mandatory = $false)] [System.Management.Automation.Remoting.PSSessionOption] $SessionOption
    )

    $ConsentRequiredErrorCode = "65001"

    $ErrorActionPreference = "Stop"
    Import-LocalizedData -BindingVariable resources -FileName SkypeOnlineConnectorPSResources.psd1

    $path = Split-Path -parent $PSCommandPath
    Add-Type -Path (Join-Path -Path $path -ChildPath Microsoft.IdentityModel.Clients.ActiveDirectory.dll)
    Add-Type -Path (Join-Path -Path $path -ChildPath Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll)

    if ($OverrideAdminDomain)
    {
        $adminDomain = $OverrideAdminDomain
    }
    else
    {
        Write-Verbose $resources.DetermineDomain

        if ($Credential) {
          $UserName = $Credential.UserName
        }
        elseif (!$UserName) {
          $UserName = Read-Host -Prompt $resources.EnterUserName
        }

        try{
            $adminDomain = ([System.Net.Mail.MailAddress]$UserName).Host
        }catch{
            throw ($resources.WrongUserName -f $($UserName))
        }
    }

    $adminDomain = $adminDomain.Trim()
    Write-Verbose "AdminDomain = '$adminDomain'"

    if ($OverridePowershellUri)
    {
        $targetUri = $OverridePowershellUri
    }
    else
    {
        if ($OverrideDiscoveryUri)
        {
            Write-Verbose ($resources.DiscoveringEndpointWithURI -f $OverrideDiscoveryUri)
            $targetUri = Get-CsPowerShellEndpoint -TargetDomain $adminDomain -OverrideDiscoveryUri $OverrideDiscoveryUri
        }
        else
        {
            Write-Verbose $resources.DiscoveringEndpoint
            $targetUri = Get-CsPowerShellEndpoint -TargetDomain $adminDomain
        }
    }

    if (!$targetUri)
    {
        throw $resources.DiscoveringEndpointFail
    }
    Write-Verbose "TargetUri = '$targetUri'"

    $appAuthInfo = Get-AuthUri -targetUri $targetUri
    $authUri = $appAuthInfo.authUri
    $clientId = $appAuthInfo.clientId

    Write-Verbose "AuthUri = $authUri, ClientId = $clientId"

    Write-Verbose $resources.RequestAuthToken

    try
    {
      $accessToken = Get-CsAccessToken -UserName $UserName -TargetUri $targetUri -AuthUri $authUri -ClientId $clientId -Credential $Credential
    }
    catch [Microsoft.Rtc.Management.OnlineConnector.ConsentRequiredException]
    {
      Write-Error ($resources.ConsentRequired + " " + $_.Exception.ApplicationLoginUri)
      return
    }
    Write-Verbose $resources.AcquiredAccessToken

    $user = "oauth"
    $pass = ConvertTo-SecureString -AsPlainText $AccessToken -Force
    $cred = New-Object System.Management.Automation.PSCredential $user,$pass

    Write-Verbose $resources.InitRemoteSession

    $ConnectionUri = [UriBuilder]$targetUri
    $ConnectionUri.Query = "AdminDomain=$adminDomain;ConnectorVersion=$($resources.ConnectorVersion)"

    $extraParams=@{}
    if ($SessionOption)
    {
        $extraParams["SessionOption"] = $SessionOption
    }

    $session = New-PSSession -ConnectionUri $ConnectionUri.Uri -Credential $cred -Authentication Basic @extraParams
    Write-Verbose $resources.CreatedPowerShellSession

    return $session
}

Function Set-WinRMNetworkDelayMS
{
    <#
    .SYNOPSIS
    Changes the WinRM setting for the NetworkDelayms property (WSMan:\localhost\Client\NetworkDelayms).
 
    .Description
    The Skype For Business Online Connector connects to Skype For Business Remote PowerShell Server in order to establish a remote session. Sometimes this remote session can be broken because of network delay. To help address this problem, Skype For Business recommends setting NetworkDelayms to 30000 milliseconds (30 seconds) instead of the default value of 5000 milliseconds (5 seconds).
 
    .Parameter value
 
    Value of the NetworkDelayms property in milliseconds (there are 1000 milliseconds in each second). This must be an integer value.
 
    .EXAMPLE
    Set-WinRMNetworkDelayMS 30000
 
    This example sets the NetworkDelayms property (WSMan:\localhost\Client\NetworkDelayms) to 30000 milliseconds (30 seconds).
 
    #>


  param
  (
    [Parameter(Mandatory = $false)] [string] $value="30000"
  )

  $networkDelay = Get-Item WSMan:\localhost\Client\NetworkDelayms

  if($networkDelay -eq $null)
  {
    # If cannot get NetworkDelayms due to permission or other reason, just return.
    return
  }

  $oldValue = $networkDelay.Value
  $newValue = $value

  if($newValue -ne $oldValue)
  {
    Set-Item WSMan:\localhost\Client\NetworkDelayms $newValue

    # Warns the user that running this command has changed their client setting.
    #Write-Warning ($resources.WSManSettingAltered -f $newValue, $oldValue)
    #Write-Warning $resources.WSManSettingAlteredReason
  }
}

function Get-AuthUri($targetUri) {
  $response = $null
  $responseException = $null

  try
  {
      $response = Invoke-WebRequest $targetUri
  }
  catch
  {
      $responseException = $_.Exception
      $response = $_.Exception.Response
  }

  if ($response -eq $null)
  {
      throw ($resources.AuthUriAcquisitionFail -f $targetUri)
  }

  if ($response.StatusCode -ne 401)
  {
      $message = ($resources.UnexpectedResponseFromServer -f $response.StatusCode)
      throw (New-Object -TypeName System.ArgumentOutOfRangeException -ArgumentList $message, $responseException)
  }

  $header = $response.Headers["WWW-Authenticate"]
  if (-not $header)
  {
      throw $resources.CannotFindAuthHeader
  }

  $authUri = $null;
  if ($header -match 'authorization_uri="(.*?)"')
  {
      $authUri = $matches[1]
  }
  else
  {
      throw $resources.CannotFindUriInAuthHeader
  }

  $clientId = [GUID]::Empty;
  if ($header -match 'client_id="(.*?)"')
  {
      if ([GUID]::TryParse($matches[1], [Ref] $clientId) -eq $false)
      {
        throw $resources.ClientIdNotGUIDInAuthHeader
      }
  }
  else
  {
      throw $resources.CannotFindClientIdInAuthHeader
  }

  $appAuthInfo = New-Object PsObject -Property @{authUri=$authUri ; clientId=$clientId}

  return $appAuthInfo
}

Export-ModuleMember New-CsOnlineSession,Set-WinRMNetworkDelayMS

# Call once when loading the module, do SilentlyContinue on error because this function should not block OnlineConnector if it fails.
Set-WinRMNetworkDelayMS -ErrorAction SilentlyContinue

# SIG # Begin signature block
# MIIdqgYJKoZIhvcNAQcCoIIdmzCCHZcCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUNAjM49gDvuYMS0njuY3DUbcr
# iRigghhUMIIEwjCCA6qgAwIBAgITMwAAALu2dyRxSiAAIAAAAAAAuzANBgkqhkiG
# 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw
# HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTYwOTA3MTc1ODQ3
# WhcNMTgwOTA3MTc1ODQ3WjCBsjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjEMMAoGA1UECxMDQU9DMScwJQYDVQQLEx5uQ2lwaGVyIERTRSBFU046
# MERFOC0yREM1LTNDQTkxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNl
# cnZpY2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC48+U38sLxQNu8
# OO1wnT9mKeHv+f/jxafTFXzx9VF59IK/n/jLv4HIXt8ucy3KjBTM5Jf6D0nQlI4h
# Sizjrn6lO61q+V8oZiYYhjgR258rg8MDIrPpZMxK6OmD0d1wtksHW1cG21YKg5jg
# idT2hmQBpiL9Cra3ccY5keu0kl6OfZFoj4DF0i0JRVFSy1C9gKP4H950XIjlA2Yo
# TWN0LuHEHYMvwD1mOpAq2dVwPZh6xeNnpV8U/qLneyb9I/SqY/87tsZCn4FH7R3x
# 0TgK2eRwpWXfwGbUb1R/UTLd20aQ+my4NWwSsndeG+0vsYwaF40heB2lo1ThmByr
# OTBmEosTAgMBAAGjggEJMIIBBTAdBgNVHQ4EFgQUj9yNX+4+R8GZ7rcy4MdnJHXO
# KkswHwYDVR0jBBgwFoAUIzT42VJGcArtQPt2+7MrsMM1sw8wVAYDVR0fBE0wSzBJ
# oEegRYZDaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
# TWljcm9zb2Z0VGltZVN0YW1wUENBLmNybDBYBggrBgEFBQcBAQRMMEowSAYIKwYB
# BQUHMAKGPGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljcm9z
# b2Z0VGltZVN0YW1wUENBLmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG
# 9w0BAQUFAAOCAQEAcMI8Q0PxQVvxZSD1fjszuD6VF/qPZjKZj9WLTjWjZT2k9lzG
# yvSL7vy9J7lnyMATrbm5ptqAfdonNygLaBm05MnrIvgPJYK89wyTIyS1u71ro7z+
# EVrGPaKZiD+WvH8SWP+OWZQNf55fEL8tZo+a1oHm3lUARi5rR916OQvb4UnCENyV
# g8IfmupnwpxHcmIBUWZtTKAuKmuX/c8G2z4KJ8WhruYjPDWYQXJrQ5t7PhZa19Ge
# kOOtigge9EKIAWhZUJkw9fnfRm2IFX0gWtOzRXVNhR109ISacbNxd0oUboRYHmlq
# wGrOz64/3SDdOeN7PjvLwFmThuoXIsxrjQD8ODCCBgEwggPpoAMCAQICEzMAAADE
# 6Yn4eoFQ6f8AAAAAAMQwDQYJKoZIhvcNAQELBQAwfjELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2ln
# bmluZyBQQ0EgMjAxMTAeFw0xNzA4MTEyMDIwMjRaFw0xODA4MTEyMDIwMjRaMHQx
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xHjAcBgNVBAMTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
# ggEBAIiKuCTDB4+agHkV/CZg/HKILPr0o5eIlka3o8tfiS86My4ekXj6fKkfggG1
# essavAPKRuvFmff7BB3yhQr/Im6h8mc9xScY5Sgf9QSUQWPs47oVjO0TmjXeOHBU
# bzvsrUUJMEnBvo8wmQzLdsn3c5UWd9GLu5THCIUg7R6oNfFxwuB0AEuK0tyR69Z4
# /o36rWCIPb25H65il7/FhLGQrtavK9NU+zXazXGS5h7/7HFry38IdnTgEFFI1PEA
# yEhMowc15VkN/XycyOZa44X11poPH46m5IQXwdbKnx0Bx/1IpxOSM5chSDL4wiSi
# ALK+U8qDbilbge84boDzu+wTC+sCAwEAAaOCAYAwggF8MB8GA1UdJQQYMBYGCisG
# AQQBgjdMCAEGCCsGAQUFBwMDMB0GA1UdDgQWBBTL1mKEz2A56v9nwlzSyLurt8MT
# mDBSBgNVHREESzBJpEcwRTENMAsGA1UECxMETU9QUjE0MDIGA1UEBRMrMjMwMDEy
# K2M4MDRiNWVhLTQ5YjQtNDIzOC04MzYyLWQ4NTFmYTIyNTRmYzAfBgNVHSMEGDAW
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
# AAYWH9tXwlDII0+iUXjX7fj9zb3VwPH5G1btU8hpRwXVxMvs4vyZW5VfETgowAVF
# E+CaeYi8Zqvbu+sCVSO3PSN4QW2u+PEAWpSZihzMCZXQmhxEMKmlFse6R1v1KzSL
# n49YN8NOHK8iyhDN2IIQqTXwriLIjySmgYvfJxzkZh2JPi7/VwNNwW6DoDLrtLMv
# UFZdBrEVjMgdY7dzDOPWeiYPKpZFpzKDPpY+V0l3I4n+sRDHiuUIFVHFK1oxWzlq
# lqikiGuWKG/xxK7qvUUXzGJOgbVUGkeOmKVtwG4nxvgnH8jtIKkLsfHOC5qU4mqd
# aYOhNtdtIP6F1f/DuJc2Cf49FMGYFKnAhszvgsGrVSRDGLVIhXiG0PnSnT8Z2RSJ
# 542faCSIaDupx4BOJucIIUxj/ZyTFU0ztVZgT9dKuTiO/y7dsV+kQ2vJeM+xu2uP
# g2yHcqrqpfuf3RrWOfxkyW0+COV8g7GtvKO6e8+WVqR6WMsSR2LSIe/8PMQxC/cv
# PmSlN29gUD+3RJBPoAuLvn5Y9sdnh2HbnpjEyIzLb0fhwC6U7bH2sDBt7GpJqOmW
# dsi9CMT+O/WuczcGslbPGdS79ZTKhxzygGoBT7YbgXOz01siPzpYGN+I7mfESacv
# 3CWLPV7Q7DREkR28kQx2gj7vxNgtoQQCjkj5790CzwOiMIIGBzCCA++gAwIBAgIK
# YRZoNAAAAAAAHDANBgkqhkiG9w0BAQUFADBfMRMwEQYKCZImiZPyLGQBGRYDY29t
# MRkwFwYKCZImiZPyLGQBGRYJbWljcm9zb2Z0MS0wKwYDVQQDEyRNaWNyb3NvZnQg
# Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcwNDAzMTI1MzA5WhcNMjEw
# NDAzMTMwMzA5WjB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ
# MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MSEwHwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwggEiMA0GCSqGSIb3
# DQEBAQUAA4IBDwAwggEKAoIBAQCfoWyx39tIkip8ay4Z4b3i48WZUSNQrc7dGE4k
# D+7Rp9FMrXQwIBHrB9VUlRVJlBtCkq6YXDAm2gBr6Hu97IkHD/cOBJjwicwfyzMk
# h53y9GccLPx754gd6udOo6HBI1PKjfpFzwnQXq/QsEIEovmmbJNn1yjcRlOwhtDl
# KEYuJ6yGT1VSDOQDLPtqkJAwbofzWTCd+n7Wl7PoIZd++NIT8wi3U21StEWQn0gA
# SkdmEScpZqiX5NMGgUqi+YSnEUcUCYKfhO1VeP4Bmh1QCIUAEDBG7bfeI0a7xC1U
# n68eeEExd8yb3zuDk6FhArUdDbH895uyAc4iS1T/+QXDwiALAgMBAAGjggGrMIIB
# pzAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQjNPjZUkZwCu1A+3b7syuwwzWz
# DzALBgNVHQ8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwgZgGA1UdIwSBkDCBjYAU
# DqyCYEBWJ5flJRP8KuEKU5VZ5KShY6RhMF8xEzARBgoJkiaJk/IsZAEZFgNjb20x
# GTAXBgoJkiaJk/IsZAEZFgltaWNyb3NvZnQxLTArBgNVBAMTJE1pY3Jvc29mdCBS
# b290IENlcnRpZmljYXRlIEF1dGhvcml0eYIQea0WoUqgpa1Mc1j0BxMuZTBQBgNV
# HR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9w
# cm9kdWN0cy9taWNyb3NvZnRyb290Y2VydC5jcmwwVAYIKwYBBQUHAQEESDBGMEQG
# CCsGAQUFBzAChjhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01p
# Y3Jvc29mdFJvb3RDZXJ0LmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG
# 9w0BAQUFAAOCAgEAEJeKw1wDRDbd6bStd9vOeVFNAbEudHFbbQwTq86+e4+4LtQS
# ooxtYrhXAstOIBNQmd16QOJXu69YmhzhHQGGrLt48ovQ7DsB7uK+jwoFyI1I4vBT
# Fd1Pq5Lk541q1YDB5pTyBi+FA+mRKiQicPv2/OR4mS4N9wficLwYTp2Oawpylbih
# OZxnLcVRDupiXD8WmIsgP+IHGjL5zDFKdjE9K3ILyOpwPf+FChPfwgphjvDXuBfr
# Tot/xTUrXqO/67x9C0J71FNyIe4wyrt4ZVxbARcKFA7S2hSY9Ty5ZlizLS/n+YWG
# zFFW6J1wlGysOUzU9nm/qhh6YinvopspNAZ3GmLJPR5tH4LwC8csu89Ds+X57H21
# 46SodDW4TsVxIxImdgs8UoxxWkZDFLyzs7BNZ8ifQv+AeSGAnhUwZuhCEl4ayJ4i
# IdBD6Svpu/RIzCzU2DKATCYqSCRfWupW76bemZ3KOm+9gSd0BhHudiG/m4LBJ1S2
# sWo9iaF2YbRuoROmv6pH8BJv/YoybLL+31HIjCPJZr2dHYcSZAI9La9Zj7jkIeW1
# sMpjtHhUBdRBLlCslLCleKuzoJZ1GtmShxN1Ii8yqAhuoFuMJb+g74TKIdbrHk/J
# mu5J4PcBZW+JC33Iacjmbuqnl84xKf8OxVtc2E0bodj6L54/LlUWa8kTo/0wggd6
# MIIFYqADAgECAgphDpDSAAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQg
# Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDla
# Fw0yNjA3MDgyMTA5MDlaMH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEw
# ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS6
# 8rZYIZ9CGypr6VpQqrgGOBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15
# ZId+lGAkbK+eSZzpaF7S35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+er
# CFDPs0S3XdjELgN1q2jzy23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVc
# eaVJKecNvqATd76UPe/74ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGM
# XeiJT4Qa8qEvWeSQOy2uM1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/
# U7qcD60ZI4TL9LoDho33X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwj
# p6lm7GEfauEoSZ1fiOIlXdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwC
# gl/bwBWzvRvUVUvnOaEP6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1J
# MKerjt/sW5+v/N2wZuLBl4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3co
# KPHtbcMojyyPQDdPweGFRInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfe
# nk70lrC8RqBsmNLg1oiMCwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAw
# HQYDVR0OBBYEFEhuZOVQBdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoA
# UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQY
# MBaAFHItOgIxkEO5FAVO4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6
# Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1
# dDIwMTFfMjAxMV8wM18yMi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAC
# hkJodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1
# dDIwMTFfMjAxMV8wM18yMi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4D
# MIGDMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz
# L2RvY3MvcHJpbWFyeWNwcy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBs
# AF8AcABvAGwAaQBjAHkAXwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcN
# AQELBQADggIBAGfyhqWY4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjD
# ctFtg/6+P+gKyju/R6mj82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw
# /WvjPgcuKZvmPRul1LUdd5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkF
# DJvtaPpoLpWgKj8qa1hJYx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3z
# Dq+ZKJeYTQ49C/IIidYfwzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEn
# Gn+x9Cf43iw6IGmYslmJaG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1F
# p3blQCplo8NdUmKGwx1jNpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0Qax
# dR8UvmFhtfDcxhsEvt9Bxw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AAp
# xbGbpT9Fdx41xtKiop96eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//W
# syNodeav+vyL6wuA6mk7r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqx
# P/uozKRdwaGIm1dxVk5IRcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIEwDCC
# BLwCAQEwgZUwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEo
# MCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAMTp
# ifh6gVDp/wAAAAAAxDAJBgUrDgMCGgUAoIHUMBkGCSqGSIb3DQEJAzEMBgorBgEE
# AYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJ
# BDEWBBTdsZvPGFHoqxMlhri/RpOh1IE5SjB0BgorBgEEAYI3AgEMMWYwZKBCgEAA
# UwBrAHkAcABlAE8AbgBsAGkAbgBlAEMAbwBuAG4AZQBjAHQAbwByAFMAdABhAHIA
# dAB1AHAALgBwAHMAbQAxoR6AHGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS91YyAw
# DQYJKoZIhvcNAQEBBQAEggEASE+yA09EVXBi9peS23sYkBAjRwjFBhiHJGydC3Ni
# r7xvgwIR8c30sWtKvdB2eorHMtUvb7AoF/xFNmeKj4FH6EXlE1jIHkjZgjq300uS
# jsRBZ3gyMfw6HSMeFHBZjorcad9+uK//VpF2TeIX8XyKNtI/wCVOrWhBwRe1E4aA
# PixZ9ANHkaPHB8rp1CmiAknK1MKSMyzlmIoCVidtAI+bu4/z+fzLd8vGV3v68FWP
# ThN80XSwPSC9EtRLbvrgbsaC5B5h9+WdBaRK4xzbE87qqskJUp0DmV4aHtEOg7iO
# DZnV1Z0wJK2R7EPj4w2BwJSx0QANI0I6fXWVhPGHh6/6PaGCAigwggIkBgkqhkiG
# 9w0BCQYxggIVMIICEQIBATCBjjB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0ECEzMA
# AAC7tnckcUogACAAAAAAALswCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkq
# hkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE4MDIyMTIxMjUyNlowIwYJKoZIhvcN
# AQkEMRYEFNHAcXdPhLyXWpvUs1k0D+GArD+6MA0GCSqGSIb3DQEBBQUABIIBAD2g
# GzjIhBtiSbpWSUTJKUkP0m/GuympBkg3r43Vf5EHAUEkyLTHz/KGDU3Y1j8b/v6h
# rTmVrBSMrTxUCApDwl8XxNTUoEmu+ygvb1aPkm0rCleR0qFyfhW+x/codARRzYdn
# qJ2LT9lKFfwbdppQhwWBWW71PRT/uRwEMbePcVkx5TdmKtMhvfdpJaGy+rA9Bj/k
# KikUlFeVnCMZQIaGqK0r+4lahUPplQQZ4Tv95RupA7KVb7+U6hEOk6Zir8OEcO6Q
# FWCbofScnOI/lA+fVxAkNh7K9QuWOLJ52JjCQYMS+bM8orpTmhwQLe2fS5svwLrt
# 2PQrQpYqKFswB6TLVpc=
# SIG # End signature block