<#
    .SYNOPSIS
        Provides cmdlets for various logging information and sending telemetry.
    .DESCRIPTION
        This acts as a Logger and Telemetry library.
        "Log" functions are meant to help users diagnose errors.
        "Send" functions are meant to help us improve the product and fix issues users hit.
        They are separate functions, since we need to be judicious in what we send back through telemetry.
#>

Class CWACLogger
{

    [string] $_logFile
    [DateTime] $_scriptStartTime
    [DateTime] $_sectionStartTime
    [string] $_sectionTitleShort
    [hashtable] $_extensions
    [hashtable] $_folders
    $_telemetry

    CWACLogger()
    {
    }

    CWACLogger([string] $logFile, [string] $DllPath)
    {
        if ([string]::IsNullOrEmpty($logFile))
        {
            throw "Log File parameter cannot be null or empty"
        }
        $this._logFile = $logFile

        [System.Reflection.Assembly]::LoadFile((Join-Path $DllPath "Telemetry.dll")) > $null
        [System.Reflection.Assembly]::LoadFile((Join-Path $DllPath "Microsoft.ApplicationInsights.dll")) > $null
        $this._telemetry = New-Object -TypeName Telemetry.Logger

        $this._scriptStartTime = Get-Date
        $this._extensions = @{}
        $this._folders = @{}
    }

    [string] GetLogFile()
    {
        return $this._logFile
    }

    [void] LogError([string] $msg)
    {
        Write-Error $msg
        $this.LogToFile($msg)
        $this._telemetry.SendError($msg)
    }

    [void] LogDiag([string] $msg)
    {
        Write-Verbose $msg
        $this.LogToFile($msg)
    }

    [void] LogWarning([string] $msg)
    {
        Write-Warning $msg
        $this.LogToFile($msg)
        $this._telemetry.SendWarning($msg)
    }

    [void] LogToFile([string] $msg)
    {
        if ($this._logFile)
        {
            $this.FormatLogMessage($msg) | Out-File -FilePath $this._logFile -Append
        }
    }

    [string] FormatLogMessage([String] $msg)
    {
        return "[$(Get-Date -format s)] $msg"
    }

    # Start a new log section and also log the time taken.  We also need a shortened version
    # since it makes the telemetry easier to read.
    [void] NewLogSection([string] $sectionTitle, [string] $sectionTitleShort)
    {
        $newline = "`r`n"
        $formattedTitle = '-' * 50 + $newline * 3 + $sectionTitle + $newline * 2
        $this.LogDiag($formattedTitle)

        $this.SendSectionTime($sectionTitleShort)
    }

    # Log the version of our tools.
    [void] LogVersion([string] $version)
    {
        $this.LogDiag($version)
        $this._telemetry.SetVersion($version)
    }

    # Send how long the previous section took, and start timing the new section
    [void] SendSectionTime([String] $sectionTitleShort)
    {
        # The very first time this is called, don't send anything.  It's the very first section
        # so the "previous" section doesn't exist.
        if ($this._sectionTitleShort)
        {
            $this.SendTimeTaken($this._sectionTitleShort, $(Get-Date) - $this._sectionStartTime)
        }

        $this._sectionStartTime = Get-Date
        $this._sectionTitleShort = $sectionTitleShort
    }

    # Send how long an event took.
    [void] SendTimeTaken([String] $event, [TimeSpan] $duration)
    {
        # Telemetry class uses doubles for all metrics (no concept of a TimeSpan), so tack on
        # "Seconds" to help document what type it is.
        $this._telemetry.SendMetric("$($event)Seconds", [math]::Round($duration.TotalSeconds))
    }

    # Send how large a file is.
    [void] SendFileSize([String] $name, [String] $fileNameAndPath)
    { 
        if (Test-Path $fileNameAndPath)
        {
            $file = Get-Item($fileNameAndPath)
            if ($file)
            {
                # Round to nearest KB, since Windows Explorer shows KB by default and it's what most people expect.
                $sizeKB = [math]::Round($file.Length/1KB)

                $this._telemetry.SendMetric("$($name)FileSizeKB", $sizeKB)
            }
        }
    }

    # Parse and send command line file parameter stripped of the path.
    [void] SendFileParameter([String] $name, [String] $file)
    {
        if (!([string]::IsNullOrEmpty($file)) -and (Test-Path $file))
        {
            # Remove filepath, since that could contain PII.
            $filename = Split-Path $file -Leaf
            $this._telemetry.SendProperty("$($name)Parameter", $filename)
        }
    }

    # Send a command line parameter if it exists.
    [void] SendParameter([String] $name, [String] $parameter)
    {
        if (!([string]::IsNullOrEmpty($parameter)))
        {
            $this._telemetry.SendProperty("$($name)Parameter", $parameter)
        }
    }

    # Send a switch command line parameter.
    [void] SendSwitchParameter([String] $name, [switch] $parameter)
    {
        $this._telemetry.SendProperty("$($name)Parameter", $parameter)
    }

    # Send a name and value pair.
    [void] SendValue([String] $name, [double] $value)
    {
        $this._telemetry.SendMetric($name, $value)
    }

    # Send file information.  We just care about file extensions and basic folder paths.
    # Batch the data up, and send at the end.
    [void] SendFileData([String] $rootName, [String] $fileName)
    {
        # We only need a set collection class and not a hashtable, but hashtables are better
        # supported in PowerShell.  So for the value, just use 1, which essentially gives us a set.
        $extension = [System.IO.Path]::GetExtension($fileName).ToLower()
        $this._extensions[$extension] = 1

        # Send the directory the file is located in, but only up to two levels deep.
        # We only care about in general where the file is going (ex. \Windows\System32), and this
        # helps prevent sending hundreds of folders.  For example, this should convert:
        #   "\<DesktopAppConverterDirectory>\Program Files(x86)\notepad\manuals\manual.txt" to
        #   "\Program Files(x86)\notepad"
        $folder = [System.IO.Path]::GetDirectoryName($filename).ToLower()
        $subFolder = $folder.Substring($rootName.Length)

        try
        {
            $slash = $subFolder.IndexOf('\', 1)
            if ($slash -ge 0)
            {
                $slash = $subFolder.IndexOf('\', $slash+1)
                if ($slash -ge 0)
                {
                    $subFolder = $subFolder.Substring(0, $slash)
                }
            }
        }
        catch
        {
            # This means there is less than two subfolders (ex. "\Fabrikam"), so just
            # return the entire folder path
        }

        $this._folders[$subFolder] = 1
    }

    # Send the data we have batched up.
    # * How long it took for the entire script to run
    # * Was there an error?
    # * All placed file data
    [void] SendAllBatchedData()
    {
        $this.SendTimeTaken("Overall", $(Get-Date) - $this._scriptStartTime)

        # Send out the final section time, and don't worry about starting another section
        # so just pass "".
        $this.SendSectionTime("");

        # Send out folders, comma delimited.  For example: "\Program Files(x86)\notepad, \Windows\System32"
        $folders = ($this._folders.Keys -join ", ")
        $this._telemetry.SendProperty("PlacedFolders", $folders)

        # Send out extensions, comma delimited.  For example: ".txt, .doc, .rtf"
        # Call it "PlacedExtensions" instead of "Extensions", since it helps differentiate it from
        # the file extensions they can register for.
        $extensions = ($this._extensions.Keys -join ", ")
        $this._telemetry.SendProperty("PlacedExtensions", $extensions)
    }

    # Send the fatal exception.
    [void] SendFatalException($errorRecord)
    {
        $this.SendAllBatchedData()

        # The Exception Message is the most helpful part and does get logged with the Exception object.  But
        # in the ApplicationInsights web portal, it's not prominent enough, so log it again as a property.
        $this._telemetry.SendProperty("ExceptionMessage", $errorRecord)
        $this._telemetry.SendFatalException($errorRecord.Exception)
    }

    # Send the final telemetry
    [void] SendCompleted()
    {
        $this.SendAllBatchedData()
        $this._telemetry.SendCompleted()
    }
}
# SIG # Begin signature block
# MIIkJgYJKoZIhvcNAQcCoIIkFzCCJBMCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDmPuALTRtIbIXI
# 9oKxjd3uzGyRC1LuyLeyFKP40LKxz6CCDZIwggYQMIID+KADAgECAhMzAAAAZEeE
# lIbbQRk4AAAAAABkMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMTUxMDI4MjAzMTQ2WhcNMTcwMTI4MjAzMTQ2WjCBgzEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9Q
# UjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMIIBIjANBgkqhkiG9w0B
# AQEFAAOCAQ8AMIIBCgKCAQEAky7a2OY+mNkbD2RfTahYTRQ793qE/DwRMTrvicJK
# LUGlSF3dEp7vq2YoNNV9KlV7TE2K8sDxstNSFYu2swi4i1AL3X/7agmg3GcExPHf
# vHUYIEC+eCyZVt3u9S7dPkL5Wh8wrgEUirCCtVGg4m1l/vcYCo0wbU06p8XzNi3u
# XyygkgCxHEziy/f/JCV/14/A3ZduzrIXtsccRKckyn6B5uYxuRbZXT7RaO6+zUjQ
# hiyu3A4hwcCKw+4bk1kT9sY7gHIYiFP7q78wPqB3vVKIv3rY6LCTraEbjNR+phBQ
# EL7hyBxk+ocu+8RHZhbAhHs2r1+6hURsAg8t4LAOG6I+JQIDAQABo4IBfzCCAXsw
# HwYDVR0lBBgwFgYIKwYBBQUHAwMGCisGAQQBgjdMCAEwHQYDVR0OBBYEFFhWcQTw
# vbsz9YNozOeARvdXr9IiMFEGA1UdEQRKMEikRjBEMQ0wCwYDVQQLEwRNT1BSMTMw
# MQYDVQQFEyozMTY0Mis0OWU4YzNmMy0yMzU5LTQ3ZjYtYTNiZS02YzhjNDc1MWM0
# YjYwHwYDVR0jBBgwFoAUSG5k5VAF04KqFzc3IrVtqMp1ApUwVAYDVR0fBE0wSzBJ
# oEegRYZDaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljQ29k
# U2lnUENBMjAxMV8yMDExLTA3LTA4LmNybDBhBggrBgEFBQcBAQRVMFMwUQYIKwYB
# BQUHMAKGRWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj
# Q29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqG
# SIb3DQEBCwUAA4ICAQCI4gxkQx3dXK6MO4UktZ1A1r1mrFtXNdn06DrARZkQTdu0
# kOTLdlGBCfCzk0309RLkvUgnFKpvLddrg9TGp3n80yUbRsp2AogyrlBU+gP5ggHF
# i7NjGEpj5bH+FDsMw9PygLg8JelgsvBVudw1SgUt625nY7w1vrwk+cDd58TvAyJQ
# FAW1zJ+0ySgB9lu2vwg0NKetOyL7dxe3KoRLaztUcqXoYW5CkI+Mv3m8HOeqlhyf
# FTYxPB5YXyQJPKQJYh8zC9b90JXLT7raM7mQ94ygDuFmlaiZ+QSUR3XVupdEngrm
# ZgUB5jX13M+Pl2Vv7PPFU3xlo3Uhj1wtupNC81epoxGhJ0tRuLdEajD/dCZ0xIni
# esRXCKSC4HCL3BMnSwVXtIoj/QFymFYwD5+sAZuvRSgkKyD1rDA7MPcEI2i/Bh5O
# MAo9App4sR0Gp049oSkXNhvRi/au7QG6NJBTSBbNBGJG8Qp+5QThKoQUk8mj0ugr
# 4yWRsA9JTbmqVw7u9suB5OKYBMUN4hL/yI+aFVsE/KJInvnxSzXJ1YHka45ADYMK
# AMl+fLdIqm3nx6rIN0RkoDAbvTAAXGehUCsIod049A1T3IJyUJXt3OsTd3WabhIB
# XICYfxMg10naaWcyUePgW3+VwP0XLKu4O1+8ZeGyaDSi33GnzmmyYacX3BTqMDCC
# B3owggVioAMCAQICCmEOkNIAAAAAAAMwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29m
# dCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTExMDcwODIwNTkw
# OVoXDTI2MDcwODIxMDkwOVowfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAx
# MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKvw+nIQHC6t2G6qghBN
# NLrytlghn0IbKmvpWlCquAY4GgRJun/DDB7dN2vGEtgL8DjCmQawyDnVARQxQtOJ
# DXlkh36UYCRsr55JnOloXtLfm1OyCizDr9mpK656Ca/XllnKYBoF6WZ26DJSJhIv
# 56sIUM+zRLdd2MQuA3WraPPLbfM6XKEW9Ea64DhkrG5kNXimoGMPLdNAk/jj3gcN
# 1Vx5pUkp5w2+oBN3vpQ97/vjK1oQH01WKKJ6cuASOrdJXtjt7UORg9l7snuGG9k+
# sYxd6IlPhBryoS9Z5JA7La4zWMW3Pv4y07MDPbGyr5I4ftKdgCz1TlaRITUlwzlu
# ZH9TupwPrRkjhMv0ugOGjfdf8NBSv4yUh7zAIXQlXxgotswnKDglmDlKNs98sZKu
# HCOnqWbsYR9q4ShJnV+I4iVd0yFLPlLEtVc/JAPw0XpbL9Uj43BdD1FGd7P4AOG8
# rAKCX9vAFbO9G9RVS+c5oQ/pI0m8GLhEfEXkwcNyeuBy5yTfv0aZxe/CHFfbg43s
# TUkwp6uO3+xbn6/83bBm4sGXgXvt1u1L50kppxMopqd9Z4DmimJ4X7IvhNdXnFy/
# dygo8e1twyiPLI9AN0/B4YVEicQJTMXUpUMvdJX3bvh4IFgsE11glZo+TzOE2rCI
# F96eTvSWsLxGoGyY0uDWiIwLAgMBAAGjggHtMIIB6TAQBgkrBgEEAYI3FQEEAwIB
# ADAdBgNVHQ4EFgQUSG5k5VAF04KqFzc3IrVtqMp1ApUwGQYJKwYBBAGCNxQCBAwe
# CgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
# BBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0
# cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2Vy
# QXV0MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAwTgYIKwYBBQUH
# MAKGQmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2Vy
# QXV0MjAxMV8yMDExXzAzXzIyLmNydDCBnwYDVR0gBIGXMIGUMIGRBgkrBgEEAYI3
# LgMwgYMwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lv
# cHMvZG9jcy9wcmltYXJ5Y3BzLmh0bTBABggrBgEFBQcCAjA0HjIgHQBMAGUAZwBh
# AGwAXwBwAG8AbABpAGMAeQBfAHMAdABhAHQAZQBtAGUAbgB0AC4gHTANBgkqhkiG
# 9w0BAQsFAAOCAgEAZ/KGpZjgVHkaLtPYdGcimwuWEeFjkplCln3SeQyQwWVfLiw+
# +MNy0W2D/r4/6ArKO79HqaPzadtjvyI1pZddZYSQfYtGUFXYDJJ80hpLHPM8QotS
# 0LD9a+M+By4pm+Y9G6XUtR13lDni6WTJRD14eiPzE32mkHSDjfTLJgJGKsKKELuk
# qQUMm+1o+mgulaAqPyprWEljHwlpblqYluSD9MCP80Yr3vw70L01724lruWvJ+3Q
# 3fMOr5kol5hNDj0L8giJ1h/DMhji8MUtzluetEk5CsYKwsatruWy2dsViFFFWDgy
# cScaf7H0J/jeLDogaZiyWYlobm+nt3TDQAUGpgEqKD6CPxNNZgvAs0314Y9/HG8V
# fUWnduVAKmWjw11SYobDHWM2l4bf2vP48hahmifhzaWX0O5dY0HjWwechz4GdwbR
# BrF1HxS+YWG18NzGGwS+30HHDiju3mUv7Jf2oVyW2ADWoUa9WfOXpQlLSBCZgB/Q
# ACnFsZulP0V3HjXG0qKin3p6IvpIlR+r+0cjgPWe+L9rt0uX4ut1eBrs6jeZeRhL
# /9azI2h15q/6/IvrC4DqaTuv/DDtBEyO3991bWORPdGdVk5Pv4BXIqF4ETIheu9B
# CrE/+6jMpF3BoYibV3FWTkhFwELJm3ZbCoBIa/15n8G9bW1qyVJzEw16UM0xghXq
# MIIV5gIBATCBlTB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ
# MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExAhMzAAAA
# ZEeElIbbQRk4AAAAAABkMA0GCWCGSAFlAwQCAQUAoIHWMBkGCSqGSIb3DQEJAzEM
# BgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqG
# SIb3DQEJBDEiBCBptym+gt7ILIaf0wXiMwrwMdVZolnWs4xJXRzsh1p4/DBqBgor
# BgEEAYI3AgEMMVwwWqAugCwAVwBpAG4AZABvAHcAcwAgAFAAaABvAG4AZQAgAFAA
# YQBjAGsAYQBnAGUAc6EogCZodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vd2luZG93
# c3Bob25lLzANBgkqhkiG9w0BAQEFAASCAQB042YC3wzucwEiZHmig9WHnyVpY5m4
# d2LkZFBmXoquTpet0YC7HMKs8PqI1/+GxAOwb3GoCIYKzLkvJfC0lQrbbEqcVqz6
# KvC07OwXLC8SgHLQEdyuIyetXl1Dogz1eTB2T4K2mrfrrhhej4jigTgGP9r2LjS/
# Y9D/kVc8r5hDHDeAhRZ42YCozSYfzZH5hejiIBWombER/2lZoe8mvbn0iom0kZAQ
# Q7FlBaHWhRaVBO2fzLmCy4o5VeS6hO2fBwj6VGB9IxVB3tXqqERE4JFpjUz+e/is
# mqbUOEp0a8pKXAVVUUBwcUC2Zi/OGSQ7dUYes1bIgS80iwfvTqfpPOxQoYITTDCC
# E0gGCisGAQQBgjcDAwExghM4MIITNAYJKoZIhvcNAQcCoIITJTCCEyECAQMxDzAN
# BglghkgBZQMEAgEFADCCATwGCyqGSIb3DQEJEAEEoIIBKwSCAScwggEjAgEBBgor
# BgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIH0GjHEKgmj2JZyLWw/zW2HFf1F5
# hoQxyuKy0+fiGhs+AgZW7BhoeiAYEjIwMTYwNDA2MDQxNDA5Ljk2WjAHAgEBgAIB
# 9KCBuaSBtjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEN
# MAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkI4RUMtMzBB
# NC03MTQ0MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIO
# 0DCCBnEwggRZoAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcNAQELBQAwgYgxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jv
# c29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4XDTEwMDcwMTIx
# MzY1NVoXDTI1MDcwMTIxNDY1NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
# c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD
# b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw
# MTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpHQ28dxGKOiDs/BOX
# 9fp/aZRrdFQQ1aUKAIKF++18aEssX8XD5WHCdrc+Zitb8BVTJwQxH0EbGpUdzgkT
# jnxhMFmxMEQP8WCIhFRDDNdNuDgIs0Ldk6zWczBXJoKjRQ3Q6vVHgc2/JGAyWGBG
# 8lhHhjKEHnRhZ5FfgVSxz5NMksHEpl3RYRNuKMYa+YaAu99h/EbBJx0kZxJyGiGK
# r0tkiVBisV39dx898Fd1rL2KQk1AUdEPnAY+Z3/1ZsADlkR+79BL/W7lmsqxqPJ6
# Kgox8NpOBpG2iAg16HgcsOmZzTznL0S6p/TcZL2kAcEgCZN4zfy8wMlEXV4WnAEF
# TyJNAgMBAAGjggHmMIIB4jAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQU1WM6
# XIoxkPNDe3xGG8UzaFqFbVUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYD
# VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxi
# aNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3Nv
# ZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMu
# Y3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNy
# b3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQw
# gaAGA1UdIAEB/wSBlTCBkjCBjwYJKwYBBAGCNy4DMIGBMD0GCCsGAQUFBwIBFjFo
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUEtJL2RvY3MvQ1BTL2RlZmF1bHQuaHRt
# MEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAFAAbwBsAGkAYwB5AF8AUwB0
# AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQAH5ohRDeLG4Jg/
# gXEDPZ2joSFvs+umzPUxvs8F4qn++ldtGTCzwsVmyWrf9efweL3HqJ4l4/m87WtU
# VwgrUYJEEvu5U4zM9GASinbMQEBBm9xcF/9c+V4XNZgkVkt070IQyK+/f8Z/8jd9
# Wj8c8pl5SpFSAK84Dxf1L3mBZdmptWvkx872ynoAb0swRCQiPM/tA6WWj1kpvLb9
# BOFwnzJKJ/1Vry/+tuWOM7tiX5rbV0Dp8c6ZZpCM/2pif93FSguRJuI57BlKcWOd
# eyFtw5yjojz6f32WapB4pm3S4Zz5Hfw42JT0xqUKloakvZ4argRCg7i1gJsiOCC1
# JeVk7Pf0v35jWSUPei45V3aicaoGig+JFrphpxHLmtgOR5qAxdDNp9DvfYPw4Ttx
# Cd9ddJgiCGHasFAeb73x4QDf5zEHpJM692VHeOj4qEir995yfmFrb3epgcunCaw5
# u+zGy9iCtHLNHfS4hQEegPsbiSpUObJb2sgNVZl6h3M7COaYLeqN4DMuEin1wC9U
# JyH3yKxO2ii4sanblrKnQqLJzxlBTeCG+SqaoxFmMNO7dDJL32N79ZmKLxvHIa9Z
# ta7cRDyXUHHXodLFVeNp3lfB0d4wwP3M5k37Db9dT+mdHhk4L7zPWAUu7w2gUDXa
# 7wknHNWzfjUeCLraNtvTX4/edIhJEjCCBNowggPCoAMCAQICEzMAAABzd9M4rzjT
# v/YAAAAAAHMwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
# IDIwMTAwHhcNMTUxMDA3MTgxNzM5WhcNMTcwMTA3MTgxNzM5WjCBszELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUG
# A1UECxMebkNpcGhlciBEU0UgRVNOOkI4RUMtMzBBNC03MTQ0MSUwIwYDVQQDExxN
# aWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkqhkiG9w0BAQEFAAOC
# AQ8AMIIBCgKCAQEAyFnMGHfMNRcL8xreuatxxVoPKKzfmx1e7fU89Ws8GKp/TV2T
# 8Ypi28EMppTWGkkv3DvyAIczorV4UeDC3F775g9v+xh0vPjTCA2ftC0q4qE6an65
# Tma9T0g1+WUwV689fc402QyhEKA2kmLhbtNIqy0WmertQ/NI81VYqymuAvbsuKq2
# Ksss5mgf6UoVczwNMk8WcMnVnRuqfDXs3zt8l5IOgbeif3HN4Q1/kGNpL1EbLA6r
# rZLvUAolGGZKpfa50MHjnuRCG3bHn9cqOts1gUog3sOhnE9AHZjI1NFCXK4KrVKl
# xOmPr0X7fQri4Y0sZc8aY1zAxhp7Jv0JHt4/SwIDAQABo4IBGzCCARcwHQYDVR0O
# BBYEFCAH8PPr9mD1SK6o11LyJISnAtjzMB8GA1UdIwQYMBaAFNVjOlyKMZDzQ3t8
# RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8yMDEwLTA3LTAxLmNy
# bDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9z
# b2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAtMDctMDEuY3J0MAwG
# A1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZIhvcNAQELBQAD
# ggEBAEh6SyRA/xn+wXsJrG7EnFxIsVjmbo7MQ/QVpamKF+wERSwZw/0qpyCFz/v7
# a3dm4EzkEb9e/+U6FRW8mmD/+kBpf4Rn4/5n5Ag9tA+qa/xGA7W/PruHZ3Yr8JRA
# hesPPjN7D9wgAGadTqBCSyikvYqf5JFHVJr/w9agPcQlDosG0s9pUsB32yR1NBWc
# OWH1Nfb/TE0SmSpcWSC44XMx+YMRK/Yqr3f73trXIbBWovspuocHhM26ZtL4hruU
# jJKELm5nkRcyLpQFHfkKNf5s3Y/AVKfno0w0gGT4EqTvjCUuU9F1tWISNoJ29CvF
# kjNqkajuwYRbMT7pBs5M7jy2aZKhggN5MIICYQIBATCB46GBuaSBtjCBszELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9QUjEn
# MCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkI4RUMtMzBBNC03MTQ0MSUwIwYDVQQD
# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiUKAQEwCQYFKw4DAhoFAAMV
# AHEU+n6gbT8z7d7nE+ve460CDmbMoIHCMIG/pIG8MIG5MQswCQYDVQQGEwJVUzET
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYDVQQLEwRNT1BSMScwJQYDVQQLEx5u
# Q2lwaGVyIE5UUyBFU046NTdGNi1DMUUwLTU1NEMxKzApBgNVBAMTIk1pY3Jvc29m
# dCBUaW1lIFNvdXJjZSBNYXN0ZXIgQ2xvY2swDQYJKoZIhvcNAQEFBQACBQDartWE
# MCIYDzIwMTYwNDA2MDAyMzMyWhgPMjAxNjA0MDcwMDIzMzJaMHcwPQYKKwYBBAGE
# WQoEATEvMC0wCgIFANqu1YQCAQAwCgIBAAICBrQCAf8wBwIBAAICHc0wCgIFANqw
# JwQCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAaAKMAgCAQACAxbj
# YKEKMAgCAQACAwehIDANBgkqhkiG9w0BAQUFAAOCAQEAQBULIybKpw8M0I/m9xWY
# 1w1EYar8SAujj6kPBImXo8uxyMQlHbk/9qiOgVic/AHC5g9p7ap9Zvf7ch3nF+tH
# NCx5Mmw3GPIjupbO8m/QTb3FEZ7+zZvkjtaZK6GXi+5/IrmWDPaHz40Fdk/xDgbu
# zmdRVn3ReJNn5PGtCIlEBhE+t/CQ6wf0j7GJvySJbbQ++BPU4XgjTXIjMGXLBhpg
# yR8jKWCiFivf+p4nJmojX7zisp4Ab77dpzfz9KxhDImBUYJeOGBLSZtMaHLa6IZS
# N3vWKidunCZN8m5jdG1HKyhsPNQ5QfCbVZNPa+WyDLvtLLTh7r8jz+D20Mg3jMC1
# szGCAvUwggLxAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMz
# AAAAc3fTOK8407/2AAAAAABzMA0GCWCGSAFlAwQCAQUAoIIBMjAaBgkqhkiG9w0B
# CQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIDRMnjcdzrHOTddlfY6S
# quMswb/Nfh3dwLpXAMSImeSeMIHiBgsqhkiG9w0BCRACDDGB0jCBzzCBzDCBsQQU
# cRT6fqBtPzPt3ucT697jrQIOZswwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFt
# cCBQQ0EgMjAxMAITMwAAAHN30zivONO/9gAAAAAAczAWBBR8T2M420nteq4fbJoc
# aUoBP1srljANBgkqhkiG9w0BAQsFAASCAQBAV9VQ6ASHO3BW+aXq7dGsJ5/2KDI9
# mH3PJAGNLSv/LtcDqNxlKc0nkFegXqeYUfRd0xUxEtkBxXz7CQ1K9Pwv21kiQj7n
# +9np2I5sGAprA2nJZAWoCQjn/qI2CvzHYOhqvMKNFuQnoeHCrYH6iLb0Y3+tlCg1
# aJWJiPk8WHnspWI11c4+UvNHCjTo5qYShNPjkpz54pRo0nW+psR9JlNAxmVnLVW3
# 5UhHRoyALzp4NL/9uD6NBUQgksIRFRhq10EOnwo1/xdVOIOvRZmbrA6D/Q6A08HV
# mdv6s0VmyGTKilGTeOHUTqJ5UQMKWkX+fJJkgDhwvhgAKV7E/UUR9wJW
# SIG # End signature block
