################################################################################
# Write message to log file and output stream
################################################################################
Function Write-LogOutput($message)
{
    Write-Log $message
    Write-Output $message
}

################################################################################
# Install AX SSRS extension components with HTTP endpoints
################################################################################
Function Install-AxSsrsExtension
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$config,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    # Initialize log file
    Initialize-Log $log
    $settings = Decode-Settings($config)
    Write-LogOutput $("")
    Write-LogOutput $settings | Format-List *

    # Get EnableSecurity value
    if ($null -eq $settings.EnableSecurity)
    {
        throw "Missing EnableSecurity value."
    }

    [Switch]$enableSecurity = [System.Convert]::ToBoolean($settings.EnableSecurity)

    [Switch]$isReportingClusterDeployment = $false
    [System.Boolean]::TryParse($settings.IsReportingClusterDeployment, [ref]$isReportingClusterDeployment)    

    # Check if use https
    if ((![System.String]::IsNullOrWhiteSpace($settings.SsrsSslCertificateThumbprint)) -and (![System.String]::IsNullOrWhiteSpace($settings.SsrsServerFqdn)))
    {
        Write-LogOutput "Install AX SSRS extension with HTTPS endpoints."
        Install-AxSsrsExtensionForHttps -config $config -log $log
        return
    }

    # Gets account list to acess reports
    [string[]] $accounts = $null
    if ($null -ne $settings.AccountListToAccessReports)
    {
        $accounts = $settings.AccountListToAccessReports.split(',')
    }

    # Use AxReportVmRoleStartupTask.exe to install reporting extensions
    Write-LogOutput $("Start installing AX SSRS extensions ...")

    [string] $reportServerUri = "http://localhost:80/ReportServer"
    [string] $ManagementAssemblyPath = Join-Path -Path $PSScriptRoot -ChildPath "Microsoft.Dynamics.AX.Framework.Management.dll"
    Import-Module $ManagementAssemblyPath
    
    # Need to install SSRS extension first with windows auth to install data sources for reporting cluster mode
    if ($isReportingClusterDeployment)
    {
        $settings.IsReportingClusterDeployment = "False"
        $settings.EnableSecurity = "True"
        $settingsJson = ConvertTo-Json $settings
        $windowsAuthConfig = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($settingsJson))

        Setup-SSRSExtension -config $windowsAuthConfig -log $log -ErrorAction Stop

        $settings.IsReportingClusterDeployment = "True"
        $settings.EnableSecurity = $enableSecurity.ToString();

        # Install shared data sources
        Install-DataSource -reportServerUri $reportServerUri -log $log

        # Create the root report folder /Dynamics
        Install-AxReportRootFolder -ReportServerAddress "localhost" -SkipReportServerAdminCheck  -ErrorAction Stop | Tee-Object -Variable InstallLog
        Add-Content -Path $log -Value $InstallLog
    }

    # Deploy SSRS extension
    Setup-SSRSExtension -config $config -log $log -ErrorAction Stop
    Write-LogOutput $("Completed installing AX SSRS extension.")
		
    #Added this step to warmup SSRS to avoid the timeout error
    Restart-WindowsService -log $log -computerName $env:COMPUTERNAME -serviceName ReportServer -ErrorAction stop
    Test-ReportServer -reportServerUri $reportServerUri -log $log -ErrorAction Stop

    # Install shared data sources
    if (-not $isReportingClusterDeployment)
    {
        Install-DataSource -reportServerUri $reportServerUri -log $log
    }

    if ($enableSecurity)
    {
        # Start Creating and configuring AX reports root folder
        Write-LogOutput $("")
        Write-LogOutput $("Start creating and configuring AX reports root folder ...")			
        Install-AxReportRootFolder -Accounts $accounts  -ErrorAction Stop | Tee-Object -Variable InstallLog          
        Add-Content -Path $log -Value $InstallLog
        Write-LogOutput $("Completed creating and configuring AX reports root folder.")
        Write-LogOutput $("")
    }

    # Test the SSRS instance prior to completing this step. If this is not successful then we should fail.
    Restart-WindowsService -log $log -computerName $env:COMPUTERNAME -serviceName ReportServer -ErrorAction stop
    Test-ReportServer -reportServerUri $reportServerUri -log $log -ErrorAction Stop
    Write-LogOutput $("")
}

