Public/System/Clear-BrowserProfileData.ps1

function Clear-BrowserProfileData {
    <#
    .SYNOPSIS
        Clears Chromium browser profile data for Chrome and/or Edge.
 
    .DESCRIPTION
        Performs a browser profile cleanup workflow for Google Chrome, Microsoft
        Edge, or both:
 
          1. Loads runtime configuration from settings.browserCleanup.
          2. Applies config-driven defaults only for parameters not explicitly
             supplied by the caller.
          3. Resolves one or both target browsers (Chrome, Edge, or All).
          4. Optionally stops browser processes before deletion to avoid file
             locks on cache and cookie databases.
          5. Discovers Chromium profile folders beneath each browser's User Data
             path.
          6. Optionally filters the discovered set to named profiles such as
             Default or Profile 1.
          7. Clears cookies, cache, and optionally local storage by delegating
             to the internal profile-cleanup helpers.
          8. Logs each stage of the run via Write-Log.
 
        CONFIG-DRIVEN DEFAULTS When a parameter is omitted, the function
        attempts to read its default value from settings.browserCleanup in
        config.json. This includes:
 
          - includeCache
          - includeCookies
          - skipLocalStorage
          - killProcesses
          - sleepAfterKillMs
          - defaultBrowser
          - defaultProfiles
 
        Caller-supplied parameter values always take precedence over config.
 
        SHOULDPROCESS / SAFETY This function supports -WhatIf and -Confirm.
        Process termination and any downstream deletion work are guarded by
        ShouldProcess-aware flow so you can preview the intended browser/profile
        targets before making changes.
 
        SCOPE This workflow is designed for Chromium-based profile layouts used
        by Chrome and Edge. It does not target Firefox, Internet Explorer, or
        non-Chromium storage paths.
 
    .PARAMETER Browser
        Specifies which browser to process. Valid values are:
 
          - Chrome
          - Edge
          - All
 
        Defaults to All unless overridden by
        settings.browserCleanup.defaultBrowser.
 
    .PARAMETER Profiles
        One or more Chromium profile folder names to target, for example:
 
          - Default
          - Profile 1
          - Profile 2
 
        When omitted, all discovered profiles for the selected browser(s) are
        processed unless settings.browserCleanup.defaultProfiles defines a
        default filter.
 
    .PARAMETER IncludeCookies
        When $true, clears cookie databases for each targeted profile by calling
        Clear-CookiesForProfile. Defaults to $true, unless overridden by
        settings.browserCleanup.includeCookies.
 
    .PARAMETER IncludeCache
        When $true, clears browser cache folders for each targeted profile by
        calling Clear-CacheForProfile. Defaults to $true, unless overridden by
        settings.browserCleanup.includeCache.
 
    .PARAMETER SkipLocalStorage
        When $true, local storage content is preserved even when cookies are
        being cleared. When $false, local storage cleanup is delegated to
        Clear-CookiesForProfile as part of that workflow. Defaults to $false,
        unless overridden by settings.browserCleanup.skipLocalStorage.
 
    .PARAMETER KillProcesses
        When $true, attempts to stop the relevant browser processes before any
        cleanup begins. This helps prevent file locks on cookies and cache
        files. Defaults to $true, unless overridden by
        settings.browserCleanup.killProcesses.
 
    .PARAMETER SleepAfterKillMs
        Number of milliseconds to wait after stopping browser processes before
        profile cleanup continues. This delay gives the browser time to fully
        release locks on profile files. Defaults to 1500, unless overridden by
        settings.browserCleanup.sleepAfterKillMs.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        None.
 
        This function does not emit structured result objects to the pipeline.
        Progress and outcomes are written through Write-Log and, during -WhatIf
        runs, additional dry-run detail is written via Write-Information.
 
    .EXAMPLE
        Clear-BrowserProfileData -Browser Chrome -Profiles 'Default','Profile 2' -WhatIf
 
        Previews cleanup of the Default and Profile 2 Chrome profiles without
        stopping processes or deleting any browser data.
 
    .EXAMPLE
        Clear-BrowserProfileData -Browser All -IncludeCache:$true -IncludeCookies:$false -Confirm
 
        Processes both Chrome and Edge, clearing cache only, and prompts before
        destructive actions are taken.
 
    .EXAMPLE
        Clear-BrowserProfileData -Browser Edge -Profiles 'Default' -KillProcesses:$false
 
        Clears the Edge Default profile without attempting to stop Edge first.
        Useful when process management is handled externally.
 
    .EXAMPLE
        Clear-BrowserProfileData -Browser Chrome -SkipLocalStorage:$true
 
        Clears Chrome cookies and cache while preserving local storage.
 
    .EXAMPLE
        Clear-BrowserProfileData -Browser All -IncludeCache:$false -IncludeCookies:$true
 
        Clears cookies for all discovered Chrome and Edge profiles, and skips
        cache deletion.
 
    .NOTES
        - Requires the internal helper functions Get-BrowserUserDataPath,
          Get-BrowserProfileFolders, Clear-CookiesForProfile, and
          Clear-CacheForProfile.
        - This function assumes Chromium-style profile folders such as Default
          and Profile 1.
        - If no profiles are discovered for a browser, that browser is skipped
          and a warning is logged.
        - If profile filtering removes all discovered profiles, that browser is
          skipped and a warning is logged.
        - The function currently returns no PSCustomObject results despite older
          help text implying otherwise.
 
    .LINK
        Get-BrowserUserDataPath
 
    .LINK
        Get-BrowserProfileFolders
 
    .LINK
        Clear-CookiesForProfile
 
    .LINK
        Clear-CacheForProfile
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    param(
        [ValidateSet('Chrome', 'Edge', 'All')]
        [string]$Browser = 'All',

        [string[]]$Profiles,

        [bool]$IncludeCookies = $true,
        [bool]$IncludeCache = $true,
        [bool]$SkipLocalStorage = $false,

        [bool]$KillProcesses = $true,
        [int]  $SleepAfterKillMs = 1500
    )

    begin {
        # --- Config & Defaults ---
        Initialize-TechToolboxRuntime
        $cfg = $script:cfg

        # Resolve settings.browserCleanup safely (works for hashtables or PSCustomObjects)
        $bc = @{}
        if ($cfg) {
            $settings = $cfg.settings
            if ($null -eq $settings) { $settings = $cfg.settings }
            if ($settings) {
                $bc = $settings.browserCleanup
                if ($null -eq $bc) { $bc = $settings.browserCleanup }
            }
            if ($null -eq $bc) { $bc = @{} }
        }

        # Apply config-driven defaults only when the parameter wasn't provided
        if (-not $PSBoundParameters.ContainsKey('IncludeCache') -and $bc.ContainsKey('includeCache')) { $IncludeCache = [bool]$bc.includeCache }
        if (-not $PSBoundParameters.ContainsKey('IncludeCookies') -and $bc.ContainsKey('includeCookies')) { $IncludeCookies = [bool]$bc.includeCookies }
        if (-not $PSBoundParameters.ContainsKey('SkipLocalStorage') -and $bc.ContainsKey('skipLocalStorage')) { $SkipLocalStorage = [bool]$bc.skipLocalStorage }
        if (-not $PSBoundParameters.ContainsKey('KillProcesses') -and $bc.ContainsKey('killProcesses')) { $KillProcesses = [bool]$bc.killProcesses }
        if (-not $PSBoundParameters.ContainsKey('SleepAfterKillMs') -and $bc.ContainsKey('sleepAfterKillMs')) { $SleepAfterKillMs = [int] $bc.sleepAfterKillMs }

        # Browser (string default)
        if (-not $PSBoundParameters.ContainsKey('Browser') -and [string]::IsNullOrWhiteSpace($Browser)) {
            if ($bc.ContainsKey('defaultBrowser') -and $bc.defaultBrowser) {
                $Browser = [string]$bc.defaultBrowser
            }
        }

        # Profiles (array or string)
        if (-not $PSBoundParameters.ContainsKey('Profiles') -and $bc.ContainsKey('defaultProfiles') -and $null -ne $bc.defaultProfiles) {
            $dp = $bc.defaultProfiles
            $Profiles = @(
                if ($dp -is [System.Collections.IEnumerable] -and -not ($dp -is [string])) { $dp }
                else { "$dp" }
            )
        }

        # Metadata per browser
        $BrowserMeta = @{
            Chrome = @{ ProcessName = 'chrome'; DisplayName = 'Google Chrome' }
            Edge   = @{ ProcessName = 'msedge'; DisplayName = 'Microsoft Edge' }
        }
    }

    process {
        $targetBrowsers = switch ($Browser) {
            'Chrome' { @('Chrome') }
            'Edge' { @('Edge') }
            'All' { @('Chrome', 'Edge') }
        }

        if ($WhatIfPreference) {
            Write-Information "=== DRY RUN SUMMARY ==="
            Write-Information ("Browsers: {0}" -f ($targetBrowsers -join ', '))
            Write-Information "Include Cache: $IncludeCache"
            Write-Information "Include Cookies: $IncludeCookies"
            Write-Information "Skip Local Storage: $SkipLocalStorage"
            Write-Information "Kill Processes: $KillProcesses"
            Write-Information ("Profiles filter: {0}" -f (($Profiles ?? @()) -join ', '))
            Write-Information "======================="
        }

        foreach ($b in $targetBrowsers) {
            Write-Log -Level Info -Message "=== Processing $b ==="

            $browserName = $BrowserMeta[$b].DisplayName
            $processName = $BrowserMeta[$b].ProcessName

            # Optional: stop processes
            if ($KillProcesses) {
                if ($PSCmdlet.ShouldProcess("$browserName ($processName)", "Stop processes")) {
                    Stop-Process -Name $processName -Force -ErrorAction SilentlyContinue
                    Start-Sleep -Milliseconds $SleepAfterKillMs
                }
            }

            $userData = Get-BrowserUserDataPath -Browser $b
            $profileDirs = @(Get-BrowserProfileFolders -UserDataPath $userData)  # ensure array

            if (-not $profileDirs -or $profileDirs.Count -eq 0) {
                Write-Log -Level Warn -Message "No profiles found for $b at '$userData'."
                continue
            }

            Write-Log -Level Info -Message ("Discovered profiles: {0}" -f ($profileDirs.Name -join ', '))

            # Optional filter by provided profile names
            if ($Profiles) {
                $profileDirs = @($profileDirs | Where-Object { $Profiles -contains $_.Name })
                Write-Log -Level Info -Message ("Filtered profiles: {0}" -f ($profileDirs.Name -join ', '))
                if (-not $profileDirs -or $profileDirs.Count -eq 0) {
                    Write-Log -Level Warn -Message "No profiles remain after filtering. Skipping $b."
                    continue
                }
            }

            foreach ($prof in $profileDirs) {
                # Support DirectoryInfo or string
                $profileName = try { $prof.Name } catch { Split-Path -Path $prof -Leaf }
                $profilePath = try { $prof.FullName } catch { [string]$prof }

                Write-Log -Level Info -Message "Profile: '$profileName' ($profilePath)"

                # Cookies & Local Storage
                if ($IncludeCookies) {
                    $cookieStatus = Clear-CookiesForProfile -ProfilePath $profilePath -SkipLocalStorage:$SkipLocalStorage
                    # (No output—driver consumes status silently; use $cookieStatus for debug if needed)
                }
                else {
                    Write-Log -Level Info -Message "Cookies deletion skipped by configuration."
                }

                # Cache
                if ($IncludeCache) {
                    # If your cache helper returns status, capture silently to avoid tables
                    $cacheStatus = Clear-CacheForProfile -ProfilePath $profilePath
                    # Or: $null = Clear-CacheForProfile -ProfilePath $profilePath
                }
                else {
                    Write-Log -Level Info -Message "Cache deletion skipped by configuration."
                }

                Write-Log -Level Ok -Message "Finished: $profileName"
            }

            Write-Log -Level Ok -Message "=== Completed $b ==="
        }

        # No PSCustomObject results returned
        return
    }

    end {
        Write-Log -Level Ok -Message "All requested browser profile cleanup completed."
    }
}
# SIG # Begin signature block
# MIIfAgYJKoZIhvcNAQcCoIIe8zCCHu8CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCF2YosZUll40k7
# JSGJ15LrVxNfUFZUs/k9avq9nEo+1aCCGEowggUMMIIC9KADAgECAhAR+U4xG7FH
# qkyqS9NIt7l5MA0GCSqGSIb3DQEBCwUAMB4xHDAaBgNVBAMME1ZBRFRFSyBDb2Rl
# IFNpZ25pbmcwHhcNMjUxMjE5MTk1NDIxWhcNMjYxMjE5MjAwNDIxWjAeMRwwGgYD
# VQQDDBNWQURURUsgQ29kZSBTaWduaW5nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
# MIICCgKCAgEA3pzzZIUEY92GDldMWuzvbLeivHOuMupgpwbezoG5v90KeuN03S5d
# nM/eom/PcIz08+fGZF04ueuCS6b48q1qFnylwg/C/TkcVRo0WFcKoFGT8yGxdfXi
# caHtapZfbSRh73r7qR7w0CioVveNBVgfMsTgE0WKcuwxemvIe/ptmkfzwAiw/IAC
# Ib0E0BjiX4PySbwWy/QKy/qMXYY19xpRItVTKNBtXzADUtzPzUcFqJU83vM2gZFs
# Or0MhPvM7xEVkOWZFBAWAubbMCJ3rmwyVv9keVDJChhCeLSz2XR11VGDOEA2OO90
# Y30WfY9aOI2sCfQcKMeJ9ypkHl0xORdhUwZ3Wz48d3yJDXGkduPm2vl05RvnA4T6
# 29HVZTmMdvP2475/8nLxCte9IB7TobAOGl6P1NuwplAMKM8qyZh62Br23vcx1fXZ
# TJlKCxBFx1nTa6VlIJk+UbM4ZPm954peB/fIqEacm8LkZ0cPwmLE5ckW7hfK4Trs
# o+RaudU1sKeA+FvpOWgsPccVRWcEYyGkwbyTB3xrIBXA+YckbANZ0XL7fv7x29hn
# gXbZipGu3DnTISiFB43V4MhNDKZYfbWdxze0SwLe8KzIaKnwlwRgvXDMwXgk99Mi
# EbYa3DvA/5ZWikLW9PxBFD7Vdr8ZiG/tRC9I2Y6fnb+PVoZKc/2xsW0CAwEAAaNG
# MEQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQW
# BBRfYLVE8caSc990rnrIHUjoB7X/KjANBgkqhkiG9w0BAQsFAAOCAgEAiGB2Wmk3
# QBtd1LcynmxHzmu+X4Y5DIpMMNC2ahsqZtPUVcGqmb5IFbVuAdQphL6PSrDjaAR8
# 1S8uTfUnMa119LmIb7di7TlH2F5K3530h5x8JMj5EErl0xmZyJtSg7BTiBA/UrMz
# 6WCf8wWIG2/4NbV6aAyFwIojfAcKoO8ng44Dal/oLGzLO3FDE5AWhcda/FbqVjSJ
# 1zMfiW8odd4LgbmoyEI024KkwOkkPyJQ2Ugn6HMqlFLazAmBBpyS7wxdaAGrl18n
# 6bS7QuAwCd9hitdMMitG8YyWL6tKeRSbuTP5E+ASbu0Ga8/fxRO5ZSQhO6/5ro1j
# PGe1/Kr49Uyuf9VSCZdNIZAyjjeVAoxmV0IfxQLKz6VOG0kGDYkFGskvllIpQbQg
# WLuPLJxoskJsoJllk7MjZJwrpr08+3FQnLkRuisjDOc3l4VxFUsUe4fnJhMUONXT
# Sk7vdspgxirNbLmXU4yYWdsizz3nMUR0zebUW29A+HYme16hzrMPOeyoQjy4I5XX
# 3wXAFdworfPEr/ozDFrdXKgbLwZopymKbBwv6wtT7+1zVhJXr+jGVQ1TWr6R+8ea
# tIOFnY7HqGaxe5XB7HzOwJKdj+bpHAfXft1vUoiKr16VajLigcYCG8MdwC3sngO3
# JDyv2V+YMfsYBmItMGBwvizlQ6557NbK95EwggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0GCSqG
# SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTlaMGkx
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4
# RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYg
# MjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHTCphB
# cr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPhof6p
# vF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mAxAHe
# HYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBvMgEd
# gkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps0wjU
# jsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF83bR
# VFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXiUOeS
# LsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOMCZIV
# NSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydPpOjL
# 6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrUG2Zd
# SoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+sdFU
# eEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0TAQH/
# BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYDVR0j
# BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E
# PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEw
# DQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WIGjB/
# T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+IQhQ
# E7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8Myb9r
# EVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2th9y
# 1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjajV/gx
# dEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2Lr3t
# y9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFzeGxcy
# tL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG7uEB
# YTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+NJpud
# /v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckTetiS
# uEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszWkPZP
# ubdcMIIG7TCCBNWgAwIBAgIQCoDvGEuN8QWC0cR2p5V0aDANBgkqhkiG9w0BAQsF
# ADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNV
# BAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hB
# MjU2IDIwMjUgQ0ExMB4XDTI1MDYwNDAwMDAwMFoXDTM2MDkwMzIzNTk1OVowYzEL
# MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE
# aWdpQ2VydCBTSEEyNTYgUlNBNDA5NiBUaW1lc3RhbXAgUmVzcG9uZGVyIDIwMjUg
# MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANBGrC0Sxp7Q6q5gVrMr
# V7pvUf+GcAoB38o3zBlCMGMyqJnfFNZx+wvA69HFTBdwbHwBSOeLpvPnZ8ZN+vo8
# dE2/pPvOx/Vj8TchTySA2R4QKpVD7dvNZh6wW2R6kSu9RJt/4QhguSssp3qome7M
# rxVyfQO9sMx6ZAWjFDYOzDi8SOhPUWlLnh00Cll8pjrUcCV3K3E0zz09ldQ//nBZ
# ZREr4h/GI6Dxb2UoyrN0ijtUDVHRXdmncOOMA3CoB/iUSROUINDT98oksouTMYFO
# nHoRh6+86Ltc5zjPKHW5KqCvpSduSwhwUmotuQhcg9tw2YD3w6ySSSu+3qU8DD+n
# igNJFmt6LAHvH3KSuNLoZLc1Hf2JNMVL4Q1OpbybpMe46YceNA0LfNsnqcnpJeIt
# K/DhKbPxTTuGoX7wJNdoRORVbPR1VVnDuSeHVZlc4seAO+6d2sC26/PQPdP51ho1
# zBp+xUIZkpSFA8vWdoUoHLWnqWU3dCCyFG1roSrgHjSHlq8xymLnjCbSLZ49kPmk
# 8iyyizNDIXj//cOgrY7rlRyTlaCCfw7aSUROwnu7zER6EaJ+AliL7ojTdS5PWPsW
# eupWs7NpChUk555K096V1hE0yZIXe+giAwW00aHzrDchIc2bQhpp0IoKRR7YufAk
# prxMiXAJQ1XCmnCfgPf8+3mnAgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB0G
# A1UdDgQWBBTkO/zyMe39/dfzkXFjGVBDz2GM6DAfBgNVHSMEGDAWgBTvb1NK6eQG
# fHrK4pBW9i/USezLTjAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYB
# BQUHAwgwgZUGCCsGAQUFBwEBBIGIMIGFMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
# cC5kaWdpY2VydC5jb20wXQYIKwYBBQUHMAKGUWh0dHA6Ly9jYWNlcnRzLmRpZ2lj
# ZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZTSEEy
# NTYyMDI1Q0ExLmNydDBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vY3JsMy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hB
# MjU2MjAyNUNBMS5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB
# MA0GCSqGSIb3DQEBCwUAA4ICAQBlKq3xHCcEua5gQezRCESeY0ByIfjk9iJP2zWL
# pQq1b4URGnwWBdEZD9gBq9fNaNmFj6Eh8/YmRDfxT7C0k8FUFqNh+tshgb4O6Lgj
# g8K8elC4+oWCqnU/ML9lFfim8/9yJmZSe2F8AQ/UdKFOtj7YMTmqPO9mzskgiC3Q
# YIUP2S3HQvHG1FDu+WUqW4daIqToXFE/JQ/EABgfZXLWU0ziTN6R3ygQBHMUBaB5
# bdrPbF6MRYs03h4obEMnxYOX8VBRKe1uNnzQVTeLni2nHkX/QqvXnNb+YkDFkxUG
# tMTaiLR9wjxUxu2hECZpqyU1d0IbX6Wq8/gVutDojBIFeRlqAcuEVT0cKsb+zJNE
# suEB7O7/cuvTQasnM9AWcIQfVjnzrvwiCZ85EE8LUkqRhoS3Y50OHgaY7T/lwd6U
# Arb+BOVAkg2oOvol/DJgddJ35XTxfUlQ+8Hggt8l2Yv7roancJIFcbojBcxlRcGG
# 0LIhp6GvReQGgMgYxQbV1S3CrWqZzBt1R9xJgKf47CdxVRd/ndUlQ05oxYy2zRWV
# FjF7mcr4C34Mj3ocCVccAvlKV9jEnstrniLvUxxVZE/rptb7IRE2lskKPIJgbaP5
# t2nGj/ULLi49xTcBZU8atufk+EMF/cWuiC7POGT75qaL6vdCvHlshtjdNXOCIUjs
# arfNZzGCBg4wggYKAgEBMDIwHjEcMBoGA1UEAwwTVkFEVEVLIENvZGUgU2lnbmlu
# ZwIQEflOMRuxR6pMqkvTSLe5eTANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3
# AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG
# AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCDG/tyQSXwO
# 24ZaBSsyIhjzfpIOL6CXojlsH9k6OQjuazANBgkqhkiG9w0BAQEFAASCAgBF8jaW
# OV4lpEUjZj+Vtoi2HWjqtP54b9AlYpqRjzy+P+SDQ2ASxsi+wcdoJOsiZ98bp3xD
# mjUn4DtBlOZue+yyL3NZW7pT3SGjBhoELjRW5Ah74u1KjC2za/VUELLpvX+vOdi7
# L1WuaekLsm9ZcWu/4SRhArnYwpHLtilthVUUb4XoqIyZ8jAdnjcHkaQunbeOgTpg
# UDcj12SeWMu/lNos6JVsbpVOW9wiwpeEcDm5mjwh18Lskm7tH36yVJTdxe0nrQXi
# OUUnkijwXOoICreUjrZ6KWnE/K4jipMPZI8YcGh0nXix+zNOIdgSittEQVwP4/bu
# cz32fyjCWf+Kenu5KTwZWihvCpqPmLAIzJzvIfhsiKfSDNYcBVAq7wR/rlmCoalg
# 943GrLw7+d39aeGnmIXJJfH4mOXASwDBjYsDCyUOdzzh9ub5N6HWkXqcpxn7ZByP
# asO6f3q/IUY3VwF6xOlfPmnV714vy4RkFveE/hCFATQORpBB8jzjn20dYB/38RYc
# H/76c7cDy12Hib9f0vK4XXsNynSlsguJgFs39nfrfEXJJodCfHjRLoVkK0YGmZpx
# 4Uotl+nxQSHHGFBYymVEK9TNJdBv//oXpjhs+elb8fGYswa4kmsM3bnKtMhSVKSN
# kSjtS2zdaHgtxnsb6RajcDrrbUYtHrr8sj7F5qGCAyYwggMiBgkqhkiG9w0BCQYx
# ggMTMIIDDwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcg
# UlNBNDA5NiBTSEEyNTYgMjAyNSBDQTECEAqA7xhLjfEFgtHEdqeVdGgwDQYJYIZI
# AWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJ
# BTEPFw0yNjA0MTQxNDQwMzlaMC8GCSqGSIb3DQEJBDEiBCAbzImeMzRRd+fISDA+
# JaxTueu9wsOgWebZwwGCJXYjkzANBgkqhkiG9w0BAQEFAASCAgB6WHSRap9tQ4Qr
# PZkvLciXUJwg97kurx5R7P+CIHrGVsJCANnTSvodYC4Uwn3d7sSDbtdbY+EREqFv
# 6sssR5mrdsGrouPNR6hyUp+lTIJSj2DePai2V9rIV/MLKxJQK8YHVCJWl7d1MvZ4
# KOkj+iFg8wtiUq1mSD/o88fKvmP7MvP8tUw+/sYd/yDemWEVkxEezngCPfVeljS6
# 40el+DEaXLNNKguIRHqy9NMeZqaDans13YpjyRI/S1OcFSmj/KxDoZeZDCBtwWSJ
# w/L0t1frTp9NoYtBSbScY+T3AflZpUte0QFz1ktd5z6mDJMwmtBqtBu6xXruZMQC
# 98xm+vVD+0Fkuj1h4hQqfe5vCOOOCJXbUpn1Qtt9tk/ZzqMqhM512y+R0FoVf4xm
# cjBDPBUkaHfcuoh3wtecxkS9sDh3OHGXiv4PqbBOc5MSBDrbM7ksRLKDDErkAspq
# qwIQM2S/VWaIAmWjScRm1dEw1kPcb0HNUndH2MvIsPVowvsl8rIvJlfbhMsZg3R6
# fYuc9vfGVXDmlFHouvUjQImHXnAgTqzY8adwWsMgSWX1V6GWGhAAQAZfYuz0YT9P
# zk0mQYUbuLL9/sRfKn30LAEucfdyevVYdejuX++g6xIBmfI/7JMEuyfZ34xNfajm
# j0fDL90EXjh1vZ1muur/iJaxZriKUA==
# SIG # End signature block