################################################################################
# Install AX SSRS extension components with HTTP endpoints
################################################################################
Function Install-AxSsrsExtensionForHttps
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$config,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    # Initialize log file
    Initialize-Log $log
    $settings = Decode-Settings($config)
    Write-LogOutput $("")
    Write-LogOutput $settings | Format-List *    

    # Enable security
    [Switch]$enableSecurity = [System.Convert]::ToBoolean($settings.EnableSecurity)

    # IsServiceFabricDeployment (Set to true by LBD deployment)
    [Switch]$isServiceFabricDeployment = $false
    [System.Boolean]::TryParse($settings.IsServiceFabricDeployment, [ref]$isServiceFabricDeployment)

    # Gets account list to acess reports
    [string[]] $accounts = $null
    if ($null -ne $settings.AccountListToAccessReports)
    {
        $accounts = $settings.AccountListToAccessReports.split(',')
    }

    # Make sure HTTPS required parameters are set properly
    $sslCertThumbprint = $settings.SsrsSslCertificateThumbprint
    $serverFqdn = $settings.SsrsServerFqdn
    $httpsPort = $settings.SsrsHttpsPort
    $useHttps = (![System.String]::IsNullOrWhiteSpace($sslCertThumbprint)) -and (![System.String]::IsNullOrWhiteSpace($serverFqdn))
    if (-not $useHttps)
    {
        throw "Install-AxSsrsExtensionForHttps should not be called because SSLCertThumbprint: $sslCertThumbprint, Server FQDN: $serverFqdn."
    }

    $httpsPortValue = 443
    if ($httpsPort)
    {
        if (-not [Int32]::TryParse($settings.SsrsHttpsPort, [ref]$httpsPortValue))
        {
            throw "Invalid vlaue for SsrsHttpsPort. The value is: $httpsPort"
        }
    }

    # Import management module
    [string] $ManagementAssemblyPath = Join-Path -Path $PSScriptRoot -ChildPath "Microsoft.Dynamics.AX.Framework.Management.dll"
    Import-Module $ManagementAssemblyPath
    $lcid = [System.Globalization.CultureInfo]::GetCultureInfo('en-US').LCID

    try 
    {
        # Use AxReportVmRoleStartupTask.exe to install reporting extensions. This will create an http endpoint for data source and ax report folder configuration
        Write-LogOutput $("Start installing AX SSRS extensions ...")
        Setup-SSRSExtension -config $config -log $log -ErrorAction Stop
        Write-LogOutput $("Completed installing AX SSRS extension.")
    
        # Install shared data sources and their parent folder if they do not exist
        Install-DataSource -reportServerUri "http://localhost/reportserver" -log $log
            
        # Start creating and configuring AX reports root folder security
        if ($enableSecurity)
        {
            Write-LogOutput $("")
            Write-LogOutput $("Start creating and configuring AX reports root folder ...")			
            Install-AxReportRootFolder -Accounts $accounts -DeleteExisting:$false -GrantPublishReportPermission:$isServiceFabricDeployment -ErrorAction Stop | Tee-Object -Variable InstallLog
            Add-Content -Path $log -Value $InstallLog
            Write-LogOutput $("Completed creating and configuring AX reports root folder.")
            Write-LogOutput $("")
        }
    }
    finally 
    {
        # Make sure that http endpoint is deleted.
        $rsConfig = Get-RsConfig -ComputerName $env:COMPUTERNAME
        Remove-HttpUrl -rsConfig $rsConfig -lcid $lcid
    }

    # Ensure SSRS endpoints to Use HTTPS
    Write-LogOutput $("Start configuring SSRS HTTPS endpoint with port: $httpsPort, cert: $sslCertThumbprint, FQDN: $serverFqdn")

    $httpsReportServerUrl = "https://" + $serverFqdn + ":" + $httpsPortValue.ToString() + "/ReportServer"
    Write-LogOutput $("HTTPS Report Server URL is: $httpsReportServerUrl")

    Confirm-SsrsHttpsEndpoints -Port $httpsPortValue -Log $log -SslCertThumbprint $sslCertThumbprint -ErrorAction Stop
    Write-LogOutput $("SSRS HTTPS endpoints were configured.")
    Write-LogOutput $("")
        
    # Added this step to warmup SSRS to avoid the timeout error
    Restart-WindowsService -log $log -computerName $env:COMPUTERNAME -serviceName ReportServer -ErrorAction stop
    $localHttpsReportServerUrl = $("https://localhost:" + $httpsPortValue.ToString() + "/ReportServer")
    Test-ReportServer -reportServerUri $localHttpsReportServerUrl -forceTls12 $true -ignoreServerCertificate $true -log $log -ErrorAction Stop
}


################################################################################
# Install Data source (for reporting that does not need deployment)
################################################################################
Function Install-DataSource
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$reportServerUri,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    Test-ReportServer -reportServerUri $reportServerUri -log $log -ErrorAction Stop
	Write-LogOutput $("")
    Write-LogOutput $("Start creating report shared data sources...")

    Install-SharedDataSource -ErrorAction Stop | Tee-Object -Variable InstallLog
    Add-Content -Path $log -Value $InstallLog
    Write-LogOutput $("Completed creating report shared data sources.")
}

################################################################################
# Setup SSRS Extension by calling exe
################################################################################
Function Setup-SSRSExtension
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$config,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    $deployExtensionExe = Join-Path -Path $PSScriptRoot -ChildPath "AxReportVmRoleStartupTask.exe"
    Write-LogOutput $deployExtensionExe
    $allArgs = @("-config", $config)
    & $deployExtensionExe $allArgs *>&1
    $exitCode = $LASTEXITCODE
    if ($exitCode -ne 0)
    {
        throw "Error occurred when running AxReportVmRoleStartupTask.exe to install extension. Please see details in events for AX-ReportPVMSetup."
    }
}


################################################################################
# Uninstall AX SSRS extension components
# $config parameter must have a property EnableSecurity with value "true" or "false"
################################################################################
Function Remove-AxSsrsExtension
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$config,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    # Initialize log file
    Initialize-Log $log

    # Verify deployment type
    $settings = Decode-Settings($config)
    Write-LogOutput $("")
    Write-LogOutput $settings | Format-List *
    if ($settings.EnableSecurity -eq $null)
    {
        throw "Missing EnableSecurity value."
    }

    [Switch]$enableSecurity = [System.Convert]::ToBoolean($settings.EnableSecurity)

    # Remove Https
    $removeHttps = $false
    if ($settings.RemoveHttps)
    {
        if (-not [System.Boolean]::TryParse($settings.RemoveHttps, [ref]$removeHttps))
        {
            throw "RemoveHttps must be 'true' or 'false'."
        }
    }

    # Verify/Add IsUninstallOnly value (true) to the $config string
    Write-LogOutput $("Verify/Add IsUninstallOnly parameter to the config string...")
    [string]$uninstallConfig = $config
    if (Get-Member -InputObject $settings -Name "IsUninstallOnly" -MemberType Properties)
    {
        if (![string]::Equals($settings.IsUninstallOnly, "true", [System.StringComparison]::OrdinalIgnoreCase))
        {
            throw "IsUninstallOnly must be true for uninstallation."
        }

        Write-LogOutput $("Completed verifying IsUninstallOnly value in the config string.")
    }
    else
    {
        $settings|Add-Member -type NoteProperty -Name "IsUninstallOnly" -Value "true"
        $uninstallConfig = ConvertTo-Json $settings
        $uninstallConfig = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($uninstallConfig))
        Write-LogOutput $("Completed Adding IsUninstallOnly value in the config string.")
    }

    # Use AxReportVmRoleStartupTask.exe to uninstall reporting extensions
    Write-LogOutput("")
    Write-LogOutput $("Start uninstalling AX SSRS extensions ...")

    $deployExtensionExe = Join-Path -Path $PSScriptRoot -ChildPath "AxReportVmRoleStartupTask.exe"
    $allArgs = @("-config", $uninstallConfig)
    & $deployExtensionExe $allArgs *>&1
    $exitCode = $LASTEXITCODE
    if ($exitCode -eq 0)
    {
        Restart-WindowsService -log $log -computerName $env:COMPUTERNAME -serviceName ReportServer -ErrorAction stop
        Write-LogOutput $("Completed uninstalling AX SSRS extension.")
    }
    else
    {
        throw "Error occurred when running AxReportVmRoleStartupTask.exe to uninstall extension. Please see details in events for AX-ReportPVMSetup."
    }

    if ($removeHttps)
    {
        Write-LogOutput "Start removing all https endpoints and SSL cert bindings"
        Config-SsrsEndpoint -Port 80 -Log $log -ErrorAction Stop
        Write-LogOutput "Completed removing all https endpoints and SSL cert bindings"
    }
}

################################################################################
# Format report publishing results
################################################################################
Function Format-PublishOutput 
{
    param
    (
        [Parameter(ValueFromPipeline=$true,Position=0)] 
        $result
    )

    process
    {
        if ($result -is [Microsoft.Dynamics.AX.Framework.Management.Reports.ReportDeploymentResult])
        {
            $result | Select-Object ReportName, ReportDeploymentStatus
        }
        else
        {
            $result
        }
    }
}


################################################################################
# Deploy AX reports To SSRS server
################################################################################
Function Deploy-AxReport
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$config,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    # Initialize the log file
    Initialize-Log $log

    # Getting values from the JSON configuration string
    $settings = Decode-Settings($config)

    [string]$reportingServers = $settings."BiReporting.ReportingServers"
    [string]$packageInstallLocation = $settings."Microsoft.Dynamics.AX.AosConfig.AzureConfig.bindir"
    [string]$useHttps = $settings."BiReporting.SsrsUseHttps"
    [string]$httpsPort = $settings."BiReporting.SsrsHttpsPort"
    [string[]]$module = $settings.Module 
    [string[]]$reportName = $settings.ReportName

    # Popuate default values 
    Write-LogOutput $('Microsoft.Dynamics.AX.AosConfig.AzureConfig.bindir: ' + $packageInstallLocation)
    Write-LogOutput $('Module: ' + $module)
    Write-LogOutput $('ReportName: ' + $reportName)

    if ($module -eq $null -or $module.Length -eq 0)
    {
        $module = "*"
    }

    if ($reportName -eq $null -or $reportName.Length -eq 0)
    {
        $reportName = "*"
    }

    Write-LogOutput ""

    # Getting Protocol and Port for ReportServer service
    $protocol = "http://"
    $port = 80

    Write-LogOutput $("Getting the protocol and port ...")
    if (-not [String]::IsNullOrWhiteSpace($useHttps))
    {
        $useHttpsValue = $false
        if (-not [Boolean]::TryParse($useHttps, [ref]$useHttpsValue))
        {
            throw "Invalid value for BiReporting.SsrsUseHttps. The value is : $($useHttps)"
        }
    
        if ($useHttpsValue)
        {
            $protocol = "https://"
            $port = 443
            if (-not [String]::IsNullOrWhiteSpace($httpsPort))
            {
                if (-not [Int32]::TryParse($httpsPort, [ref]$port))
                {
                    throw "Invalid vlaue for BiReporting.SsrsHttpsPort. The value is: $httpsPort"
                }
            }
        }
    }
    
    Write-LogOutput $("Protocol: $protocol; Port: $port")
    Write-LogOutput ""

    # Split report servers string
    Write-LogOutput $('Reporting Servers: ' + $reportingServers)
    $rsServers = $reportingServers.Split(",", [System.StringSplitOptions]::RemoveEmptyEntries)|%{$_.trim()}
    $rsServers = $rsServers.Where({-not [System.String]::IsNullOrWhiteSpace($_)})
    
    # Test each SSRS instance prior to deploying any reports. If this is not successful
    # then there is no need to deploy reports.
    $reportServerUrls = @{}
    foreach ($rsServer in $rsServers)
    {
        [string]$rsUrl = $($protocol + $rsServer + ":" + $port.ToString() + "/ReportServer")
        Write-LogOutput $("Testing: $rsUrl ...")
        Test-ReportServer -reportServerUri $rsUrl -log $log -ErrorAction Stop
        $reportServerUrls.Add($rsServer, $rsUrl)
    }

    Write-LogOutput $("Testing reporting services completed.")
    Write-LogOutput ""
    
    # Start deploying reports
    Write-LogOutput $("Start deploying reports ...")
    $startTime = $(Get-Date)

    if ($rsServers.Count -eq 1)
    {
        [string]$ManagementAssemblyPath = Join-Path -Path $PSScriptRoot -ChildPath "Microsoft.Dynamics.AX.Framework.Management.dll"
        Import-Module $ManagementAssemblyPath

        $err = @()
        Publish-AXReport -MaxDegreeOfParallelism 1 -ErrorAction Continue -ErrorVariable err -ReportName $reportName -SkipReportServerAdminCheck -ReportServerAddress $reportServerUrls.Values[0] -BinDirectory $PackageInstallLocation -DeleteExisting -Module $module *>&1 | Format-PublishOutput | Tee-Object -Variable DeployReportsLog
        Add-Content -Path $log -Value $($DeployReportsLog | Out-String)
        Write-LogOutput $(($(Get-Date) - $startTime).TotalSeconds.ToString() + " Seconds.")

        if ($err.Count -gt 0)
        {
            throw "Errors occured during report deployment."
        }
    }
    else
    {
        foreach ($rsServer in $rsServers)
        {
            Start-Job -Name $("Job" + $rsServer) -ScriptBlock {
                Param
                (
                    [Parameter(Mandatory=$true)]
                    [string]$scriptRoot,
                    [Parameter(Mandatory=$true)]
                    [string]$rsUrlArg,
                    [Parameter(Mandatory=$true)]
                    [string[]]$reportNameArg,
                    [Parameter(Mandatory=$true)]
                    [string]$packageInstallLocationArg,
                    [Parameter(Mandatory=$true)]
                    [string[]]$moduleArg
                )

                Import-Module "$scriptRoot\AosCommon.psm1" -Force -DisableNameChecking -ErrorAction Stop
                Import-Module "$scriptRoot\Reporting.psm1" -Force -DisableNameChecking -ErrorAction Stop

                [string]$ManagementAssemblyPath = Join-Path -Path $scriptRoot -ChildPath "Microsoft.Dynamics.AX.Framework.Management.dll"
                Import-Module $ManagementAssemblyPath -ErrorAction Stop

                $err = @()
                Publish-AXReport -MaxDegreeOfParallelism 1 -ErrorAction Continue -ErrorVariable err -ReportName $reportNameArg -SkipReportServerAdminCheck -ReportServerAddress $rsUrlArg -BinDirectory $packageInstallLocationArg -DeleteExisting -Module $moduleArg *>&1 | Format-PublishOutput | Out-String -OutVariable DeployReportsLog
                return @{"Error" = $err; "Log" = $DeployReportsLog}
            } -ArgumentList $PSScriptRoot, $reportServerUrls[$rsServer], $reportName, $packageInstallLocation, $module
        }

        $allErrors = @() 
        foreach ($rsServer in $rsServers)
        {
            $job = Get-Job $("Job" + $rsServer)
            $jobResult = Receive-Job -Job $job -Wait -AutoRemoveJob

            if ($jobResult."Error")
            {
                $allErrors += $jobResult."Error"
            }

            if ($jobResult."Log")
            {
                Write-LogOutput $($jobResult."Log" | Out-String)
            }
        }

        Write-LogOutput $(($(Get-Date) - $startTime).TotalSeconds.ToString() + " Seconds.")

        foreach ($error in $allErrors)
        {
            if ($error.Count -gt 0)
            {
                throw @("Errors occured during report deployment for server " + $rsServer)
            }
        }
    }
}


################################################################################
# Remove all AX reports from SSRS server
################################################################################
Function Remove-AllAxReports
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$config,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    # Initialize the log file
    Initialize-Log $log

    # Getting values from the JSON configuration string
    $settings = Decode-Settings($config)

    [string]$reportingServers = $settings."BiReporting.ReportingServers"
    [string[]]$reportName = $settings.ReportName
    [string]$useHttps = $settings."BiReporting.SsrsUseHttps"
    [string]$httpsPort = $settings."BiReporting.SsrsHttpsPort"    

    # populate default values
    Write-LogOutput $('ReportName: ' + $reportName)
    if ($reportName -eq $null -or $reportName.Length -eq 0)
    {
        $reportName = "*"
    }

    # Getting Protocol and Port for ReportServer service
    $protocol = "http://"
    $port = 80

    Write-LogOutput $("Getting the protocol and port ...")
    if (-not [String]::IsNullOrWhiteSpace($useHttps))
    {
        $useHttpsValue = $false
        if (-not [Boolean]::TryParse($useHttps, [ref]$useHttpsValue))
        {
            throw "Invalid value for BiReporting.SsrsUseHttps. The value is : $($useHttps)"
        }
    
        if ($useHttpsValue)
        {
            $protocol = "https://"
            $port = 443
            if (-not [String]::IsNullOrWhiteSpace($httpsPort))
            {
                if (-not [Int32]::TryParse($httpsPort, [ref]$port))
                {
                    throw "Invalid vlaue for BiReporting.SsrsHttpsPort. The value is: $httpsPort"
                }
            }
        }
    }
    
    Write-LogOutput $("Protocol: $protocol; Port: $port")
    Write-LogOutput ""    

    # split report servers string
    Write-LogOutput $('Reporting Servers: ' + $reportingServers)
    $rsServers = $reportingServers.Split(",", [System.StringSplitOptions]::RemoveEmptyEntries)|%{$_.trim()}
    $rsServers = $rsServers.Where({-not [System.String]::IsNullOrWhiteSpace($_)})
    
    # Test each SSRS instance prior to deploying any reports. If this is not successful
    # then there is no need to deploy reports.
    $reportServerUrls = @{}
    foreach ($rsServer in $rsServers)
    {
        [string]$rsUrl = $($protocol + $rsServer + ":" + $port.ToString() + "/ReportServer")
        Write-LogOutput $("Testing: $rsUrl ...")
        Test-ReportServer -reportServerUri $rsUrl -log $log -ErrorAction Stop
        $reportServerUrls.Add($rsServer, $rsUrl)
    }
    Write-LogOutput $("Testing reporting services completed.")
    Write-LogOutput ""

    # Start clearing reports
    Write-LogOutput $("Start removing reports ....")
    $startTime = $(Get-Date)

    if ($rsServers.Count -eq 1)
    {
        [string]$ManagementAssemblyPath = Join-Path -Path $PSScriptRoot -ChildPath "Microsoft.Dynamics.AX.Framework.Management.dll"
        Import-Module $ManagementAssemblyPath

        Remove-AxReport -ErrorAction Continue -MaxDegreeOfParallelism 1 -ReportName $reportName -ReportServerAddress $reportServerUrls.Values[0] *>&1 |  Format-PublishOutput | Tee-Object -Variable ReportRemovalLog
        Add-Content -Path $log -Value $ReportRemovalLog
        Write-LogOutput $(($(Get-Date) - $startTime).TotalSeconds.ToString() + " Seconds.")
    }
    else
    {
        foreach ($rsServer in $rsServers)
        {
            Start-Job -Name $("RmJob" + $rsServer) -ScriptBlock {
                Param
                (
                    [Parameter(Mandatory=$true)]
                    [string]$scriptRoot,
                    [Parameter(Mandatory=$true)]
                    [string]$rsUrlArg,
                    [Parameter(Mandatory=$true)]
                    [string[]]$reportNameArg
                )

                Import-Module "$scriptRoot\AosCommon.psm1" -Force -DisableNameChecking -ErrorAction Stop
                Import-Module "$scriptRoot\Reporting.psm1" -Force -DisableNameChecking -ErrorAction Stop

                [string]$ManagementAssemblyPath = Join-Path -Path $scriptRoot -ChildPath "Microsoft.Dynamics.AX.Framework.Management.dll"
                Import-Module $ManagementAssemblyPath -ErrorAction Stop

                Remove-AxReport -ErrorAction Continue -MaxDegreeOfParallelism 1 -ReportName $reportNameArg -ReportServerAddress $rsUrlArg *>&1 | Format-PublishOutput | Out-String -OutVariable ReportRemovalLog
            } -ArgumentList $PSScriptRoot, $reportServerUrls[$rsServer], $reportName
        }

        foreach ($rsServer in $rsServers)
        {
            $job = Get-Job $("RmJob" + $rsServer)
            $jobResultLog = Receive-Job -Job $job -Wait -AutoRemoveJob

            if ($jobResultLog)
            {
                Write-LogOutput $($jobResultLog | Out-String)
            }
        }

        Write-LogOutput $(($(Get-Date) - $startTime).TotalSeconds.ToString() + " Seconds.")
    }
}

################################################################################
# Install report fonts to SSRS server
################################################################################
Function Install-Font
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$config,
        [Parameter(Mandatory=$true)]
        [string]$log,
        [Parameter(Mandatory=$true)]
        [string]$fontFilePath
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    # Initialize the log file
    Initialize-Log $log

    # Start installing fonts
    Write-Output("")
    Write-LogOutput "Start installing fonts to SSRS ..."
    Write-LogOutput $("Font file path: " + $fontFilePath)
    $MangementAssemblyPath = Join-Path -Path $PSScriptRoot -ChildPath "Microsoft.Dynamics.AX.Framework.Management.dll"
    Import-Module $MangementAssemblyPath

    (Get-ChildItem -Path $fontFilePath -Filter "*.ttf").FullName | Install-ReportFont *>&1 | Tee-Object -Variable ReportFontLog
    Add-Content -Path $log -Value $ReportFontLog

    # Restart SSRS
    Get-Service -Name ReportServer | Restart-Service *>&1 | Tee-Object -Variable RestartSsrsLog
    Add-Content -Path $log -Value $RestartSsrsLog

    Write-LogOutput $("Completed installing fonts to SSRS.")
}

#####################################################
# Configure SSRS web service and web app protocols
#####################################################
function Config-SsrsEndpoint
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true)]
        [int]$Port,
        [Parameter(Mandatory=$true)]
        [string]$log,
        [Parameter(Mandatory=$false)]
        [string]$SslCertThumbprint
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    $rsConfig = Get-RsConfig -ComputerName $env:COMPUTERNAME
    if (!$rsConfig)
    {
        throw "Could not find reporting service WMI object MSReportServer_ConfigurationSetting"
    }

    $lcid = [System.Globalization.CultureInfo]::GetCultureInfo('en-US').LCID
    $rsWebServiceAppName = 'ReportServerWebService'
    $reportManagerAppName = 'ReportServerWebApp'

    # Remove all existing ResvervedUrls
    $result = $rsConfig.ListReservedUrls()
    Verify-SsrsWmiCall -resultObject $result -methodName 'ListReservedurls'
    if ($result.Application)
    {
        for ($i = 0; $i -lt $result.Application.length; $i++)
        {
            $removeResult = $rsConfig.RemoveURL($result.Application[$i], $result.UrlString[$i], $lcid)
            Verify-SsrsWmiCall -resultObject $removeResult -methodName 'RemoveURL'
            Write-LogOutput $([string]::Format("Removed URL Application={0} UrlString= {1}", $result.Application[$i], $result.UrlString[$i]))
        }
    }

    $removedIpPorts = New-Object -TypeName System.Collections.Generic.HashSet[string]

    # Remove all SSL Certficate Bindings from Reporting Service
    $result = $rsConfig.ListSSLCertificateBindings($lcid)
    if ($result.Application)
    {
        for ($i = 0; $i -lt $result.Application.length; $i++)
        {
            $removeResult = $rsConfig.RemoveSSLCertificateBindings($result.Application[$i], $result.CertificateHash[$i], $result.IPAddress[$i], $result.Port[$i], $lcid)
            Verify-SsrsWmiCall -resultObject $removeResult -methodName 'RemoveSSLCertificateBindings'
            Write-LogOutput $([string]::Format("Removed SSL Binding Application={0} Certificate={1} IPAddress={2} Port={3}", $result.Application[$i], $result.CertificateHash[$i], $result.IPAddress[$i], $result.Port[$i]))

            Remove-SSLBindings -ipAddress $($result.IPAddress[$i]).ToString() -port $($result.Port[$i]).ToString() -removedIpPorts $removedIpPorts
        }
    }

    # Remove all SSL Certficate Bindings and ssl bindings from OS
    if ($SslCertThumbprint)
    {
        Remove-SSLBindings -ipAddress "0.0.0.0" -port $Port.ToString() -removedIpPorts $removedIpPorts
        Remove-SSLBindings -ipAddress "[::]" -port $Port.ToString() -removedIpPorts $removedIpPorts
        Remove-ReservedUrl -url "https://+:$($Port.ToString())/ReportServer/"
        Remove-ReservedUrl -url "https://+:$($Port.ToString())/Reports/"
    }

    # Reserve URL for web service and web app
    $urlString = $([string]::Format("http://+:{0}", $Port))
    if ($SslCertThumbprint)
    {
        $urlString = [string]::Format("https://+:{0}", $Port)
    }

    $result = $rsConfig.ReserveURL($rsWebServiceAppName, $urlString, $lcid)
    Verify-SsrsWmiCall -resultObject $result -methodName 'ReserveURL'
    Write-LogOutput $([string]::Format("Reserved URL string {0} for {1}", $urlString, $rsWebServiceAppName))

    $rsConfig.SetVirtualDirectory($reportManagerAppName, "Reports", $lcid)
    $result = $rsConfig.ReserveURL($reportManagerAppName, $urlString, $lcid)
    Verify-SsrsWmiCall -resultObject $result -methodName 'ReserveURL'
    Write-LogOutput $([string]::Format("Reserved URL string {0} for {1}", $urlString, $reportManagerAppName))

    # Create SSL Certificate Bindings for web service and web app
    if ($SslCertThumbprint)
    {
        $ipV4Address = "0.0.0.0";
        $ipV6Address = "::";

        $result = $rsConfig.CreateSSLCertificateBinding($rsWebServiceAppName, $SslCertThumbprint, $ipV4Address, $Port, $lcid);
        Verify-SsrsWmiCall -resultObject $result -methodName 'CreateSSLCertificateBinding'
        Write-LogOutput $([string]::Format("Created SSL Certificate Binding Application={0} SslCertThumbPrint={1} IPAddress={2} Port={3}", $rsWebServiceAppName, $SslCertThumbprint, $ipV4Address, $Port))

        $result = $rsConfig.CreateSSLCertificateBinding($rsWebServiceAppName, $SslCertThumbprint, $ipV6Address, $Port, $lcid);
        Verify-SsrsWmiCall -resultObject $result -methodName 'CreateSSLCertificateBinding'
        Write-LogOutput $([string]::Format("Created SSL Certificate Binding Application={0} SslCertThumbPrint={1} IPAddress={2} Port={3}", $rsWebServiceAppName, $SslCertThumbprint, $ipV6Address, $Port))

        $result = $rsConfig.CreateSSLCertificateBinding($reportManagerAppName, $SslCertThumbprint, $ipV4Address, $Port, $lcid);
        Verify-SsrsWmiCall -resultObject $result -methodName 'CreateSSLCertificateBinding'
        Write-LogOutput $([string]::Format("Created SSL Certificate Binding Application={0} SslCertThumbPrint={1} IPAddress={2} Port={3}", $reportManagerAppName, $SslCertThumbprint, $ipV4Address, $Port))

        $result = $rsConfig.CreateSSLCertificateBinding($reportManagerAppName, $SslCertThumbprint, $ipV6Address, $Port, $lcid);
        Verify-SsrsWmiCall -resultObject $result -methodName 'CreateSSLCertificateBinding'
        Write-LogOutput $([string]::Format("Created SSL Certificate Binding Application={0} SslCertThumbPrint={1} IPAddress={2} Port={3}", $reportManagerAppName, $SslCertThumbprint, $ipV6Address, $Port))
    }

    #Restart reporting services service
    Restart-WindowsService -computerName $env:COMPUTERNAME -serviceName ReportServer -log $log
}

#####################################################
# Confirm SSRS web service and web app HTTPS endpoints
#####################################################
function Confirm-SsrsHttpsEndpoints
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$false)]
        [string]$SslCertThumbprint,
        [Parameter(Mandatory=$true)]
        [int]$Port,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    $rsConfig = Get-RsConfig -ComputerName $env:COMPUTERNAME
    if (!$rsConfig)
    {
        throw "Could not find reporting service WMI object MSReportServer_ConfigurationSetting"
    }

    $lcid = [System.Globalization.CultureInfo]::GetCultureInfo('en-US').LCID
    $rsWebServiceAppName = 'ReportServerWebService'
    $reportManagerAppName = 'ReportServerWebApp'

    # Test whether local HTTPS URL is configured
    Restart-WindowsService -log $log -computerName $env:COMPUTERNAME -serviceName ReportServer -ErrorAction stop
    $localHttpsReportServerUrl = $("https://localhost:" + $httpsPortValue.ToString() + "/ReportServer")

    $reconfigEndoints = $false
    $httpsEndpointExists = $true
    try 
    {
        Test-ReportServer -reportServerUri $localHttpsReportServerUrl -forceTls12 $true -ignoreServerCertificate $true -log $log -ErrorAction Stop
    }
    catch 
    {
        $httpsEndpointExists = $false
    }

    if (-not $httpsEndpointExists)
    {
        # No https endpoint, so there is no need to validate.
        $reconfigEndoints = $true
    }
    else
    {
        # Validate whether SSL Bindings need to be updated
        $expectedSslBindings = @{}
        $expectedSslBindings.Add($("$rsWebServiceAppName-0.0.0.0-$Port-$SslCertThumbprint"), 1)
        $expectedSslBindings.Add($("$rsWebServiceAppName-::-$Port-$SslCertThumbprint"), 1)
        $expectedSslBindings.Add($("$reportManagerAppName-0.0.0.0-$Port-$SslCertThumbprint"), 1)
        $expectedSslBindings.Add($("$reportManagerAppName-::-$Port-$SslCertThumbprint"), 1)
        
        $result = $rsConfig.ListSSLCertificateBindings($lcid)
        $foundBindingCount = 0
        if ($result.Application -and $result.Application.Length -eq $expectedSslBindings.Count)
        {
            for ($i = 0; $i -lt $result.Application.length; $i++)
            {
                $bindingString = $("$($result.Application[$i])-$($result.IPAddress[$i])-$($result.Port[$i])-$($result.CertificateHash[$i])")
                if ($expectedSslBindings.ContainsKey($bindingString))
                {
                    Write-LogOutput "Found $bindingString"
                    $foundBindingCount++
                }
            }
        }

        if ($foundBindingCount -ne $expectedSslBindings.Count)
        {
            # SSL bindings do not have expected values, needs reconfig
            $reconfigEndoints = $true
        }
        else
        {
            # Remove all Http based URLs
            Write-LogOutput "SSRS reserved URLs and SSL bindings are already configured. Skip configuring."
            Remove-HttpUrl -rsConfig $rsConfig -lcid $lcid
        }
    }

    if ($reconfigEndoints)
    {
        Write-LogOutput "SSRS reserved URLs and SSL bindings need to be reconfigured."
        Config-SsrsEndpoint -Port $Port -log $log -SslCertThumbprint $SslCertThumbprint    
    }
}

####################################################################
# Remove SSL bindings from network configuration
####################################################################
function Remove-SSLBindings
{
    param 
    (
        [Parameter(Mandatory=$true)]
        [string]$ipAddress,
        [Parameter(Mandatory=$true)]
        [string]$port,
        [Parameter(Mandatory=$true)]
        [AllowEmptyCollection()]
        [System.Collections.Generic.HashSet[string]]$removedIpPorts
    )

    if ($ipAddress -eq "::")
    {
        $ipAddress = "[::]"
    }

    $ipAddressWithPort = "$($ipAddress):$($port)"
    if (!$removedIpPorts.Contains($ipAddressWithPort))
    {
        $showCommand = $("netsh http show sslcert ipport=$ipAddressWithPort")
        Write-LogOutput ""
        Write-LogOutput("Check SSL cert bindings from computer network config with '$showCommand")
        $netshResult = Invoke-Expression $showCommand -ErrorAction Stop
        Write-LogOutput $netshResult

        if ($netshResult.Count -ge 10)
        {
            $removeCommand = $("netsh http delete sslcert ipport=$ipAddressWithPort")
            Write-LogOutput("Remove SSL cert bindings from computer network config with '$removeCommand")
            $netshResult = Invoke-Expression $removeCommand -ErrorAction Stop
            $removedIpPorts.Add($ipAddressWithPort) | Out-Null
            Write-LogOutput $netshResult
        }
    }
}

####################################################################
# Remove reserved URL
####################################################################
function Remove-ReservedUrl
{
    param 
    (
        [Parameter(Mandatory=$true)]
        [string]$url
    )

    $showCommand = $("netsh http show urlacl url=$url")
    Write-LogOutput ""
    Write-LogOutput $("Check reserved URL with $showCommand")
    $netshResult = Invoke-Expression $showCommand -ErrorAction Stop
    Write-LogOutput $netshResult

    if ($netshResult.Count -ge 6)
    {
        $removeCommand = $("netsh http delete urlacl url=$url")
        Write-LogOutput $("Remove reserved URL with $removeCommand")
        $netshResult = Invoke-Expression $removeCommand -ErrorAction Stop
        Write-LogOutput $netshResult
    }
}

####################################################################
# Remove all HTTP based URLs
####################################################################
function Remove-HttpUrl
{
    param 
    (
        [Parameter(Mandatory=$true)]
        $rsConfig,
        [Parameter(Mandatory=$true)]
        $lcid
    )

    Write-LogOutput "Remove all HTTP URLs..."
    $result = $rsConfig.ListReservedUrls()
    Verify-SsrsWmiCall -resultObject $result -methodName 'ListReservedurls'
    if ($result.Application)
    {
        for ($i = 0; $i -lt $result.Application.length; $i++)
        {
            if ($result.UrlString[$i] -and $result.UrlString[$i].StartsWith("http://", [System.StringComparison]::OrdinalIgnoreCase))
            {
                $removeResult = $rsConfig.RemoveURL($result.Application[$i], $result.UrlString[$i], $lcid)
                Verify-SsrsWmiCall -resultObject $removeResult -methodName 'RemoveURL'
                Write-LogOutput $([string]::Format("Removed URL Application={0} UrlString= {1}", $result.Application[$i], $result.UrlString[$i]))
            }
        }
    }    
}

####################################################################
# Verify SSRS WMI calls
####################################################################
function Verify-SsrsWmiCall
{
    param
    (
        $resultObject,
        $methodName
    )

    if (!$resultObject)
    {
        throw $("Returned Null object when calling $methodName")
    }

    if ($resultObject.HRESULT -ne 0)
    {
        throw $("Error occured when calling {0}. HResult = {1} Error={2}" -f $methodName, $resultObject.HRESULT, $resultObject.Error)
    }
}


################################################################################
# Test the SSRS Server
################################################################################
Function Test-ReportServer
{
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$reportServerUri,
        [Parameter(Mandatory=$false)]
        [bool]$ignoreServerCertificate = $false,
        [Parameter(Mandatory=$false)]
        [bool]$forceTls12 = $false,
        [Parameter(Mandatory=$true)]
        [string]$log
    )

    # Initialize the log file
    Initialize-Log $log

    Write-LogOutput $('Checking status of Report Server URL: ' + $reportServerUri)

    # Assume a 400 response code
    $statusCode = 400

    try
    {
        # Invoke the web request and get the status
        $uri = New-Object -TypeName System.Uri($reportServerUri)
        [System.Net.HttpWebRequest]$request = [System.Net.HttpWebRequest]::CreateHttp($uri)
        
        $request.Timeout = 10 * 60 * 1000 
        $request.UseDefaultCredentials = $true
        $request.KeepAlive = $false
        if ($ignoreServerCertificate)
        {
            $request.ServerCertificateValidationCallback = {$true}
        }

        if ($forceTls12)
        {
            [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
        }

        [System.Net.WebResponse]$response = $request.GetResponse()
        $statusCode = $response.StatusCode
    }
    catch [System.Net.WebException]
    {
        Write-LogOutput $('Failure! Status check of Report Server URL: ' + $reportServerUri)
        Write-LogOutput $($_.Exception.ToString())

        throw "An exception of type System.Net.WebException occurred when making an http request to: " + $reportServerUri + ". Refer to the log file for more details."
    }
    
    # check the status code is 200 OK 
    if ($statusCode -eq 200)
    {
        Write-LogOutput $('Success! Status check of Report Server URL: ' + $reportServerUri)
    }
    else
    {
        Write-LogOutput $('Failure! Status check of Report Server URL: ' + $reportServerUri)
        Write-LogOutput $('StatusCode value: ' + $statusCode)
            
        throw "Http response contains StatusCode of " + $statusCode + ". Unable to communicate with the SQL Server ReportServer service."
    }
}

################################################################################
# Restart a windows service
################################################################################
function Restart-WindowsService
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$log,
        [Parameter(Mandatory=$true)]
        [string]$computerName,
        [Parameter(Mandatory=$true)]
        [string]$serviceName
    )

    Import-Module "$PSScriptRoot\AosCommon.psm1" -DisableNameChecking

    # Initialize log file
    Initialize-Log $log

    $retryCount = 3;

    while ($retryCount -gt 0)
    {
        Write-LogOutput $("Restart " + $serviceName + " service on " + $computerName + "...")
        
        try
        {
            Get-Service -ErrorAction Stop -Name $serviceName -ComputerName $computerName | Restart-Service -ErrorAction Stop -Force *>&1 | Tee-Object -Variable RestartServiceLog
            Add-Content -Path $log -Value $RestartServiceLog
            break
        }
        catch
        {
            $retryCount -= 1;
            if ($retryCount -le 0)
            {
                throw
            }

            Start-Sleep -Seconds 30
        }
    }

    Write-LogOutput $($serviceName + " service restarted on " + $computerName)
}

################################################################################
# Get reporting service config WMI object
################################################################################
function Get-RsConfig
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true)]
        [string]$ComputerName
    )

    try
    {
        # SQL Server 2016
        $rsconfig = Get-WmiObject -ErrorAction Stop –namespace "root\Microsoft\SqlServer\ReportServer\RS_MSSQLSERVER\v13\Admin" –class MSReportServer_ConfigurationSetting –ComputerName $ComputerName -Filter "InstanceName='MSSQLSERVER'"
    }
    catch
    {
        if ($_.Exception.Message.IndexOf("Invalid namespace", [System.StringComparison]::OrdinalIgnoreCase) -ge 0)
        {
            # SQL Server 2014
            $rsconfig = Get-WmiObject -ErrorAction Stop –namespace "root\Microsoft\SqlServer\ReportServer\RS_MSSQLSERVER\v12\Admin" –class MSReportServer_ConfigurationSetting –ComputerName $ComputerName -Filter "InstanceName='MSSQLSERVER'"
        }
        else
        {
            throw
        }
    }

    return $rsconfig
}
# SIG # Begin signature block
# MIIjkgYJKoZIhvcNAQcCoIIjgzCCI38CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCESWCH2NdLvUG2
# kvbVAVEk1qn8zdqJbNe8IGRldfp6vqCCDYEwggX/MIID56ADAgECAhMzAAABh3IX
# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy
# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVZzCCFWMCAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgZCUWmra7
# f+RnH/pH9OrXhMrtt+mUD87zD77nGtBoQQIwQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQCL9hvwbeLeImjh0QcabPFLdLUo0oU37kW0ul169g60
# 4VX1ZNyI1DaKqUh7zu8UBJgKxgepABkVTzrqIOnwxPJuy5wfUPJ0y9HVOazq5c4O
# gMbMwhElqTSm9B7H3vFmo+t4C0qBlzMmzLvDucATs+Nv5Qddw2KouKSx27hN908R
# HGUe3obwT3l745jUvUpSWQaTt7BmQTh2lOOHwncvpk+SQMEFh740TKvx8My0hLKg
# vRkLxi31kAGJsumOcIJQG2nNk7dcVCASeKOkJ8zX2jh0B7mcBweDpg65DAHi0fPz
# Il3D7VIn0OUaiQ6ZxKirkRdGurbAVb0Ue2kdUOwr9V8IoYIS8TCCEu0GCisGAQQB
# gjcDAwExghLdMIIS2QYJKoZIhvcNAQcCoIISyjCCEsYCAQMxDzANBglghkgBZQME
# AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIKF574ry+DDgmhbDNeGzmOyTlFV8UoD6MyDMPZV1
# BumCAgZfs/ZhE60YEzIwMjAxMTIwMDczOTUzLjIwNlowBIACAfSggdSkgdEwgc4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p
# Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg
# VFNTIEVTTjo3ODgwLUUzOTAtODAxNDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt
# U3RhbXAgU2VydmljZaCCDkQwggT1MIID3aADAgECAhMzAAABKKAOgeE21U/CAAAA
# AAEoMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo
# aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw
# MB4XDTE5MTIxOTAxMTUwMFoXDTIxMDMxNzAxMTUwMFowgc4xCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy
# YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo3ODgw
# LUUzOTAtODAxNDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
# ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ2Rsdb3VNuGPs2/Dgpc
# 9gt77LG0JPkD4VWTlEJLkqznTJl+RoZfiOwN6iWfPu4k/kj8nwY7pvLs1OsBy494
# yusg4rHLwHNUJPtw1Tc54MOLgdcosA4Nxki73fDyqWwDtjOdk6H7kNczBPqADD6B
# 98ot77/wSACBJIxm9qAUudquS5fczCF0++aWUavDu46U3cv6HEjIdV2ZdJTUKg4W
# UIdTYMQXI082+qSs45WBZjcK98/tIfx8uq8q8ksWF9+zUjGTFiMaKHhn7cSCoEj7
# E1tVmW08ISpS678WFP2+A0OQwaWcJKNACK+J+La7Lz2bGupCidOGz5XDewc1lD9n
# LPcCAwEAAaOCARswggEXMB0GA1UdDgQWBBSE4vKD8X61N5vUAcNOdH9QBMum8jAf
# BgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBH
# hkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNU
# aW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUF
# BzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0
# YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsG
# AQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQCLX2ZHGIULgDk/iccHWUywjDyAsBHl
# hkmtmBp4lldwL3dNo0bXZZHiSZB+c2KzvPqY64BlECjS/Pqur2m9UaT1N0BeUowR
# HQT88wdzd94gYqKXmLDbVR8yeVgBkcP/JiVWbXdQzcz1ETHgWrh+uzA8BwUgAaHJ
# w+nXYccIuDgPJM1UTeNl9R5Ovf+6zR2E5ZI4DrIqvS4jH4QsoMPTn27AjN7VZt4a
# moRxMLEcQAS7vPT1JUUaRFpFHmkUYVln1YMsw///6968aRvy3cmClS44uxkkaILb
# hh1h09ejZjHhrEn+k9McVkWiuY724jJ/57tylM7A/jzIWNj1F8VlhkyyMIIGcTCC
# BFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJv
# b3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcN
# MjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIw
# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0
# VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEw
# RA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQe
# dGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKx
# Xf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4G
# kbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEA
# AaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7
# fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMC
# AYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvX
# zpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
# cGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYI
# KwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0g
# AQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93
# d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYB
# BQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUA
# bQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOh
# IW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS
# +7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlK
# kVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon
# /VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOi
# PPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/
# fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCII
# YdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0
# cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7a
# KLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQ
# cdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+
# NR4Iuto229Nfj950iEkSoYIC0jCCAjsCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP
# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjo3
# ODgwLUUzOTAtODAxNDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
# dmljZaIjCgEBMAcGBSsOAwIaAxUAMT1LG/KAEj0XsiL9n7mxmX1afZuggYMwgYCk
# fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIF
# AONhwHgwIhgPMjAyMDExMjAwODExMzZaGA8yMDIwMTEyMTA4MTEzNlowdzA9Bgor
# BgEEAYRZCgQBMS8wLTAKAgUA42HAeAIBADAKAgEAAgIZZgIB/zAHAgEAAgIQrzAK
# AgUA42MR+AIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIB
# AAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GBALQQ+z/ef39UDA16
# Nmugn7cdE/0tdN70SrSNX0a0oomg2hAtJHonR9eKiLzCH4pSy9OlNveR6n4y0SB1
# FlWuey9g908QGf0nQQdghsRI1wpZtes7k4gSgVFpT42E4XjQUyN8FhUq3nHkuomy
# CeQyeTc4sUfsyUm1r/mwwlOO6dTzMYIDDTCCAwkCAQEwgZMwfDELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgUENBIDIwMTACEzMAAAEooA6B4TbVT8IAAAAAASgwDQYJYIZIAWUD
# BAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0B
# CQQxIgQg7Yu7QFe6iDCW7DNXIzs4nSk2+MuvW+n8/QtRks2o9m4wgfoGCyqGSIb3
# DQEJEAIvMYHqMIHnMIHkMIG9BCC8RWqLrwVSd+/cGxDfBqS4b1tPXhoPFrC615vV
# 1ugU2jCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAB
# KKAOgeE21U/CAAAAAAEoMCIEIGthXPILw7AHdi147gd2fyUVBPhICJ5LoByTu/0H
# RUy9MA0GCSqGSIb3DQEBCwUABIIBAF/ZQY0HlrBJnEGT4WujOCCX4i2ikv/LuMdi
# kWxnoHm+wzflYWBXCvaYYci/BCHrJL61Rek55pPqujdiCNRm46rI2tqqx15xP5wn
# UQ/D1vfmVGOxnq2lmsaWGF6hrHd4Zo5wstlpiGHCogu0rBymlscuijeJx6yWDXX4
# FSy02LlpJcfjutiLmRinoowYCZ1wHOrBkSS+gwei0Atnn1b6tgqkgxr/Xa/CIQ9S
# lZ4pNOcOFCWd0S69xJ+ca512lvCse/1h8x0onKBr/J4rplALluq6LE7bBUWKslmR
# op6URsXU0Zkks9fwT6K6Eojihq8ubBrHAneggiopjzufuOF4akg=
# SIG # End signature block
